Skip to content

Commit

Permalink
Fix bug with final segment regex
Browse files Browse the repository at this point in the history
  • Loading branch information
ahopkins committed Apr 19, 2021
1 parent 8da5426 commit 2e65ee2
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 17 deletions.
2 changes: 1 addition & 1 deletion sanic_routing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
from .route import Route
from .router import BaseRouter

__version__ = "0.6.1"
__version__ = "0.6.2"
__all__ = ("BaseRouter", "Route", "RouteGroup")
42 changes: 28 additions & 14 deletions sanic_routing/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def __init__(
self.last = False
self.children_basketed = False
self.children_param_injected = False
self.has_deferred = False

def __str__(self) -> str:
internals = ", ".join(
Expand Down Expand Up @@ -154,6 +155,8 @@ def to_src(self) -> t.Tuple[t.List[Line], t.List[Line], t.List[Line]]:
if self.group.params and not self.group.regex:
if not self.last:
return_bump += 1
if self.parent.has_deferred:
return_bump += 1
self._inject_params(
location,
indent + return_bump + bool(not self.children),
Expand All @@ -165,6 +168,17 @@ def to_src(self) -> t.Tuple[t.List[Line], t.List[Line], t.List[Line]]:
return_indent = (
indent + return_bump + bool(not self.children) + param_offset
)
if self.group.regex:
if self._has_nested_path(self, recursive=False):
location.append(Line("...", return_indent - 1))
return_indent = 2
location = final
self._mark_parents_defer(self.parent)
self._inject_regex(
location,
return_indent,
not self.parent.children_param_injected,
)
if route_idx == 0 and len(self.group.routes) > 1:
route_idx = "route_idx"
for i, route in enumerate(self.group.routes):
Expand All @@ -184,16 +198,6 @@ def to_src(self) -> t.Tuple[t.List[Line], t.List[Line], t.List[Line]]:
Line("raise NoMethod", return_indent + 1),
]
)
if self.group.regex:
if self._has_nested_path(self, recursive=False):
location.append(Line("...", return_indent - 1))
return_indent = 2
location = final
self._inject_regex(
location,
return_indent,
not self.parent.children_param_injected,
)
routes = "regex_routes" if self.group.regex else "dynamic_routes"
route_return = (
"" if self.group.router.stacking else f"[{route_idx}]"
Expand All @@ -215,6 +219,11 @@ def to_src(self) -> t.Tuple[t.List[Line], t.List[Line], t.List[Line]]:
def add_child(self, child: "Node") -> None:
self._children[child.part] = child

def _mark_parents_defer(self, parent):
parent.has_deferred = True
if getattr(parent, "parent", None):
self._mark_parents_defer(parent.parent)

def _inject_requirements(self, location, indent):
for k, route in enumerate(self.group):
if k == 0:
Expand Down Expand Up @@ -266,10 +275,15 @@ def _inject_regex(self, location, indent, first_params):

def _inject_params(self, location, indent, first_params):
if self.last:
lines = [
Line(f"if num > {self.level}:", indent),
Line("raise NotFound", indent + 1),
]
if self.parent.has_deferred:
lines = [
Line(f"if num == {self.level}:", indent - 1),
]
else:
lines = [
Line(f"if num > {self.level}:", indent),
Line("raise NotFound", indent + 1),
]
else:
lines = []
if first_params:
Expand Down
32 changes: 30 additions & 2 deletions tests/test_routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,10 +389,38 @@ def handler(**kwargs):

router.finalize()

print(router.find_route_src)

_, handler, params = router.get(
"/path/to/726a7d33-4bd5-46a3-a02d-37da7b4b029b.jpeg", "BASE"
)
assert handler(**params) == params
assert params == {"file_uuid": "726a7d33-4bd5-46a3-a02d-37da7b4b029b"}


def test_multiple_handlers_on_final_regex_segment(handler):
def handler1():
return "handler1"

def handler2():
return "handler2"

router = Router()
router.add("/path/to/<foo:bar>", handler1, methods=("one", "two"))
router.add("/path/to/<foo:bar>", handler2, methods=("three",))
router.add("/path/<to>/distraction", handler)
router.add("/path/<to>", handler)
router.add("/path", handler)
router.add("/somehwere/<else>", handler)

router.finalize()

_, handler, params = router.get("/path/to/bar", "one")
assert handler() == "handler1"
assert params == {"foo": "bar"}

_, handler, params = router.get("/path/to/bar", "two")
assert handler() == "handler1"
assert params == {"foo": "bar"}

_, handler, params = router.get("/path/to/bar", "three")
assert handler() == "handler2"
assert params == {"foo": "bar"}

0 comments on commit 2e65ee2

Please sign in to comment.