reorder page evaluation
This commit is contained in:
parent
7dda611364
commit
c9f7ddd4d0
102
reflex/app.py
102
reflex/app.py
@ -9,6 +9,7 @@ import dataclasses
|
||||
import functools
|
||||
import inspect
|
||||
import io
|
||||
import dill
|
||||
import multiprocess
|
||||
from pathos import multiprocessing, pools
|
||||
import os
|
||||
@ -47,7 +48,10 @@ from reflex.app_mixins import AppMixin, LifespanMixin, MiddlewareMixin
|
||||
from reflex.base import Base
|
||||
from reflex.compiler import compiler
|
||||
from reflex.compiler import utils as compiler_utils
|
||||
from reflex.compiler.compiler import ExecutorSafeFunctions
|
||||
from reflex.compiler.compiler import (
|
||||
ExecutorSafeFunctions,
|
||||
compile_uncompiled_page_helper,
|
||||
)
|
||||
from reflex.components.base.app_wrap import AppWrap
|
||||
from reflex.components.base.error_boundary import ErrorBoundary
|
||||
from reflex.components.base.fragment import Fragment
|
||||
@ -554,49 +558,8 @@ class App(MiddlewareMixin, LifespanMixin, Base):
|
||||
Args:
|
||||
route: The route of the page to compile.
|
||||
"""
|
||||
uncompiled_page = self.uncompiled_pages[route]
|
||||
|
||||
on_load = uncompiled_page.on_load
|
||||
|
||||
# Generate the component if it is a callable.
|
||||
component = self._generate_component(uncompiled_page.component)
|
||||
|
||||
# unpack components that return tuples in an rx.fragment.
|
||||
if isinstance(component, tuple):
|
||||
component = Fragment.create(*component)
|
||||
|
||||
# Ensure state is enabled if this page uses state.
|
||||
if self.state is None:
|
||||
if on_load or component._has_stateful_event_triggers():
|
||||
self._enable_state()
|
||||
else:
|
||||
for var in component._get_vars(include_children=True):
|
||||
if not var._var_data:
|
||||
continue
|
||||
if not var._var_data.state:
|
||||
continue
|
||||
self._enable_state()
|
||||
break
|
||||
|
||||
component = OverlayFragment.create(component)
|
||||
|
||||
meta_args = {
|
||||
"title": (
|
||||
uncompiled_page.title
|
||||
if uncompiled_page.title is not None
|
||||
else format.make_default_page_title(get_config().app_name, route)
|
||||
),
|
||||
"image": uncompiled_page.image,
|
||||
"meta": uncompiled_page.meta,
|
||||
}
|
||||
|
||||
if uncompiled_page.description is not None:
|
||||
meta_args["description"] = uncompiled_page.description
|
||||
|
||||
# Add meta information to the component.
|
||||
compiler_utils.add_meta(
|
||||
component,
|
||||
**meta_args,
|
||||
component = compiler.compile_uncompiled_page_helper(
|
||||
route, self.uncompiled_pages[route]
|
||||
)
|
||||
|
||||
# Add the page.
|
||||
@ -892,6 +855,10 @@ class App(MiddlewareMixin, LifespanMixin, Base):
|
||||
self._add_optional_endpoints()
|
||||
|
||||
if not self._should_compile():
|
||||
for route in self.uncompiled_pages:
|
||||
if route in self.pages:
|
||||
continue
|
||||
self._compile_page(route)
|
||||
return
|
||||
|
||||
self._validate_var_dependencies()
|
||||
@ -957,11 +924,6 @@ class App(MiddlewareMixin, LifespanMixin, Base):
|
||||
|
||||
progress.advance(task)
|
||||
|
||||
for route, uncompiled_page in self.uncompiled_pages.items():
|
||||
ExecutorSafeFunctions.UNCOMPILED_PAGES[route] = uncompiled_page
|
||||
|
||||
ExecutorSafeFunctions.STYLE = self.style
|
||||
|
||||
# Use a forking process pool, if possible. Much faster, especially for large sites.
|
||||
# Fallback to ThreadPoolExecutor as something that will always work.
|
||||
executor = None
|
||||
@ -969,6 +931,9 @@ class App(MiddlewareMixin, LifespanMixin, Base):
|
||||
platform.system() in ("Linux", "Darwin")
|
||||
and os.environ.get("REFLEX_COMPILE_PROCESSES") is not None
|
||||
):
|
||||
for route in self.uncompiled_pages:
|
||||
self._compile_page(route)
|
||||
|
||||
executor = pools.ProcessPool()
|
||||
else:
|
||||
executor = pools.ThreadPool()
|
||||
@ -979,27 +944,40 @@ class App(MiddlewareMixin, LifespanMixin, Base):
|
||||
result_futures = []
|
||||
pages_futures = []
|
||||
|
||||
# def _mark_complete(_=None):
|
||||
# progress.advance(task)
|
||||
|
||||
def _submit_work(fn, *args, **kwargs):
|
||||
f = executor.apipe(fn, *args, **kwargs)
|
||||
# f.add_done_callback(_mark_complete)
|
||||
result_futures.append(f)
|
||||
|
||||
# Compile all page components.
|
||||
for route in self.uncompiled_pages:
|
||||
for route, page in self.uncompiled_pages.items():
|
||||
if route in self.pages:
|
||||
continue
|
||||
|
||||
f = executor.apipe(
|
||||
ExecutorSafeFunctions.compile_uncompiled_page, route
|
||||
ExecutorSafeFunctions.compile_uncompiled_page,
|
||||
route,
|
||||
page,
|
||||
self.state,
|
||||
self.style,
|
||||
self.theme,
|
||||
)
|
||||
# f.add_done_callback(_mark_complete)
|
||||
pages_futures.append((route, f))
|
||||
|
||||
# Compile the pre-compiled pages.
|
||||
for route, component in self.pages.items():
|
||||
component._add_style_recursive(self.style, self.theme)
|
||||
_submit_work(
|
||||
ExecutorSafeFunctions.compile_page,
|
||||
route,
|
||||
component,
|
||||
self.state,
|
||||
)
|
||||
|
||||
# Compile the root stylesheet with base styles.
|
||||
_submit_work(compiler.compile_root_stylesheet, self.stylesheets)
|
||||
|
||||
# Compile the theme.
|
||||
_submit_work(ExecutorSafeFunctions.compile_theme)
|
||||
_submit_work(ExecutorSafeFunctions.compile_theme, self.style)
|
||||
|
||||
# Compile the Tailwind config.
|
||||
if config.tailwind is not None:
|
||||
@ -1013,18 +991,18 @@ class App(MiddlewareMixin, LifespanMixin, Base):
|
||||
# Wait for all compilation tasks to complete.
|
||||
for future in result_futures:
|
||||
compile_results.append(future.get())
|
||||
progress.advance(task)
|
||||
|
||||
for route, future in pages_futures:
|
||||
print(f"Compiled {route}")
|
||||
pages_results.append(future.get())
|
||||
progress.advance(task)
|
||||
|
||||
for route, component, compiled_page in pages_results:
|
||||
self.pages[compiled_page] = component
|
||||
self._check_routes_conflict(route)
|
||||
self.pages[route] = component
|
||||
compile_results.append(compiled_page)
|
||||
|
||||
# Merge the component style with the app style.
|
||||
component._add_style_recursive(self.style, self.theme)
|
||||
|
||||
for route, component in self.pages.items():
|
||||
# Add component._get_all_imports() to all_imports.
|
||||
all_imports.update(component._get_all_imports())
|
||||
|
||||
|
@ -517,9 +517,7 @@ if TYPE_CHECKING:
|
||||
from reflex.event import EventHandler, EventSpec
|
||||
|
||||
|
||||
def compile_uncompiled_page(
|
||||
route: str, page: UncompiledPage
|
||||
) -> tuple[EventHandler | EventSpec | list[EventHandler | EventSpec] | None, Fragment]:
|
||||
def compile_uncompiled_page_helper(route: str, page: UncompiledPage) -> Component:
|
||||
"""Compiles an uncompiled page into a component and adds meta information.
|
||||
|
||||
Args:
|
||||
@ -527,7 +525,7 @@ def compile_uncompiled_page(
|
||||
page (UncompiledPage): The uncompiled page object.
|
||||
|
||||
Returns:
|
||||
tuple[EventHandler | EventSpec | list[EventHandler | EventSpec] | None, Fragment]: The on_load event handler or spec, and the compiled component.
|
||||
Component: The compiled component.
|
||||
"""
|
||||
# Generate the component if it is a callable.
|
||||
component = page.component
|
||||
@ -589,13 +587,10 @@ class ExecutorSafeFunctions:
|
||||
|
||||
"""
|
||||
|
||||
UNCOMPILED_PAGES = {}
|
||||
COMPILED_COMPONENTS = {}
|
||||
STATE: Type[BaseState] | None = None
|
||||
STYLE: ComponentStyle | None = None
|
||||
|
||||
@classmethod
|
||||
def compile_page(cls, route: str):
|
||||
def compile_page(
|
||||
cls, route: str, component: Component, state: Type[BaseState]
|
||||
) -> tuple[str, str]:
|
||||
"""Compile a page.
|
||||
|
||||
Args:
|
||||
@ -604,10 +599,17 @@ class ExecutorSafeFunctions:
|
||||
Returns:
|
||||
The path and code of the compiled page.
|
||||
"""
|
||||
return compile_page(route, cls.COMPILED_COMPONENTS[route], cls.STATE)
|
||||
return compile_page(route, component, state)
|
||||
|
||||
@classmethod
|
||||
def compile_uncompiled_page(cls, route: str):
|
||||
def compile_uncompiled_page(
|
||||
cls,
|
||||
route: str,
|
||||
page: UncompiledPage,
|
||||
state: Type[BaseState],
|
||||
style: ComponentStyle,
|
||||
theme: Component,
|
||||
) -> tuple[str, Component, tuple[str, str]]:
|
||||
"""Compile an uncompiled page.
|
||||
|
||||
Args:
|
||||
@ -616,12 +618,13 @@ class ExecutorSafeFunctions:
|
||||
Returns:
|
||||
The path and code of the compiled page.
|
||||
"""
|
||||
component = compile_uncompiled_page(route, cls.UNCOMPILED_PAGES[route])
|
||||
component = compile_uncompiled_page_helper(route, page)
|
||||
component = component if isinstance(component, Component) else component()
|
||||
return route, component, compile_page(route, component, cls.STATE)
|
||||
component._add_style_recursive(style, theme)
|
||||
return route, component, compile_page(route, component, state)
|
||||
|
||||
@classmethod
|
||||
def compile_theme(cls):
|
||||
def compile_theme(cls, style: ComponentStyle | None) -> tuple[str, str]:
|
||||
"""Compile the theme.
|
||||
|
||||
Returns:
|
||||
@ -630,6 +633,6 @@ class ExecutorSafeFunctions:
|
||||
Raises:
|
||||
ValueError: If the style is not set.
|
||||
"""
|
||||
if cls.STYLE is None:
|
||||
if style is None:
|
||||
raise ValueError("STYLE should be set")
|
||||
return compile_theme(cls.STYLE)
|
||||
return compile_theme(style)
|
||||
|
Loading…
Reference in New Issue
Block a user