123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- """The route decorator and associated variables and functions."""
- from __future__ import annotations
- import re
- from reflex import constants
- from reflex.event import EventHandler
- from reflex.page import page
- from reflex.utils.console import deprecate
- def route(
- route: str | None = None,
- title: str | None = None,
- image: str | None = None,
- description: str | None = None,
- on_load: EventHandler | list[EventHandler] | None = None,
- ):
- """Decorate a function as a page.
- rx.App() will automatically call add_page() for any method decorated with route
- when App.compile is called.
- All defaults are None because they will use the one from add_page().
- Note: the decorated functions still need to be imported.
- Args:
- route: The route to reach the page.
- title: The title of the page.
- image: The favicon of the page.
- description: The description of the page
- on_load: The event handler(s) called when the page load.
- Returns:
- The decorated function.
- """
- deprecate("@rx.route is deprecated and is being replaced by @rx.page instead")
- return page(
- route=route,
- title=title,
- image=image,
- description=description,
- on_load=on_load,
- )
- def verify_route_validity(route: str) -> None:
- """Verify if the route is valid, and throw an error if not.
- Args:
- route: The route that need to be checked
- Raises:
- ValueError: If the route is invalid.
- """
- pattern = catchall_in_route(route)
- if pattern and not route.endswith(pattern):
- raise ValueError(f"Catch-all must be the last part of the URL: {route}")
- def get_route_args(route: str) -> dict[str, str]:
- """Get the dynamic arguments for the given route.
- Args:
- route: The route to get the arguments for.
- Returns:
- The route arguments.
- """
- args = {}
- def add_route_arg(match: re.Match[str], type_: str):
- """Add arg from regex search result.
- Args:
- match: Result of a regex search
- type_: The assigned type for this arg
- Raises:
- ValueError: If the route is invalid.
- """
- arg_name = match.groups()[0]
- if arg_name in args:
- raise ValueError(
- f"Arg name [{arg_name}] is used more than once in this URL"
- )
- args[arg_name] = type_
- # Regex to check for route args.
- check = constants.RouteRegex.ARG
- check_strict_catchall = constants.RouteRegex.STRICT_CATCHALL
- check_opt_catchall = constants.RouteRegex.OPT_CATCHALL
- # Iterate over the route parts and check for route args.
- for part in route.split("/"):
- match_opt = check_opt_catchall.match(part)
- if match_opt:
- add_route_arg(match_opt, constants.RouteArgType.LIST)
- break
- match_strict = check_strict_catchall.match(part)
- if match_strict:
- add_route_arg(match_strict, constants.RouteArgType.LIST)
- break
- match = check.match(part)
- if match:
- # Add the route arg to the list.
- add_route_arg(match, constants.RouteArgType.SINGLE)
- return args
- def catchall_in_route(route: str) -> str:
- """Extract the catchall part from a route.
- Args:
- route: the route from which to extract
- Returns:
- str: the catchall part of the URI
- """
- match_ = constants.RouteRegex.CATCHALL.search(route)
- return match_.group() if match_ else ""
- def catchall_prefix(route: str) -> str:
- """Extract the prefix part from a route that contains a catchall.
- Args:
- route: the route from which to extract
- Returns:
- str: the prefix part of the URI
- """
- pattern = catchall_in_route(route)
- return route.replace(pattern, "") if pattern else ""
|