Skip to content

Commit 2e65ee2

Browse files
committed
Fix bug with final segment regex
1 parent 8da5426 commit 2e65ee2

File tree

3 files changed

+59
-17
lines changed

3 files changed

+59
-17
lines changed

sanic_routing/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
from .route import Route
33
from .router import BaseRouter
44

5-
__version__ = "0.6.1"
5+
__version__ = "0.6.2"
66
__all__ = ("BaseRouter", "Route", "RouteGroup")

sanic_routing/tree.py

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def __init__(
2525
self.last = False
2626
self.children_basketed = False
2727
self.children_param_injected = False
28+
self.has_deferred = False
2829

2930
def __str__(self) -> str:
3031
internals = ", ".join(
@@ -154,6 +155,8 @@ def to_src(self) -> t.Tuple[t.List[Line], t.List[Line], t.List[Line]]:
154155
if self.group.params and not self.group.regex:
155156
if not self.last:
156157
return_bump += 1
158+
if self.parent.has_deferred:
159+
return_bump += 1
157160
self._inject_params(
158161
location,
159162
indent + return_bump + bool(not self.children),
@@ -165,6 +168,17 @@ def to_src(self) -> t.Tuple[t.List[Line], t.List[Line], t.List[Line]]:
165168
return_indent = (
166169
indent + return_bump + bool(not self.children) + param_offset
167170
)
171+
if self.group.regex:
172+
if self._has_nested_path(self, recursive=False):
173+
location.append(Line("...", return_indent - 1))
174+
return_indent = 2
175+
location = final
176+
self._mark_parents_defer(self.parent)
177+
self._inject_regex(
178+
location,
179+
return_indent,
180+
not self.parent.children_param_injected,
181+
)
168182
if route_idx == 0 and len(self.group.routes) > 1:
169183
route_idx = "route_idx"
170184
for i, route in enumerate(self.group.routes):
@@ -184,16 +198,6 @@ def to_src(self) -> t.Tuple[t.List[Line], t.List[Line], t.List[Line]]:
184198
Line("raise NoMethod", return_indent + 1),
185199
]
186200
)
187-
if self.group.regex:
188-
if self._has_nested_path(self, recursive=False):
189-
location.append(Line("...", return_indent - 1))
190-
return_indent = 2
191-
location = final
192-
self._inject_regex(
193-
location,
194-
return_indent,
195-
not self.parent.children_param_injected,
196-
)
197201
routes = "regex_routes" if self.group.regex else "dynamic_routes"
198202
route_return = (
199203
"" if self.group.router.stacking else f"[{route_idx}]"
@@ -215,6 +219,11 @@ def to_src(self) -> t.Tuple[t.List[Line], t.List[Line], t.List[Line]]:
215219
def add_child(self, child: "Node") -> None:
216220
self._children[child.part] = child
217221

222+
def _mark_parents_defer(self, parent):
223+
parent.has_deferred = True
224+
if getattr(parent, "parent", None):
225+
self._mark_parents_defer(parent.parent)
226+
218227
def _inject_requirements(self, location, indent):
219228
for k, route in enumerate(self.group):
220229
if k == 0:
@@ -266,10 +275,15 @@ def _inject_regex(self, location, indent, first_params):
266275

267276
def _inject_params(self, location, indent, first_params):
268277
if self.last:
269-
lines = [
270-
Line(f"if num > {self.level}:", indent),
271-
Line("raise NotFound", indent + 1),
272-
]
278+
if self.parent.has_deferred:
279+
lines = [
280+
Line(f"if num == {self.level}:", indent - 1),
281+
]
282+
else:
283+
lines = [
284+
Line(f"if num > {self.level}:", indent),
285+
Line("raise NotFound", indent + 1),
286+
]
273287
else:
274288
lines = []
275289
if first_params:

tests/test_routing.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -389,10 +389,38 @@ def handler(**kwargs):
389389

390390
router.finalize()
391391

392-
print(router.find_route_src)
393-
394392
_, handler, params = router.get(
395393
"/path/to/726a7d33-4bd5-46a3-a02d-37da7b4b029b.jpeg", "BASE"
396394
)
397395
assert handler(**params) == params
398396
assert params == {"file_uuid": "726a7d33-4bd5-46a3-a02d-37da7b4b029b"}
397+
398+
399+
def test_multiple_handlers_on_final_regex_segment(handler):
400+
def handler1():
401+
return "handler1"
402+
403+
def handler2():
404+
return "handler2"
405+
406+
router = Router()
407+
router.add("/path/to/<foo:bar>", handler1, methods=("one", "two"))
408+
router.add("/path/to/<foo:bar>", handler2, methods=("three",))
409+
router.add("/path/<to>/distraction", handler)
410+
router.add("/path/<to>", handler)
411+
router.add("/path", handler)
412+
router.add("/somehwere/<else>", handler)
413+
414+
router.finalize()
415+
416+
_, handler, params = router.get("/path/to/bar", "one")
417+
assert handler() == "handler1"
418+
assert params == {"foo": "bar"}
419+
420+
_, handler, params = router.get("/path/to/bar", "two")
421+
assert handler() == "handler1"
422+
assert params == {"foo": "bar"}
423+
424+
_, handler, params = router.get("/path/to/bar", "three")
425+
assert handler() == "handler2"
426+
assert params == {"foo": "bar"}

0 commit comments

Comments
 (0)