make app dataclass
This commit is contained in:
parent
303293b58e
commit
6ccb617b4e
@ -46,7 +46,6 @@ from starlette_admin.contrib.sqla.view import ModelView
|
|||||||
from reflex import constants
|
from reflex import constants
|
||||||
from reflex.admin import AdminDash
|
from reflex.admin import AdminDash
|
||||||
from reflex.app_mixins import AppMixin, LifespanMixin, MiddlewareMixin
|
from reflex.app_mixins import AppMixin, LifespanMixin, MiddlewareMixin
|
||||||
from reflex.base import Base
|
|
||||||
from reflex.compiler import compiler
|
from reflex.compiler import compiler
|
||||||
from reflex.compiler import utils as compiler_utils
|
from reflex.compiler import utils as compiler_utils
|
||||||
from reflex.compiler.compiler import (
|
from reflex.compiler.compiler import (
|
||||||
@ -200,7 +199,8 @@ class UnevaluatedPage:
|
|||||||
meta: List[Dict[str, str]]
|
meta: List[Dict[str, str]]
|
||||||
|
|
||||||
|
|
||||||
class App(MiddlewareMixin, LifespanMixin, Base):
|
@dataclasses.dataclass()
|
||||||
|
class App(MiddlewareMixin, LifespanMixin):
|
||||||
"""The main Reflex app that encapsulates the backend and frontend.
|
"""The main Reflex app that encapsulates the backend and frontend.
|
||||||
|
|
||||||
Every Reflex app needs an app defined in its main module.
|
Every Reflex app needs an app defined in its main module.
|
||||||
@ -222,24 +222,26 @@ class App(MiddlewareMixin, LifespanMixin, Base):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# The global [theme](https://reflex.dev/docs/styling/theming/#theme) for the entire app.
|
# The global [theme](https://reflex.dev/docs/styling/theming/#theme) for the entire app.
|
||||||
theme: Optional[Component] = themes.theme(accent_color="blue")
|
theme: Optional[Component] = dataclasses.field(
|
||||||
|
default_factory=lambda: themes.theme(accent_color="blue")
|
||||||
|
)
|
||||||
|
|
||||||
# The [global style](https://reflex.dev/docs/styling/overview/#global-styles}) for the app.
|
# The [global style](https://reflex.dev/docs/styling/overview/#global-styles}) for the app.
|
||||||
style: ComponentStyle = {}
|
style: ComponentStyle = dataclasses.field(default_factory=dict)
|
||||||
|
|
||||||
# A list of URLs to [stylesheets](https://reflex.dev/docs/styling/custom-stylesheets/) to include in the app.
|
# A list of URLs to [stylesheets](https://reflex.dev/docs/styling/custom-stylesheets/) to include in the app.
|
||||||
stylesheets: List[str] = []
|
stylesheets: List[str] = dataclasses.field(default_factory=list)
|
||||||
|
|
||||||
# A component that is present on every page (defaults to the Connection Error banner).
|
# A component that is present on every page (defaults to the Connection Error banner).
|
||||||
overlay_component: Optional[Union[Component, ComponentCallable]] = (
|
overlay_component: Optional[Union[Component, ComponentCallable]] = (
|
||||||
default_overlay_component()
|
dataclasses.field(default_factory=default_overlay_component)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Error boundary component to wrap the app with.
|
# Error boundary component to wrap the app with.
|
||||||
error_boundary: Optional[ComponentCallable] = default_error_boundary
|
error_boundary: Optional[ComponentCallable] = default_error_boundary
|
||||||
|
|
||||||
# Components to add to the head of every page.
|
# Components to add to the head of every page.
|
||||||
head_components: List[Component] = []
|
head_components: List[Component] = dataclasses.field(default_factory=list)
|
||||||
|
|
||||||
# The Socket.IO AsyncServer instance.
|
# The Socket.IO AsyncServer instance.
|
||||||
sio: Optional[AsyncServer] = None
|
sio: Optional[AsyncServer] = None
|
||||||
@ -251,10 +253,12 @@ class App(MiddlewareMixin, LifespanMixin, Base):
|
|||||||
html_custom_attrs: Optional[Dict[str, str]] = None
|
html_custom_attrs: Optional[Dict[str, str]] = None
|
||||||
|
|
||||||
# A map from a route to an unevaluated page. PRIVATE.
|
# A map from a route to an unevaluated page. PRIVATE.
|
||||||
unevaluated_pages: Dict[str, UnevaluatedPage] = {}
|
unevaluated_pages: Dict[str, UnevaluatedPage] = dataclasses.field(
|
||||||
|
default_factory=dict
|
||||||
|
)
|
||||||
|
|
||||||
# A map from a page route to the component to render. Users should use `add_page`. PRIVATE.
|
# A map from a page route to the component to render. Users should use `add_page`. PRIVATE.
|
||||||
pages: Dict[str, Component] = {}
|
pages: Dict[str, Component] = dataclasses.field(default_factory=dict)
|
||||||
|
|
||||||
# The backend API object. PRIVATE.
|
# The backend API object. PRIVATE.
|
||||||
api: FastAPI = None # type: ignore
|
api: FastAPI = None # type: ignore
|
||||||
@ -266,7 +270,9 @@ class App(MiddlewareMixin, LifespanMixin, Base):
|
|||||||
_state_manager: Optional[StateManager] = None
|
_state_manager: Optional[StateManager] = None
|
||||||
|
|
||||||
# Mapping from a route to event handlers to trigger when the page loads. PRIVATE.
|
# Mapping from a route to event handlers to trigger when the page loads. PRIVATE.
|
||||||
load_events: Dict[str, List[IndividualEventType[[]]]] = {}
|
load_events: Dict[str, List[IndividualEventType[[...]]]] = dataclasses.field(
|
||||||
|
default_factory=dict
|
||||||
|
)
|
||||||
|
|
||||||
# Admin dashboard to view and manage the database. PRIVATE.
|
# Admin dashboard to view and manage the database. PRIVATE.
|
||||||
admin_dash: Optional[AdminDash] = None
|
admin_dash: Optional[AdminDash] = None
|
||||||
@ -275,7 +281,7 @@ class App(MiddlewareMixin, LifespanMixin, Base):
|
|||||||
event_namespace: Optional[EventNamespace] = None
|
event_namespace: Optional[EventNamespace] = None
|
||||||
|
|
||||||
# Background tasks that are currently running. PRIVATE.
|
# Background tasks that are currently running. PRIVATE.
|
||||||
background_tasks: Set[asyncio.Task] = set()
|
background_tasks: Set[asyncio.Task] = dataclasses.field(default_factory=set)
|
||||||
|
|
||||||
# Frontend Error Handler Function
|
# Frontend Error Handler Function
|
||||||
frontend_exception_handler: Callable[[Exception], None] = (
|
frontend_exception_handler: Callable[[Exception], None] = (
|
||||||
@ -287,23 +293,14 @@ class App(MiddlewareMixin, LifespanMixin, Base):
|
|||||||
[Exception], Union[EventSpec, List[EventSpec], None]
|
[Exception], Union[EventSpec, List[EventSpec], None]
|
||||||
] = default_backend_exception_handler
|
] = default_backend_exception_handler
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __post_init__(self):
|
||||||
"""Initialize the app.
|
"""Initialize the app.
|
||||||
|
|
||||||
Args:
|
|
||||||
**kwargs: Kwargs to initialize the app with.
|
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
ValueError: If the event namespace is not provided in the config.
|
ValueError: If the event namespace is not provided in the config.
|
||||||
Also, if there are multiple client subclasses of rx.BaseState(Subclasses of rx.BaseState should consist
|
Also, if there are multiple client subclasses of rx.BaseState(Subclasses of rx.BaseState should consist
|
||||||
of the DefaultState and the client app state).
|
of the DefaultState and the client app state).
|
||||||
"""
|
"""
|
||||||
if "connect_error_component" in kwargs:
|
|
||||||
raise ValueError(
|
|
||||||
"`connect_error_component` is deprecated, use `overlay_component` instead"
|
|
||||||
)
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
# Special case to allow test cases have multiple subclasses of rx.BaseState.
|
# Special case to allow test cases have multiple subclasses of rx.BaseState.
|
||||||
if not is_testing_env() and BaseState.__subclasses__() != [State]:
|
if not is_testing_env() and BaseState.__subclasses__() != [State]:
|
||||||
# Only rx.State is allowed as Base State subclass.
|
# Only rx.State is allowed as Base State subclass.
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import dataclasses
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from reflex.event import Event
|
from reflex.event import Event
|
||||||
@ -12,11 +13,12 @@ from reflex.state import BaseState, StateUpdate
|
|||||||
from .mixin import AppMixin
|
from .mixin import AppMixin
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
class MiddlewareMixin(AppMixin):
|
class MiddlewareMixin(AppMixin):
|
||||||
"""Middleware Mixin that allow to add middleware to the app."""
|
"""Middleware Mixin that allow to add middleware to the app."""
|
||||||
|
|
||||||
# Middleware to add to the app. Users should use `add_middleware`. PRIVATE.
|
# Middleware to add to the app. Users should use `add_middleware`. PRIVATE.
|
||||||
middleware: List[Middleware] = []
|
middleware: List[Middleware] = dataclasses.field(default_factory=list)
|
||||||
|
|
||||||
def _init_mixin(self):
|
def _init_mixin(self):
|
||||||
self.middleware.append(HydrateMiddleware())
|
self.middleware.append(HydrateMiddleware())
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
"""Default mixin for all app mixins."""
|
"""Default mixin for all app mixins."""
|
||||||
|
|
||||||
from reflex.base import Base
|
import dataclasses
|
||||||
|
|
||||||
|
|
||||||
class AppMixin(Base):
|
@dataclasses.dataclass
|
||||||
|
class AppMixin:
|
||||||
"""Define the base class for all app mixins."""
|
"""Define the base class for all app mixins."""
|
||||||
|
|
||||||
def _init_mixin(self):
|
def _init_mixin(self):
|
||||||
|
@ -1403,13 +1403,6 @@ def test_app_state_determination():
|
|||||||
assert a4.state is not None
|
assert a4.state is not None
|
||||||
|
|
||||||
|
|
||||||
# for coverage
|
|
||||||
def test_raise_on_connect_error():
|
|
||||||
"""Test that the connect_error function is called."""
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
App(connect_error_component="Foo")
|
|
||||||
|
|
||||||
|
|
||||||
def test_raise_on_state():
|
def test_raise_on_state():
|
||||||
"""Test that the state is set."""
|
"""Test that the state is set."""
|
||||||
# state kwargs is deprecated, we just make sure the app is created anyway.
|
# state kwargs is deprecated, we just make sure the app is created anyway.
|
||||||
|
Loading…
Reference in New Issue
Block a user