|
@@ -17,11 +17,12 @@ import stat
|
|
import sys
|
|
import sys
|
|
import tempfile
|
|
import tempfile
|
|
import time
|
|
import time
|
|
|
|
+import typing
|
|
import zipfile
|
|
import zipfile
|
|
from datetime import datetime
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
from pathlib import Path
|
|
from types import ModuleType
|
|
from types import ModuleType
|
|
-from typing import Callable, List, Optional
|
|
|
|
|
|
+from typing import Callable, List, NamedTuple, Optional
|
|
|
|
|
|
import httpx
|
|
import httpx
|
|
import typer
|
|
import typer
|
|
@@ -42,9 +43,19 @@ from reflex.utils.exceptions import (
|
|
from reflex.utils.format import format_library_name
|
|
from reflex.utils.format import format_library_name
|
|
from reflex.utils.registry import _get_npm_registry
|
|
from reflex.utils.registry import _get_npm_registry
|
|
|
|
|
|
|
|
+if typing.TYPE_CHECKING:
|
|
|
|
+ from reflex.app import App
|
|
|
|
+
|
|
CURRENTLY_INSTALLING_NODE = False
|
|
CURRENTLY_INSTALLING_NODE = False
|
|
|
|
|
|
|
|
|
|
|
|
+class AppInfo(NamedTuple):
|
|
|
|
+ """A tuple containing the app instance and module."""
|
|
|
|
+
|
|
|
|
+ app: App
|
|
|
|
+ module: ModuleType
|
|
|
|
+
|
|
|
|
+
|
|
@dataclasses.dataclass(frozen=True)
|
|
@dataclasses.dataclass(frozen=True)
|
|
class Template:
|
|
class Template:
|
|
"""A template for a Reflex app."""
|
|
"""A template for a Reflex app."""
|
|
@@ -291,8 +302,11 @@ def get_app(reload: bool = False) -> ModuleType:
|
|
)
|
|
)
|
|
module = config.module
|
|
module = config.module
|
|
sys.path.insert(0, str(Path.cwd()))
|
|
sys.path.insert(0, str(Path.cwd()))
|
|
- app = __import__(module, fromlist=(constants.CompileVars.APP,))
|
|
|
|
-
|
|
|
|
|
|
+ app = (
|
|
|
|
+ __import__(module, fromlist=(constants.CompileVars.APP,))
|
|
|
|
+ if not config.app_module
|
|
|
|
+ else config.app_module
|
|
|
|
+ )
|
|
if reload:
|
|
if reload:
|
|
from reflex.state import reload_state_module
|
|
from reflex.state import reload_state_module
|
|
|
|
|
|
@@ -308,6 +322,29 @@ def get_app(reload: bool = False) -> ModuleType:
|
|
raise
|
|
raise
|
|
|
|
|
|
|
|
|
|
|
|
+def get_and_validate_app(reload: bool = False) -> AppInfo:
|
|
|
|
+ """Get the app instance based on the default config and validate it.
|
|
|
|
+
|
|
|
|
+ Args:
|
|
|
|
+ reload: Re-import the app module from disk
|
|
|
|
+
|
|
|
|
+ Returns:
|
|
|
|
+ The app instance and the app module.
|
|
|
|
+
|
|
|
|
+ Raises:
|
|
|
|
+ RuntimeError: If the app instance is not an instance of rx.App.
|
|
|
|
+ """
|
|
|
|
+ from reflex.app import App
|
|
|
|
+
|
|
|
|
+ app_module = get_app(reload=reload)
|
|
|
|
+ app = getattr(app_module, constants.CompileVars.APP)
|
|
|
|
+ if not isinstance(app, App):
|
|
|
|
+ raise RuntimeError(
|
|
|
|
+ "The app instance in the specified app_module_import in rxconfig must be an instance of rx.App."
|
|
|
|
+ )
|
|
|
|
+ return AppInfo(app=app, module=app_module)
|
|
|
|
+
|
|
|
|
+
|
|
def get_compiled_app(reload: bool = False, export: bool = False) -> ModuleType:
|
|
def get_compiled_app(reload: bool = False, export: bool = False) -> ModuleType:
|
|
"""Get the app module based on the default config after first compiling it.
|
|
"""Get the app module based on the default config after first compiling it.
|
|
|
|
|
|
@@ -318,8 +355,7 @@ def get_compiled_app(reload: bool = False, export: bool = False) -> ModuleType:
|
|
Returns:
|
|
Returns:
|
|
The compiled app based on the default config.
|
|
The compiled app based on the default config.
|
|
"""
|
|
"""
|
|
- app_module = get_app(reload=reload)
|
|
|
|
- app = getattr(app_module, constants.CompileVars.APP)
|
|
|
|
|
|
+ app, app_module = get_and_validate_app(reload=reload)
|
|
# For py3.9 compatibility when redis is used, we MUST add any decorator pages
|
|
# For py3.9 compatibility when redis is used, we MUST add any decorator pages
|
|
# before compiling the app in a thread to avoid event loop error (REF-2172).
|
|
# before compiling the app in a thread to avoid event loop error (REF-2172).
|
|
app._apply_decorated_pages()
|
|
app._apply_decorated_pages()
|