diff --git a/pynecone/app.py b/pynecone/app.py index 7370bec0f..26b3e6d3f 100644 --- a/pynecone/app.py +++ b/pynecone/app.py @@ -161,6 +161,7 @@ class App(Base): self, component: Union[Component, ComponentCallable], path: Optional[str] = None, + route: Optional[str] = None, title: str = constants.DEFAULT_TITLE, description: str = constants.DEFAULT_DESCRIPTION, image=constants.DEFAULT_IMAGE, @@ -172,22 +173,30 @@ class App(Base): Args: 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. description: The description of the page. image: The image to display on the page. """ - # If the path is not set, get it from the callable. - if path is None: + if path is not 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( component, Callable - ), "Path must be set if component is not a callable." - path = component.__name__ + ), "Route must be set if component is not a callable." + route = component.__name__ - # Check if the path given is valid - utils.verify_path_validity(path) + # Check if the route given is valid + 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. component = component if isinstance(component, Component) else component() @@ -198,7 +207,8 @@ class App(Base): ) # Format the route. - route = utils.format_route(path) + route = utils.format_route(route) + # Add the page. self._check_routes_conflict(route) self.pages[route] = component @@ -209,7 +219,7 @@ class App(Base): Based on conflicts that NextJS would throw if not intercepted. 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: new_route: the route being newly added. @@ -233,7 +243,7 @@ class App(Base): and utils.catchall_prefix(route) == utils.catchall_prefix(new_route) ): 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): @@ -297,9 +307,9 @@ class App(Base): # Compile the pages. custom_components = set() - for path, component in self.pages.items(): + for route, component in self.pages.items(): 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. custom_components |= component.get_custom_components() diff --git a/pynecone/constants.py b/pynecone/constants.py index 1c5016c91..579e88686 100644 --- a/pynecone/constants.py +++ b/pynecone/constants.py @@ -192,8 +192,8 @@ class Endpoint(Enum): return url -class PathArgType(SimpleNamespace): - """Type of pathArg extracted from URI path.""" +class RouteArgType(SimpleNamespace): + """Type of dynamic route arg extracted from URI route.""" # Typecast to str is needed for Enum to work. SINGLE = str("arg_single") @@ -209,7 +209,7 @@ class RouteVar(SimpleNamespace): class RouteRegex(SimpleNamespace): - """Regex used for extracting path args in path.""" + """Regex used for extracting route args in route.""" ARG = re.compile(r"\[(?!\.)([^\[\]]+)\]") # group return the catchall pattern (i.e "[[..slug]]") diff --git a/pynecone/state.py b/pynecone/state.py index 18b1341bf..095700128 100644 --- a/pynecone/state.py +++ b/pynecone/state.py @@ -310,10 +310,9 @@ class State(Base, ABC): return inner_func for param, value in args.items(): - - if value == constants.PathArgType.SINGLE: + if value == constants.RouteArgType.SINGLE: func = argsingle_factory(param) - elif value == constants.PathArgType.LIST: + elif value == constants.RouteArgType.LIST: func = arglist_factory(param) else: continue diff --git a/pynecone/utils.py b/pynecone/utils.py index 6b1b8bcf6..97ab1fbe4 100644 --- a/pynecone/utils.py +++ b/pynecone/utils.py @@ -64,6 +64,15 @@ PrimitiveType = Union[int, float, bool, str, list, dict, tuple] 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, ...]: """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 -def verify_path_validity(path: str) -> None: - """Verify if the path is valid, and throw an error if not. +def verify_route_validity(route: str) -> None: + """Verify if the route is valid, and throw an error if not. Args: - path: the path that need to be checked + route: The route that need to be checked Raises: - ValueError: explains what is wrong with the path. + ValueError: If the route is invalid. """ - pattern = catchall_in_route(path) - if pattern and not path.endswith(pattern): - raise ValueError(f"Catch-all must be the last part of the URL: {path}") + 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_path_args(path: str) -> Dict[str, str]: - """Get the path arguments for the given path. +def get_route_args(route: str) -> Dict[str, str]: + """Get the dynamic arguments for the given route. Args: - path: The path to get the arguments for. + route: The route to get the arguments for. 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. Args: - match: result of a regex search - type_: the assigned type for this arg + match: Result of a regex search + type_: The assigned type for this arg Raises: - ValueError: explains what is wrong with the path. + 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" + f"Arg name [{arg_name}] is used more than once in this URL" ) args[arg_name] = type_ - # Regex to check for path args. + # 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 path parts and check for path args. - args = {} - for part in path.split("/"): + # 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_path_arg(match_opt, constants.PathArgType.LIST) + add_route_arg(match_opt, constants.RouteArgType.LIST) break match_strict = check_strict_catchall.match(part) if match_strict: - add_path_arg(match_strict, constants.PathArgType.LIST) + add_route_arg(match_strict, constants.RouteArgType.LIST) break match = check.match(part) if match: - # Add the path arg to the list. - add_path_arg(match, constants.PathArgType.SINGLE) + # Add the route arg to the list. + add_route_arg(match, constants.RouteArgType.SINGLE) return args diff --git a/tests/test_app.py b/tests/test_app.py index 4e8baf46c..4f1dc09af 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -95,7 +95,7 @@ def test_add_page_set_route(app: App, index_page): index_page: The index page. """ assert app.pages == {} - app.add_page(index_page, path="/test") + app.add_page(index_page, route="/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. """ 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"}