Skip to content

Commit c99b450

Browse files
typing improvements and cleanup
1 parent de1804a commit c99b450

6 files changed

Lines changed: 142 additions & 162 deletions

File tree

packages/reflex-base/src/reflex_base/compiler/templates.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,6 @@ def context_template(
281281
UpdateVarsInternalState,
282282
)
283283

284-
# Compute dynamic state names that respect minification settings
285284
main_state_name = State.get_name()
286285
on_load_internal = format_event_handler(OnLoadInternalState.on_load_internal)
287286
update_vars_internal = format_event_handler(

packages/reflex-base/src/reflex_base/constants/compiler.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,18 +67,6 @@ class CompileVars(SimpleNamespace):
6767
CONNECT_ERROR = "connectErrors"
6868
# The name of the function for converting a dict to an event.
6969
TO_EVENT = "ReflexEvent"
70-
# The name of the internal on_load event.
71-
ON_LOAD_INTERNAL = "reflex___state____on_load_internal_state.on_load_internal"
72-
# The name of the internal event to update generic state vars.
73-
UPDATE_VARS_INTERNAL = (
74-
"reflex___state____update_vars_internal_state.update_vars_internal"
75-
)
76-
# The name of the frontend event exception state
77-
FRONTEND_EXCEPTION_STATE = "reflex___state____frontend_event_exception_state"
78-
# The full name of the frontend exception state
79-
FRONTEND_EXCEPTION_STATE_FULL = (
80-
f"reflex___state____state.{FRONTEND_EXCEPTION_STATE}"
81-
)
8270

8371

8472
class PageNames(SimpleNamespace):

packages/reflex-base/src/reflex_base/utils/format.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import json
77
import os
88
import re
9-
from collections.abc import Callable
109
from typing import TYPE_CHECKING, Any
1110

1211
from reflex_base import constants
@@ -440,9 +439,7 @@ def format_props(*single_props, **key_value_props) -> list[str]:
440439
] + [(f"...{LiteralVar.create(prop)!s}") for prop in single_props]
441440

442441

443-
def get_event_handler_parts(
444-
handler: EventHandler | Callable[..., Any],
445-
) -> tuple[str, str]:
442+
def get_event_handler_parts(handler: EventHandler) -> tuple[str, str]:
446443
"""Get the (state, function) name pair for an event handler.
447444
448445
Both names pass through the active
@@ -454,17 +451,9 @@ def get_event_handler_parts(
454451
455452
Returns:
456453
``(state_full_name, handler_name)`` — both resolved.
457-
458-
Raises:
459-
TypeError: If the handler is not an EventHandler.
460454
"""
461-
from reflex_base.event import EventHandler
462455
from reflex_base.registry import RegistrationContext
463456

464-
if not isinstance(handler, EventHandler):
465-
msg = f"Expected EventHandler, got {type(handler)}"
466-
raise TypeError(msg)
467-
468457
name = handler.fn.__qualname__
469458
if handler.state is None:
470459
return ("", name)
@@ -477,7 +466,7 @@ def get_event_handler_parts(
477466
return (state_full_name, ctx.get_handler_name(handler.state, func_name))
478467

479468

480-
def format_event_handler(handler: EventHandler | Callable[..., Any]) -> str:
469+
def format_event_handler(handler: EventHandler) -> str:
481470
"""Format an event handler.
482471
483472
Args:

reflex/minify.py

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -199,17 +199,23 @@ def from_disk(cls) -> MinifyNameResolver:
199199
"""Build a resolver from the current ``minify.json`` and env vars.
200200
201201
Bypasses the lru_cache on :func:`get_minify_config` so the snapshot
202-
reflects the cwd at install time. Malformed configs become
203-
``config=None`` — the validate CLI surfaces them separately.
202+
reflects the cwd at install time. A malformed config becomes
203+
``config=None`` (graceful degradation — the app still runs without
204+
minification) and a warning is logged once per install so the user
205+
notices.
204206
205207
Returns:
206208
A configured resolver.
207209
"""
208210
from reflex.environment import MinifyMode, environment
211+
from reflex.utils import console
209212

210213
try:
211214
config = _load_minify_config_uncached()
212-
except ValueError:
215+
except ValueError as e:
216+
console.warn(
217+
f"{MINIFY_JSON} could not be loaded: {e}; minification disabled."
218+
)
213219
config = None
214220
return cls(
215221
config=config,
@@ -297,16 +303,20 @@ def install_minify_resolver() -> None:
297303
def ensure_minify_resolver_for_active_context() -> None:
298304
"""Install a :class:`MinifyNameResolver` for the active context if needed.
299305
300-
Idempotent once a config-loaded resolver is in place — safe to wire into
301-
hot paths (e.g. :func:`reflex.utils.prerequisites.get_app`, which can be
302-
re-entered at runtime from a different cwd than the one that loaded the
303-
config). Re-installs only if the current resolver has ``config=None``.
306+
Idempotent in the steady state — safe to wire into hot paths
307+
(e.g. :func:`reflex.utils.prerequisites.get_app`, which can be re-entered
308+
at runtime from a different cwd than the one that loaded the config).
309+
Re-installs only when something on disk could have changed: a config
310+
appearing where there wasn't one, or a non-minify resolver in the slot.
304311
"""
305312
from reflex_base.registry import RegistrationContext
306313

307314
ctx = RegistrationContext.ensure_context()
308-
if isinstance(ctx.name_resolver, MinifyNameResolver) and ctx.name_resolver.config:
309-
return
315+
if isinstance(ctx.name_resolver, MinifyNameResolver):
316+
if ctx.name_resolver.config is not None:
317+
return # already loaded with a config — no work to do
318+
if not _get_minify_json_path().exists():
319+
return # no config and none on disk; nothing changed
310320
ctx.set_name_resolver(MinifyNameResolver.from_disk())
311321

312322

@@ -493,8 +503,8 @@ def _assign_next_ids(
493503
) -> dict[str, str]:
494504
"""Assign minified ids to ``new_keys`` while skipping ``existing_ids``.
495505
496-
Mutates ``existing_ids`` so callers can chain assignments against the same
497-
pool. Keys are sorted for deterministic output.
506+
Keys are sorted for deterministic output. ``existing_ids`` is read-only —
507+
a working copy is taken internally.
498508
499509
Args:
500510
new_keys: Keys needing new ids.
@@ -505,13 +515,14 @@ def _assign_next_ids(
505515
Returns:
506516
Mapping from key to its newly-assigned minified id.
507517
"""
508-
next_id = 0 if reassign_deleted else max(existing_ids, default=-1) + 1
518+
pool = set(existing_ids)
519+
next_id = 0 if reassign_deleted else max(pool, default=-1) + 1
509520
out: dict[str, str] = {}
510521
for key in sorted(new_keys):
511-
while next_id in existing_ids:
522+
while next_id in pool:
512523
next_id += 1
513524
out[key] = int_to_minified_name(next_id)
514-
existing_ids.add(next_id)
525+
pool.add(next_id)
515526
next_id += 1
516527
return out
517528

@@ -673,7 +684,7 @@ def sync_minify_config(
673684

674685
# Assign new state IDs (unique among siblings of the same parent class).
675686
for parent_cls, children in parent_cls_to_new_children.items():
676-
existing_ids = parent_cls_to_existing_ids.get(parent_cls, set()).copy()
687+
existing_ids = parent_cls_to_existing_ids.get(parent_cls, set())
677688
new_states.update(_assign_next_ids(children, existing_ids, reassign_deleted))
678689

679690
# Assign new event IDs (unique within each state).

reflex/reflex.py

Lines changed: 15 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,69 +1209,39 @@ def minify_lookup(output_json: bool, minified_path: str):
12091209
12101210
Walks the state tree from the root to resolve each segment.
12111211
"""
1212-
from reflex.minify import get_state_full_path
1213-
from reflex.state import BaseState, State
1212+
from reflex.minify import collect_all_states, get_state_full_path
1213+
from reflex.state import State
12141214

12151215
config = _open_minify_session()
12161216

1217-
def collect_states(
1218-
state_cls: type[BaseState],
1219-
) -> list[type[BaseState]]:
1220-
"""Recursively collect all states.
1221-
1222-
Args:
1223-
state_cls: The state class to start from.
1217+
# Build lookup: full_path -> minified_id (None if no entry).
1218+
path_to_id = {
1219+
get_state_full_path(s): config["states"].get(get_state_full_path(s))
1220+
for s in collect_all_states(State)
1221+
}
12241222

1225-
Returns:
1226-
List of all state classes in the hierarchy.
1227-
"""
1228-
result = [state_cls]
1229-
for sub in state_cls.get_substates():
1230-
result.extend(collect_states(sub))
1231-
return result
1232-
1233-
# Build lookup: full_path -> (state_class, minified_id)
1234-
all_states = collect_states(State)
1235-
path_to_info: dict[str, tuple[type[BaseState], str | None]] = {}
1236-
for state_cls in all_states:
1237-
full_path = get_state_full_path(state_cls)
1238-
minified_id = config["states"].get(full_path)
1239-
path_to_info[full_path] = (state_cls, minified_id)
1240-
1241-
# Walk the minified path
12421223
parts = minified_path.split(".")
12431224
result_parts = []
12441225
current = State
12451226

12461227
for i, part in enumerate(parts):
1247-
# Find state whose minified ID matches 'part'
1248-
found = None
1249-
if i == 0:
1250-
# First segment should match root state
1251-
state_path = get_state_full_path(current)
1252-
_, state_id = path_to_info.get(state_path, (None, None))
1253-
if state_id == part:
1254-
found = current
1255-
else:
1256-
# Find among children of current
1257-
for child in current.get_substates():
1258-
child_path = get_state_full_path(child)
1259-
_, child_id = path_to_info.get(child_path, (None, None))
1260-
if child_id == part:
1261-
found = child
1262-
break
1263-
1228+
# Find the state whose minified id matches ``part``: the root state
1229+
# for the first segment, otherwise a child of the previous match.
1230+
candidates = [current] if i == 0 else current.get_substates()
1231+
found = next(
1232+
(c for c in candidates if path_to_id.get(get_state_full_path(c)) == part),
1233+
None,
1234+
)
12641235
if found is None:
12651236
console.error(
12661237
f"No state found for minified segment '{part}' in path '{minified_path}'"
12671238
)
12681239
raise SystemExit(1)
12691240

12701241
state_path = get_state_full_path(found)
1271-
_, state_id = path_to_info.get(state_path, (None, None))
12721242
result_parts.append({
12731243
"minified": part,
1274-
"state_id": state_id,
1244+
"state_id": part, # we just matched on it
12751245
"module": found.__module__,
12761246
"class": found.__name__,
12771247
"full_path": state_path,

0 commit comments

Comments
 (0)