فهرست منبع

apps should no longer call "app.compile()" (#2291)

jackie-pc 1 سال پیش
والد
کامیت
7388617b72

+ 0 - 1
README.md

@@ -123,7 +123,6 @@ def index():
 # Add state and page to the app.
 # Add state and page to the app.
 app = rx.App()
 app = rx.App()
 app.add_page(index, title="reflex:DALL·E")
 app.add_page(index, title="reflex:DALL·E")
-app.compile()
 ```
 ```
 
 
 ## Let's break this down.
 ## Let's break this down.

+ 0 - 2
docs/es/README.md

@@ -121,7 +121,6 @@ def index():
 # Add state and page to the app.
 # Add state and page to the app.
 app = rx.App()
 app = rx.App()
 app.add_page(index, title="reflex:DALL·E")
 app.add_page(index, title="reflex:DALL·E")
-app.compile()
 ```
 ```
 
 
 ## Vamos a desglosarlo.
 ## Vamos a desglosarlo.
@@ -191,7 +190,6 @@ Añadimos una página desde la raíz (root) de la aplicación al componente de 
 
 
 ```python
 ```python
 app.add_page(index, title="DALL-E")
 app.add_page(index, title="DALL-E")
-app.compile()
 ```
 ```
 
 
 Puedes crear una aplicación multipágina añadiendo más páginas.
 Puedes crear una aplicación multipágina añadiendo más páginas.

+ 0 - 2
docs/in/README.md

@@ -120,7 +120,6 @@ def index():
 # Add state and page to the app.
 # Add state and page to the app.
 app = rx.App()
 app = rx.App()
 app.add_page(index, title="reflex:DALL·E")
 app.add_page(index, title="reflex:DALL·E")
-app.compile()
 ```
 ```
 
 
 ## चलो इसे विस्तार से देखते हैं।
 ## चलो इसे विस्तार से देखते हैं।
@@ -190,7 +189,6 @@ app = rx.App()
 
 
 ```python
 ```python
 app.add_page(index, title="DALL-E")
 app.add_page(index, title="DALL-E")
-app.compile()
 ```
 ```
 
 
 आप और पेज जोड़कर एक मल्टी-पेज एप्लिकेशन बना सकते हैं।
 आप और पेज जोड़कर एक मल्टी-पेज एप्लिकेशन बना सकते हैं।

+ 0 - 2
docs/it/README.md

@@ -121,7 +121,6 @@ def index():
 # Aggiungi stato e pagina all'app.
 # Aggiungi stato e pagina all'app.
 app = rx.App()
 app = rx.App()
 app.add_page(index, title="reflex:DALL·E")
 app.add_page(index, title="reflex:DALL·E")
-app.compile()
 ```
 ```
 
 
 ## Analizziamolo
 ## Analizziamolo
@@ -191,7 +190,6 @@ Possiamo aggiungere una pagina dalla radice dell'app al componente dell'indice.A
 
 
 ```python
 ```python
 app.add_page(index, title="DALL-E")
 app.add_page(index, title="DALL-E")
-app.compile()
 ```
 ```
 
 
 Puoi creare un'app multi-pagina aggiungendo altre pagine.
 Puoi creare un'app multi-pagina aggiungendo altre pagine.

+ 0 - 2
docs/kr/README.md

@@ -121,7 +121,6 @@ def index():
 # Add state and page to the app.
 # Add state and page to the app.
 app = rx.App()
 app = rx.App()
 app.add_page(index, title="reflex:DALL·E")
 app.add_page(index, title="reflex:DALL·E")
-app.compile()
 ```
 ```
 
 
 ## 하나씩 살펴보겠습니다.
 ## 하나씩 살펴보겠습니다.
@@ -194,7 +193,6 @@ app = rx.App()
 
 
 ```python
 ```python
 app.add_page(index, title="DALL-E")
 app.add_page(index, title="DALL-E")
-app.compile()
 ```
 ```
 
 
 여러 페이지를 추가하여 멀티 페이지 앱을 만들 수 있습니다.
 여러 페이지를 추가하여 멀티 페이지 앱을 만들 수 있습니다.

+ 0 - 2
docs/pt/pt_br/README.md

@@ -121,7 +121,6 @@ def index():
 # Adição do estado e da página no app.
 # Adição do estado e da página no app.
 app = rx.App()
 app = rx.App()
 app.add_page(index, title="reflex:DALL·E")
 app.add_page(index, title="reflex:DALL·E")
-app.compile()
 ```
 ```
 
 
 ## Vamos por partes.
 ## Vamos por partes.
@@ -192,7 +191,6 @@ Adicionamos uma página na raíz do app, apontando para o componente index. Tamb
 
 
 ```python
 ```python
 app.add_page(index, title="DALL-E")
 app.add_page(index, title="DALL-E")
-app.compile()
 ```
 ```
 
 
 Você pode criar mais páginas e adicioná-las ao seu app.
 Você pode criar mais páginas e adicioná-las ao seu app.

+ 0 - 2
docs/tr/README.md

@@ -124,7 +124,6 @@ def index():
 # Sayfa ve durumu uygulamaya ekleyin.
 # Sayfa ve durumu uygulamaya ekleyin.
 app = rx.App()
 app = rx.App()
 app.add_page(index, title="reflex:DALL·E")
 app.add_page(index, title="reflex:DALL·E")
-app.compile()
 ```
 ```
 
 
 ## Daha Detaylı İceleyelim
 ## Daha Detaylı İceleyelim
@@ -194,7 +193,6 @@ Uygulamamızın kök dizinine index bileşeninden bir sayfa ekliyoruz. Ayrıca s
 
 
 ```python
 ```python
 app.add_page(index, title="DALL-E")
 app.add_page(index, title="DALL-E")
-app.compile()
 ```
 ```
 
 
 Daha fazla sayfa ekleyerek çok sayfalı bir uygulama oluşturabilirsiniz.
 Daha fazla sayfa ekleyerek çok sayfalı bir uygulama oluşturabilirsiniz.

+ 0 - 2
docs/zh/zh_cn/README.md

@@ -122,7 +122,6 @@ def index():
 # Add state and page to the app.
 # Add state and page to the app.
 app = rx.App()
 app = rx.App()
 app.add_page(index, title="reflex:DALL·E")
 app.add_page(index, title="reflex:DALL·E")
-app.compile()
 ```
 ```
 
 
 ## 让我们分解以上步骤.
 ## 让我们分解以上步骤.
@@ -194,7 +193,6 @@ app = rx.App()
 
 
 ```python
 ```python
 app.add_page(index, title="DALL-E")
 app.add_page(index, title="DALL-E")
-app.compile()
 ```
 ```
 
 
 您可以通过增加更多页面来创建一个多页面的应用.
 您可以通过增加更多页面来创建一个多页面的应用.

+ 0 - 2
docs/zh/zh_tw/README.md

@@ -121,7 +121,6 @@ def index():
 # 把狀態跟頁面添加到應用程式。
 # 把狀態跟頁面添加到應用程式。
 app = rx.App()
 app = rx.App()
 app.add_page(index, title="reflex:DALL·E")
 app.add_page(index, title="reflex:DALL·E")
-app.compile()
 ```
 ```
 
 
 ## 讓我們來拆解一下。
 ## 讓我們來拆解一下。
@@ -192,7 +191,6 @@ app = rx.App()
 
 
 ```python
 ```python
 app.add_page(index, title="DALL-E")
 app.add_page(index, title="DALL-E")
-app.compile()
 ```
 ```
 
 
 你可以添加更多頁面至路由藉此來建立多頁面應用程式(multi-page app)
 你可以添加更多頁面至路由藉此來建立多頁面應用程式(multi-page app)

+ 0 - 1
integration/test_background_task.py

@@ -95,7 +95,6 @@ def BackgroundTask():
 
 
     app = rx.App(state=rx.State)
     app = rx.App(state=rx.State)
     app.add_page(index)
     app.add_page(index)
-    app.compile()
 
 
 
 
 @pytest.fixture(scope="session")
 @pytest.fixture(scope="session")

+ 0 - 2
integration/test_call_script.py

@@ -227,8 +227,6 @@ def CallScript():
             rx.button("Reset", id="reset", on_click=CallScriptState.reset_),
             rx.button("Reset", id="reset", on_click=CallScriptState.reset_),
         )
         )
 
 
-    app.compile()
-
 
 
 @pytest.fixture(scope="session")
 @pytest.fixture(scope="session")
 def call_script(tmp_path_factory) -> Generator[AppHarness, None, None]:
 def call_script(tmp_path_factory) -> Generator[AppHarness, None, None]:

+ 0 - 1
integration/test_client_storage.py

@@ -100,7 +100,6 @@ def ClientSide():
     app = rx.App(state=rx.State)
     app = rx.App(state=rx.State)
     app.add_page(index)
     app.add_page(index)
     app.add_page(index, route="/foo")
     app.add_page(index, route="/foo")
-    app.compile()
 
 
 
 
 @pytest.fixture(scope="session")
 @pytest.fixture(scope="session")

+ 0 - 1
integration/test_connection_banner.py

@@ -21,7 +21,6 @@ def ConnectionBanner():
 
 
     app = rx.App(state=rx.State)
     app = rx.App(state=rx.State)
     app.add_page(index)
     app.add_page(index)
-    app.compile()
 
 
 
 
 @pytest.fixture()
 @pytest.fixture()

+ 0 - 1
integration/test_dynamic_routes.py

@@ -66,7 +66,6 @@ def DynamicRoute():
     app.add_page(index, route="/page/[page_id]", on_load=DynamicState.on_load)  # type: ignore
     app.add_page(index, route="/page/[page_id]", on_load=DynamicState.on_load)  # type: ignore
     app.add_page(index, route="/static/x", on_load=DynamicState.on_load)  # type: ignore
     app.add_page(index, route="/static/x", on_load=DynamicState.on_load)  # type: ignore
     app.add_custom_404_page(on_load=DynamicState.on_load)  # type: ignore
     app.add_custom_404_page(on_load=DynamicState.on_load)  # type: ignore
-    app.compile()
 
 
 
 
 @pytest.fixture(scope="session")
 @pytest.fixture(scope="session")

+ 0 - 1
integration/test_event_actions.py

@@ -132,7 +132,6 @@ def TestEventAction():
 
 
     app = rx.App(state=rx.State)
     app = rx.App(state=rx.State)
     app.add_page(index)
     app.add_page(index)
-    app.compile()
 
 
 
 
 @pytest.fixture(scope="session")
 @pytest.fixture(scope="session")

+ 0 - 2
integration/test_event_chain.py

@@ -242,8 +242,6 @@ def EventChain():
     app.add_page(on_mount_return_chain)
     app.add_page(on_mount_return_chain)
     app.add_page(on_mount_yield_chain)
     app.add_page(on_mount_yield_chain)
 
 
-    app.compile()
-
 
 
 @pytest.fixture(scope="session")
 @pytest.fixture(scope="session")
 def event_chain(tmp_path_factory) -> Generator[AppHarness, None, None]:
 def event_chain(tmp_path_factory) -> Generator[AppHarness, None, None]:

+ 0 - 4
integration/test_form_submit.py

@@ -62,8 +62,6 @@ def FormSubmit():
             height="100vh",
             height="100vh",
         )
         )
 
 
-    app.compile()
-
 
 
 def FormSubmitName():
 def FormSubmitName():
     """App with a form using on_submit."""
     """App with a form using on_submit."""
@@ -124,8 +122,6 @@ def FormSubmitName():
             height="100vh",
             height="100vh",
         )
         )
 
 
-    app.compile()
-
 
 
 @pytest.fixture(
 @pytest.fixture(
     scope="session", params=[FormSubmit, FormSubmitName], ids=["id", "name"]
     scope="session", params=[FormSubmit, FormSubmitName], ids=["id", "name"]

+ 0 - 2
integration/test_input.py

@@ -40,8 +40,6 @@ def FullyControlledInput():
             rx.button("CLEAR", on_click=rx.set_value("on_change_input", "")),
             rx.button("CLEAR", on_click=rx.set_value("on_change_input", "")),
         )
         )
 
 
-    app.compile()
-
 
 
 @pytest.fixture()
 @pytest.fixture()
 def fully_controlled_input(tmp_path) -> Generator[AppHarness, None, None]:
 def fully_controlled_input(tmp_path) -> Generator[AppHarness, None, None]:

+ 0 - 1
integration/test_login_flow.py

@@ -45,7 +45,6 @@ def LoginSample():
     app = rx.App(state=rx.State)
     app = rx.App(state=rx.State)
     app.add_page(index)
     app.add_page(index)
     app.add_page(login)
     app.add_page(login)
-    app.compile()
 
 
 
 
 @pytest.fixture(scope="session")
 @pytest.fixture(scope="session")

+ 0 - 2
integration/test_server_side_event.py

@@ -75,8 +75,6 @@ def ServerSideEvent():
             ),
             ),
         )
         )
 
 
-    app.compile()
-
 
 
 @pytest.fixture(scope="session")
 @pytest.fixture(scope="session")
 def server_side_event(tmp_path_factory) -> Generator[AppHarness, None, None]:
 def server_side_event(tmp_path_factory) -> Generator[AppHarness, None, None]:

+ 0 - 2
integration/test_table.py

@@ -88,8 +88,6 @@ def Table():
             )
             )
         )
         )
 
 
-    app.compile()
-
 
 
 @pytest.fixture()
 @pytest.fixture()
 def table(tmp_path_factory) -> Generator[AppHarness, None, None]:
 def table(tmp_path_factory) -> Generator[AppHarness, None, None]:

+ 0 - 1
integration/test_upload.py

@@ -115,7 +115,6 @@ def UploadFile():
 
 
     app = rx.App(state=rx.State)
     app = rx.App(state=rx.State)
     app.add_page(index)
     app.add_page(index)
-    app.compile()
 
 
 
 
 @pytest.fixture(scope="session")
 @pytest.fixture(scope="session")

+ 0 - 2
integration/test_var_operations.py

@@ -565,8 +565,6 @@ def VarOperations():
             ),
             ),
         )
         )
 
 
-    app.compile()
-
 
 
 @pytest.fixture(scope="session")
 @pytest.fixture(scope="session")
 def var_operations(tmp_path_factory) -> Generator[AppHarness, None, None]:
 def var_operations(tmp_path_factory) -> Generator[AppHarness, None, None]:

+ 13 - 0
reflex/app.py

@@ -619,6 +619,19 @@ class App(Base):
         return True
         return True
 
 
     def compile(self):
     def compile(self):
+        """compile_() is the new function for performing compilation.
+        Reflex framework will call it automatically as needed.
+        """
+        console.deprecate(
+            feature_name="app.compile()",
+            reason="Explicit calls to app.compile() are not needed."
+            " Method will be removed in 0.4.0",
+            deprecation_version="0.3.8",
+            removal_version="0.4.0",
+        )
+        return
+
+    def compile_(self):
         """Compile the app and output it to the pages folder."""
         """Compile the app and output it to the pages folder."""
         # add the pages before the compile check so App know onload methods
         # add the pages before the compile check so App know onload methods
         for render, kwargs in DECORATED_PAGES:
         for render, kwargs in DECORATED_PAGES:

+ 1 - 0
reflex/app.pyi

@@ -120,6 +120,7 @@ class App(Base):
     def setup_admin_dash(self) -> None: ...
     def setup_admin_dash(self) -> None: ...
     def get_frontend_packages(self, imports: Dict[str, str]): ...
     def get_frontend_packages(self, imports: Dict[str, str]): ...
     def compile(self) -> None: ...
     def compile(self) -> None: ...
+    def compile_(self) -> None: ...
     def modify_state(self, token: str) -> AsyncContextManager[State]: ...
     def modify_state(self, token: str) -> AsyncContextManager[State]: ...
     def _process_background(
     def _process_background(
         self, state: State, event: Event
         self, state: State, event: Event

+ 13 - 0
reflex/app_module_for_backend.py

@@ -0,0 +1,13 @@
+"""Shims the real reflex app module for running backend server (uvicorn or gunicorn).
+Only the app attribute is explicitly exposed.
+"""
+from reflex import constants
+from reflex.utils.prerequisites import get_compiled_app
+
+if "app" != constants.CompileVars.APP:
+    raise AssertionError("unexpected variable name for 'app'")
+app = getattr(get_compiled_app(), constants.CompileVars.APP)
+
+# ensure only "app" is exposed.
+del get_compiled_app
+del constants

+ 6 - 4
reflex/reflex.py

@@ -178,7 +178,7 @@ def _run(
     if frontend:
     if frontend:
         prerequisites.update_next_config()
         prerequisites.update_next_config()
         # Get the app module.
         # Get the app module.
-        prerequisites.get_app()
+        prerequisites.get_compiled_app()
 
 
     # Warn if schema is not up to date.
     # Warn if schema is not up to date.
     prerequisites.check_schema_up_to_date()
     prerequisites.check_schema_up_to_date()
@@ -362,7 +362,7 @@ def db_init():
 
 
     # Initialize the database.
     # Initialize the database.
     _skip_compile()
     _skip_compile()
-    prerequisites.get_app()
+    prerequisites.get_compiled_app()
     model.Model.alembic_init()
     model.Model.alembic_init()
     model.Model.migrate(autogenerate=True)
     model.Model.migrate(autogenerate=True)
 
 
@@ -373,8 +373,9 @@ def migrate():
     from reflex import model
     from reflex import model
     from reflex.utils import prerequisites
     from reflex.utils import prerequisites
 
 
+    # TODO see if we can use `get_app()` instead (no compile).  Would _skip_compile still be needed then?
     _skip_compile()
     _skip_compile()
-    prerequisites.get_app()
+    prerequisites.get_compiled_app()
     if not prerequisites.check_db_initialized():
     if not prerequisites.check_db_initialized():
         return
         return
     model.Model.migrate()
     model.Model.migrate()
@@ -393,8 +394,9 @@ def makemigrations(
     from reflex import model
     from reflex import model
     from reflex.utils import prerequisites
     from reflex.utils import prerequisites
 
 
+    # TODO see if we can use `get_app()` instead (no compile).  Would _skip_compile still be needed then?
     _skip_compile()
     _skip_compile()
-    prerequisites.get_app()
+    prerequisites.get_compiled_app()
     if not prerequisites.check_db_initialized():
     if not prerequisites.check_db_initialized():
         return
         return
     with model.Model.get_db_engine().connect() as connection:
     with model.Model.get_db_engine().connect() as connection:

+ 2 - 0
reflex/state.py

@@ -1316,6 +1316,7 @@ class State(BaseState):
         Returns:
         Returns:
             The list of events to queue for on load handling.
             The list of events to queue for on load handling.
         """
         """
+        # Do not app.compile_()!  It should be already compiled by now.
         app = getattr(prerequisites.get_app(), constants.CompileVars.APP)
         app = getattr(prerequisites.get_app(), constants.CompileVars.APP)
         load_events = app.get_load_events(self.router.page.path)
         load_events = app.get_load_events(self.router.page.path)
         if not load_events and self.is_hydrated:
         if not load_events and self.is_hydrated:
@@ -1364,6 +1365,7 @@ class StateProxy(wrapt.ObjectProxy):
             state_instance: The state instance to proxy.
             state_instance: The state instance to proxy.
         """
         """
         super().__init__(state_instance)
         super().__init__(state_instance)
+        # compile is not relevant to backend logic
         self._self_app = getattr(prerequisites.get_app(), constants.CompileVars.APP)
         self._self_app = getattr(prerequisites.get_app(), constants.CompileVars.APP)
         self._self_substate_path = state_instance.get_full_name().split(".")
         self._self_substate_path = state_instance.get_full_name().split(".")
         self._self_actx = None
         self._self_actx = None

+ 1 - 1
reflex/testing.py

@@ -165,7 +165,7 @@ class AppHarness:
             # reset rx.State subclasses
             # reset rx.State subclasses
             State.class_subclasses.clear()
             State.class_subclasses.clear()
             # self.app_module.app.
             # self.app_module.app.
-            self.app_module = reflex.utils.prerequisites.get_app(reload=True)
+            self.app_module = reflex.utils.prerequisites.get_compiled_app(reload=True)
         self.app_instance = self.app_module.app
         self.app_instance = self.app_module.app
         if isinstance(self.app_instance.state_manager, StateManagerRedis):
         if isinstance(self.app_instance.state_manager, StateManagerRedis):
             # Create our own redis connection for testing.
             # Create our own redis connection for testing.

+ 2 - 2
reflex/utils/exec.py

@@ -160,7 +160,7 @@ def run_backend(
     import uvicorn
     import uvicorn
 
 
     config = get_config()
     config = get_config()
-    app_module = f"{config.app_name}.{config.app_name}:{constants.CompileVars.APP}"
+    app_module = f"reflex.app_module_for_backend:{constants.CompileVars.APP}"
 
 
     # Create a .nocompile file to skip compile for backend.
     # Create a .nocompile file to skip compile for backend.
     if os.path.exists(constants.Dirs.WEB):
     if os.path.exists(constants.Dirs.WEB):
@@ -196,7 +196,7 @@ def run_backend_prod(
     config = get_config()
     config = get_config()
     RUN_BACKEND_PROD = f"gunicorn --worker-class {config.gunicorn_worker_class} --preload --timeout {config.timeout} --log-level critical".split()
     RUN_BACKEND_PROD = f"gunicorn --worker-class {config.gunicorn_worker_class} --preload --timeout {config.timeout} --log-level critical".split()
     RUN_BACKEND_PROD_WINDOWS = f"uvicorn --timeout-keep-alive {config.timeout}".split()
     RUN_BACKEND_PROD_WINDOWS = f"uvicorn --timeout-keep-alive {config.timeout}".split()
-    app_module = f"{config.app_name}.{config.app_name}:{constants.CompileVars.APP}"
+    app_module = f"reflex.app_module_for_backend:{constants.CompileVars.APP}"
     command = (
     command = (
         [
         [
             *RUN_BACKEND_PROD_WINDOWS,
             *RUN_BACKEND_PROD_WINDOWS,

+ 1 - 1
reflex/utils/export.py

@@ -56,7 +56,7 @@ def export(
         # Update some parameters for export
         # Update some parameters for export
         prerequisites.update_next_config(export=True)
         prerequisites.update_next_config(export=True)
         # Ensure module can be imported and app.compile() is called.
         # Ensure module can be imported and app.compile() is called.
-        prerequisites.get_app()
+        prerequisites.get_compiled_app()
         # Set up .web directory and install frontend dependencies.
         # Set up .web directory and install frontend dependencies.
         build.setup_frontend(Path.cwd())
         build.setup_frontend(Path.cwd())
 
 

+ 15 - 0
reflex/utils/prerequisites.py

@@ -160,9 +160,24 @@ def get_app(reload: bool = False) -> ModuleType:
     app = __import__(module, fromlist=(constants.CompileVars.APP,))
     app = __import__(module, fromlist=(constants.CompileVars.APP,))
     if reload:
     if reload:
         importlib.reload(app)
         importlib.reload(app)
+
     return app
     return app
 
 
 
 
+def get_compiled_app(reload: bool = False) -> ModuleType:
+    """Get the app module based on the default config after first compiling it.
+
+    Args:
+        reload: Re-import the app module from disk
+
+    Returns:
+        The compiled app based on the default config.
+    """
+    app_module = get_app(reload=reload)
+    getattr(app_module, constants.CompileVars.APP).compile_()
+    return app_module
+
+
 def get_redis() -> Redis | None:
 def get_redis() -> Redis | None:
     """Get the redis client.
     """Get the redis client.
 
 

+ 2 - 2
tests/test_app.py

@@ -1213,7 +1213,7 @@ def test_app_wrap_compile_theme(compilable_app):
     """
     """
     app, web_dir = compilable_app
     app, web_dir = compilable_app
     app.theme = rdxt.theme(accent_color="plum")
     app.theme = rdxt.theme(accent_color="plum")
-    app.compile()
+    app.compile_()
     app_js_contents = (web_dir / "pages" / "_app.js").read_text()
     app_js_contents = (web_dir / "pages" / "_app.js").read_text()
     app_js_lines = [
     app_js_lines = [
         line.strip() for line in app_js_contents.splitlines() if line.strip()
         line.strip() for line in app_js_contents.splitlines() if line.strip()
@@ -1263,7 +1263,7 @@ def test_app_wrap_priority(compilable_app):
         return Fragment1.create(Fragment3.create())
         return Fragment1.create(Fragment3.create())
 
 
     app.add_page(page)
     app.add_page(page)
-    app.compile()
+    app.compile_()
     app_js_contents = (web_dir / "pages" / "_app.js").read_text()
     app_js_contents = (web_dir / "pages" / "_app.js").read_text()
     app_js_lines = [
     app_js_lines = [
         line.strip() for line in app_js_contents.splitlines() if line.strip()
         line.strip() for line in app_js_contents.splitlines() if line.strip()

+ 5 - 1
tests/test_state.py

@@ -1590,7 +1590,11 @@ def mock_app(monkeypatch, state_manager: StateManager) -> rx.App:
     app.state = TestState
     app.state = TestState
     app._state_manager = state_manager
     app._state_manager = state_manager
     app.event_namespace.emit = AsyncMock()  # type: ignore
     app.event_namespace.emit = AsyncMock()  # type: ignore
-    monkeypatch.setattr(prerequisites, "get_app", lambda: app_module)
+
+    def _mock_get_app(*args, **kwargs):
+        return app_module
+
+    monkeypatch.setattr(prerequisites, "get_app", _mock_get_app)
     return app
     return app
 
 
 
 

+ 1 - 1
tests/test_testing.py

@@ -21,7 +21,7 @@ def test_app_harness(tmp_path):
 
 
         app = rx.App(state=State)
         app = rx.App(state=State)
         app.add_page(lambda: rx.text("Basic App"), route="/", title="index")
         app.add_page(lambda: rx.text("Basic App"), route="/", title="index")
-        app.compile()
+        app.compile_()
 
 
     with AppHarness.create(
     with AppHarness.create(
         root=tmp_path,
         root=tmp_path,