From 23e08a62e7a24d57fe6637314440e9aafb77a15c Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Tue, 27 Aug 2024 16:50:58 -0700 Subject: [PATCH] adjust testcases --- reflex/app.py | 9 +++++---- reflex/compiler/compiler.py | 30 +++++++++++++++++++++++++----- tests/test_app.py | 21 +++++++++++++++++---- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/reflex/app.py b/reflex/app.py index 101d8bb4c..b530a2ff7 100644 --- a/reflex/app.py +++ b/reflex/app.py @@ -557,10 +557,13 @@ class App(MiddlewareMixin, LifespanMixin, Base): Args: route: The route of the page to compile. """ - component = compiler.compile_unevaluated_page( - route, self.unevaluated_pages[route] + component, enable_state = compiler.compile_unevaluated_page( + route, self.unevaluated_pages[route], self.state ) + if enable_state: + self._enable_state() + # Add the page. self._check_routes_conflict(route) self.pages[route] = component @@ -841,8 +844,6 @@ class App(MiddlewareMixin, LifespanMixin, Base): self.pages = {} - self._enable_state() - def get_compilation_time() -> str: return str(datetime.now().time()).split(".")[0] diff --git a/reflex/compiler/compiler.py b/reflex/compiler/compiler.py index 6b0a86428..fb1c6ebc9 100644 --- a/reflex/compiler/compiler.py +++ b/reflex/compiler/compiler.py @@ -5,7 +5,7 @@ from __future__ import annotations import os from datetime import datetime from pathlib import Path -from typing import TYPE_CHECKING, Dict, Iterable, Optional, Type, Union +from typing import TYPE_CHECKING, Dict, Iterable, Optional, Tuple, Type, Union from reflex import constants from reflex.compiler import templates, utils @@ -517,15 +517,18 @@ if TYPE_CHECKING: from reflex.app import UnevaluatedPage -def compile_unevaluated_page(route: str, page: UnevaluatedPage) -> Component: +def compile_unevaluated_page( + route: str, page: UnevaluatedPage, state: Type[BaseState] | None = None +) -> Tuple[Component, bool]: """Compiles an uncompiled page into a component and adds meta information. Args: route: The route of the page. page: The uncompiled page object. + state: The state of the app. Returns: - The compiled component. + The compiled component and whether state should be enabled. """ # Generate the component if it is a callable. component = page.component @@ -535,6 +538,21 @@ def compile_unevaluated_page(route: str, page: UnevaluatedPage) -> Component: if isinstance(component, tuple): component = Fragment.create(*component) + enable_state = False + # Ensure state is enabled if this page uses state. + if state is None: + if page.on_load or component._has_stateful_event_triggers(): + enable_state = True + else: + for var in component._get_vars(include_children=True): + var_data = var._get_all_var_data() + if not var_data: + continue + if not var_data.state: + continue + enable_state = True + break + from reflex.app import OverlayFragment from reflex.utils.format import make_default_page_title @@ -559,7 +577,7 @@ def compile_unevaluated_page(route: str, page: UnevaluatedPage) -> Component: **meta_args, ) - return component + return component, enable_state class ExecutorSafeFunctions: @@ -620,7 +638,9 @@ class ExecutorSafeFunctions: Returns: The route, compiled component, and compiled page. """ - component = compile_unevaluated_page(route, cls.UNCOMPILED_PAGES[route]) + component, enable_state = compile_unevaluated_page( + route, cls.UNCOMPILED_PAGES[route] + ) component = component if isinstance(component, Component) else component() component._add_style_recursive(style, theme) return route, component, compile_page(route, component, cls.STATE) diff --git a/tests/test_app.py b/tests/test_app.py index efaca4234..6c5a63dd4 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -237,9 +237,12 @@ def test_add_page_default_route(app: App, index_page, about_page): about_page: The about page. """ assert app.pages == {} + assert app.unevaluated_pages == {} app.add_page(index_page) + app._compile_page("index") assert app.pages.keys() == {"index"} app.add_page(about_page) + app._compile_page("about") assert app.pages.keys() == {"index", "about"} @@ -252,8 +255,9 @@ def test_add_page_set_route(app: App, index_page, windows_platform: bool): windows_platform: Whether the system is windows. """ route = "test" if windows_platform else "/test" - assert app.pages == {} + assert app.unevaluated_pages == {} app.add_page(index_page, route=route) + app._compile_page("test") assert app.pages.keys() == {"test"} @@ -269,8 +273,9 @@ def test_add_page_set_route_dynamic(index_page, windows_platform: bool): route = "/test/[dynamic]" if windows_platform: route.lstrip("/").replace("/", "\\") - assert app.pages == {} + assert app.unevaluated_pages == {} app.add_page(index_page, route=route) + app._compile_page("test/[dynamic]") assert app.pages.keys() == {"test/[dynamic]"} assert "dynamic" in app.state.computed_vars assert app.state.computed_vars["dynamic"]._deps(objclass=EmptyState) == { @@ -288,9 +293,9 @@ def test_add_page_set_route_nested(app: App, index_page, windows_platform: bool) windows_platform: Whether the system is windows. """ route = "test\\nested" if windows_platform else "/test/nested" - assert app.pages == {} + assert app.unevaluated_pages == {} app.add_page(index_page, route=route) - assert app.pages.keys() == {route.strip(os.path.sep)} + assert app.unevaluated_pages.keys() == {route.strip(os.path.sep)} def test_add_page_invalid_api_route(app: App, index_page): @@ -1201,6 +1206,7 @@ def test_overlay_component( app.add_page(rx.box("Index"), route="/test") # overlay components are wrapped during compile only + app._compile_page("test") app._setup_overlay_component() page = app.pages["test"] @@ -1330,6 +1336,7 @@ def test_app_state_determination(): # Add a page with `on_load` enables state. a1.add_page(rx.box("About"), route="/about", on_load=rx.console_log("")) + a1._compile_page("about") assert a1.state is not None a2 = App() @@ -1337,6 +1344,7 @@ def test_app_state_determination(): # Referencing a state Var enables state. a2.add_page(rx.box(rx.text(GenState.value)), route="/") + a2._compile_page("index") assert a2.state is not None a3 = App() @@ -1344,6 +1352,7 @@ def test_app_state_determination(): # Referencing router enables state. a3.add_page(rx.box(rx.text(State.router.page.full_path)), route="/") + a3._compile_page("index") assert a3.state is not None a4 = App() @@ -1355,6 +1364,7 @@ def test_app_state_determination(): a4.add_page( rx.box(rx.button("Click", on_click=DynamicState.on_counter)), route="/page2" ) + a4._compile_page("page2") assert a4.state is not None @@ -1432,6 +1442,9 @@ def test_add_page_component_returning_tuple(): app.add_page(index) # type: ignore app.add_page(page2) # type: ignore + app._compile_page("index") + app._compile_page("page2") + assert isinstance((fragment_wrapper := app.pages["index"].children[0]), Fragment) assert isinstance((first_text := fragment_wrapper.children[0]), Text) assert str(first_text.children[0].contents) == '"first"' # type: ignore