Skip to content

Commit 3f9efc9

Browse files
authored
Setup pre-commit hook (#385)
1 parent a257457 commit 3f9efc9

18 files changed

+516
-436
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ jobs:
3434
path: ~/.cache/pip
3535
restore-keys: |
3636
pip-lint-
37+
- name: Pre-Commit hooks
38+
uses: pre-commit/action@v2.0.0
3739
- name: Install dependencies
3840
uses: py-actions/py-dependency-install@v2
3941
with:
@@ -43,7 +45,7 @@ jobs:
4345
python setup.py install
4446
- name: Run linter
4547
run: |
46-
make flake
48+
make lint
4749
- name: Prepare twine checker
4850
run: |
4951
pip install -U twine wheel

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,4 @@ coverage/
6161
.vscode
6262

6363
.mypy_cache
64-
.python-version
64+
.python-version

.pre-commit-config.yaml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: 'v3.3.0'
4+
hooks:
5+
- id: check-merge-conflict
6+
- repo: https://github.com/asottile/yesqa
7+
rev: v1.2.2
8+
hooks:
9+
- id: yesqa
10+
- repo: https://github.com/pre-commit/mirrors-isort
11+
rev: 'v5.6.4'
12+
hooks:
13+
- id: isort
14+
- repo: https://github.com/psf/black
15+
rev: '20.8b1'
16+
hooks:
17+
- id: black
18+
language_version: python3 # Should be a command that runs python3.6+
19+
- repo: https://github.com/pre-commit/pre-commit-hooks
20+
rev: 'v3.3.0'
21+
hooks:
22+
- id: end-of-file-fixer
23+
exclude: >-
24+
^docs/[^/]*\.svg$
25+
- id: requirements-txt-fixer
26+
- id: trailing-whitespace
27+
- id: file-contents-sorter
28+
files: |
29+
CONTRIBUTORS.txt|
30+
docs/spelling_wordlist.txt|
31+
.gitignore|
32+
.gitattributes
33+
- id: check-case-conflict
34+
- id: check-json
35+
- id: check-xml
36+
- id: check-executables-have-shebangs
37+
- id: check-toml
38+
- id: check-xml
39+
- id: check-yaml
40+
- id: debug-statements
41+
- id: check-added-large-files
42+
- id: check-symlinks
43+
- id: debug-statements
44+
- id: detect-aws-credentials
45+
args: ['--allow-missing-credentials']
46+
- id: detect-private-key
47+
exclude: ^examples/
48+
- repo: https://github.com/asottile/pyupgrade
49+
rev: 'v2.7.3'
50+
hooks:
51+
- id: pyupgrade
52+
args: ['--py36-plus']
53+
- repo: https://gitlab.com/pycqa/flake8
54+
rev: '3.8.4'
55+
hooks:
56+
- id: flake8
57+
exclude: "^docs/"
58+
59+
- repo: git://github.com/Lucas-C/pre-commit-hooks-markup
60+
rev: v1.0.0
61+
hooks:
62+
- id: rst-linter
63+
files: >-
64+
^[^/]+[.]rst$

LICENSE

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,4 +199,3 @@ Apache License
199199
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200200
See the License for the specific language governing permissions and
201201
limitations under the License.
202-

Makefile

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
# Some simple testing tasks (sorry, UNIX only).
22

3-
flake:
4-
flake8 aiohttp_jinja2 tests
3+
.PHONY: init setup
4+
init setup:
5+
pip install -r requirements-dev.txt
6+
pre-commit install
7+
8+
.PHONY: fmt
9+
fmt:
10+
python -m pre_commit run --all-files --show-diff-on-failure
11+
12+
.PHONY: lint
13+
lint: fmt
514
mypy --strict aiohttp_jinja2
615

7-
test: flake
16+
.PHONY: test
17+
test:
818
py.test -s ./tests/
919

10-
cov cover coverage:
11-
py.test --cov=aiohttp_jinja2 --cov-report=html --cov-report=term ./tests/
12-
@echo "open file://`pwd`/htmlcov/index.html"
13-
20+
.PHONY: clean
1421
clean:
1522
rm -rf `find . -name __pycache__`
1623
rm -f `find . -type f -name '*.py[co]' `
@@ -25,8 +32,7 @@ clean:
2532
rm -rf build
2633
rm -rf cover
2734

35+
.PHONY: doc
2836
doc:
2937
make -C docs html
3038
@echo "open file://`pwd`/docs/_build/html/index.html"
31-
32-
.PHONY: all build venv flake test vtest testloop cov clean doc

aiohttp_jinja2/__init__.py

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,35 @@
11
import asyncio
22
import functools
33
import warnings
4+
from typing import (
5+
Any,
6+
Awaitable,
7+
Callable,
8+
Dict,
9+
Iterable,
10+
Mapping,
11+
Optional,
12+
Type,
13+
Union,
14+
cast,
15+
overload,
16+
)
17+
418
import jinja2
5-
from collections.abc import Mapping
6-
from typing import Any, Awaitable, Callable, Dict, Iterable, Optional, Type, Union, cast, overload
719
from aiohttp import web
820
from aiohttp.abc import AbstractView
21+
922
from .helpers import GLOBAL_HELPERS
1023
from .typedefs import Filters
1124

25+
__version__ = "1.2.0"
1226

13-
__version__ = '1.2.0'
27+
__all__ = ("setup", "get_env", "render_template", "render_string", "template")
1428

15-
__all__ = ('setup', 'get_env', 'render_template', 'render_string', 'template')
1629

17-
18-
APP_CONTEXT_PROCESSORS_KEY = 'aiohttp_jinja2_context_processors'
19-
APP_KEY = 'aiohttp_jinja2_environment'
20-
REQUEST_CONTEXT_KEY = 'aiohttp_jinja2_context'
30+
APP_CONTEXT_PROCESSORS_KEY = "aiohttp_jinja2_context_processors"
31+
APP_KEY = "aiohttp_jinja2_environment"
32+
REQUEST_CONTEXT_KEY = "aiohttp_jinja2_context"
2133

2234
_SimpleHandler = Callable[[web.Request], Awaitable[web.StreamResponse]]
2335
_MethodHandler = Callable[[Any, web.Request], Awaitable[web.StreamResponse]]
@@ -27,7 +39,9 @@
2739
_SimpleTemplateHandler = Callable[[web.Request], _TemplateReturnType]
2840
_MethodTemplateHandler = Callable[[Any, web.Request], _TemplateReturnType]
2941
_ViewTemplateHandler = Callable[[AbstractView], _TemplateReturnType]
30-
_TemplateHandler = Union[_SimpleTemplateHandler, _MethodTemplateHandler, _ViewTemplateHandler]
42+
_TemplateHandler = Union[
43+
_SimpleTemplateHandler, _MethodTemplateHandler, _ViewTemplateHandler
44+
]
3145

3246

3347
def setup(
@@ -37,7 +51,7 @@ def setup(
3751
context_processors: Iterable[Callable[[web.Request], Dict[str, Any]]] = (),
3852
filters: Optional[Filters] = None,
3953
default_helpers: bool = True,
40-
**kwargs: Any
54+
**kwargs: Any,
4155
) -> jinja2.Environment:
4256
kwargs.setdefault("autoescape", True)
4357
env = jinja2.Environment(*args, **kwargs)
@@ -50,16 +64,12 @@ def setup(
5064
app[APP_CONTEXT_PROCESSORS_KEY] = context_processors
5165
app.middlewares.append(context_processors_middleware)
5266

53-
env.globals['app'] = app
67+
env.globals["app"] = app
5468

5569
return env
5670

5771

58-
def get_env(
59-
app: web.Application,
60-
*,
61-
app_key: str = APP_KEY
62-
) -> jinja2.Environment:
72+
def get_env(app: web.Application, *, app_key: str = APP_KEY) -> jinja2.Environment:
6373
return cast(jinja2.Environment, app.get(app_key))
6474

6575

@@ -68,21 +78,23 @@ def render_string(
6878
request: web.Request,
6979
context: Mapping[str, Any],
7080
*,
71-
app_key: str = APP_KEY
81+
app_key: str = APP_KEY,
7282
) -> str:
7383
env = request.config_dict.get(app_key)
7484
if env is None:
75-
text = ("Template engine is not initialized, "
76-
"call aiohttp_jinja2.setup(..., app_key={}) first"
77-
"".format(app_key))
85+
text = (
86+
"Template engine is not initialized, "
87+
"call aiohttp_jinja2.setup(..., app_key={}) first"
88+
"".format(app_key)
89+
)
7890
# in order to see meaningful exception message both: on console
7991
# output and rendered page we add same message to *reason* and
8092
# *text* arguments.
8193
raise web.HTTPInternalServerError(reason=text, text=text)
8294
try:
8395
template = env.get_template(template_name)
8496
except jinja2.TemplateNotFound as e:
85-
text = "Template '{}' not found".format(template_name)
97+
text = f"Template '{template_name}' not found"
8698
raise web.HTTPInternalServerError(reason=text, text=text) from e
8799
if not isinstance(context, Mapping):
88100
text = "context should be mapping, not {}".format(type(context))
@@ -100,14 +112,14 @@ def render_template(
100112
context: Mapping[str, Any],
101113
*,
102114
app_key: str = APP_KEY,
103-
encoding: str = 'utf-8',
104-
status: int = 200
115+
encoding: str = "utf-8",
116+
status: int = 200,
105117
) -> web.Response:
106118
response = web.Response(status=status)
107119
if context is None:
108120
context = {}
109121
text = render_string(template_name, request, context, app_key=app_key)
110-
response.content_type = 'text/html'
122+
response.content_type = "text/html"
111123
response.charset = encoding
112124
response.text = text
113125
return response
@@ -117,27 +129,31 @@ def template(
117129
template_name: str,
118130
*,
119131
app_key: str = APP_KEY,
120-
encoding: str = 'utf-8',
121-
status: int = 200
132+
encoding: str = "utf-8",
133+
status: int = 200,
122134
) -> Callable[[_TemplateHandler], _HandlerType]:
123-
124135
def wrapper(func: _TemplateHandler) -> _HandlerType:
125136
@overload
126137
async def wrapped(request: web.Request) -> web.StreamResponse:
127138
...
139+
128140
@overload
129141
async def wrapped(view: AbstractView) -> web.StreamResponse:
130142
...
143+
131144
@overload
132145
async def wrapped(_self: Any, request: web.Request) -> web.StreamResponse:
133146
...
147+
134148
@functools.wraps(func)
135-
async def wrapped(*args):
149+
async def wrapped(*args: Any) -> web.StreamResponse:
136150
if asyncio.iscoroutinefunction(func):
137151
coro = func
138152
else:
139-
warnings.warn("Bare functions are deprecated, "
140-
"use async ones", DeprecationWarning)
153+
warnings.warn(
154+
"Bare functions are deprecated, " "use async ones",
155+
DeprecationWarning,
156+
)
141157
coro = asyncio.coroutine(func)
142158
context = await coro(*args)
143159
if isinstance(context, web.StreamResponse):
@@ -149,18 +165,21 @@ async def wrapped(*args):
149165
else:
150166
request = args[-1]
151167

152-
response = render_template(template_name, request, context,
153-
app_key=app_key, encoding=encoding)
168+
response = render_template(
169+
template_name, request, context, app_key=app_key, encoding=encoding
170+
)
154171
response.set_status(status)
155172
return response
173+
156174
return wrapped
175+
157176
return wrapper
158177

159178

160179
@web.middleware
161180
async def context_processors_middleware(
162181
request: web.Request,
163-
handler: Callable[[web.Request], Awaitable[web.StreamResponse]]
182+
handler: Callable[[web.Request], Awaitable[web.StreamResponse]],
164183
) -> web.StreamResponse:
165184

166185
if REQUEST_CONTEXT_KEY not in request:
@@ -171,4 +190,4 @@ async def context_processors_middleware(
171190

172191

173192
async def request_processor(request: web.Request) -> Dict[str, web.Request]:
174-
return {'request': request}
193+
return {"request": request}

aiohttp_jinja2/helpers.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ def url_for(context: Dict[str, Any], __route_name: str, **parts: Any) -> URL:
1717
{{ url('item-details', id=123, query={'active': 'true'}) }}
1818
might become "/items/1?active=true".
1919
"""
20-
app = cast(web.Application, context['app'])
20+
app = cast(web.Application, context["app"])
2121

2222
query = None
23-
if 'query_' in parts:
24-
query = parts.pop('query_')
23+
if "query_" in parts:
24+
query = parts.pop("query_")
2525

2626
for key in parts:
2727
val = parts[key]
@@ -33,8 +33,10 @@ def url_for(context: Dict[str, Any], __route_name: str, **parts: Any) -> URL:
3333
# int inherited classes like bool are forbidden
3434
val = str(val)
3535
else:
36-
raise TypeError("argument value should be str or int, "
37-
"got {} -> [{}] {!r}".format(key, type(val), val))
36+
raise TypeError(
37+
"argument value should be str or int, "
38+
"got {} -> [{}] {!r}".format(key, type(val), val)
39+
)
3840
parts[key] = val
3941

4042
url = app.router[__route_name].url_for(**parts)
@@ -53,15 +55,16 @@ def static_url(context: Dict[str, Any], static_file_path: str) -> str:
5355
Usage: {{ static('styles.css') }} might become
5456
"/static/styles.css" or "http://mycdn.example.com/styles.css"
5557
"""
56-
app = context['app']
58+
app = context["app"]
5759
try:
58-
static_url = app['static_root_url']
60+
static_url = app["static_root_url"]
5961
except KeyError:
6062
raise RuntimeError(
6163
"app does not define a static root url "
6264
"'static_root_url', you need to set the url root "
63-
"with app['static_root_url'] = '<static root>'.") from None
64-
return '{}/{}'.format(static_url.rstrip('/'), static_file_path.lstrip('/'))
65+
"with app['static_root_url'] = '<static root>'."
66+
) from None
67+
return "{}/{}".format(static_url.rstrip("/"), static_file_path.lstrip("/"))
6568

6669

6770
GLOBAL_HELPERS = dict(

aiohttp_jinja2/py.typed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
# marker
1+
# marker

aiohttp_jinja2/typedefs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Callable, Union, Iterable, Tuple, Mapping
1+
from typing import Callable, Iterable, Mapping, Tuple, Union
22

33
Filter = Callable[..., str]
44
Filters = Union[Iterable[Tuple[str, Filter]], Mapping[str, Filter]]

docs/api.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,3 @@ Assuming the initialization from the example above has been done::
131131
return response
132132

133133
app.router.add_get('/tmpl', handler)
134-

0 commit comments

Comments
 (0)