|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
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 |
7 | 5 |
|
8 | 6 | from reactpy_django.router.converters import CONVERTERS |
9 | 7 |
|
10 | | -PARAM_PATTERN = re.compile(r"<(?P<type>\w+:)?(?P<name>\w+)>") |
11 | | - |
12 | 8 |
|
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): |
15 | 10 | """A simple route resolver that uses regex to match paths""" |
16 | 11 |
|
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 | + ) |
0 commit comments