diff --git a/pyi_hashes.json b/pyi_hashes.json index 92a76f37ef8..7d69cdc9565 100644 --- a/pyi_hashes.json +++ b/pyi_hashes.json @@ -1,5 +1,5 @@ { - "reflex/__init__.pyi": "8f9482b205f5a33a59f748006ded637b", + "reflex/__init__.pyi": "e9f08e115b1e1dd89beabacade84a589", "reflex/components/__init__.pyi": "ac05995852baa81062ba3d18fbc489fb", "reflex/components/base/__init__.pyi": "16e47bf19e0d62835a605baa3d039c5a", "reflex/components/base/app_wrap.pyi": "ae600e2cc9d70f2ce613bdd6c1da3b16", diff --git a/reflex/__init__.py b/reflex/__init__.py index 5d3daff80de..33e86ea3da3 100644 --- a/reflex/__init__.py +++ b/reflex/__init__.py @@ -84,20 +84,11 @@ from __future__ import annotations -from types import ModuleType -from typing import Any - from reflex.utils import ( compat, # for side-effects lazy_loader, ) -from .event import event as event - -# import this here explicitly to avoid returning the page module since page attr has the -# same name as page module(page.py) -from .page import page as page - # Remove the `compat` name from the namespace, it was imported for side-effects only. del compat @@ -301,6 +292,7 @@ "constants": ["Env"], "constants.colors": ["Color"], "event": [ + "event", "EventChain", "EventHandler", "call_script", @@ -331,6 +323,7 @@ ], "middleware": ["middleware", "Middleware"], "model": ["asession", "session", "Model"], + "page": ["page"], "state": [ "var", "ComponentState", diff --git a/reflex/event.py b/reflex/event.py index 318f526db89..1ab9d57af51 100644 --- a/reflex/event.py +++ b/reflex/event.py @@ -2,6 +2,7 @@ import dataclasses import inspect +import sys import types import urllib.parse from base64 import b64encode @@ -403,7 +404,7 @@ def __init__(self, fn: Callable[..., EventSpec] | None = None, **kwargs): Args: fn: The function to decorate. - **kwargs: The kwargs to pass to pydantic initializer + **kwargs: The kwargs to pass to the EventSpec constructor. """ if fn is not None: default_event_spec = fn() @@ -1243,19 +1244,6 @@ def download( ) -# This function seems unused. Check if we still need it. If not, remove in 0.7.0 -def _callback_arg_spec(eval_result: Any): - """ArgSpec for call_script callback function. - - Args: - eval_result: The result of the javascript execution. - - Returns: - Args for the callback function - """ - return [eval_result] - - def call_script( javascript_code: str | Var[str], callback: "EventType[Any] | None" = None, @@ -2197,7 +2185,9 @@ def __call__(self, *args: Var) -> Any: class EventNamespace: """A namespace for event related classes.""" + # Core Event Classes Event = Event + EventActionsMixin = EventActionsMixin EventHandler = EventHandler EventSpec = EventSpec CallableEventSpec = CallableEventSpec @@ -2206,8 +2196,43 @@ class EventNamespace: LiteralEventVar = LiteralEventVar EventChainVar = EventChainVar LiteralEventChainVar = LiteralEventChainVar - EventType = EventType EventCallback = EventCallback + LambdaEventCallback = LambdaEventCallback + + # Javascript Event Classes + JavascriptHTMLInputElement = JavascriptHTMLInputElement + JavascriptInputEvent = JavascriptInputEvent + JavascriptKeyboardEvent = JavascriptKeyboardEvent + JavascriptMouseEvent = JavascriptMouseEvent + JavascriptPointerEvent = JavascriptPointerEvent + + # Type Info Classes + KeyInputInfo = KeyInputInfo + MouseEventInfo = MouseEventInfo + PointerEventInfo = PointerEventInfo + IdentityEventReturn = IdentityEventReturn + + # File Upload + FileUpload = FileUpload + + # Type Aliases + EventType = EventType + LAMBDA_OR_STATE = LAMBDA_OR_STATE + BASIC_EVENT_TYPES = BASIC_EVENT_TYPES + IndividualEventType = IndividualEventType + + # Constants + BACKGROUND_TASK_MARKER = BACKGROUND_TASK_MARKER + _EVENT_FIELDS = _EVENT_FIELDS + upload_files = upload_files + stop_propagation = stop_propagation + prevent_default = prevent_default + + # Private/Internal Functions + _values_returned_from_event = staticmethod(_values_returned_from_event) + _check_event_args_subclass_of_callback = staticmethod( + _check_event_args_subclass_of_callback + ) @overload def __new__( @@ -2359,10 +2384,20 @@ def wrapper( check_fn_match_arg_spec = staticmethod(check_fn_match_arg_spec) resolve_annotation = staticmethod(resolve_annotation) parse_args_spec = staticmethod(parse_args_spec) + unwrap_var_annotation = staticmethod(unwrap_var_annotation) + get_fn_signature = staticmethod(get_fn_signature) + + # Event Spec Functions passthrough_event_spec = staticmethod(passthrough_event_spec) input_event = staticmethod(input_event) + int_input_event = staticmethod(int_input_event) + float_input_event = staticmethod(float_input_event) + checked_input_event = staticmethod(checked_input_event) key_event = staticmethod(key_event) + pointer_event_spec = staticmethod(pointer_event_spec) no_args_event_spec = staticmethod(no_args_event_spec) + + # Server Side Events server_side = staticmethod(server_side) redirect = staticmethod(redirect) console_log = staticmethod(console_log) @@ -2383,6 +2418,9 @@ def wrapper( call_script = staticmethod(call_script) call_function = staticmethod(call_function) run_script = staticmethod(run_script) + __file__ = __file__ event = EventNamespace +event.event = event # pyright: ignore[reportAttributeAccessIssue] +sys.modules[__name__] = event # pyright: ignore[reportArgumentType] diff --git a/reflex/page.py b/reflex/page.py index a2907ca2546..9b09682436f 100644 --- a/reflex/page.py +++ b/reflex/page.py @@ -2,12 +2,15 @@ from __future__ import annotations +import sys from collections import defaultdict -from collections.abc import Callable -from typing import Any +from typing import TYPE_CHECKING -from reflex.config import get_config -from reflex.event import EventType +if TYPE_CHECKING: + from collections.abc import Callable + from typing import Any + + from reflex.event import EventType DECORATED_PAGES: dict[str, list] = defaultdict(list) @@ -42,6 +45,7 @@ def page( Returns: The decorated function. """ + from reflex.config import get_config def decorator(render_fn: Callable): kwargs = {} @@ -65,3 +69,57 @@ def decorator(render_fn: Callable): return render_fn return decorator + + +class PageNamespace: + """A namespace for page names.""" + + DECORATED_PAGES = DECORATED_PAGES + + def __new__( + cls, + route: str | None = None, + title: str | None = None, + image: str | None = None, + description: str | None = None, + meta: list[Any] | None = None, + script_tags: list[Any] | None = None, + on_load: EventType[()] | None = None, + ): + """Decorate a function as a page. + + rx.App() will automatically call add_page() for any method decorated with page + 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. + meta: Additional meta to add to the page. + on_load: The event handler(s) called when the page load. + script_tags: scripts to attach to the page + + Returns: + The decorated function. + """ + return page( + route=route, + title=title, + image=image, + description=description, + meta=meta, + script_tags=script_tags, + on_load=on_load, + ) + + page = staticmethod(page) + __file__ = __file__ + + +page_namespace = PageNamespace +sys.modules[__name__] = page_namespace # pyright: ignore[reportArgumentType]