-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Route definitions #2004
Route definitions #2004
Changes from all commits
a2fbd23
62f653a
2ce063f
727ea50
daa31ec
0c23ebf
6cab8b8
8b44cde
1d5492c
3eb5137
a5c24a0
910cf1c
36d4fc0
de48fda
234ed0e
2f5bb08
d158513
b8ad2f4
7391a69
341da53
ec0630a
9c1845c
a9cbbb4
e2bc869
58686cb
875ae8e
7c54e36
48203d3
68f7225
aaab3ed
c10f4e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,8 @@ | |
import os | ||
import re | ||
import warnings | ||
from collections.abc import Container, Iterable, Sized | ||
from collections import namedtuple | ||
from collections.abc import Container, Iterable, Sequence, Sized | ||
from functools import wraps | ||
from pathlib import Path | ||
from types import MappingProxyType | ||
|
@@ -28,13 +29,32 @@ | |
__all__ = ('UrlDispatcher', 'UrlMappingMatchInfo', | ||
'AbstractResource', 'Resource', 'PlainResource', 'DynamicResource', | ||
'AbstractRoute', 'ResourceRoute', | ||
'StaticResource', 'View') | ||
'StaticResource', 'View', 'RouteDef', 'RouteTableDef', | ||
'head', 'get', 'post', 'patch', 'put', 'delete', 'route') | ||
|
||
HTTP_METHOD_RE = re.compile(r"^[0-9A-Za-z!#\$%&'\*\+\-\.\^_`\|~]+$") | ||
ROUTE_RE = re.compile(r'(\{[_a-zA-Z][^{}]*(?:\{[^{}]*\}[^{}]*)*\})') | ||
PATH_SEP = re.escape('/') | ||
|
||
|
||
class RouteDef(namedtuple('_RouteDef', 'method, path, handler, kwargs')): | ||
def __repr__(self): | ||
info = [] | ||
for name, value in sorted(self.kwargs.items()): | ||
info.append(", {}={!r}".format(name, value)) | ||
return ("<RouteDef {method} {path} -> {handler.__name__!r}" | ||
"{info}>".format(method=self.method, path=self.path, | ||
handler=self.handler, info=''.join(info))) | ||
|
||
def register(self, router): | ||
if self.method in hdrs.METH_ALL: | ||
reg = getattr(router, 'add_'+self.method.lower()) | ||
reg(self.path, self.handler, **self.kwargs) | ||
else: | ||
router.add_route(self.method, self.path, self.handler, | ||
**self.kwargs) | ||
|
||
|
||
class AbstractResource(Sized, Iterable): | ||
|
||
def __init__(self, *, name=None): | ||
|
@@ -897,3 +917,86 @@ def freeze(self): | |
super().freeze() | ||
for resource in self._resources: | ||
resource.freeze() | ||
|
||
def add_routes(self, routes): | ||
"""Append routes to route table. | ||
|
||
Parameter should be a sequence of RouteDef objects. | ||
""" | ||
# TODO: add_table maybe? | ||
for route in routes: | ||
route.register(self) | ||
|
||
|
||
def route(method, path, handler, **kwargs): | ||
return RouteDef(method, path, handler, kwargs) | ||
|
||
|
||
def head(path, handler, **kwargs): | ||
return route(hdrs.METH_HEAD, path, handler, **kwargs) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the code gets more readable when we do not use abbreviations. Can I open a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be good in general but for this particular case it doesn't make sense I think. |
||
|
||
|
||
def get(path, handler, *, name=None, allow_head=True, **kwargs): | ||
return route(hdrs.METH_GET, path, handler, name=name, | ||
allow_head=allow_head, **kwargs) | ||
|
||
|
||
def post(path, handler, **kwargs): | ||
return route(hdrs.METH_POST, path, handler, **kwargs) | ||
|
||
|
||
def put(path, handler, **kwargs): | ||
return route(hdrs.METH_PUT, path, handler, **kwargs) | ||
|
||
|
||
def patch(path, handler, **kwargs): | ||
return route(hdrs.METH_PATCH, path, handler, **kwargs) | ||
|
||
|
||
def delete(path, handler, **kwargs): | ||
return route(hdrs.METH_DELETE, path, handler, **kwargs) | ||
|
||
|
||
class RouteTableDef(Sequence): | ||
"""Route definition table""" | ||
def __init__(self): | ||
self._items = [] | ||
|
||
def __repr__(self): | ||
return "<RouteTableDef count={}>".format(len(self._items)) | ||
|
||
def __getitem__(self, index): | ||
return self._items[index] | ||
|
||
def __iter__(self): | ||
return iter(self._items) | ||
|
||
def __len__(self): | ||
return len(self._items) | ||
|
||
def __contains__(self, item): | ||
return item in self._items | ||
|
||
def route(self, method, path, **kwargs): | ||
def inner(handler): | ||
self._items.append(RouteDef(method, path, handler, kwargs)) | ||
return handler | ||
return inner | ||
|
||
def head(self, path, **kwargs): | ||
return self.route(hdrs.METH_HEAD, path, **kwargs) | ||
|
||
def get(self, path, **kwargs): | ||
return self.route(hdrs.METH_GET, path, **kwargs) | ||
|
||
def post(self, path, **kwargs): | ||
return self.route(hdrs.METH_POST, path, **kwargs) | ||
|
||
def put(self, path, **kwargs): | ||
return self.route(hdrs.METH_PUT, path, **kwargs) | ||
|
||
def patch(self, path, **kwargs): | ||
return self.route(hdrs.METH_PATCH, path, **kwargs) | ||
|
||
def delete(self, path, **kwargs): | ||
return self.route(hdrs.METH_DELETE, path, **kwargs) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Implement `router.add_routes` and router decorators. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think after refactoring this function is not required
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is: user might want to provide custom HTTP method in very rare cases