Skip to content

Commit 72095b9

Browse files
Async rendering support (#393)
1 parent 858bd57 commit 72095b9

File tree

3 files changed

+100
-25
lines changed

3 files changed

+100
-25
lines changed

.mypy.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@ disallow_any_unimported = True
2121
warn_return_any = True
2222

2323
[mypy-tests.*]
24+
disallow_any_decorated = False
25+
disallow_untyped_calls = False
2426
disallow_untyped_defs = False

aiohttp_jinja2/__init__.py

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
Iterable,
1111
Mapping,
1212
Optional,
13+
Tuple,
1314
TypeVar,
1415
Union,
1516
cast,
@@ -97,13 +98,12 @@ def get_env(app: web.Application, *, app_key: str = APP_KEY) -> jinja2.Environme
9798
return cast(jinja2.Environment, app.get(app_key))
9899

99100

100-
def render_string(
101+
def _render_string(
101102
template_name: str,
102103
request: web.Request,
103104
context: Mapping[str, Any],
104-
*,
105-
app_key: str = APP_KEY,
106-
) -> str:
105+
app_key: str,
106+
) -> Tuple[jinja2.Template, Mapping[str, Any]]:
107107
env = request.config_dict.get(app_key)
108108
if env is None:
109109
text = (
@@ -126,26 +126,71 @@ def render_string(
126126
raise web.HTTPInternalServerError(reason=text, text=text)
127127
if request.get(REQUEST_CONTEXT_KEY):
128128
context = dict(request[REQUEST_CONTEXT_KEY], **context)
129-
text = template.render(context)
130-
return text
129+
return template, context
131130

132131

133-
def render_template(
132+
def render_string(
134133
template_name: str,
135134
request: web.Request,
136-
context: Optional[Mapping[str, Any]],
135+
context: Mapping[str, Any],
137136
*,
138137
app_key: str = APP_KEY,
139-
encoding: str = "utf-8",
140-
status: int = 200,
141-
) -> web.Response:
138+
) -> str:
139+
template, context = _render_string(template_name, request, context, app_key)
140+
return template.render(context)
141+
142+
143+
async def render_string_async(
144+
template_name: str,
145+
request: web.Request,
146+
context: Mapping[str, Any],
147+
*,
148+
app_key: str = APP_KEY,
149+
) -> str:
150+
template, context = _render_string(template_name, request, context, app_key)
151+
return await template.render_async(context)
152+
153+
154+
def _render_template(
155+
context: Optional[Mapping[str, Any]],
156+
encoding: str,
157+
status: int,
158+
) -> Tuple[web.Response, Mapping[str, Any]]:
142159
response = web.Response(status=status)
143160
if context is None:
144161
context = {}
145-
text = render_string(template_name, request, context, app_key=app_key)
146162
response.content_type = "text/html"
147163
response.charset = encoding
148-
response.text = text
164+
return response, context
165+
166+
167+
def render_template(
168+
template_name: str,
169+
request: web.Request,
170+
context: Optional[Mapping[str, Any]],
171+
*,
172+
app_key: str = APP_KEY,
173+
encoding: str = "utf-8",
174+
status: int = 200,
175+
) -> web.Response:
176+
response, context = _render_template(context, encoding, status)
177+
response.text = render_string(template_name, request, context, app_key=app_key)
178+
return response
179+
180+
181+
async def render_template_async(
182+
template_name: str,
183+
request: web.Request,
184+
context: Optional[Mapping[str, Any]],
185+
*,
186+
app_key: str = APP_KEY,
187+
encoding: str = "utf-8",
188+
status: int = 200,
189+
) -> web.Response:
190+
response, context = _render_template(context, encoding, status)
191+
response.text = await render_string_async(
192+
template_name, request, context, app_key=app_key
193+
)
149194
return response
150195

151196

@@ -197,9 +242,15 @@ async def wrapped(*args: Any) -> web.StreamResponse:
197242
else:
198243
request = args[-1]
199244

200-
response = render_template(
201-
template_name, request, context, app_key=app_key, encoding=encoding
202-
)
245+
env = request.config_dict.get(app_key)
246+
if env and env.is_async:
247+
response = await render_template_async(
248+
template_name, request, context, app_key=app_key, encoding=encoding
249+
)
250+
else:
251+
response = render_template(
252+
template_name, request, context, app_key=app_key, encoding=encoding
253+
)
203254
response.set_status(status)
204255
return response
205256

tests/test_simple_renderer.py

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,19 @@
1010
_T = TypeVar("_T")
1111

1212

13-
async def test_func(aiohttp_client):
13+
@pytest.mark.parametrize("enable_async", (False, True))
14+
async def test_func(aiohttp_client, enable_async):
1415
@aiohttp_jinja2.template("tmpl.jinja2")
1516
async def func(request: web.Request) -> Dict[str, str]:
1617
return {"head": "HEAD", "text": "text"}
1718

1819
template = "<html><body><h1>{{head}}</h1>{{text}}</body></html>"
1920
app = web.Application()
20-
aiohttp_jinja2.setup(app, loader=jinja2.DictLoader({"tmpl.jinja2": template}))
21+
aiohttp_jinja2.setup(
22+
app,
23+
enable_async=enable_async,
24+
loader=jinja2.DictLoader({"tmpl.jinja2": template}),
25+
)
2126

2227
app.router.add_route("*", "/", func)
2328

@@ -137,16 +142,15 @@ async def func(request):
137142
assert "<html><body><h1>HEAD</h1>text</body></html>" == txt
138143

139144

140-
async def test_render_template(aiohttp_client):
141-
async def func(request):
142-
return aiohttp_jinja2.render_template(
143-
"tmpl.jinja2", request, {"head": "HEAD", "text": "text"}
144-
)
145-
145+
async def _test_render_template(func, aiohttp_client, enable_async):
146146
template = "<html><body><h1>{{head}}</h1>{{text}}</body></html>"
147147

148148
app = web.Application()
149-
aiohttp_jinja2.setup(app, loader=jinja2.DictLoader({"tmpl.jinja2": template}))
149+
aiohttp_jinja2.setup(
150+
app,
151+
enable_async=enable_async,
152+
loader=jinja2.DictLoader({"tmpl.jinja2": template}),
153+
)
150154

151155
app.router.add_route("*", "/", func)
152156

@@ -159,6 +163,24 @@ async def func(request):
159163
assert "<html><body><h1>HEAD</h1>text</body></html>" == txt
160164

161165

166+
async def test_render_template(aiohttp_client):
167+
async def func(request):
168+
return aiohttp_jinja2.render_template(
169+
"tmpl.jinja2", request, {"head": "HEAD", "text": "text"}
170+
)
171+
172+
await _test_render_template(func, aiohttp_client, enable_async=False)
173+
174+
175+
async def test_render_template_async(aiohttp_client):
176+
async def func(request):
177+
return await aiohttp_jinja2.render_template_async(
178+
"tmpl.jinja2", request, {"head": "HEAD", "text": "text"}
179+
)
180+
181+
await _test_render_template(func, aiohttp_client, enable_async=True)
182+
183+
162184
async def test_render_template_custom_status(aiohttp_client):
163185
async def func(request):
164186
return aiohttp_jinja2.render_template(

0 commit comments

Comments
 (0)