diff --git a/pynecone/__init__.py b/pynecone/__init__.py index b0fcb441f..56e66b33f 100644 --- a/pynecone/__init__.py +++ b/pynecone/__init__.py @@ -13,6 +13,7 @@ from .constants import Env, Transports from .event import EventChain, console_log, redirect, window_alert from .middleware import Middleware from .model import Model, session +from .route import route from .state import ComputedVar as var from .state import State from .style import toggle_color_mode diff --git a/pynecone/app.py b/pynecone/app.py index e98c2c5ce..0de0ac6f3 100644 --- a/pynecone/app.py +++ b/pynecone/app.py @@ -12,6 +12,7 @@ from pynecone.compiler import utils as compiler_utils from pynecone.components.component import Component, ComponentStyle from pynecone.event import Event, EventHandler from pynecone.middleware import HydrateMiddleware, Middleware +from pynecone.route import DECORATED_ROUTES from pynecone.state import DefaultState, Delta, State, StateManager, StateUpdate # Define custom types. @@ -306,6 +307,9 @@ class App(Base): Args: force_compile: Whether to force the app to compile. """ + for render, kwargs in DECORATED_ROUTES: + self.add_page(render, **kwargs) + # Get the env mode. config = utils.get_config() if config.env != constants.Env.DEV and not force_compile: diff --git a/pynecone/route.py b/pynecone/route.py new file mode 100644 index 000000000..b50a0a2e5 --- /dev/null +++ b/pynecone/route.py @@ -0,0 +1,54 @@ +"""The route decorator and associated variables.""" + +from typing import Optional + +from pynecone.event import EventHandler + +DECORATED_ROUTES = [] + + +def route( + route: Optional[str] = None, + title: Optional[str] = None, + image: Optional[str] = None, + description: Optional[str] = None, + on_load: Optional[EventHandler] = None, +): + """Decorate a function as a page. + + pc.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. Defaults to None. + title: The title of the page. Defaults to None. + image: The favicon of the page. Defaults to None. + description: The description of the page. Defaults to None. + on_load: The event handler called when the page load. Defaults to None. + + Returns: + The decorated function. + """ + + def decorator(render_fn): + kwargs = {} + if route: + kwargs["route"] = route + if title: + kwargs["title"] = title + if image: + kwargs["image"] = image + if description: + kwargs["description"] = description + if on_load: + kwargs["on_load"] = on_load + + DECORATED_ROUTES.append((render_fn, kwargs)) + + return render_fn + + return decorator diff --git a/pynecone/utils.py b/pynecone/utils.py index 93ac514a8..da4d6ebeb 100644 --- a/pynecone/utils.py +++ b/pynecone/utils.py @@ -716,8 +716,9 @@ def change_or_terminate_port(port, _type) -> str: def setup_backend(): - """Sets up backend. Specifically ensures backend - database is updated when running --no-frontend. + """Set up backend. + + Specifically ensures backend database is updated when running --no-frontend. """ config = get_config() if config.db_url is not None: