apps should no longer call "app.compile()" (#2291)
This commit is contained in:
parent
3c07537c11
commit
7388617b72
@ -123,7 +123,6 @@ def index():
|
||||
# Add state and page to the app.
|
||||
app = rx.App()
|
||||
app.add_page(index, title="reflex:DALL·E")
|
||||
app.compile()
|
||||
```
|
||||
|
||||
## Let's break this down.
|
||||
|
@ -121,7 +121,6 @@ def index():
|
||||
# Add state and page to the app.
|
||||
app = rx.App()
|
||||
app.add_page(index, title="reflex:DALL·E")
|
||||
app.compile()
|
||||
```
|
||||
|
||||
## 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
|
||||
app.add_page(index, title="DALL-E")
|
||||
app.compile()
|
||||
```
|
||||
|
||||
Puedes crear una aplicación multipágina añadiendo más páginas.
|
||||
|
@ -120,7 +120,6 @@ def index():
|
||||
# Add state and page to the app.
|
||||
app = rx.App()
|
||||
app.add_page(index, title="reflex:DALL·E")
|
||||
app.compile()
|
||||
```
|
||||
|
||||
## चलो इसे विस्तार से देखते हैं।
|
||||
@ -190,7 +189,6 @@ app = rx.App()
|
||||
|
||||
```python
|
||||
app.add_page(index, title="DALL-E")
|
||||
app.compile()
|
||||
```
|
||||
|
||||
आप और पेज जोड़कर एक मल्टी-पेज एप्लिकेशन बना सकते हैं।
|
||||
|
@ -121,7 +121,6 @@ def index():
|
||||
# Aggiungi stato e pagina all'app.
|
||||
app = rx.App()
|
||||
app.add_page(index, title="reflex:DALL·E")
|
||||
app.compile()
|
||||
```
|
||||
|
||||
## Analizziamolo
|
||||
@ -191,7 +190,6 @@ Possiamo aggiungere una pagina dalla radice dell'app al componente dell'indice.A
|
||||
|
||||
```python
|
||||
app.add_page(index, title="DALL-E")
|
||||
app.compile()
|
||||
```
|
||||
|
||||
Puoi creare un'app multi-pagina aggiungendo altre pagine.
|
||||
|
@ -121,7 +121,6 @@ def index():
|
||||
# Add state and page to the app.
|
||||
app = rx.App()
|
||||
app.add_page(index, title="reflex:DALL·E")
|
||||
app.compile()
|
||||
```
|
||||
|
||||
## 하나씩 살펴보겠습니다.
|
||||
@ -194,7 +193,6 @@ app = rx.App()
|
||||
|
||||
```python
|
||||
app.add_page(index, title="DALL-E")
|
||||
app.compile()
|
||||
```
|
||||
|
||||
여러 페이지를 추가하여 멀티 페이지 앱을 만들 수 있습니다.
|
||||
|
@ -121,7 +121,6 @@ def index():
|
||||
# Adição do estado e da página no app.
|
||||
app = rx.App()
|
||||
app.add_page(index, title="reflex:DALL·E")
|
||||
app.compile()
|
||||
```
|
||||
|
||||
## Vamos por partes.
|
||||
@ -192,7 +191,6 @@ Adicionamos uma página na raíz do app, apontando para o componente index. Tamb
|
||||
|
||||
```python
|
||||
app.add_page(index, title="DALL-E")
|
||||
app.compile()
|
||||
```
|
||||
|
||||
Você pode criar mais páginas e adicioná-las ao seu app.
|
||||
|
@ -124,7 +124,6 @@ def index():
|
||||
# Sayfa ve durumu uygulamaya ekleyin.
|
||||
app = rx.App()
|
||||
app.add_page(index, title="reflex:DALL·E")
|
||||
app.compile()
|
||||
```
|
||||
|
||||
## Daha Detaylı İceleyelim
|
||||
@ -194,7 +193,6 @@ Uygulamamızın kök dizinine index bileşeninden bir sayfa ekliyoruz. Ayrıca s
|
||||
|
||||
```python
|
||||
app.add_page(index, title="DALL-E")
|
||||
app.compile()
|
||||
```
|
||||
|
||||
Daha fazla sayfa ekleyerek çok sayfalı bir uygulama oluşturabilirsiniz.
|
||||
|
@ -122,7 +122,6 @@ def index():
|
||||
# Add state and page to the app.
|
||||
app = rx.App()
|
||||
app.add_page(index, title="reflex:DALL·E")
|
||||
app.compile()
|
||||
```
|
||||
|
||||
## 让我们分解以上步骤.
|
||||
@ -194,7 +193,6 @@ app = rx.App()
|
||||
|
||||
```python
|
||||
app.add_page(index, title="DALL-E")
|
||||
app.compile()
|
||||
```
|
||||
|
||||
您可以通过增加更多页面来创建一个多页面的应用.
|
||||
|
@ -121,7 +121,6 @@ def index():
|
||||
# 把狀態跟頁面添加到應用程式。
|
||||
app = rx.App()
|
||||
app.add_page(index, title="reflex:DALL·E")
|
||||
app.compile()
|
||||
```
|
||||
|
||||
## 讓我們來拆解一下。
|
||||
@ -192,7 +191,6 @@ app = rx.App()
|
||||
|
||||
```python
|
||||
app.add_page(index, title="DALL-E")
|
||||
app.compile()
|
||||
```
|
||||
|
||||
你可以添加更多頁面至路由藉此來建立多頁面應用程式(multi-page app)
|
||||
|
@ -95,7 +95,6 @@ def BackgroundTask():
|
||||
|
||||
app = rx.App(state=rx.State)
|
||||
app.add_page(index)
|
||||
app.compile()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
|
@ -227,8 +227,6 @@ def CallScript():
|
||||
rx.button("Reset", id="reset", on_click=CallScriptState.reset_),
|
||||
)
|
||||
|
||||
app.compile()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def call_script(tmp_path_factory) -> Generator[AppHarness, None, None]:
|
||||
|
@ -100,7 +100,6 @@ def ClientSide():
|
||||
app = rx.App(state=rx.State)
|
||||
app.add_page(index)
|
||||
app.add_page(index, route="/foo")
|
||||
app.compile()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
|
@ -21,7 +21,6 @@ def ConnectionBanner():
|
||||
|
||||
app = rx.App(state=rx.State)
|
||||
app.add_page(index)
|
||||
app.compile()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
|
@ -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="/static/x", 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")
|
||||
|
@ -132,7 +132,6 @@ def TestEventAction():
|
||||
|
||||
app = rx.App(state=rx.State)
|
||||
app.add_page(index)
|
||||
app.compile()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
|
@ -242,8 +242,6 @@ def EventChain():
|
||||
app.add_page(on_mount_return_chain)
|
||||
app.add_page(on_mount_yield_chain)
|
||||
|
||||
app.compile()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def event_chain(tmp_path_factory) -> Generator[AppHarness, None, None]:
|
||||
|
@ -62,8 +62,6 @@ def FormSubmit():
|
||||
height="100vh",
|
||||
)
|
||||
|
||||
app.compile()
|
||||
|
||||
|
||||
def FormSubmitName():
|
||||
"""App with a form using on_submit."""
|
||||
@ -124,8 +122,6 @@ def FormSubmitName():
|
||||
height="100vh",
|
||||
)
|
||||
|
||||
app.compile()
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
scope="session", params=[FormSubmit, FormSubmitName], ids=["id", "name"]
|
||||
|
@ -40,8 +40,6 @@ def FullyControlledInput():
|
||||
rx.button("CLEAR", on_click=rx.set_value("on_change_input", "")),
|
||||
)
|
||||
|
||||
app.compile()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def fully_controlled_input(tmp_path) -> Generator[AppHarness, None, None]:
|
||||
|
@ -45,7 +45,6 @@ def LoginSample():
|
||||
app = rx.App(state=rx.State)
|
||||
app.add_page(index)
|
||||
app.add_page(login)
|
||||
app.compile()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
|
@ -75,8 +75,6 @@ def ServerSideEvent():
|
||||
),
|
||||
)
|
||||
|
||||
app.compile()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def server_side_event(tmp_path_factory) -> Generator[AppHarness, None, None]:
|
||||
|
@ -88,8 +88,6 @@ def Table():
|
||||
)
|
||||
)
|
||||
|
||||
app.compile()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def table(tmp_path_factory) -> Generator[AppHarness, None, None]:
|
||||
|
@ -115,7 +115,6 @@ def UploadFile():
|
||||
|
||||
app = rx.App(state=rx.State)
|
||||
app.add_page(index)
|
||||
app.compile()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
|
@ -565,8 +565,6 @@ def VarOperations():
|
||||
),
|
||||
)
|
||||
|
||||
app.compile()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def var_operations(tmp_path_factory) -> Generator[AppHarness, None, None]:
|
||||
|
@ -619,6 +619,19 @@ class App(Base):
|
||||
return True
|
||||
|
||||
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."""
|
||||
# add the pages before the compile check so App know onload methods
|
||||
for render, kwargs in DECORATED_PAGES:
|
||||
|
@ -120,6 +120,7 @@ class App(Base):
|
||||
def setup_admin_dash(self) -> None: ...
|
||||
def get_frontend_packages(self, imports: Dict[str, str]): ...
|
||||
def compile(self) -> None: ...
|
||||
def compile_(self) -> None: ...
|
||||
def modify_state(self, token: str) -> AsyncContextManager[State]: ...
|
||||
def _process_background(
|
||||
self, state: State, event: Event
|
||||
|
13
reflex/app_module_for_backend.py
Normal file
13
reflex/app_module_for_backend.py
Normal file
@ -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
|
@ -178,7 +178,7 @@ def _run(
|
||||
if frontend:
|
||||
prerequisites.update_next_config()
|
||||
# Get the app module.
|
||||
prerequisites.get_app()
|
||||
prerequisites.get_compiled_app()
|
||||
|
||||
# Warn if schema is not up to date.
|
||||
prerequisites.check_schema_up_to_date()
|
||||
@ -362,7 +362,7 @@ def db_init():
|
||||
|
||||
# Initialize the database.
|
||||
_skip_compile()
|
||||
prerequisites.get_app()
|
||||
prerequisites.get_compiled_app()
|
||||
model.Model.alembic_init()
|
||||
model.Model.migrate(autogenerate=True)
|
||||
|
||||
@ -373,8 +373,9 @@ def migrate():
|
||||
from reflex import model
|
||||
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()
|
||||
prerequisites.get_app()
|
||||
prerequisites.get_compiled_app()
|
||||
if not prerequisites.check_db_initialized():
|
||||
return
|
||||
model.Model.migrate()
|
||||
@ -393,8 +394,9 @@ def makemigrations(
|
||||
from reflex import model
|
||||
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()
|
||||
prerequisites.get_app()
|
||||
prerequisites.get_compiled_app()
|
||||
if not prerequisites.check_db_initialized():
|
||||
return
|
||||
with model.Model.get_db_engine().connect() as connection:
|
||||
|
@ -1316,6 +1316,7 @@ class State(BaseState):
|
||||
Returns:
|
||||
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)
|
||||
load_events = app.get_load_events(self.router.page.path)
|
||||
if not load_events and self.is_hydrated:
|
||||
@ -1364,6 +1365,7 @@ class StateProxy(wrapt.ObjectProxy):
|
||||
state_instance: The state instance to proxy.
|
||||
"""
|
||||
super().__init__(state_instance)
|
||||
# compile is not relevant to backend logic
|
||||
self._self_app = getattr(prerequisites.get_app(), constants.CompileVars.APP)
|
||||
self._self_substate_path = state_instance.get_full_name().split(".")
|
||||
self._self_actx = None
|
||||
|
@ -165,7 +165,7 @@ class AppHarness:
|
||||
# reset rx.State subclasses
|
||||
State.class_subclasses.clear()
|
||||
# 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
|
||||
if isinstance(self.app_instance.state_manager, StateManagerRedis):
|
||||
# Create our own redis connection for testing.
|
||||
|
@ -160,7 +160,7 @@ def run_backend(
|
||||
import uvicorn
|
||||
|
||||
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.
|
||||
if os.path.exists(constants.Dirs.WEB):
|
||||
@ -196,7 +196,7 @@ def run_backend_prod(
|
||||
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_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 = (
|
||||
[
|
||||
*RUN_BACKEND_PROD_WINDOWS,
|
||||
|
@ -56,7 +56,7 @@ def export(
|
||||
# Update some parameters for export
|
||||
prerequisites.update_next_config(export=True)
|
||||
# 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.
|
||||
build.setup_frontend(Path.cwd())
|
||||
|
||||
|
@ -160,9 +160,24 @@ def get_app(reload: bool = False) -> ModuleType:
|
||||
app = __import__(module, fromlist=(constants.CompileVars.APP,))
|
||||
if reload:
|
||||
importlib.reload(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:
|
||||
"""Get the redis client.
|
||||
|
||||
|
@ -1213,7 +1213,7 @@ def test_app_wrap_compile_theme(compilable_app):
|
||||
"""
|
||||
app, web_dir = compilable_app
|
||||
app.theme = rdxt.theme(accent_color="plum")
|
||||
app.compile()
|
||||
app.compile_()
|
||||
app_js_contents = (web_dir / "pages" / "_app.js").read_text()
|
||||
app_js_lines = [
|
||||
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())
|
||||
|
||||
app.add_page(page)
|
||||
app.compile()
|
||||
app.compile_()
|
||||
app_js_contents = (web_dir / "pages" / "_app.js").read_text()
|
||||
app_js_lines = [
|
||||
line.strip() for line in app_js_contents.splitlines() if line.strip()
|
||||
|
@ -1590,7 +1590,11 @@ def mock_app(monkeypatch, state_manager: StateManager) -> rx.App:
|
||||
app.state = TestState
|
||||
app._state_manager = state_manager
|
||||
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
|
||||
|
||||
|
||||
|
@ -21,7 +21,7 @@ def test_app_harness(tmp_path):
|
||||
|
||||
app = rx.App(state=State)
|
||||
app.add_page(lambda: rx.text("Basic App"), route="/", title="index")
|
||||
app.compile()
|
||||
app.compile_()
|
||||
|
||||
with AppHarness.create(
|
||||
root=tmp_path,
|
||||
|
Loading…
Reference in New Issue
Block a user