Skip to content

Commit 0b41bdf

Browse files
authored
[0.8] don't use reserve words for variable names (#5251)
* don't use reserve words for variable names * use underscore suffix instead * fix various places that got the wrong name * fix the test * fix unit tests * fix dynamic components * i don't know how to do inheritance * maybe * remove that suffix * ok we can't do that * add something to update vars internal * fix dynamic route * fix unit tests * fix is hydrated * solve post merge artifcats * simplify rx base * fix a few more post merge artifacts * make all of those guys into a constant * it's ruff out there * use field marker * add ignore field makrer * msg = msg replace
1 parent dd40447 commit 0b41bdf

File tree

24 files changed

+425
-406
lines changed

24 files changed

+425
-406
lines changed

reflex/.templates/web/utils/state.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,10 @@ const applyClientStorageDelta = (client_storage, delta) => {
777777
);
778778
if (unqualified_states.length === 1) {
779779
const main_state = delta[unqualified_states[0]];
780-
if (main_state.is_hydrated !== undefined && !main_state.is_hydrated) {
780+
if (
781+
main_state.is_hydrated_rx_state_ !== undefined &&
782+
!main_state.is_hydrated_rx_state_
783+
) {
781784
// skip if the state is not hydrated yet, since all client storage
782785
// values are sent in the hydrate event
783786
return;
@@ -1025,7 +1028,7 @@ export const useEventLoop = (
10251028
const change_start = () => {
10261029
const main_state_dispatch = dispatch["reflex___state____state"];
10271030
if (main_state_dispatch !== undefined) {
1028-
main_state_dispatch({ is_hydrated: false });
1031+
main_state_dispatch({ is_hydrated_rx_state_: false });
10291032
}
10301033
};
10311034
change_start();

reflex/app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1100,7 +1100,7 @@ def _validate_var_dependencies(self, state: type[BaseState] | None = None) -> No
11001100
)
11011101
for dep in dep_set:
11021102
if dep not in state_cls.vars and dep not in state_cls.backend_vars:
1103-
msg = f"ComputedVar {var._js_expr} on state {state.__name__} has an invalid dependency {state_name}.{dep}"
1103+
msg = f"ComputedVar {var._name} on state {state.__name__} has an invalid dependency {state_name}.{dep}"
11041104
raise exceptions.VarDependencyError(msg)
11051105

11061106
for substate in state.class_subclasses:

reflex/base.py

Lines changed: 1 addition & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,6 @@
11
"""Define the base Reflex class."""
22

3-
from __future__ import annotations
4-
5-
import os
6-
from typing import TYPE_CHECKING, Any
7-
8-
import pydantic.v1.main as pydantic_main
93
from pydantic.v1 import BaseModel
10-
from pydantic.v1.fields import ModelField
11-
12-
13-
def validate_field_name(bases: list[type[BaseModel]], field_name: str) -> None:
14-
"""Ensure that the field's name does not shadow an existing attribute of the model.
15-
16-
Args:
17-
bases: List of base models to check for shadowed attrs.
18-
field_name: name of attribute
19-
20-
Raises:
21-
VarNameError: If state var field shadows another in its parent state
22-
"""
23-
from reflex.utils.exceptions import VarNameError
24-
25-
# can't use reflex.config.environment here cause of circular import
26-
reload = os.getenv("__RELOAD_CONFIG", "").lower() == "true"
27-
base = None
28-
try:
29-
for base in bases:
30-
if not reload and getattr(base, field_name, None):
31-
pass
32-
except TypeError as te:
33-
msg = (
34-
f'State var "{field_name}" in {base} has been shadowed by a substate var; '
35-
f'use a different field name instead".'
36-
)
37-
raise VarNameError(msg) from te
38-
39-
40-
# monkeypatch pydantic validate_field_name method to skip validating
41-
# shadowed state vars when reloading app via utils.prerequisites.get_app(reload=True)
42-
pydantic_main.validate_field_name = validate_field_name # pyright: ignore [reportPrivateImportUsage]
43-
44-
if TYPE_CHECKING:
45-
from reflex.vars import Var
464

475

486
class Base(BaseModel):
@@ -75,7 +33,7 @@ def json(self) -> str:
7533
default=serialize,
7634
)
7735

78-
def set(self, **kwargs: Any):
36+
def set(self, **kwargs: object):
7937
"""Set multiple fields and return the object.
8038
8139
Args:
@@ -87,47 +45,3 @@ def set(self, **kwargs: Any):
8745
for key, value in kwargs.items():
8846
setattr(self, key, value)
8947
return self
90-
91-
@classmethod
92-
def get_fields(cls) -> dict[str, ModelField]:
93-
"""Get the fields of the object.
94-
95-
Returns:
96-
The fields of the object.
97-
"""
98-
return cls.__fields__
99-
100-
@classmethod
101-
def add_field(cls, var: Var, default_value: Any):
102-
"""Add a pydantic field after class definition.
103-
104-
Used by State.add_var() to correctly handle the new variable.
105-
106-
Args:
107-
var: The variable to add a pydantic field for.
108-
default_value: The default value of the field
109-
"""
110-
var_name = var._var_field_name
111-
new_field = ModelField.infer(
112-
name=var_name,
113-
value=default_value,
114-
annotation=var._var_type,
115-
class_validators=None,
116-
config=cls.__config__,
117-
)
118-
cls.__fields__.update({var_name: new_field})
119-
120-
def get_value(self, key: str) -> Any:
121-
"""Get the value of a field.
122-
123-
Args:
124-
key: The key of the field.
125-
126-
Returns:
127-
The value of the field.
128-
"""
129-
if isinstance(key, str):
130-
# Seems like this function signature was wrong all along?
131-
# If the user wants a field that we know of, get it and pass it off to _get_value
132-
return getattr(self, key)
133-
return key

reflex/compiler/compiler.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
)
2222
from reflex.config import get_config
2323
from reflex.constants.compiler import PageNames
24+
from reflex.constants.state import FIELD_MARKER
2425
from reflex.environment import environment
2526
from reflex.state import BaseState
2627
from reflex.style import SYSTEM_COLOR_MODE
@@ -694,6 +695,8 @@ def _modify_exception(e: Exception) -> None:
694695
f"{msg[:state_index]}{module_path}.{actual_state_name}{msg[dot_index:]}"
695696
)
696697

698+
msg = msg.replace(FIELD_MARKER, "")
699+
697700
e.args = (msg,)
698701

699702

reflex/compiler/utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from reflex.components.el.elements.metadata import Head, Meta, Title
2020
from reflex.components.el.elements.other import Html
2121
from reflex.components.el.elements.sectioning import Body
22+
from reflex.constants.state import FIELD_MARKER
2223
from reflex.istate.storage import Cookie, LocalStorage, SessionStorage
2324
from reflex.state import BaseState, _resolve_delta
2425
from reflex.style import Style
@@ -252,7 +253,7 @@ def _compile_client_storage_recursive(
252253
if name in state.inherited_vars:
253254
# only include vars defined in this state
254255
continue
255-
state_key = f"{state_name}.{name}"
256+
state_key = f"{state_name}.{name}" + FIELD_MARKER
256257
field_type, options = _compile_client_storage_field(field)
257258
if field_type is Cookie:
258259
cookies[state_key] = options

reflex/components/core/foreach.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from reflex.components.core.cond import cond
1313
from reflex.components.tags import IterTag
1414
from reflex.constants import MemoizationMode
15+
from reflex.constants.state import FIELD_MARKER
1516
from reflex.state import ComponentState
1617
from reflex.utils import types
1718
from reflex.utils.exceptions import UntypedVarError
@@ -132,11 +133,11 @@ def _render(self) -> IterTag:
132133

133134
if len(params) >= 1:
134135
# Determine the arg var name based on the params accepted by render_fn.
135-
props["arg_var_name"] = params[0].name
136+
props["arg_var_name"] = params[0].name + FIELD_MARKER
136137

137138
if len(params) == 2:
138139
# Determine the index var name based on the params accepted by render_fn.
139-
props["index_var_name"] = params[1].name
140+
props["index_var_name"] = params[1].name + FIELD_MARKER
140141
else:
141142
render_fn = self.render_fn
142143
# Otherwise, use a deterministic index, based on the render function bytecode.

reflex/constants/state.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ class StateManagerMode(str, Enum):
1313

1414
# Used for things like console_log, etc.
1515
FRONTEND_EVENT_STATE = "__reflex_internal_frontend_event_state"
16+
17+
FIELD_MARKER = "_rx_state_"

0 commit comments

Comments
 (0)