Skip to content

Commit e731ed2

Browse files
committed
Support reactpy-router v1
1 parent a0574e6 commit e731ed2

File tree

3 files changed

+17
-52
lines changed

3 files changed

+17
-52
lines changed

src/reactpy_django/router/converters.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
name: {"regex": converter.regex, "func": converter.to_python}
66
for name, converter in get_converters().items()
77
}
8+
CONVERTERS["any"] = {"regex": r".*", "func": str}
Lines changed: 14 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,22 @@
11
from __future__ import annotations
22

3-
import re
4-
from typing import Any
5-
6-
from reactpy_router.types import ConverterMapping, Route
3+
from reactpy_router.resolvers import StarletteResolver
4+
from reactpy_router.types import ConversionInfo, Route
75

86
from reactpy_django.router.converters import CONVERTERS
97

10-
PARAM_PATTERN = re.compile(r"<(?P<type>\w+:)?(?P<name>\w+)>")
11-
128

13-
# TODO: Make reactpy_router's SimpleResolver generic enough to where we don't have to define our own
14-
class DjangoResolver:
9+
class DjangoResolver(StarletteResolver):
1510
"""A simple route resolver that uses regex to match paths"""
1611

17-
def __init__(self, route: Route) -> None:
18-
self.element = route.element
19-
self.pattern, self.converters = parse_path(route.path)
20-
self.key = self.pattern.pattern
21-
22-
def resolve(self, path: str) -> tuple[Any, dict[str, Any]] | None:
23-
match = self.pattern.match(path)
24-
if match:
25-
return (
26-
self.element,
27-
{k: self.converters[k](v) for k, v in match.groupdict().items()},
28-
)
29-
return None
30-
31-
32-
# TODO: Make reactpy_router's parse_path generic enough to where we don't have to define our own
33-
def parse_path(path: str) -> tuple[re.Pattern[str], ConverterMapping]:
34-
# Convert path to regex pattern, and make sure to interpret the registered converters (ex. <int:foo>)
35-
pattern = "^"
36-
last_match_end = 0
37-
converters: ConverterMapping = {}
38-
for match in PARAM_PATTERN.finditer(path):
39-
param_name = match.group("name")
40-
param_type = (match.group("type") or "str").strip(":")
41-
try:
42-
param_conv = CONVERTERS[param_type]
43-
except KeyError as e:
44-
raise ValueError(
45-
f"Unknown conversion type {param_type!r} in {path!r}"
46-
) from e
47-
pattern += re.escape(path[last_match_end : match.start()])
48-
pattern += f"(?P<{param_name}>{param_conv['regex']})"
49-
converters[param_name] = param_conv["func"]
50-
last_match_end = match.end()
51-
pattern += f"{re.escape(path[last_match_end:])}$"
52-
53-
# Replace literal `*` with "match anything" regex pattern, if it's at the end of the path
54-
if pattern.endswith(r"\*$"):
55-
pattern = f"{pattern[:-3]}.*$"
56-
57-
return re.compile(pattern), converters
12+
def __init__(
13+
self,
14+
route: Route,
15+
param_pattern=r"<(?P<type>\w+:)?(?P<name>\w+)>",
16+
converters: dict[str, ConversionInfo] | None = None,
17+
) -> None:
18+
super().__init__(
19+
route=route,
20+
param_pattern=param_pattern,
21+
converters=converters or CONVERTERS,
22+
)

tests/test_app/router/components.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,9 @@ def main():
3838
display_params("Path 9"),
3939
),
4040
route(
41-
"/router/any/",
41+
"/router/<any:name1>/",
4242
None,
4343
route("one/", display_params("Path 11")),
44-
route("{name:any}", display_params("Path 12")),
44+
route("<any:name2>", display_params("Path 12")),
4545
),
46-
route("{404:any}", display_params("Not Found")),
4746
)

0 commit comments

Comments
 (0)