reflex 0.8.14.post1__py3-none-any.whl → 0.8.15a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of reflex might be problematic. Click here for more details.

Files changed (49) hide show
  1. reflex/__init__.py +12 -7
  2. reflex/__init__.pyi +11 -3
  3. reflex/app.py +5 -2
  4. reflex/base.py +58 -33
  5. reflex/components/datadisplay/dataeditor.py +17 -2
  6. reflex/components/datadisplay/dataeditor.pyi +6 -2
  7. reflex/components/field.py +3 -1
  8. reflex/components/lucide/icon.py +2 -1
  9. reflex/components/lucide/icon.pyi +2 -1
  10. reflex/components/markdown/markdown.py +101 -27
  11. reflex/components/sonner/toast.py +3 -2
  12. reflex/components/sonner/toast.pyi +3 -2
  13. reflex/constants/base.py +5 -0
  14. reflex/constants/installer.py +3 -3
  15. reflex/environment.py +9 -1
  16. reflex/event.py +3 -0
  17. reflex/istate/manager/__init__.py +120 -0
  18. reflex/istate/manager/disk.py +210 -0
  19. reflex/istate/manager/memory.py +76 -0
  20. reflex/istate/{manager.py → manager/redis.py} +5 -372
  21. reflex/istate/proxy.py +35 -24
  22. reflex/model.py +534 -511
  23. reflex/plugins/tailwind_v4.py +2 -2
  24. reflex/reflex.py +16 -10
  25. reflex/state.py +35 -34
  26. reflex/testing.py +12 -14
  27. reflex/utils/build.py +11 -1
  28. reflex/utils/compat.py +51 -48
  29. reflex/utils/misc.py +2 -1
  30. reflex/utils/monitoring.py +1 -2
  31. reflex/utils/prerequisites.py +19 -4
  32. reflex/utils/processes.py +3 -1
  33. reflex/utils/redir.py +21 -37
  34. reflex/utils/serializers.py +21 -20
  35. reflex/utils/telemetry.py +0 -2
  36. reflex/utils/templates.py +4 -4
  37. reflex/utils/types.py +82 -90
  38. reflex/vars/base.py +108 -41
  39. reflex/vars/color.py +28 -8
  40. reflex/vars/datetime.py +6 -2
  41. reflex/vars/dep_tracking.py +2 -2
  42. reflex/vars/number.py +26 -0
  43. reflex/vars/object.py +51 -7
  44. reflex/vars/sequence.py +32 -1
  45. {reflex-0.8.14.post1.dist-info → reflex-0.8.15a1.dist-info}/METADATA +8 -3
  46. {reflex-0.8.14.post1.dist-info → reflex-0.8.15a1.dist-info}/RECORD +49 -46
  47. {reflex-0.8.14.post1.dist-info → reflex-0.8.15a1.dist-info}/WHEEL +0 -0
  48. {reflex-0.8.14.post1.dist-info → reflex-0.8.15a1.dist-info}/entry_points.txt +0 -0
  49. {reflex-0.8.14.post1.dist-info → reflex-0.8.15a1.dist-info}/licenses/LICENSE +0 -0
reflex/__init__.py CHANGED
@@ -84,13 +84,18 @@ In the example above, you will be able to do `rx.list`
84
84
 
85
85
  from __future__ import annotations
86
86
 
87
- from reflex.utils import (
88
- compat, # for side-effects
89
- lazy_loader,
90
- )
87
+ import sys
88
+
89
+ from reflex.utils import lazy_loader
90
+
91
+ if sys.version_info < (3, 11):
92
+ from reflex.utils import console
91
93
 
92
- # Remove the `compat` name from the namespace, it was imported for side-effects only.
93
- del compat
94
+ console.warn(
95
+ "Reflex support for Python 3.10 is deprecated and will be removed in a future release. Please upgrade to Python 3.11 or higher for continued support."
96
+ )
97
+ del console
98
+ del sys
94
99
 
95
100
  RADIX_THEMES_MAPPING: dict = {
96
101
  "components.radix.themes.base": ["color_mode", "theme", "theme_panel"],
@@ -323,7 +328,7 @@ _MAPPING: dict = {
323
328
  "SessionStorage",
324
329
  ],
325
330
  "middleware": ["middleware", "Middleware"],
326
- "model": ["asession", "session", "Model"],
331
+ "model": ["asession", "session", "Model", "ModelRegistry"],
327
332
  "page": ["page"],
328
333
  "state": [
329
334
  "var",
reflex/__init__.pyi CHANGED
@@ -3,7 +3,7 @@
3
3
  # This file was generated by `reflex/utils/pyi_generator.py`!
4
4
  # ------------------------------------------------------
5
5
 
6
- from reflex.utils import compat
6
+ import sys
7
7
 
8
8
  from . import (
9
9
  admin,
@@ -151,7 +151,7 @@ from .experimental import _x
151
151
  from .istate.storage import Cookie, LocalStorage, SessionStorage
152
152
  from .istate.wrappers import get_state
153
153
  from .middleware import Middleware, middleware
154
- from .model import Model, asession, session
154
+ from .model import Model, ModelRegistry, asession, session
155
155
  from .page import page
156
156
  from .state import ComponentState, State, dynamic, var
157
157
  from .style import Style, toggle_color_mode
@@ -160,7 +160,14 @@ from .utils.misc import run_in_thread
160
160
  from .utils.serializers import serializer
161
161
  from .vars import Field, Var, field
162
162
 
163
- del compat
163
+ if sys.version_info < (3, 11):
164
+ from reflex.utils import console
165
+
166
+ console.warn(
167
+ "Reflex support for Python 3.10 is deprecated and will be removed in a future release. Please upgrade to Python 3.11 or higher for continued support."
168
+ )
169
+ del console
170
+ del sys
164
171
  RADIX_THEMES_MAPPING: dict
165
172
  RADIX_THEMES_COMPONENTS_MAPPING: dict
166
173
  RADIX_THEMES_LAYOUT_MAPPING: dict
@@ -192,6 +199,7 @@ __all__ = [
192
199
  "LocalStorage",
193
200
  "Middleware",
194
201
  "Model",
202
+ "ModelRegistry",
195
203
  "MomentDelta",
196
204
  "NoSSRComponent",
197
205
  "PropsBase",
reflex/app.py CHANGED
@@ -83,7 +83,6 @@ from reflex.event import (
83
83
  get_hydrate_event,
84
84
  noop,
85
85
  )
86
- from reflex.model import Model, get_db_status
87
86
  from reflex.page import DECORATED_PAGES
88
87
  from reflex.route import (
89
88
  get_route_args,
@@ -648,7 +647,7 @@ class App(MiddlewareMixin, LifespanMixin):
648
647
 
649
648
  for api_transformer in api_transformers:
650
649
  if isinstance(api_transformer, Starlette):
651
- # Mount the api to the fastapi app.
650
+ # Mount the api to the starlette app.
652
651
  App._add_cors(api_transformer)
653
652
  api_transformer.mount("", asgi_app)
654
653
  asgi_app = api_transformer
@@ -957,6 +956,8 @@ class App(MiddlewareMixin, LifespanMixin):
957
956
  try:
958
957
  from starlette_admin.contrib.sqla.admin import Admin
959
958
  from starlette_admin.contrib.sqla.view import ModelView
959
+
960
+ from reflex.model import Model
960
961
  except ImportError:
961
962
  return
962
963
 
@@ -1849,6 +1850,8 @@ async def health(_request: Request) -> JSONResponse:
1849
1850
  tasks = []
1850
1851
 
1851
1852
  if prerequisites.check_db_used():
1853
+ from reflex.model import get_db_status
1854
+
1852
1855
  tasks.append(get_db_status())
1853
1856
  if prerequisites.check_redis_used():
1854
1857
  tasks.append(prerequisites.get_redis_status())
reflex/base.py CHANGED
@@ -1,47 +1,72 @@
1
1
  """Define the base Reflex class."""
2
2
 
3
- from pydantic.v1 import BaseModel
3
+ from importlib.util import find_spec
4
4
 
5
+ if find_spec("pydantic") and find_spec("pydantic.v1"):
6
+ from pydantic.v1 import BaseModel
5
7
 
6
- class Base(BaseModel):
7
- """The base class subclassed by all Reflex classes.
8
+ from reflex.utils.compat import ModelMetaclassLazyAnnotations
8
9
 
9
- This class wraps Pydantic and provides common methods such as
10
- serialization and setting fields.
10
+ class Base(BaseModel, metaclass=ModelMetaclassLazyAnnotations):
11
+ """The base class subclassed by all Reflex classes.
11
12
 
12
- Any data structure that needs to be transferred between the
13
- frontend and backend should subclass this class.
14
- """
13
+ This class wraps Pydantic and provides common methods such as
14
+ serialization and setting fields.
15
15
 
16
- class Config:
17
- """Pydantic config."""
16
+ Any data structure that needs to be transferred between the
17
+ frontend and backend should subclass this class.
18
+ """
18
19
 
19
- arbitrary_types_allowed = True
20
- use_enum_values = True
21
- extra = "allow"
20
+ class Config:
21
+ """Pydantic config."""
22
22
 
23
- def json(self) -> str:
24
- """Convert the object to a json string.
23
+ arbitrary_types_allowed = True
24
+ use_enum_values = True
25
+ extra = "allow"
25
26
 
26
- Returns:
27
- The object as a json string.
28
- """
29
- from reflex.utils.serializers import serialize
27
+ def __init_subclass__(cls):
28
+ """Warn that rx.Base is deprecated."""
29
+ from reflex.utils import console
30
30
 
31
- return self.__config__.json_dumps(
32
- self.dict(),
33
- default=serialize,
34
- )
31
+ console.deprecate(
32
+ feature_name="rx.Base",
33
+ reason=f"{cls!r} is subclassing rx.Base. You can subclass from `pydantic.BaseModel` directly instead or use dataclasses if possible.",
34
+ deprecation_version="0.8.15",
35
+ removal_version="0.9.0",
36
+ )
37
+ super().__init_subclass__()
35
38
 
36
- def set(self, **kwargs: object):
37
- """Set multiple fields and return the object.
39
+ def json(self) -> str:
40
+ """Convert the object to a json string.
38
41
 
39
- Args:
40
- **kwargs: The fields and values to set.
42
+ Returns:
43
+ The object as a json string.
44
+ """
45
+ from reflex.utils.serializers import serialize
41
46
 
42
- Returns:
43
- The object with the fields set.
44
- """
45
- for key, value in kwargs.items():
46
- setattr(self, key, value)
47
- return self
47
+ return self.__config__.json_dumps(
48
+ self.dict(),
49
+ default=serialize,
50
+ )
51
+ else:
52
+
53
+ class PydanticNotFoundFallback:
54
+ """Fallback base class for environments without Pydantic."""
55
+
56
+ def __init__(self, *args, **kwargs):
57
+ """Initialize the base class.
58
+
59
+ Args:
60
+ *args: Positional arguments.
61
+ **kwargs: Keyword arguments.
62
+
63
+ Raises:
64
+ ImportError: As Pydantic is not installed.
65
+ """
66
+ msg = (
67
+ "Pydantic is not installed. Please install it to use rx.Base."
68
+ "You can install it with `pip install pydantic`."
69
+ )
70
+ raise ImportError(msg)
71
+
72
+ Base = PydanticNotFoundFallback # pyright: ignore[reportAssignmentType]
@@ -2,11 +2,11 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import dataclasses
5
6
  from collections.abc import Mapping, Sequence
6
7
  from enum import Enum
7
8
  from typing import Any, Literal, TypedDict
8
9
 
9
- from reflex.base import Base
10
10
  from reflex.components.component import Component, NoSSRComponent
11
11
  from reflex.components.literals import LiteralRowMarker
12
12
  from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
@@ -50,7 +50,8 @@ class GridColumnIcons(Enum):
50
50
  VideoUri = "video_uri"
51
51
 
52
52
 
53
- class DataEditorTheme(Base):
53
+ @dataclasses.dataclass
54
+ class DataEditorThemeBase:
54
55
  """The theme for the DataEditor component."""
55
56
 
56
57
  accent_color: str | None = None
@@ -87,6 +88,20 @@ class DataEditorTheme(Base):
87
88
  text_medium: str | None = None
88
89
 
89
90
 
91
+ @dataclasses.dataclass(init=False)
92
+ class DataEditorTheme(DataEditorThemeBase):
93
+ """The theme for the DataEditor component."""
94
+
95
+ def __init__(self, **kwargs: Any):
96
+ """Initialize the DataEditorTheme.
97
+
98
+ Args:
99
+ **kwargs: The keyword arguments to initialize the theme.
100
+ """
101
+ kwargs = {format.to_snake_case(k): v for k, v in kwargs.items()}
102
+ super().__init__(**kwargs)
103
+
104
+
90
105
  class Bounds(TypedDict):
91
106
  """The bounds of the group header."""
92
107
 
@@ -3,11 +3,11 @@
3
3
  # ------------------- DO NOT EDIT ----------------------
4
4
  # This file was generated by `reflex/utils/pyi_generator.py`!
5
5
  # ------------------------------------------------------
6
+ import dataclasses
6
7
  from collections.abc import Mapping, Sequence
7
8
  from enum import Enum
8
9
  from typing import Any, Literal, TypedDict
9
10
 
10
- from reflex.base import Base
11
11
  from reflex.components.component import NoSSRComponent
12
12
  from reflex.components.core.breakpoints import Breakpoints
13
13
  from reflex.event import EventType, PointerEventInfo
@@ -43,7 +43,8 @@ class GridColumnIcons(Enum):
43
43
  Uri = "uri"
44
44
  VideoUri = "video_uri"
45
45
 
46
- class DataEditorTheme(Base):
46
+ @dataclasses.dataclass
47
+ class DataEditorThemeBase:
47
48
  accent_color: str | None
48
49
  accent_fg: str | None
49
50
  accent_light: str | None
@@ -77,6 +78,9 @@ class DataEditorTheme(Base):
77
78
  text_light: str | None
78
79
  text_medium: str | None
79
80
 
81
+ @dataclasses.dataclass(init=False)
82
+ class DataEditorTheme(DataEditorThemeBase): ...
83
+
80
84
  class Bounds(TypedDict):
81
85
  x: int
82
86
  y: int
@@ -7,6 +7,7 @@ from dataclasses import _MISSING_TYPE, MISSING
7
7
  from typing import Annotated, Any, Generic, TypeVar, get_origin
8
8
 
9
9
  from reflex.utils import types
10
+ from reflex.utils.compat import annotations_from_namespace
10
11
 
11
12
  FIELD_TYPE = TypeVar("FIELD_TYPE")
12
13
 
@@ -117,7 +118,8 @@ class FieldBasedMeta(type):
117
118
  cls, namespace: dict[str, Any], name: str
118
119
  ) -> dict[str, Any]:
119
120
  return types.resolve_annotations(
120
- namespace.get("__annotations__", {}), namespace["__module__"]
121
+ annotations_from_namespace(namespace),
122
+ namespace["__module__"],
121
123
  )
122
124
 
123
125
  @classmethod
@@ -6,7 +6,7 @@ from reflex.utils.imports import ImportVar
6
6
  from reflex.vars.base import LiteralVar, Var
7
7
  from reflex.vars.sequence import LiteralStringVar, StringVar
8
8
 
9
- LUCIDE_LIBRARY = "lucide-react@0.544.0"
9
+ LUCIDE_LIBRARY = "lucide-react@0.545.0"
10
10
 
11
11
 
12
12
  class LucideIconComponent(Component):
@@ -1129,6 +1129,7 @@ LUCIDE_ICON_LIST = [
1129
1129
  "monitor",
1130
1130
  "moon_star",
1131
1131
  "moon",
1132
+ "motorbike",
1132
1133
  "mountain_snow",
1133
1134
  "mountain",
1134
1135
  "mouse_off",
@@ -11,7 +11,7 @@ from reflex.components.core.breakpoints import Breakpoints
11
11
  from reflex.event import EventType, PointerEventInfo
12
12
  from reflex.vars.base import Var
13
13
 
14
- LUCIDE_LIBRARY = "lucide-react@0.544.0"
14
+ LUCIDE_LIBRARY = "lucide-react@0.545.0"
15
15
 
16
16
  class LucideIconComponent(Component):
17
17
  @classmethod
@@ -1194,6 +1194,7 @@ LUCIDE_ICON_LIST = [
1194
1194
  "monitor",
1195
1195
  "moon_star",
1196
1196
  "moon",
1197
+ "motorbike",
1197
1198
  "mountain_snow",
1198
1199
  "mountain",
1199
1200
  "mouse_off",
@@ -38,6 +38,84 @@ _REHYPE_PLUGINS = LiteralVar.create([_REHYPE_KATEX, _REHYPE_RAW])
38
38
  NO_PROPS_TAGS = ("ul", "ol", "li")
39
39
 
40
40
 
41
+ def _h1(value: object):
42
+ from reflex.components.radix.themes.typography.heading import Heading
43
+
44
+ return Heading.create(value, as_="h1", size="6", margin_y="0.5em")
45
+
46
+
47
+ def _h2(value: object):
48
+ from reflex.components.radix.themes.typography.heading import Heading
49
+
50
+ return Heading.create(value, as_="h2", size="5", margin_y="0.5em")
51
+
52
+
53
+ def _h3(value: object):
54
+ from reflex.components.radix.themes.typography.heading import Heading
55
+
56
+ return Heading.create(value, as_="h3", size="4", margin_y="0.5em")
57
+
58
+
59
+ def _h4(value: object):
60
+ from reflex.components.radix.themes.typography.heading import Heading
61
+
62
+ return Heading.create(value, as_="h4", size="3", margin_y="0.5em")
63
+
64
+
65
+ def _h5(value: object):
66
+ from reflex.components.radix.themes.typography.heading import Heading
67
+
68
+ return Heading.create(value, as_="h5", size="2", margin_y="0.5em")
69
+
70
+
71
+ def _h6(value: object):
72
+ from reflex.components.radix.themes.typography.heading import Heading
73
+
74
+ return Heading.create(value, as_="h6", size="1", margin_y="0.5em")
75
+
76
+
77
+ def _p(value: object):
78
+ from reflex.components.radix.themes.typography.text import Text
79
+
80
+ return Text.create(value, margin_y="1em")
81
+
82
+
83
+ def _ul(value: object):
84
+ from reflex.components.radix.themes.layout.list import UnorderedList
85
+
86
+ return UnorderedList.create(value, margin_y="1em")
87
+
88
+
89
+ def _ol(value: object):
90
+ from reflex.components.radix.themes.layout.list import OrderedList
91
+
92
+ return OrderedList.create(value, margin_y="1em")
93
+
94
+
95
+ def _li(value: object):
96
+ from reflex.components.radix.themes.layout.list import ListItem
97
+
98
+ return ListItem.create(value, margin_y="0.5em")
99
+
100
+
101
+ def _a(value: object):
102
+ from reflex.components.radix.themes.typography.link import Link
103
+
104
+ return Link.create(value)
105
+
106
+
107
+ def _code(value: object):
108
+ from reflex.components.radix.themes.typography.code import Code
109
+
110
+ return Code.create(value)
111
+
112
+
113
+ def _codeblock(value: object, **props):
114
+ from reflex.components.datadisplay.code import CodeBlock
115
+
116
+ return CodeBlock.create(value, margin_y="1em", wrap_long_lines=True, **props)
117
+
118
+
41
119
  # Component Mapping
42
120
  @lru_cache
43
121
  def get_base_component_map() -> dict[str, Callable]:
@@ -46,33 +124,20 @@ def get_base_component_map() -> dict[str, Callable]:
46
124
  Returns:
47
125
  The base component map.
48
126
  """
49
- from reflex.components.datadisplay.code import CodeBlock
50
- from reflex.components.radix.themes.layout.list import (
51
- ListItem,
52
- OrderedList,
53
- UnorderedList,
54
- )
55
- from reflex.components.radix.themes.typography.code import Code
56
- from reflex.components.radix.themes.typography.heading import Heading
57
- from reflex.components.radix.themes.typography.link import Link
58
- from reflex.components.radix.themes.typography.text import Text
59
-
60
127
  return {
61
- "h1": lambda value: Heading.create(value, as_="h1", size="6", margin_y="0.5em"),
62
- "h2": lambda value: Heading.create(value, as_="h2", size="5", margin_y="0.5em"),
63
- "h3": lambda value: Heading.create(value, as_="h3", size="4", margin_y="0.5em"),
64
- "h4": lambda value: Heading.create(value, as_="h4", size="3", margin_y="0.5em"),
65
- "h5": lambda value: Heading.create(value, as_="h5", size="2", margin_y="0.5em"),
66
- "h6": lambda value: Heading.create(value, as_="h6", size="1", margin_y="0.5em"),
67
- "p": lambda value: Text.create(value, margin_y="1em"),
68
- "ul": lambda value: UnorderedList.create(value, margin_y="1em"),
69
- "ol": lambda value: OrderedList.create(value, margin_y="1em"),
70
- "li": lambda value: ListItem.create(value, margin_y="0.5em"),
71
- "a": lambda value: Link.create(value),
72
- "code": lambda value: Code.create(value),
73
- "codeblock": lambda value, **props: CodeBlock.create(
74
- value, margin_y="1em", wrap_long_lines=True, **props
75
- ),
128
+ "h1": _h1,
129
+ "h2": _h2,
130
+ "h3": _h3,
131
+ "h4": _h4,
132
+ "h5": _h5,
133
+ "h6": _h6,
134
+ "p": _p,
135
+ "ul": _ul,
136
+ "ol": _ol,
137
+ "li": _li,
138
+ "a": _a,
139
+ "code": _code,
140
+ "codeblock": _codeblock,
76
141
  }
77
142
 
78
143
 
@@ -413,7 +478,16 @@ let {_LANGUAGE!s} = match ? match[1] : '';
413
478
  @staticmethod
414
479
  def _component_map_hash(component_map: dict) -> str:
415
480
  inp = str(
416
- {tag: component(_MOCK_ARG) for tag, component in component_map.items()}
481
+ {
482
+ tag: (
483
+ f"{component.__module__}.{component.__qualname__}"
484
+ if (
485
+ "<" not in component.__name__
486
+ ) # simple way to check against lambdas
487
+ else component(_MOCK_ARG)
488
+ )
489
+ for tag, component in component_map.items()
490
+ }
417
491
  ).encode()
418
492
  return md5(inp).hexdigest()
419
493
 
@@ -2,9 +2,9 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import dataclasses
5
6
  from typing import Any, Literal
6
7
 
7
- from reflex.base import Base
8
8
  from reflex.components.component import Component, ComponentNamespace
9
9
  from reflex.components.lucide.icon import Icon
10
10
  from reflex.components.props import NoExtrasAllowedProps
@@ -35,7 +35,8 @@ toast_ref = Var(
35
35
  )
36
36
 
37
37
 
38
- class ToastAction(Base):
38
+ @dataclasses.dataclass
39
+ class ToastAction:
39
40
  """A toast action that render a button in the toast."""
40
41
 
41
42
  label: str
@@ -3,10 +3,10 @@
3
3
  # ------------------- DO NOT EDIT ----------------------
4
4
  # This file was generated by `reflex/utils/pyi_generator.py`!
5
5
  # ------------------------------------------------------
6
+ import dataclasses
6
7
  from collections.abc import Mapping, Sequence
7
8
  from typing import Any, Literal
8
9
 
9
- from reflex.base import Base
10
10
  from reflex.components.component import Component, ComponentNamespace
11
11
  from reflex.components.core.breakpoints import Breakpoints
12
12
  from reflex.components.lucide.icon import Icon
@@ -32,7 +32,8 @@ toast_ref = Var(
32
32
  _var_data=VarData(imports={f"$/{Dirs.STATE_PATH}": [ImportVar(tag="refs")]}),
33
33
  )
34
34
 
35
- class ToastAction(Base):
35
+ @dataclasses.dataclass
36
+ class ToastAction:
36
37
  label: str
37
38
  on_click: Any
38
39
 
reflex/constants/base.py CHANGED
@@ -134,6 +134,11 @@ class Templates(SimpleNamespace):
134
134
  # The reflex.build frontend host
135
135
  REFLEX_BUILD_FRONTEND = "https://build.reflex.dev"
136
136
 
137
+ # The reflex.build frontend with referrer
138
+ REFLEX_BUILD_FRONTEND_WITH_REFERRER = (
139
+ f"{REFLEX_BUILD_FRONTEND}/?utm_source=reflex_cli"
140
+ )
141
+
137
142
  class Dirs(SimpleNamespace):
138
143
  """Folders used by the template system of Reflex."""
139
144
 
@@ -87,7 +87,7 @@ def _determine_react_router_version() -> str:
87
87
 
88
88
 
89
89
  def _determine_react_version() -> str:
90
- default_version = "19.1.1"
90
+ default_version = "19.2.0"
91
91
  if (version := os.getenv("REACT_VERSION")) and version != default_version:
92
92
  from reflex.utils import console
93
93
 
@@ -143,11 +143,11 @@ class PackageJson(SimpleNamespace):
143
143
  "postcss-import": "16.1.1",
144
144
  "@react-router/dev": _react_router_version,
145
145
  "@react-router/fs-routes": _react_router_version,
146
- "vite": "npm:rolldown-vite@7.1.13",
146
+ "vite": "npm:rolldown-vite@7.1.16",
147
147
  }
148
148
  OVERRIDES = {
149
149
  # This should always match the `react` version in DEPENDENCIES for recharts compatibility.
150
150
  "react-is": _react_version,
151
151
  "cookie": "1.0.2",
152
- "vite": "npm:rolldown-vite@7.1.13",
152
+ "vite": "npm:rolldown-vite@7.1.16",
153
153
  }
reflex/environment.py CHANGED
@@ -24,6 +24,7 @@ from typing import (
24
24
  )
25
25
 
26
26
  from reflex import constants
27
+ from reflex.constants.base import LogLevel
27
28
  from reflex.plugins import Plugin
28
29
  from reflex.utils.exceptions import EnvironmentVarValueError
29
30
  from reflex.utils.types import GenericType, is_union, value_inside_optional
@@ -204,7 +205,8 @@ def interpret_env_var_value(
204
205
  The interpreted value.
205
206
 
206
207
  Raises:
207
- ValueError: If the environment variable type is invalid.
208
+ ValueError: If the value is invalid.
209
+ EnvironmentVarValueError: If the value is invalid for the specific type.
208
210
  """
209
211
  field_type = value_inside_optional(field_type)
210
212
 
@@ -218,6 +220,12 @@ def interpret_env_var_value(
218
220
  return interpret_boolean_env(value, field_name)
219
221
  if field_type is str:
220
222
  return value
223
+ if field_type is LogLevel:
224
+ loglevel = LogLevel.from_string(value)
225
+ if loglevel is None:
226
+ msg = f"Invalid log level value: {value} for {field_name}"
227
+ raise EnvironmentVarValueError(msg)
228
+ return loglevel
221
229
  if field_type is int:
222
230
  return interpret_int_env(value, field_name)
223
231
  if field_type is Path:
reflex/event.py CHANGED
@@ -1866,6 +1866,9 @@ def fix_events(
1866
1866
  # Fix the events created by the handler.
1867
1867
  out = []
1868
1868
  for e in events:
1869
+ if callable(e) and getattr(e, "__name__", "") == "<lambda>":
1870
+ # A lambda was returned, assume the user wants to call it with no args.
1871
+ e = e()
1869
1872
  if isinstance(e, Event):
1870
1873
  # If the event is already an event, append it to the list.
1871
1874
  out.append(e)