4545)
4646from reflex .utils import console
4747from reflex .utils .export import export
48+ from reflex .utils .types import ASGIApp
4849
4950try :
5051 from selenium import webdriver
@@ -110,6 +111,7 @@ class AppHarness:
110111 app_module_path : Path
111112 app_module : types .ModuleType | None = None
112113 app_instance : reflex .App | None = None
114+ app_asgi : ASGIApp | None = None
113115 frontend_process : subprocess .Popen | None = None
114116 frontend_url : str | None = None
115117 frontend_output_thread : threading .Thread | None = None
@@ -270,11 +272,14 @@ def _initialize_app(self):
270272 # Ensure the AppHarness test does not skip State assignment due to running via pytest
271273 os .environ .pop (reflex .constants .PYTEST_CURRENT_TEST , None )
272274 os .environ [reflex .constants .APP_HARNESS_FLAG ] = "true"
273- self .app_module = reflex .utils .prerequisites .get_compiled_app (
274- # Do not reload the module for pre-existing apps (only apps generated from source)
275- reload = self .app_source is not None
275+ # Ensure we actually compile the app during first initialization.
276+ self .app_instance , self .app_module = (
277+ reflex .utils .prerequisites .get_and_validate_app (
278+ # Do not reload the module for pre-existing apps (only apps generated from source)
279+ reload = self .app_source is not None
280+ )
276281 )
277- self .app_instance = self .app_module . app
282+ self .app_asgi = self .app_instance ()
278283 if self .app_instance and isinstance (
279284 self .app_instance ._state_manager , StateManagerRedis
280285 ):
@@ -300,10 +305,10 @@ def _get_backend_shutdown_handler(self):
300305 async def _shutdown (* args , ** kwargs ) -> None :
301306 # ensure redis is closed before event loop
302307 if self .app_instance is not None and isinstance (
303- self .app_instance .state_manager , StateManagerRedis
308+ self .app_instance ._state_manager , StateManagerRedis
304309 ):
305310 with contextlib .suppress (ValueError ):
306- await self .app_instance .state_manager .close ()
311+ await self .app_instance ._state_manager .close ()
307312
308313 # socketio shutdown handler
309314 if self .app_instance is not None and self .app_instance .sio is not None :
@@ -323,11 +328,11 @@ async def _shutdown(*args, **kwargs) -> None:
323328 return _shutdown
324329
325330 def _start_backend (self , port : int = 0 ):
326- if self .app_instance is None or self . app_instance . _api is None :
331+ if self .app_asgi is None :
327332 raise RuntimeError ("App was not initialized." )
328333 self .backend = uvicorn .Server (
329334 uvicorn .Config (
330- app = self .app_instance . _api ,
335+ app = self .app_asgi ,
331336 host = "127.0.0.1" ,
332337 port = port ,
333338 )
@@ -349,13 +354,13 @@ async def _reset_backend_state_manager(self):
349354 if (
350355 self .app_instance is not None
351356 and isinstance (
352- self .app_instance .state_manager ,
357+ self .app_instance ._state_manager ,
353358 StateManagerRedis ,
354359 )
355360 and self .app_instance ._state is not None
356361 ):
357362 with contextlib .suppress (RuntimeError ):
358- await self .app_instance .state_manager .close ()
363+ await self .app_instance ._state_manager .close ()
359364 self .app_instance ._state_manager = StateManagerRedis .create (
360365 state = self .app_instance ._state ,
361366 )
@@ -959,12 +964,12 @@ def _wait_frontend(self):
959964 raise RuntimeError ("Frontend did not start" )
960965
961966 def _start_backend (self ):
962- if self .app_instance is None :
967+ if self .app_asgi is None :
963968 raise RuntimeError ("App was not initialized." )
964969 environment .REFLEX_SKIP_COMPILE .set (True )
965970 self .backend = uvicorn .Server (
966971 uvicorn .Config (
967- app = self .app_instance ,
972+ app = self .app_asgi ,
968973 host = "127.0.0.1" ,
969974 port = 0 ,
970975 workers = reflex .utils .processes .get_num_workers (),
0 commit comments