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