Rename path to route everywhere (#329)
This commit is contained in:
parent
f7e35771e9
commit
6f3d763f82
@ -161,6 +161,7 @@ class App(Base):
|
|||||||
self,
|
self,
|
||||||
component: Union[Component, ComponentCallable],
|
component: Union[Component, ComponentCallable],
|
||||||
path: Optional[str] = None,
|
path: Optional[str] = None,
|
||||||
|
route: Optional[str] = None,
|
||||||
title: str = constants.DEFAULT_TITLE,
|
title: str = constants.DEFAULT_TITLE,
|
||||||
description: str = constants.DEFAULT_DESCRIPTION,
|
description: str = constants.DEFAULT_DESCRIPTION,
|
||||||
image=constants.DEFAULT_IMAGE,
|
image=constants.DEFAULT_IMAGE,
|
||||||
@ -172,22 +173,30 @@ class App(Base):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
component: The component to display at the page.
|
component: The component to display at the page.
|
||||||
path: The path to display the component at.
|
path: (deprecated) The path to the component.
|
||||||
|
route: The route to display the component at.
|
||||||
title: The title of the page.
|
title: The title of the page.
|
||||||
description: The description of the page.
|
description: The description of the page.
|
||||||
image: The image to display on the page.
|
image: The image to display on the page.
|
||||||
"""
|
"""
|
||||||
# If the path is not set, get it from the callable.
|
if path is not None:
|
||||||
if path is None:
|
utils.deprecate(
|
||||||
|
"The `path` argument is deprecated for `add_page`. Use `route` instead."
|
||||||
|
)
|
||||||
|
route = path
|
||||||
|
|
||||||
|
# If the route is not set, get it from the callable.
|
||||||
|
if route is None:
|
||||||
assert isinstance(
|
assert isinstance(
|
||||||
component, Callable
|
component, Callable
|
||||||
), "Path must be set if component is not a callable."
|
), "Route must be set if component is not a callable."
|
||||||
path = component.__name__
|
route = component.__name__
|
||||||
|
|
||||||
# Check if the path given is valid
|
# Check if the route given is valid
|
||||||
utils.verify_path_validity(path)
|
utils.verify_route_validity(route)
|
||||||
|
|
||||||
self.state.setup_dynamic_args(utils.get_path_args(path))
|
# Apply dynamic args to the route.
|
||||||
|
self.state.setup_dynamic_args(utils.get_route_args(route))
|
||||||
|
|
||||||
# Generate the component if it is a callable.
|
# Generate the component if it is a callable.
|
||||||
component = component if isinstance(component, Component) else component()
|
component = component if isinstance(component, Component) else component()
|
||||||
@ -198,7 +207,8 @@ class App(Base):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Format the route.
|
# Format the route.
|
||||||
route = utils.format_route(path)
|
route = utils.format_route(route)
|
||||||
|
|
||||||
# Add the page.
|
# Add the page.
|
||||||
self._check_routes_conflict(route)
|
self._check_routes_conflict(route)
|
||||||
self.pages[route] = component
|
self.pages[route] = component
|
||||||
@ -209,7 +219,7 @@ class App(Base):
|
|||||||
Based on conflicts that NextJS would throw if not intercepted.
|
Based on conflicts that NextJS would throw if not intercepted.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
ValueError: exception showing which conflict exist with the path to be added
|
ValueError: exception showing which conflict exist with the route to be added
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
new_route: the route being newly added.
|
new_route: the route being newly added.
|
||||||
@ -233,7 +243,7 @@ class App(Base):
|
|||||||
and utils.catchall_prefix(route) == utils.catchall_prefix(new_route)
|
and utils.catchall_prefix(route) == utils.catchall_prefix(new_route)
|
||||||
):
|
):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"You cannot use multiple catchall for the same dynamic path ({route} !== {new_route})"
|
f"You cannot use multiple catchall for the same dynamic route ({route} !== {new_route})"
|
||||||
)
|
)
|
||||||
|
|
||||||
def add_custom_404_page(self, component, title=None, image=None, description=None):
|
def add_custom_404_page(self, component, title=None, image=None, description=None):
|
||||||
@ -297,9 +307,9 @@ class App(Base):
|
|||||||
|
|
||||||
# Compile the pages.
|
# Compile the pages.
|
||||||
custom_components = set()
|
custom_components = set()
|
||||||
for path, component in self.pages.items():
|
for route, component in self.pages.items():
|
||||||
component.add_style(self.style)
|
component.add_style(self.style)
|
||||||
compiler.compile_page(path, component, self.state)
|
compiler.compile_page(route, component, self.state)
|
||||||
|
|
||||||
# Add the custom components from the page to the set.
|
# Add the custom components from the page to the set.
|
||||||
custom_components |= component.get_custom_components()
|
custom_components |= component.get_custom_components()
|
||||||
|
@ -192,8 +192,8 @@ class Endpoint(Enum):
|
|||||||
return url
|
return url
|
||||||
|
|
||||||
|
|
||||||
class PathArgType(SimpleNamespace):
|
class RouteArgType(SimpleNamespace):
|
||||||
"""Type of pathArg extracted from URI path."""
|
"""Type of dynamic route arg extracted from URI route."""
|
||||||
|
|
||||||
# Typecast to str is needed for Enum to work.
|
# Typecast to str is needed for Enum to work.
|
||||||
SINGLE = str("arg_single")
|
SINGLE = str("arg_single")
|
||||||
@ -209,7 +209,7 @@ class RouteVar(SimpleNamespace):
|
|||||||
|
|
||||||
|
|
||||||
class RouteRegex(SimpleNamespace):
|
class RouteRegex(SimpleNamespace):
|
||||||
"""Regex used for extracting path args in path."""
|
"""Regex used for extracting route args in route."""
|
||||||
|
|
||||||
ARG = re.compile(r"\[(?!\.)([^\[\]]+)\]")
|
ARG = re.compile(r"\[(?!\.)([^\[\]]+)\]")
|
||||||
# group return the catchall pattern (i.e "[[..slug]]")
|
# group return the catchall pattern (i.e "[[..slug]]")
|
||||||
|
@ -310,10 +310,9 @@ class State(Base, ABC):
|
|||||||
return inner_func
|
return inner_func
|
||||||
|
|
||||||
for param, value in args.items():
|
for param, value in args.items():
|
||||||
|
if value == constants.RouteArgType.SINGLE:
|
||||||
if value == constants.PathArgType.SINGLE:
|
|
||||||
func = argsingle_factory(param)
|
func = argsingle_factory(param)
|
||||||
elif value == constants.PathArgType.LIST:
|
elif value == constants.RouteArgType.LIST:
|
||||||
func = arglist_factory(param)
|
func = arglist_factory(param)
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
@ -64,6 +64,15 @@ PrimitiveType = Union[int, float, bool, str, list, dict, tuple]
|
|||||||
StateVar = Union[PrimitiveType, Base, None]
|
StateVar = Union[PrimitiveType, Base, None]
|
||||||
|
|
||||||
|
|
||||||
|
def deprecate(msg: str):
|
||||||
|
"""Print a deprecation warning.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg: The deprecation message.
|
||||||
|
"""
|
||||||
|
console.print(f"[yellow]DeprecationWarning: {msg}[/yellow]")
|
||||||
|
|
||||||
|
|
||||||
def get_args(alias: _GenericAlias) -> Tuple[Type, ...]:
|
def get_args(alias: _GenericAlias) -> Tuple[Type, ...]:
|
||||||
"""Get the arguments of a type alias.
|
"""Get the arguments of a type alias.
|
||||||
|
|
||||||
@ -769,69 +778,69 @@ def indent(text: str, indent_level: int = 2) -> str:
|
|||||||
return os.linesep.join(f"{' ' * indent_level}{line}" for line in lines) + os.linesep
|
return os.linesep.join(f"{' ' * indent_level}{line}" for line in lines) + os.linesep
|
||||||
|
|
||||||
|
|
||||||
def verify_path_validity(path: str) -> None:
|
def verify_route_validity(route: str) -> None:
|
||||||
"""Verify if the path is valid, and throw an error if not.
|
"""Verify if the route is valid, and throw an error if not.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path: the path that need to be checked
|
route: The route that need to be checked
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
ValueError: explains what is wrong with the path.
|
ValueError: If the route is invalid.
|
||||||
"""
|
"""
|
||||||
pattern = catchall_in_route(path)
|
pattern = catchall_in_route(route)
|
||||||
if pattern and not path.endswith(pattern):
|
if pattern and not route.endswith(pattern):
|
||||||
raise ValueError(f"Catch-all must be the last part of the URL: {path}")
|
raise ValueError(f"Catch-all must be the last part of the URL: {route}")
|
||||||
|
|
||||||
|
|
||||||
def get_path_args(path: str) -> Dict[str, str]:
|
def get_route_args(route: str) -> Dict[str, str]:
|
||||||
"""Get the path arguments for the given path.
|
"""Get the dynamic arguments for the given route.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path: The path to get the arguments for.
|
route: The route to get the arguments for.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The path arguments.
|
The route arguments.
|
||||||
"""
|
"""
|
||||||
|
args = {}
|
||||||
|
|
||||||
def add_path_arg(match: re.Match[str], type_: str):
|
def add_route_arg(match: re.Match[str], type_: str):
|
||||||
"""Add arg from regex search result.
|
"""Add arg from regex search result.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
match: result of a regex search
|
match: Result of a regex search
|
||||||
type_: the assigned type for this arg
|
type_: The assigned type for this arg
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
ValueError: explains what is wrong with the path.
|
ValueError: If the route is invalid.
|
||||||
"""
|
"""
|
||||||
arg_name = match.groups()[0]
|
arg_name = match.groups()[0]
|
||||||
if arg_name in args:
|
if arg_name in args:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"arg name [{arg_name}] is used more than once in this URL"
|
f"Arg name [{arg_name}] is used more than once in this URL"
|
||||||
)
|
)
|
||||||
args[arg_name] = type_
|
args[arg_name] = type_
|
||||||
|
|
||||||
# Regex to check for path args.
|
# Regex to check for route args.
|
||||||
check = constants.RouteRegex.ARG
|
check = constants.RouteRegex.ARG
|
||||||
check_strict_catchall = constants.RouteRegex.STRICT_CATCHALL
|
check_strict_catchall = constants.RouteRegex.STRICT_CATCHALL
|
||||||
check_opt_catchall = constants.RouteRegex.OPT_CATCHALL
|
check_opt_catchall = constants.RouteRegex.OPT_CATCHALL
|
||||||
|
|
||||||
# Iterate over the path parts and check for path args.
|
# Iterate over the route parts and check for route args.
|
||||||
args = {}
|
for part in route.split("/"):
|
||||||
for part in path.split("/"):
|
|
||||||
match_opt = check_opt_catchall.match(part)
|
match_opt = check_opt_catchall.match(part)
|
||||||
if match_opt:
|
if match_opt:
|
||||||
add_path_arg(match_opt, constants.PathArgType.LIST)
|
add_route_arg(match_opt, constants.RouteArgType.LIST)
|
||||||
break
|
break
|
||||||
|
|
||||||
match_strict = check_strict_catchall.match(part)
|
match_strict = check_strict_catchall.match(part)
|
||||||
if match_strict:
|
if match_strict:
|
||||||
add_path_arg(match_strict, constants.PathArgType.LIST)
|
add_route_arg(match_strict, constants.RouteArgType.LIST)
|
||||||
break
|
break
|
||||||
|
|
||||||
match = check.match(part)
|
match = check.match(part)
|
||||||
if match:
|
if match:
|
||||||
# Add the path arg to the list.
|
# Add the route arg to the list.
|
||||||
add_path_arg(match, constants.PathArgType.SINGLE)
|
add_route_arg(match, constants.RouteArgType.SINGLE)
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ def test_add_page_set_route(app: App, index_page):
|
|||||||
index_page: The index page.
|
index_page: The index page.
|
||||||
"""
|
"""
|
||||||
assert app.pages == {}
|
assert app.pages == {}
|
||||||
app.add_page(index_page, path="/test")
|
app.add_page(index_page, route="/test")
|
||||||
assert set(app.pages.keys()) == {"test"}
|
assert set(app.pages.keys()) == {"test"}
|
||||||
|
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ def test_add_page_set_route_nested(app: App, index_page):
|
|||||||
index_page: The index page.
|
index_page: The index page.
|
||||||
"""
|
"""
|
||||||
assert app.pages == {}
|
assert app.pages == {}
|
||||||
app.add_page(index_page, path="/test/nested")
|
app.add_page(index_page, route="/test/nested")
|
||||||
assert set(app.pages.keys()) == {"test/nested"}
|
assert set(app.pages.keys()) == {"test/nested"}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user