Skip to content

Commit 051c0c3

Browse files
Use AppKey (#534)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 9619811 commit 051c0c3

File tree

8 files changed

+67
-49
lines changed

8 files changed

+67
-49
lines changed

aiohttp_jinja2/__init__.py

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,45 @@
44
Awaitable,
55
Callable,
66
Dict,
7+
Final,
78
Mapping,
89
Optional,
910
Protocol,
1011
Sequence,
1112
Tuple,
1213
TypeVar,
1314
Union,
14-
cast,
1515
overload,
1616
)
1717

1818
import jinja2
1919
from aiohttp import web
2020
from aiohttp.abc import AbstractView
2121

22-
from .helpers import GLOBAL_HELPERS
22+
from .helpers import GLOBAL_HELPERS, static_root_key
2323
from .typedefs import Filters
2424

2525
__version__ = "1.5.1"
2626

27-
__all__ = ("setup", "get_env", "render_template", "render_string", "template")
28-
29-
30-
APP_CONTEXT_PROCESSORS_KEY = "aiohttp_jinja2_context_processors"
31-
APP_KEY = "aiohttp_jinja2_environment"
32-
REQUEST_CONTEXT_KEY = "aiohttp_jinja2_context"
27+
__all__ = (
28+
"get_env",
29+
"render_string",
30+
"render_template",
31+
"setup",
32+
"static_root_key",
33+
"template",
34+
)
3335

3436
_TemplateReturnType = Awaitable[Union[web.StreamResponse, Mapping[str, Any]]]
3537
_SimpleTemplateHandler = Callable[[web.Request], _TemplateReturnType]
3638
_ContextProcessor = Callable[[web.Request], Awaitable[Dict[str, Any]]]
3739

40+
APP_CONTEXT_PROCESSORS_KEY: Final = web.AppKey[Sequence[_ContextProcessor]](
41+
"APP_CONTEXT_PROCESSORS_KEY"
42+
)
43+
APP_KEY: Final = web.AppKey[jinja2.Environment]("APP_KEY")
44+
REQUEST_CONTEXT_KEY: Final = "aiohttp_jinja2_context"
45+
3846
_T = TypeVar("_T")
3947
_AbstractView = TypeVar("_AbstractView", bound=AbstractView)
4048

@@ -62,7 +70,7 @@ def __call__(
6270
def setup(
6371
app: web.Application,
6472
*args: Any,
65-
app_key: str = APP_KEY,
73+
app_key: web.AppKey[jinja2.Environment] = APP_KEY,
6674
context_processors: Sequence[_ContextProcessor] = (),
6775
filters: Optional[Filters] = None,
6876
default_helpers: bool = True,
@@ -84,23 +92,24 @@ def setup(
8492
return env
8593

8694

87-
def get_env(app: web.Application, *, app_key: str = APP_KEY) -> jinja2.Environment:
88-
return cast(jinja2.Environment, app.get(app_key))
95+
def get_env(
96+
app: web.Application, *, app_key: web.AppKey[jinja2.Environment] = APP_KEY
97+
) -> jinja2.Environment:
98+
try:
99+
return app[app_key]
100+
except KeyError:
101+
raise RuntimeError("aiohttp_jinja2.setup(...) must be called first.")
89102

90103

91104
def _render_string(
92105
template_name: str,
93106
request: web.Request,
94107
context: Mapping[str, Any],
95-
app_key: str,
108+
app_key: web.AppKey[jinja2.Environment],
96109
) -> Tuple[jinja2.Template, Mapping[str, Any]]:
97110
env = request.config_dict.get(app_key)
98111
if env is None:
99-
text = (
100-
"Template engine is not initialized, "
101-
"call aiohttp_jinja2.setup(..., app_key={}) first"
102-
"".format(app_key)
103-
)
112+
text = "Template engine is not initialized, call aiohttp_jinja2.setup() first"
104113
# in order to see meaningful exception message both: on console
105114
# output and rendered page we add same message to *reason* and
106115
# *text* arguments.
@@ -124,7 +133,7 @@ def render_string(
124133
request: web.Request,
125134
context: Mapping[str, Any],
126135
*,
127-
app_key: str = APP_KEY,
136+
app_key: web.AppKey[jinja2.Environment] = APP_KEY,
128137
) -> str:
129138
template, context = _render_string(template_name, request, context, app_key)
130139
return template.render(context)
@@ -135,7 +144,7 @@ async def render_string_async(
135144
request: web.Request,
136145
context: Mapping[str, Any],
137146
*,
138-
app_key: str = APP_KEY,
147+
app_key: web.AppKey[jinja2.Environment] = APP_KEY,
139148
) -> str:
140149
template, context = _render_string(template_name, request, context, app_key)
141150
return await template.render_async(context)
@@ -159,7 +168,7 @@ def render_template(
159168
request: web.Request,
160169
context: Optional[Mapping[str, Any]],
161170
*,
162-
app_key: str = APP_KEY,
171+
app_key: web.AppKey[jinja2.Environment] = APP_KEY,
163172
encoding: str = "utf-8",
164173
status: int = 200,
165174
) -> web.Response:
@@ -173,7 +182,7 @@ async def render_template_async(
173182
request: web.Request,
174183
context: Optional[Mapping[str, Any]],
175184
*,
176-
app_key: str = APP_KEY,
185+
app_key: web.AppKey[jinja2.Environment] = APP_KEY,
177186
encoding: str = "utf-8",
178187
status: int = 200,
179188
) -> web.Response:
@@ -187,7 +196,7 @@ async def render_template_async(
187196
def template(
188197
template_name: str,
189198
*,
190-
app_key: str = APP_KEY,
199+
app_key: web.AppKey[jinja2.Environment] = APP_KEY,
191200
encoding: str = "utf-8",
192201
status: int = 200,
193202
) -> _TemplateWrapper:

aiohttp_jinja2/helpers.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
useful context functions, see
33
http://jinja.pocoo.org/docs/dev/api/#jinja2.contextfunction
44
"""
5+
import warnings
56
from typing import Dict, Optional, TypedDict, Union
67

78
import jinja2
@@ -13,6 +14,9 @@ class _Context(TypedDict, total=False):
1314
app: web.Application
1415

1516

17+
static_root_key = web.AppKey("static_root_key", str)
18+
19+
1620
@jinja2.pass_context
1721
def url_for(
1822
context: _Context,
@@ -55,21 +59,30 @@ def url_for(
5559
def static_url(context: _Context, static_file_path: str) -> str:
5660
"""Filter for generating urls for static files.
5761
58-
NOTE: you'll need
59-
to set app['static_root_url'] to be used as the root for the urls returned.
62+
NOTE: you'll need to set app[aiohttp_jinja2.static_root_key] to be used as the
63+
root for the urls returned.
6064
6165
Usage: {{ static('styles.css') }} might become
6266
"/static/styles.css" or "http://mycdn.example.com/styles.css"
6367
"""
6468
app = context["app"]
6569
try:
66-
static_url = app["static_root_url"]
70+
static_url = app[static_root_key]
6771
except KeyError:
68-
raise RuntimeError(
69-
"app does not define a static root url "
70-
"'static_root_url', you need to set the url root "
71-
"with app['static_root_url'] = '<static root>'."
72-
) from None
72+
try:
73+
# TODO (aiohttp 3.10+): Remove this fallback
74+
static_url = app["static_root_url"]
75+
except KeyError:
76+
raise RuntimeError(
77+
"app does not define a static root url, you need to set the url root "
78+
"with app[aiohttp_jinja2.static_root_key] = '<static root>'."
79+
) from None
80+
else:
81+
warnings.warn(
82+
"'static_root_url' is deprecated, use aiohttp_jinja2.static_root_key.",
83+
category=DeprecationWarning,
84+
stacklevel=2,
85+
)
7386
return "{}/{}".format(static_url.rstrip("/"), static_file_path.lstrip("/"))
7487

7588

docs/index.rst

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,14 +201,13 @@ This is useful as it would allow your static path to switch in
201201
deployment or testing with just one line.
202202

203203
The ``static`` function has similar usage, except it requires you to
204-
set ``static_root_url`` on the app
204+
set ``app[aiohttp_jinja2.static_root_key]``.
205205

206-
.. code-block:: ruby
206+
.. code-block:: python
207207
208208
app = web.Application()
209-
aiohttp_jinja2.setup(app,
210-
loader=jinja2.FileSystemLoader('/path/to/templates/folder'))
211-
app['static_root_url'] = '/static'
209+
aiohttp_jinja2.setup(app, loader=jinja2.FileSystemLoader("/path/to/templates/folder"))
210+
app[aiohttp_jinja2.static_root_key] = "/static"
212211
213212
Then in the template::
214213

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
-e .
2-
aiohttp==3.8.6
2+
aiohttp==3.9.0
33
alabaster>=0.6.2
44
coverage==7.2.7
55
jinja2==3.1.2

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,6 @@ def read(f):
5252
license="Apache 2",
5353
packages=["aiohttp_jinja2"],
5454
python_requires=">=3.8",
55-
install_requires=("aiohttp>=3.6.3", "jinja2>=3.0.0"),
55+
install_requires=("aiohttp>=3.9.0", "jinja2>=3.0.0"),
5656
include_package_data=True,
5757
)

tests/test_context_processors.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Dict, Union
1+
from typing import Dict, Tuple, Union
22

33
import jinja2
44
from aiohttp import web
@@ -22,10 +22,11 @@ async def func(request):
2222
async def processor(request: web.Request) -> Dict[str, Union[str, int]]:
2323
return {"foo": 1, "bar": "should be overwriten"}
2424

25-
app["aiohttp_jinja2_context_processors"] = (
25+
f: Tuple[aiohttp_jinja2._ContextProcessor, ...] = (
2626
aiohttp_jinja2.request_processor,
2727
processor,
2828
)
29+
app[aiohttp_jinja2.APP_CONTEXT_PROCESSORS_KEY] = f
2930

3031
app.router.add_get("/", func)
3132

@@ -56,7 +57,7 @@ async def func(request):
5657
async def subprocessor(request):
5758
return {"foo": 1, "bar": "should be overwriten"}
5859

59-
subapp["aiohttp_jinja2_context_processors"] = (
60+
subapp[aiohttp_jinja2.APP_CONTEXT_PROCESSORS_KEY] = (
6061
aiohttp_jinja2.request_processor,
6162
subprocessor,
6263
)
@@ -69,7 +70,7 @@ async def subprocessor(request):
6970
async def processor(request):
7071
return {"baz": 5}
7172

72-
app["aiohttp_jinja2_context_processors"] = (
73+
app[aiohttp_jinja2.APP_CONTEXT_PROCESSORS_KEY] = (
7374
aiohttp_jinja2.request_processor,
7475
processor,
7576
)

tests/test_jinja_globals.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ async def index(request):
141141
app, loader=jinja2.DictLoader({"tmpl.jinja2": "{{ static('whatever.js') }}"})
142142
)
143143

144-
app["static_root_url"] = "/static"
144+
app[aiohttp_jinja2.static_root_key] = "/static"
145145
app.router.add_route("GET", "/", index)
146146
client = await aiohttp_client(app)
147147

@@ -153,7 +153,7 @@ async def index(request):
153153

154154
async def test_static_var_missing(aiohttp_client, caplog):
155155
async def index(request):
156-
with pytest.raises(RuntimeError, match="static_root_url"):
156+
with pytest.raises(RuntimeError, match="static_root_key"):
157157
aiohttp_jinja2.render_template("tmpl.jinja2", request, {})
158158
return web.Response()
159159

@@ -166,4 +166,4 @@ async def index(request):
166166
client = await aiohttp_client(app)
167167

168168
resp = await client.get("/")
169-
assert 200 == resp.status # static_root_url is not set
169+
assert 200 == resp.status # static_root_key is not set

tests/test_simple_renderer.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,7 @@ async def func(request: web.Request) -> web.Response:
107107
app.router.add_route("GET", "/", func)
108108

109109
req = make_mocked_request("GET", "/", app=app)
110-
msg = (
111-
"Template engine is not initialized, "
112-
"call aiohttp_jinja2.setup(..., app_key={}"
113-
") first".format(aiohttp_jinja2.APP_KEY)
114-
)
110+
msg = "Template engine is not initialized, call aiohttp_jinja2.setup() first"
115111

116112
with pytest.raises(web.HTTPInternalServerError) as ctx:
117113
await func(req)

0 commit comments

Comments
 (0)