Re-write router to accept all rules in the init method

This commit is contained in:
Ivan Salamakha 2017-11-16 10:47:59 +02:00
parent 6ce559d13d
commit 5e1b7ddb55
2 changed files with 31 additions and 9 deletions

View File

@ -2,6 +2,7 @@ import re
from collections import defaultdict, namedtuple from collections import defaultdict, namedtuple
from collections.abc import Iterable from collections.abc import Iterable
from functools import lru_cache from functools import lru_cache
from types import MappingProxyType
from sanic.exceptions import NotFound, InvalidUsage from sanic.exceptions import NotFound, InvalidUsage
from sanic.views import CompositionView from sanic.views import CompositionView
@ -11,13 +12,13 @@ Route = namedtuple(
['handler', 'methods', 'pattern', 'parameters', 'name', 'uri']) ['handler', 'methods', 'pattern', 'parameters', 'name', 'uri'])
Parameter = namedtuple('Parameter', ['name', 'cast']) Parameter = namedtuple('Parameter', ['name', 'cast'])
REGEX_TYPES = { REGEX_TYPES = MappingProxyType({
'string': (str, r'[^/]+'), 'string': (str, r'[^/]+'),
'int': (int, r'\d+'), 'int': (int, r'\d+'),
'number': (float, r'[0-9\\.]+'), 'number': (float, r'[0-9\\.]+'),
'alpha': (str, r'[A-Za-z]+'), 'alpha': (str, r'[A-Za-z]+'),
'path': (str, r'[^/].*?'), 'path': (str, r'[^/].*?'),
} })
ROUTER_CACHE_SIZE = 1024 ROUTER_CACHE_SIZE = 1024
@ -65,7 +66,7 @@ class Router:
routes_always_check = None routes_always_check = None
parameter_pattern = re.compile(r'<(.+?)>') parameter_pattern = re.compile(r'<(.+?)>')
def __init__(self, converters=None): def __init__(self, converters=REGEX_TYPES):
self.routes_all = {} self.routes_all = {}
self.routes_names = {} self.routes_names = {}
self.routes_static_files = {} self.routes_static_files = {}
@ -73,9 +74,7 @@ class Router:
self.routes_dynamic = defaultdict(list) self.routes_dynamic = defaultdict(list)
self.routes_always_check = [] self.routes_always_check = []
self.hosts = set() self.hosts = set()
self._converters = REGEX_TYPES self._converters = dict(converters)
if converters:
self._converters.update(converters)
def parse_parameter_string(self, parameter_string): def parse_parameter_string(self, parameter_string):
"""Parse a parameter string into its constituent name, type, and """Parse a parameter string into its constituent name, type, and

View File

@ -1,11 +1,12 @@
import asyncio import asyncio
import pytest
import uuid import uuid
import pytest
from sanic import Sanic from sanic import Sanic
from sanic.response import text
from sanic.router import RouteExists, RouteDoesNotExist, Router
from sanic.constants import HTTP_METHODS from sanic.constants import HTTP_METHODS
from sanic.response import text
from sanic.router import RouteExists, RouteDoesNotExist, Router, REGEX_TYPES
# ------------------------------------------------------------ # # ------------------------------------------------------------ #
@ -886,3 +887,25 @@ def test_custom_route_converters():
assert response.text == 'OK' assert response.text == 'OK'
assert isinstance(results[0], uuid.UUID) assert isinstance(results[0], uuid.UUID)
def test_extend_default_rules():
regex = r'[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-' \
r'[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}'
rules = dict(REGEX_TYPES)
rules.update({
"uuid": (uuid.UUID, regex)
})
custom_router = Router(converters=rules)
app = Sanic('test_custom_route_converters', router=custom_router)
results = []
@app.route('/<id:uuid>')
async def handler(request, id):
results.append(id)
return text('OK')
request, response = app.test_client.get('/e010dcb8-6b40-11e7-8e04-0242ac120022')
assert response.text == 'OK'
assert isinstance(results[0], uuid.UUID)