Skip to content

Commit 70a7ea0

Browse files
committed
self review
1 parent 4633ab2 commit 70a7ea0

File tree

6 files changed

+41
-36
lines changed

6 files changed

+41
-36
lines changed

docs/examples/python/use-search-params.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
@component
77
def search():
8-
query = use_search_params()
9-
return html._(html.h1(f"Search Results for {query['q'][0]} 🔍"), html.p("Nothing (yet)."))
8+
search_params = use_search_params()
9+
return html._(html.h1(f"Search Results for {search_params['query'][0]} 🔍"), html.p("Nothing (yet)."))
1010

1111

1212
@component
@@ -16,7 +16,7 @@ def root():
1616
"/",
1717
html.div(
1818
html.h1("Home Page 🏠"),
19-
link("Search", to="/search?q=reactpy"),
19+
link("Search", to="/search?query=reactpy"),
2020
),
2121
),
2222
route("/search", search()),

src/reactpy_router/converters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,4 @@
3434
"func": str,
3535
},
3636
}
37-
"""The conversion types supported by the default Resolver. You can add more types if needed."""
37+
"""The conversion types supported by the default Resolver."""

src/reactpy_router/hooks.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,14 @@ def use_search_params(
5353
separator: str = "&",
5454
) -> dict[str, list[str]]:
5555
"""
56-
The `use_search_params` hook is used to read and modify the query string in the URL \
57-
for the current location. Like React's own `use_state` hook, `use_search_params` returns \
58-
an array of two values: the current location's search parameters and a function that may \
59-
be used to update them.
56+
The `use_search_params` hook is used to read the query string in the URL \
57+
for the current location.
6058
6159
See `urllib.parse.parse_qs` for info on this hook's parameters."""
6260

63-
# FIXME: This needs to return a tuple of the search params and a function to update them
61+
# TODO: In order to match `react-router`, this will need to return a tuple of the search params \
62+
# and a function to update them. This is currently not possible without reactpy core having a \
63+
# communication layer.
6464
return parse_qs(
6565
use_location().search[1:],
6666
keep_blank_values=keep_blank_values,

src/reactpy_router/resolvers.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010

1111

1212
class StarletteResolver:
13-
"""URL resolver that matches routes that match the starlette URL routing syntax.
13+
"""URL resolver that matches routes using starlette's URL routing syntax.
1414
15-
However, we add a few additional parameter types on top of Starlette's syntax."""
15+
However, this resolver adds a few additional parameter types on top of Starlette's syntax."""
1616

1717
def __init__(
1818
self,
@@ -34,10 +34,14 @@ def parse_path(self, path: str) -> re.Pattern[str]:
3434

3535
# Iterate through matches of the parameter pattern
3636
for match in self.param_regex.finditer(path):
37-
# Extract parameter name and type
37+
# Extract parameter name
3838
name = match.group("name")
3939
if name[0].isnumeric():
40+
# Regex group names can't begin with a number, so we must prefix them with
41+
# "_numeric_". This prefix is removed later within this function.
4042
name = f"_numeric_{name}"
43+
44+
# Extract the parameter type
4145
param_type = (match.group("type") or "str").strip(":")
4246

4347
# Check if a converter exists for the type

src/reactpy_router/routers.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from dataclasses import replace
66
from logging import getLogger
7-
from typing import Any, Iterator, Literal, Sequence, TypeVar
7+
from typing import Any, Iterator, Literal, Sequence
88

99
from reactpy import (
1010
component,
@@ -20,33 +20,32 @@
2020
from reactpy_router.components import History
2121
from reactpy_router.hooks import _route_state_context, _RouteState
2222
from reactpy_router.resolvers import StarletteResolver
23-
from reactpy_router.types import Route, RouteCompiler, Router, RouteResolver
23+
from reactpy_router.types import CompiledRoute, Resolver, Router, RouteType
2424

2525
__all__ = ["browser_router", "create_router"]
2626
_logger = getLogger(__name__)
27-
R = TypeVar("R", bound=Route)
2827

2928

30-
def create_router(compiler: RouteCompiler[R]) -> Router[R]:
31-
"""A decorator that turns a route compiler into a router"""
29+
def create_router(resolver: Resolver[RouteType]) -> Router[RouteType]:
30+
"""A decorator that turns a resolver into a router"""
3231

33-
def wrapper(*routes: R) -> ComponentType:
34-
return router(*routes, compiler=compiler)
32+
def wrapper(*routes: RouteType) -> ComponentType:
33+
return router(*routes, resolver=resolver)
3534

3635
return wrapper
3736

3837

3938
browser_router = create_router(StarletteResolver)
4039
"""This is the recommended router for all ReactPy Router web projects.
41-
It uses the DOM History API to update the URL and manage the history stack."""
40+
It uses the JavaScript DOM History API to manage the history stack."""
4241

4342

4443
@component
4544
def router(
46-
*routes: R,
47-
compiler: RouteCompiler[R],
45+
*routes: RouteType,
46+
resolver: Resolver[RouteType],
4847
) -> VdomDict | None:
49-
"""A component that renders matching route(s) using the given compiler function.
48+
"""A component that renders matching route(s) using the given resolver.
5049
5150
This typically should never be used by a user. Instead, use `create_router` if creating
5251
a custom routing engine."""
@@ -55,8 +54,8 @@ def router(
5554
location, set_location = use_state(old_conn.location)
5655

5756
resolvers = use_memo(
58-
lambda: tuple(map(compiler, _iter_routes(routes))),
59-
dependencies=(compiler, hash(routes)),
57+
lambda: tuple(map(resolver, _iter_routes(routes))),
58+
dependencies=(resolver, hash(routes)),
6059
)
6160

6261
match = use_memo(lambda: _match_route(resolvers, location, select="first"))
@@ -80,15 +79,15 @@ def router(
8079
return None
8180

8281

83-
def _iter_routes(routes: Sequence[R]) -> Iterator[R]:
82+
def _iter_routes(routes: Sequence[RouteType]) -> Iterator[RouteType]:
8483
for parent in routes:
8584
for child in _iter_routes(parent.routes):
8685
yield replace(child, path=parent.path + child.path) # type: ignore[misc]
8786
yield parent
8887

8988

9089
def _match_route(
91-
compiled_routes: Sequence[RouteResolver],
90+
compiled_routes: Sequence[CompiledRoute],
9291
location: Location,
9392
select: Literal["first", "all"],
9493
) -> list[tuple[Any, dict[str, Any]]]:
@@ -100,8 +99,9 @@ def _match_route(
10099
if select == "first":
101100
return [match]
102101

103-
# This is no longer used by `reactpy-router`, since `react-router>=6.0.0` no longer supports
104-
# multiple matches. However, it's kept here to support future changes.
102+
# Matching multiple routes is disabled since `react-router` no longer supports multiple
103+
# matches via the `Route` component. However, it's kept here to support future changes
104+
# or third-party routers.
105105
matches.append(match) # pragma: no cover
106106

107107
if not matches:

src/reactpy_router/types.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,22 +32,23 @@ def __hash__(self) -> int:
3232
return hash((self.path, key, self.routes))
3333

3434

35-
R_contra = TypeVar("R_contra", bound=Route, contravariant=True)
35+
RouteType = TypeVar("RouteType", bound=Route)
36+
RouteType_contra = TypeVar("RouteType_contra", bound=Route, contravariant=True)
3637

3738

38-
class Router(Protocol[R_contra]):
39+
class Router(Protocol[RouteType_contra]):
3940
"""Return a component that renders the first matching route."""
4041

41-
def __call__(self, *routes: R_contra) -> ComponentType: ...
42+
def __call__(self, *routes: RouteType_contra) -> ComponentType: ...
4243

4344

44-
class RouteCompiler(Protocol[R_contra]):
45-
"""Compile a route into a resolver that can be matched against a path."""
45+
class Resolver(Protocol[RouteType_contra]):
46+
"""Compile a route into a resolver that can be matched against a given path."""
4647

47-
def __call__(self, route: R_contra) -> RouteResolver: ...
48+
def __call__(self, route: RouteType_contra) -> CompiledRoute: ...
4849

4950

50-
class RouteResolver(Protocol):
51+
class CompiledRoute(Protocol):
5152
"""A compiled route that can be matched against a path."""
5253

5354
@property

0 commit comments

Comments
 (0)