Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ dependencies = [
"python-socketio >=5.7.0,<6.0",
"redis >=4.3.5,<6.0",
"reflex-hosting-cli >=0.1.29",
"rich >=13.0.0,<14.0",
"setuptools >=75.0",
"starlette-admin >=0.11.0,<1.0",
"sqlmodel >=0.0.14,<0.1",
Expand Down
76 changes: 49 additions & 27 deletions reflex/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
from fastapi.middleware import cors
from fastapi.responses import JSONResponse, StreamingResponse
from fastapi.staticfiles import StaticFiles
from rich.progress import MofNCompleteColumn, Progress, TimeElapsedColumn
from socketio import ASGIApp, AsyncNamespace, AsyncServer
from starlette.datastructures import Headers
from starlette.datastructures import UploadFile as StarletteUploadFile
Expand Down Expand Up @@ -110,6 +109,14 @@
)
from reflex.utils.exec import get_compile_context, is_prod_mode, is_testing_env
from reflex.utils.imports import ImportVar
from reflex.utils.progress import (
CounterComponent,
MessageComponent,
ProgressBar,
SimpleProgressComponent,
TimeComponent,
)
from reflex.utils.terminal import colored

if TYPE_CHECKING:
from reflex.vars import Var
Expand Down Expand Up @@ -1122,23 +1129,38 @@ def get_compilation_time() -> str:

return

# Create a progress bar.
progress = Progress(
*Progress.get_default_columns()[:-1],
MofNCompleteColumn(),
TimeElapsedColumn(),
)

# try to be somewhat accurate - but still not 100%
adhoc_steps_without_executor = 7
fixed_pages_within_executor = 5
progress.start()
task = progress.add_task(
f"[{get_compilation_time()}] Compiling:",
total=len(self._pages)
+ (len(self._unevaluated_pages) * 2)
+ fixed_pages_within_executor
+ adhoc_steps_without_executor,

# Create a progress bar.
progress = ProgressBar(
steps=(
len(self._pages)
+ (len(self._unevaluated_pages) * 2)
+ fixed_pages_within_executor
+ adhoc_steps_without_executor
),
components=(
(
MessageComponent(
message=colored(f"[{get_compilation_time()}]", "cyan")
+ " Compiling:",
),
0,
),
(
SimpleProgressComponent(
colorer=lambda x: colored(x, "light_green")
),
2,
),
(
CounterComponent(colorer=lambda x: colored(x, "green")),
1,
),
(TimeComponent(colorer=lambda x: colored(x, "yellow")), 3),
),
)

with console.timing("Evaluate Pages (Frontend)"):
Expand All @@ -1149,7 +1171,7 @@ def get_compilation_time() -> str:
self._compile_page(route, save_page=should_compile)
end = timer()
performance_metrics.append((route, end - start))
progress.advance(task)
progress.update(1)
console.debug(
"Slowest pages:\n"
+ "\n".join(
Expand Down Expand Up @@ -1180,12 +1202,12 @@ def get_compilation_time() -> str:
if is_prod_mode() and config.show_built_with_reflex:
self._setup_sticky_badge()

progress.advance(task)
progress.update(1)

# Store the compile results.
compile_results: list[tuple[str, str]] = []

progress.advance(task)
progress.update(1)

# Track imports and custom components found.
all_imports = {}
Expand Down Expand Up @@ -1239,7 +1261,7 @@ def memoized_toast_provider():
stateful_components_code,
page_components,
) = compiler.compile_stateful_components(self._pages.values())
progress.advance(task)
progress.update(1)

# Catch "static" apps (that do not define a rx.State subclass) which are trying to access rx.State.
if code_uses_state_contexts(stateful_components_code) and self._state is None:
Expand All @@ -1249,7 +1271,7 @@ def memoized_toast_provider():
)
compile_results.append((stateful_components_path, stateful_components_code))

progress.advance(task)
progress.update(1)

# Compile the root document before fork.
compile_results.append(
Expand All @@ -1262,7 +1284,7 @@ def memoized_toast_provider():
)
)

progress.advance(task)
progress.update(1)

# Copy the assets.
assets_src = Path.cwd() / constants.Dirs.APP_ASSETS
Expand All @@ -1287,7 +1309,7 @@ def memoized_toast_provider():

def _submit_work(fn: Callable[..., tuple[str, str]], *args, **kwargs):
f = executor.submit(fn, *args, **kwargs)
f.add_done_callback(lambda _: progress.advance(task))
f.add_done_callback(lambda _: progress.update(1))
result_futures.append(f)

# Compile the pre-compiled pages.
Expand Down Expand Up @@ -1323,7 +1345,7 @@ def _submit_work(fn: Callable[..., tuple[str, str]], *args, **kwargs):
# Get imports from AppWrap components.
all_imports.update(app_root._get_all_imports())

progress.advance(task)
progress.update(1)

# Compile the contexts.
compile_results.append(
Expand All @@ -1332,13 +1354,13 @@ def _submit_work(fn: Callable[..., tuple[str, str]], *args, **kwargs):
if self.theme is not None:
# Fix #2992 by removing the top-level appearance prop
self.theme.appearance = None
progress.advance(task)
progress.update(1)

# Compile the app root.
compile_results.append(
compiler.compile_app(app_root),
)
progress.advance(task)
progress.update(1)

# Compile custom components.
(
Expand All @@ -1349,8 +1371,8 @@ def _submit_work(fn: Callable[..., tuple[str, str]], *args, **kwargs):
compile_results.append((custom_components_output, custom_components_result))
all_imports.update(custom_components_imports)

progress.advance(task)
progress.stop()
progress.update(1)
progress.finish()

# Install frontend packages.
with console.timing("Install Frontend Packages"):
Expand Down
20 changes: 10 additions & 10 deletions reflex/custom_components/custom_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ def init(
# Check the name follows the convention if picked.
name_variants = _validate_library_name(library_name)

console.rule(f"[bold]Initializing {name_variants.package_name} project")
console.rule(f"Initializing {name_variants.package_name} project")

_populate_custom_component_project(name_variants)

Expand All @@ -351,25 +351,25 @@ def init(

if install:
package_name = name_variants.package_name
console.rule(f"[bold]Installing {package_name} in editable mode.")
console.rule(f"Installing {package_name} in editable mode.")
if _pip_install_on_demand(package_name=".", install_args=["-e"]):
console.info(f"Package {package_name} installed!")
else:
raise typer.Exit(code=1)

console.print("[bold]Custom component initialized successfully!")
console.rule("[bold]Project Summary")
console.success("Custom component initialized successfully!", bold=True)
console.rule("Project Summary")
console.print(
f"[ {CustomComponents.PACKAGE_README} ]: Package description. Please add usage examples."
f"[{CustomComponents.PACKAGE_README}]: Package description. Please add usage examples."
)
console.print(
f"[ {CustomComponents.PYPROJECT_TOML} ]: Project configuration file. Please fill in details such as your name, email, homepage URL."
f"[{CustomComponents.PYPROJECT_TOML}]: Project configuration file. Please fill in details such as your name, email, homepage URL."
)
console.print(
f"[ {CustomComponents.SRC_DIR}/ ]: Custom component code template. Start by editing it with your component implementation."
f"[{CustomComponents.SRC_DIR}/]: Custom component code template. Start by editing it with your component implementation."
)
console.print(
f"[ {name_variants.demo_app_dir}/ ]: Demo App. Add more code to this app and test."
f"[{name_variants.demo_app_dir}/]: Demo App. Add more code to this app and test."
)


Expand Down Expand Up @@ -829,7 +829,7 @@ def _collect_details_for_gallery():
import reflex_cli.constants
from reflex_cli.utils import hosting

console.rule("[bold]Authentication with Reflex Services")
console.rule("Authentication with Reflex Services")
console.print("First let's log in to Reflex backend services.")
access_token, _ = hosting.authenticated_token()

Expand All @@ -839,7 +839,7 @@ def _collect_details_for_gallery():
)
raise typer.Exit(code=1)

console.rule("[bold]Custom Component Information")
console.rule("Custom Component Information")
params = {}
package_name = None
try:
Expand Down
11 changes: 9 additions & 2 deletions reflex/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from reflex.config import environment, get_config
from reflex.utils import console
from reflex.utils.compat import sqlmodel, sqlmodel_field_has_primary_key
from reflex.utils.terminal import colored

_ENGINE: dict[str, sqlalchemy.engine.Engine] = {}
_ASYNC_ENGINE: dict[str, sqlalchemy.ext.asyncio.AsyncEngine] = {}
Expand Down Expand Up @@ -91,7 +92,10 @@ def get_engine(url: str | None = None) -> sqlalchemy.engine.Engine:

if not environment.ALEMBIC_CONFIG.get().exists():
console.warn(
"Database is not initialized, run [bold]reflex db init[/bold] first."
colored("Database is not initialized, run ", "warning")
+ colored("reflex db init", "warning", attrs=("bold",))
+ colored(" first.", "warning"),
color=None,
)
_ENGINE[url] = sqlmodel.create_engine(
url,
Expand Down Expand Up @@ -133,7 +137,10 @@ def get_async_engine(url: str | None) -> sqlalchemy.ext.asyncio.AsyncEngine:

if not environment.ALEMBIC_CONFIG.get().exists():
console.warn(
"Database is not initialized, run [bold]reflex db init[/bold] first."
colored("Database is not initialized, run ", "warning")
+ colored("reflex db init", "warning", attrs=("bold",))
+ colored(" first.", "warning"),
color=None,
)
_ASYNC_ENGINE[url] = sqlalchemy.ext.asyncio.create_async_engine(
url,
Expand Down
20 changes: 13 additions & 7 deletions reflex/reflex.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from reflex.state import reset_disk_state_manager
from reflex.utils import console, redir, telemetry
from reflex.utils.exec import should_use_granian
from reflex.utils.terminal import colored

# Disable typer+rich integration for help panels
typer.core.rich = None # pyright: ignore [reportPrivateImportUsage]
Expand Down Expand Up @@ -79,7 +80,7 @@ def _init(

# Validate the app name.
app_name = prerequisites.validate_app_name(name)
console.rule(f"[bold]Initializing {app_name}")
console.rule(f"Initializing {app_name}")

# Check prerequisites.
prerequisites.check_latest_package_version(constants.Reflex.MODULE_NAME)
Expand Down Expand Up @@ -200,7 +201,7 @@ def _run(
# Reload the config to make sure the env vars are persistent.
get_config(reload=True)

console.rule("[bold]Starting Reflex App")
console.rule("Starting Reflex App")

prerequisites.check_latest_package_version(constants.Reflex.MODULE_NAME)

Expand Down Expand Up @@ -457,10 +458,12 @@ def db_init():
# Check the alembic config.
if environment.ALEMBIC_CONFIG.get().exists():
console.error(
"Database is already initialized. Use "
"[bold]reflex db makemigrations[/bold] to create schema change "
"scripts and [bold]reflex db migrate[/bold] to apply migrations "
"to a new or existing database.",
colored("Database is already initialized. Use ", "error")
+ colored("reflex db makemigrations", "error", attrs=("bold",))
+ colored(" to create schema change scripts and ", "error")
+ colored("reflex db migrate", "error", attrs=("bold",))
+ colored(" to apply migrations to a new or existing database.", "error"),
color=None,
)
return

Expand Down Expand Up @@ -510,7 +513,10 @@ def makemigrations(
if "Target database is not up to date." not in str(command_error):
raise
console.error(
f"{command_error} Run [bold]reflex db migrate[/bold] to update database."
colored(f"{command_error} Run ", "error")
+ colored("reflex db migrate", "error", attrs=("bold",))
+ colored(" to update database.", "error"),
color=None,
)


Expand Down
4 changes: 2 additions & 2 deletions reflex/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -3564,7 +3564,7 @@ async def _get_pubsub_message(
if timeout is None:
timeout = self.lock_expiration / 1000.0

started = time.time()
started = time.monotonic()
message = await pubsub.get_message(
ignore_subscribe_messages=True,
timeout=timeout,
Expand All @@ -3573,7 +3573,7 @@ async def _get_pubsub_message(
message is None
or message["data"] not in self._redis_keyspace_lock_release_events
):
remaining = timeout - (time.time() - started)
remaining = timeout - (time.monotonic() - started)
if remaining <= 0:
return
await self._get_pubsub_message(pubsub, timeout=remaining)
Expand Down
8 changes: 4 additions & 4 deletions reflex/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -525,8 +525,8 @@ def _poll_for(
timeout = DEFAULT_TIMEOUT
if step is None:
step = POLL_INTERVAL
deadline = time.time() + timeout
while time.time() < deadline:
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
success = target()
if success:
return success
Expand Down Expand Up @@ -554,8 +554,8 @@ async def _poll_for_async(
timeout = DEFAULT_TIMEOUT
if step is None:
step = POLL_INTERVAL
deadline = time.time() + timeout
while time.time() < deadline:
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
success = await target()
if success:
return success
Expand Down
16 changes: 2 additions & 14 deletions reflex/utils/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
import zipfile
from pathlib import Path

from rich.progress import MofNCompleteColumn, Progress, TimeElapsedColumn

from reflex import constants
from reflex.config import get_config
from reflex.utils import console, path_ops, prerequisites, processes
Expand Down Expand Up @@ -114,19 +112,9 @@ def _zip(
]

# Create a progress bar for zipping the component.
progress = Progress(
*Progress.get_default_columns()[:-1],
MofNCompleteColumn(),
TimeElapsedColumn(),
)
task = progress.add_task(
f"Zipping {component_name.value}:", total=len(files_to_zip)
)

with progress, zipfile.ZipFile(target, "w", zipfile.ZIP_DEFLATED) as zipf:
console.info(f"Zipping {component_name.value} to {target}")
with zipfile.ZipFile(target, "w", zipfile.ZIP_DEFLATED) as zipf:
for file in files_to_zip:
console.debug(f"{target}: {file}", progress=progress)
progress.advance(task)
zipf.write(file, Path(file).relative_to(root_dir))


Expand Down
Loading