reflex 0.7.14a5__py3-none-any.whl → 0.8.0a1__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 (205) hide show
  1. reflex/.templates/jinja/app/rxconfig.py.jinja2 +4 -1
  2. reflex/.templates/jinja/web/package.json.jinja2 +1 -1
  3. reflex/.templates/jinja/web/pages/_app.js.jinja2 +16 -10
  4. reflex/.templates/jinja/web/pages/_document.js.jinja2 +1 -1
  5. reflex/.templates/jinja/web/pages/base_page.js.jinja2 +0 -1
  6. reflex/.templates/jinja/web/utils/context.js.jinja2 +25 -6
  7. reflex/.templates/web/app/entry.client.js +8 -0
  8. reflex/.templates/web/app/routes.js +10 -0
  9. reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +12 -32
  10. reflex/.templates/web/postcss.config.js +1 -1
  11. reflex/.templates/web/react-router.config.js +6 -0
  12. reflex/.templates/web/utils/client_side_routing.js +21 -19
  13. reflex/.templates/web/utils/react-theme.js +89 -0
  14. reflex/.templates/web/utils/state.js +155 -67
  15. reflex/.templates/web/vite.config.js +32 -0
  16. reflex/__init__.py +1 -6
  17. reflex/__init__.pyi +0 -4
  18. reflex/app.py +69 -132
  19. reflex/base.py +1 -87
  20. reflex/compiler/compiler.py +40 -3
  21. reflex/compiler/utils.py +54 -28
  22. reflex/components/__init__.py +0 -2
  23. reflex/components/__init__.pyi +0 -3
  24. reflex/components/base/__init__.py +1 -5
  25. reflex/components/base/__init__.pyi +4 -6
  26. reflex/components/base/app_wrap.pyi +5 -4
  27. reflex/components/base/body.pyi +5 -4
  28. reflex/components/base/document.py +18 -14
  29. reflex/components/base/document.pyi +83 -27
  30. reflex/components/base/error_boundary.pyi +5 -4
  31. reflex/components/base/fragment.pyi +5 -4
  32. reflex/components/base/link.pyi +9 -7
  33. reflex/components/base/meta.pyi +17 -13
  34. reflex/components/base/script.py +60 -58
  35. reflex/components/base/script.pyi +246 -31
  36. reflex/components/base/strict_mode.pyi +5 -4
  37. reflex/components/component.py +109 -194
  38. reflex/components/core/__init__.py +1 -0
  39. reflex/components/core/__init__.pyi +1 -0
  40. reflex/components/core/auto_scroll.pyi +5 -4
  41. reflex/components/core/banner.pyi +25 -19
  42. reflex/components/core/client_side_routing.py +7 -6
  43. reflex/components/core/client_side_routing.pyi +6 -56
  44. reflex/components/core/clipboard.pyi +5 -4
  45. reflex/components/core/debounce.py +1 -0
  46. reflex/components/core/debounce.pyi +5 -4
  47. reflex/components/core/foreach.py +3 -2
  48. reflex/components/core/helmet.py +14 -0
  49. reflex/components/{next/base.pyi → core/helmet.pyi} +10 -7
  50. reflex/components/core/html.pyi +5 -4
  51. reflex/components/core/sticky.pyi +17 -13
  52. reflex/components/core/upload.py +2 -1
  53. reflex/components/core/upload.pyi +21 -16
  54. reflex/components/datadisplay/code.pyi +9 -7
  55. reflex/components/datadisplay/dataeditor.pyi +5 -4
  56. reflex/components/datadisplay/shiki_code_block.pyi +13 -10
  57. reflex/components/dynamic.py +4 -5
  58. reflex/components/el/element.pyi +5 -4
  59. reflex/components/el/elements/base.pyi +5 -4
  60. reflex/components/el/elements/forms.pyi +69 -52
  61. reflex/components/el/elements/inline.pyi +113 -85
  62. reflex/components/el/elements/media.pyi +105 -79
  63. reflex/components/el/elements/metadata.pyi +25 -19
  64. reflex/components/el/elements/other.pyi +29 -22
  65. reflex/components/el/elements/scripts.pyi +13 -10
  66. reflex/components/el/elements/sectioning.pyi +61 -46
  67. reflex/components/el/elements/tables.pyi +41 -31
  68. reflex/components/el/elements/typography.pyi +61 -46
  69. reflex/components/field.py +175 -0
  70. reflex/components/gridjs/datatable.py +2 -2
  71. reflex/components/gridjs/datatable.pyi +11 -9
  72. reflex/components/lucide/icon.py +6 -2
  73. reflex/components/lucide/icon.pyi +15 -10
  74. reflex/components/markdown/markdown.pyi +5 -4
  75. reflex/components/moment/moment.pyi +5 -4
  76. reflex/components/plotly/plotly.pyi +19 -10
  77. reflex/components/props.py +376 -27
  78. reflex/components/radix/primitives/accordion.py +8 -1
  79. reflex/components/radix/primitives/accordion.pyi +29 -22
  80. reflex/components/radix/primitives/base.pyi +9 -7
  81. reflex/components/radix/primitives/drawer.pyi +45 -34
  82. reflex/components/radix/primitives/form.pyi +41 -31
  83. reflex/components/radix/primitives/progress.pyi +21 -16
  84. reflex/components/radix/primitives/slider.pyi +21 -16
  85. reflex/components/radix/themes/base.py +3 -3
  86. reflex/components/radix/themes/base.pyi +33 -25
  87. reflex/components/radix/themes/color_mode.pyi +13 -10
  88. reflex/components/radix/themes/components/alert_dialog.pyi +29 -22
  89. reflex/components/radix/themes/components/aspect_ratio.pyi +5 -4
  90. reflex/components/radix/themes/components/avatar.pyi +5 -4
  91. reflex/components/radix/themes/components/badge.pyi +5 -4
  92. reflex/components/radix/themes/components/button.pyi +5 -4
  93. reflex/components/radix/themes/components/callout.pyi +21 -16
  94. reflex/components/radix/themes/components/card.pyi +5 -4
  95. reflex/components/radix/themes/components/checkbox.pyi +13 -10
  96. reflex/components/radix/themes/components/checkbox_cards.pyi +9 -7
  97. reflex/components/radix/themes/components/checkbox_group.pyi +9 -7
  98. reflex/components/radix/themes/components/context_menu.pyi +53 -40
  99. reflex/components/radix/themes/components/data_list.pyi +17 -13
  100. reflex/components/radix/themes/components/dialog.pyi +29 -22
  101. reflex/components/radix/themes/components/dropdown_menu.pyi +33 -25
  102. reflex/components/radix/themes/components/hover_card.pyi +17 -13
  103. reflex/components/radix/themes/components/icon_button.pyi +5 -4
  104. reflex/components/radix/themes/components/inset.pyi +5 -4
  105. reflex/components/radix/themes/components/popover.pyi +17 -13
  106. reflex/components/radix/themes/components/progress.pyi +5 -4
  107. reflex/components/radix/themes/components/radio.pyi +5 -4
  108. reflex/components/radix/themes/components/radio_cards.pyi +9 -7
  109. reflex/components/radix/themes/components/radio_group.pyi +17 -13
  110. reflex/components/radix/themes/components/scroll_area.pyi +5 -4
  111. reflex/components/radix/themes/components/segmented_control.pyi +9 -7
  112. reflex/components/radix/themes/components/select.pyi +37 -28
  113. reflex/components/radix/themes/components/separator.pyi +5 -4
  114. reflex/components/radix/themes/components/skeleton.pyi +5 -4
  115. reflex/components/radix/themes/components/slider.pyi +5 -4
  116. reflex/components/radix/themes/components/spinner.pyi +5 -4
  117. reflex/components/radix/themes/components/switch.pyi +5 -4
  118. reflex/components/radix/themes/components/table.pyi +29 -22
  119. reflex/components/radix/themes/components/tabs.pyi +21 -16
  120. reflex/components/radix/themes/components/text_area.pyi +5 -4
  121. reflex/components/radix/themes/components/text_field.pyi +13 -10
  122. reflex/components/radix/themes/components/tooltip.pyi +5 -4
  123. reflex/components/radix/themes/layout/base.pyi +5 -4
  124. reflex/components/radix/themes/layout/box.pyi +5 -4
  125. reflex/components/radix/themes/layout/center.pyi +5 -4
  126. reflex/components/radix/themes/layout/container.pyi +5 -4
  127. reflex/components/radix/themes/layout/flex.pyi +5 -4
  128. reflex/components/radix/themes/layout/grid.pyi +5 -4
  129. reflex/components/radix/themes/layout/list.pyi +21 -16
  130. reflex/components/radix/themes/layout/section.pyi +5 -4
  131. reflex/components/radix/themes/layout/spacer.pyi +5 -4
  132. reflex/components/radix/themes/layout/stack.pyi +13 -10
  133. reflex/components/radix/themes/typography/blockquote.pyi +5 -4
  134. reflex/components/radix/themes/typography/code.pyi +5 -4
  135. reflex/components/radix/themes/typography/heading.pyi +5 -4
  136. reflex/components/radix/themes/typography/link.py +42 -9
  137. reflex/components/radix/themes/typography/link.pyi +311 -6
  138. reflex/components/radix/themes/typography/text.pyi +29 -22
  139. reflex/components/react_player/audio.pyi +5 -4
  140. reflex/components/react_player/react_player.pyi +5 -4
  141. reflex/components/react_player/video.pyi +5 -4
  142. reflex/components/recharts/cartesian.py +2 -1
  143. reflex/components/recharts/cartesian.pyi +65 -46
  144. reflex/components/recharts/charts.py +4 -2
  145. reflex/components/recharts/charts.pyi +36 -24
  146. reflex/components/recharts/general.pyi +24 -18
  147. reflex/components/recharts/polar.py +8 -4
  148. reflex/components/recharts/polar.pyi +16 -10
  149. reflex/components/recharts/recharts.pyi +9 -7
  150. reflex/components/sonner/toast.py +2 -2
  151. reflex/components/sonner/toast.pyi +7 -6
  152. reflex/config.py +3 -77
  153. reflex/constants/__init__.py +1 -0
  154. reflex/constants/base.py +38 -8
  155. reflex/constants/compiler.py +4 -2
  156. reflex/constants/event.py +1 -0
  157. reflex/constants/installer.py +23 -16
  158. reflex/constants/state.py +2 -0
  159. reflex/custom_components/custom_components.py +0 -14
  160. reflex/environment.py +1 -1
  161. reflex/event.py +178 -81
  162. reflex/experimental/__init__.py +0 -30
  163. reflex/istate/proxy.py +5 -3
  164. reflex/page.py +0 -27
  165. reflex/plugins/__init__.py +3 -2
  166. reflex/plugins/base.py +5 -1
  167. reflex/plugins/shared_tailwind.py +158 -0
  168. reflex/plugins/sitemap.py +206 -0
  169. reflex/plugins/tailwind_v3.py +13 -106
  170. reflex/plugins/tailwind_v4.py +15 -108
  171. reflex/reflex.py +1 -0
  172. reflex/state.py +134 -140
  173. reflex/testing.py +57 -9
  174. reflex/utils/build.py +9 -69
  175. reflex/utils/exec.py +59 -161
  176. reflex/utils/export.py +1 -1
  177. reflex/utils/imports.py +0 -4
  178. reflex/utils/misc.py +28 -0
  179. reflex/utils/prerequisites.py +62 -59
  180. reflex/utils/processes.py +6 -6
  181. reflex/utils/pyi_generator.py +21 -9
  182. reflex/utils/serializers.py +14 -1
  183. reflex/utils/types.py +196 -61
  184. reflex/vars/__init__.py +2 -0
  185. reflex/vars/base.py +367 -134
  186. {reflex-0.7.14a5.dist-info → reflex-0.8.0a1.dist-info}/METADATA +12 -5
  187. {reflex-0.7.14a5.dist-info → reflex-0.8.0a1.dist-info}/RECORD +190 -196
  188. reflex/.templates/web/next.config.js +0 -7
  189. reflex/components/base/head.py +0 -20
  190. reflex/components/base/head.pyi +0 -116
  191. reflex/components/next/__init__.py +0 -10
  192. reflex/components/next/base.py +0 -7
  193. reflex/components/next/image.py +0 -117
  194. reflex/components/next/image.pyi +0 -94
  195. reflex/components/next/link.py +0 -20
  196. reflex/components/next/link.pyi +0 -67
  197. reflex/components/next/video.py +0 -38
  198. reflex/components/next/video.pyi +0 -68
  199. reflex/components/suneditor/__init__.py +0 -5
  200. reflex/components/suneditor/editor.py +0 -269
  201. reflex/components/suneditor/editor.pyi +0 -199
  202. reflex/experimental/layout.py +0 -254
  203. {reflex-0.7.14a5.dist-info → reflex-0.8.0a1.dist-info}/WHEEL +0 -0
  204. {reflex-0.7.14a5.dist-info → reflex-0.8.0a1.dist-info}/entry_points.txt +0 -0
  205. {reflex-0.7.14a5.dist-info → reflex-0.8.0a1.dist-info}/licenses/LICENSE +0 -0
reflex/vars/base.py CHANGED
@@ -14,11 +14,14 @@ import re
14
14
  import string
15
15
  import uuid
16
16
  import warnings
17
+ from abc import ABCMeta
17
18
  from collections.abc import Callable, Coroutine, Iterable, Mapping, Sequence
19
+ from dataclasses import _MISSING_TYPE, MISSING
18
20
  from decimal import Decimal
19
21
  from types import CodeType, FunctionType
20
22
  from typing import ( # noqa: UP035
21
23
  TYPE_CHECKING,
24
+ Annotated,
22
25
  Any,
23
26
  ClassVar,
24
27
  Dict,
@@ -40,11 +43,12 @@ from typing import ( # noqa: UP035
40
43
  )
41
44
 
42
45
  from rich.markup import escape
43
- from typing_extensions import deprecated, override
46
+ from typing_extensions import dataclass_transform, override
44
47
 
45
48
  from reflex import constants
46
49
  from reflex.base import Base
47
50
  from reflex.constants.compiler import Hooks
51
+ from reflex.constants.state import FIELD_MARKER
48
52
  from reflex.utils import console, exceptions, imports, serializers, types
49
53
  from reflex.utils.exceptions import (
50
54
  ComputedVarSignatureError,
@@ -416,37 +420,6 @@ class Var(Generic[VAR_TYPE], metaclass=MetaclassVar):
416
420
  """
417
421
  return False
418
422
 
419
- @property
420
- @deprecated("Use `_js_expr` instead.")
421
- def _var_name(self) -> str:
422
- """The name of the var.
423
-
424
- Returns:
425
- The name of the var.
426
- """
427
- return self._js_expr
428
-
429
- @property
430
- def _var_field_name(self) -> str:
431
- """The name of the field.
432
-
433
- Returns:
434
- The name of the field.
435
- """
436
- var_data = self._get_all_var_data()
437
- field_name = var_data.field_name if var_data else None
438
- return field_name or self._js_expr
439
-
440
- @property
441
- @deprecated("Use `_js_expr` instead.")
442
- def _var_name_unwrapped(self) -> str:
443
- """The name of the var without extra curly braces.
444
-
445
- Returns:
446
- The name of the var.
447
- """
448
- return self._js_expr
449
-
450
423
  @property
451
424
  def _var_is_string(self) -> bool:
452
425
  """Whether the var is a string literal.
@@ -727,24 +700,6 @@ class Var(Generic[VAR_TYPE], metaclass=MetaclassVar):
727
700
 
728
701
  return LiteralVar.create(value, _var_data=_var_data)
729
702
 
730
- @classmethod
731
- @deprecated("Use `.create()` instead.")
732
- def create_safe(
733
- cls,
734
- *args: Any,
735
- **kwargs: Any,
736
- ) -> Var:
737
- """Create a var from a value.
738
-
739
- Args:
740
- *args: The arguments to create the var from.
741
- **kwargs: The keyword arguments to create the var from.
742
-
743
- Returns:
744
- The var.
745
- """
746
- return cls.create(*args, **kwargs)
747
-
748
703
  def __format__(self, format_spec: str) -> str:
749
704
  """Format the var into a Javascript equivalent to an f-string.
750
705
 
@@ -952,72 +907,29 @@ class Var(Generic[VAR_TYPE], metaclass=MetaclassVar):
952
907
 
953
908
  return self
954
909
 
955
- def _get_default_value(self) -> Any:
956
- """Get the default value of the var.
957
-
958
- Returns:
959
- The default value of the var.
960
-
961
- Raises:
962
- ImportError: If the var is a dataframe and pandas is not installed.
963
- """
964
- if types.is_optional(self._var_type):
965
- return None
966
-
967
- type_ = (
968
- get_origin(self._var_type)
969
- if types.is_generic_alias(self._var_type)
970
- else self._var_type
971
- )
972
- if type_ is Literal:
973
- args = get_args(self._var_type)
974
- return args[0] if args else None
975
- if safe_issubclass(type_, str):
976
- return ""
977
- if safe_issubclass(type_, types.get_args(int | float)):
978
- return 0
979
- if safe_issubclass(type_, bool):
980
- return False
981
- if safe_issubclass(type_, list):
982
- return []
983
- if safe_issubclass(type_, Mapping):
984
- return {}
985
- if safe_issubclass(type_, tuple):
986
- return ()
987
- if types.is_dataframe(type_):
988
- try:
989
- import pandas as pd
990
-
991
- return pd.DataFrame()
992
- except ImportError as e:
993
- msg = "Please install pandas to use dataframes in your app."
994
- raise ImportError(msg) from e
995
- return set() if safe_issubclass(type_, set) else None
996
-
997
- def _get_setter_name(self, include_state: bool = True) -> str:
910
+ @staticmethod
911
+ def _get_setter_name_for_name(
912
+ name: str,
913
+ ) -> str:
998
914
  """Get the name of the var's generated setter function.
999
915
 
1000
916
  Args:
1001
- include_state: Whether to include the state name in the setter name.
917
+ name: The name of the var.
1002
918
 
1003
919
  Returns:
1004
920
  The name of the setter function.
1005
921
  """
1006
- setter = constants.SETTER_PREFIX + self._var_field_name
1007
- var_data = self._get_all_var_data()
1008
- if var_data is None:
1009
- return setter
1010
- if not include_state or var_data.state == "":
1011
- return setter
1012
- return var_data.state + "." + setter
922
+ return constants.SETTER_PREFIX + name
1013
923
 
1014
- def _get_setter(self) -> Callable[[BaseState, Any], None]:
924
+ def _get_setter(self, name: str) -> Callable[[BaseState, Any], None]:
1015
925
  """Get the var's setter function.
1016
926
 
927
+ Args:
928
+ name: The name of the var.
929
+
1017
930
  Returns:
1018
931
  A function that that creates a setter for the var.
1019
932
  """
1020
- actual_name = self._var_field_name
1021
933
 
1022
934
  def setter(state: Any, value: Any):
1023
935
  """Get the setter for the var.
@@ -1029,17 +941,17 @@ class Var(Generic[VAR_TYPE], metaclass=MetaclassVar):
1029
941
  if self._var_type in [int, float]:
1030
942
  try:
1031
943
  value = self._var_type(value)
1032
- setattr(state, actual_name, value)
944
+ setattr(state, name, value)
1033
945
  except ValueError:
1034
946
  console.debug(
1035
947
  f"{type(state).__name__}.{self._js_expr}: Failed conversion of {value!s} to '{self._var_type.__name__}'. Value not set.",
1036
948
  )
1037
949
  else:
1038
- setattr(state, actual_name, value)
950
+ setattr(state, name, value)
1039
951
 
1040
952
  setter.__annotations__["value"] = self._var_type
1041
953
 
1042
- setter.__qualname__ = self._get_setter_name()
954
+ setter.__qualname__ = Var._get_setter_name_for_name(name)
1043
955
 
1044
956
  return setter
1045
957
 
@@ -1218,18 +1130,6 @@ class Var(Generic[VAR_TYPE], metaclass=MetaclassVar):
1218
1130
  ).to(ObjectVar, Mapping[str, str])
1219
1131
  return refs[LiteralVar.create(str(self))]
1220
1132
 
1221
- @deprecated("Use `.js_type()` instead.")
1222
- def _type(self) -> StringVar:
1223
- """Returns the type of the object.
1224
-
1225
- This method uses the `typeof` function from the `FunctionStringVar` class
1226
- to determine the type of the object.
1227
-
1228
- Returns:
1229
- StringVar: A string variable representing the type of the object.
1230
- """
1231
- return self.js_type()
1232
-
1233
1133
  def js_type(self) -> StringVar:
1234
1134
  """Returns the javascript type of the object.
1235
1135
 
@@ -2111,6 +2011,8 @@ class ComputedVar(Var[RETURN_TYPE]):
2111
2011
  default_factory=lambda: lambda _: None
2112
2012
  ) # pyright: ignore [reportAssignmentType]
2113
2013
 
2014
+ _name: str = dataclasses.field(default="")
2015
+
2114
2016
  def __init__(
2115
2017
  self,
2116
2018
  fget: Callable[[BASE_STATE], RETURN_TYPE],
@@ -2144,14 +2046,18 @@ class ComputedVar(Var[RETURN_TYPE]):
2144
2046
 
2145
2047
  if hint is Any:
2146
2048
  raise UntypedComputedVarError(var_name=fget.__name__)
2147
- kwargs.setdefault("_js_expr", fget.__name__)
2049
+ is_using_fget_name = "_js_expr" not in kwargs
2050
+ js_expr = kwargs.pop("_js_expr", fget.__name__ + FIELD_MARKER)
2148
2051
  kwargs.setdefault("_var_type", hint)
2149
2052
 
2150
2053
  Var.__init__(
2151
2054
  self,
2152
- _js_expr=kwargs.pop("_js_expr"),
2055
+ _js_expr=js_expr,
2153
2056
  _var_type=kwargs.pop("_var_type"),
2154
- _var_data=kwargs.pop("_var_data", None),
2057
+ _var_data=kwargs.pop(
2058
+ "_var_data",
2059
+ VarData(field_name=fget.__name__) if is_using_fget_name else None,
2060
+ ),
2155
2061
  )
2156
2062
 
2157
2063
  if kwargs:
@@ -2164,6 +2070,7 @@ class ComputedVar(Var[RETURN_TYPE]):
2164
2070
  object.__setattr__(self, "_backend", backend)
2165
2071
  object.__setattr__(self, "_initial_value", initial_value)
2166
2072
  object.__setattr__(self, "_cache", cache)
2073
+ object.__setattr__(self, "_name", fget.__name__)
2167
2074
 
2168
2075
  if isinstance(interval, int):
2169
2076
  interval = datetime.timedelta(seconds=interval)
@@ -2395,7 +2302,7 @@ class ComputedVar(Var[RETURN_TYPE]):
2395
2302
  """
2396
2303
  if instance is None:
2397
2304
  state_where_defined = owner
2398
- while self._js_expr in state_where_defined.inherited_vars:
2305
+ while self._name in state_where_defined.inherited_vars:
2399
2306
  state_where_defined = state_where_defined.get_parent_state()
2400
2307
 
2401
2308
  field_name = (
@@ -2406,7 +2313,7 @@ class ComputedVar(Var[RETURN_TYPE]):
2406
2313
 
2407
2314
  return dispatch(
2408
2315
  field_name,
2409
- var_data=VarData.from_state(state_where_defined, self._js_expr),
2316
+ var_data=VarData.from_state(state_where_defined, self._name),
2410
2317
  result_var_type=self._var_type,
2411
2318
  existing_var=self,
2412
2319
  )
@@ -2518,7 +2425,7 @@ class ComputedVar(Var[RETURN_TYPE]):
2518
2425
  objclass.get_root_state().get_class_substate(
2519
2426
  state_name
2520
2427
  )._var_dependencies.setdefault(var_name, set()).add(
2521
- (objclass.get_full_name(), self._js_expr)
2428
+ (objclass.get_full_name(), self._name)
2522
2429
  )
2523
2430
  return
2524
2431
  msg = (
@@ -3382,19 +3289,106 @@ if TYPE_CHECKING:
3382
3289
  MAPPING_TYPE = TypeVar("MAPPING_TYPE", bound=Mapping | None)
3383
3290
  V = TypeVar("V")
3384
3291
 
3292
+
3385
3293
  FIELD_TYPE = TypeVar("FIELD_TYPE")
3386
3294
 
3387
3295
 
3388
3296
  class Field(Generic[FIELD_TYPE]):
3389
- """Shadow class for Var to allow for type hinting in the IDE."""
3297
+ """A field for a state."""
3390
3298
 
3391
- def __set__(self, instance: Any, value: FIELD_TYPE):
3392
- """Set the Var.
3299
+ if TYPE_CHECKING:
3300
+ type_: GenericType
3301
+ default: FIELD_TYPE | _MISSING_TYPE
3302
+ default_factory: Callable[[], FIELD_TYPE] | None
3303
+
3304
+ def __init__(
3305
+ self,
3306
+ default: FIELD_TYPE | _MISSING_TYPE = MISSING,
3307
+ default_factory: Callable[[], FIELD_TYPE] | None = None,
3308
+ is_var: bool = True,
3309
+ annotated_type: GenericType # pyright: ignore [reportRedeclaration]
3310
+ | _MISSING_TYPE = MISSING,
3311
+ ) -> None:
3312
+ """Initialize the field.
3393
3313
 
3394
3314
  Args:
3395
- instance: The instance of the class setting the Var.
3396
- value: The value to set the Var to.
3315
+ default: The default value for the field.
3316
+ default_factory: The default factory for the field.
3317
+ is_var: Whether the field is a Var.
3318
+ annotated_type: The annotated type for the field.
3319
+ """
3320
+ self.default = default
3321
+ self.default_factory = default_factory
3322
+ self.is_var = is_var
3323
+ if annotated_type is not MISSING:
3324
+ type_origin = get_origin(annotated_type) or annotated_type
3325
+ if type_origin is Field and (
3326
+ args := getattr(annotated_type, "__args__", None)
3327
+ ):
3328
+ annotated_type: GenericType = args[0]
3329
+ type_origin = get_origin(annotated_type) or annotated_type
3330
+
3331
+ if self.default is MISSING and self.default_factory is None:
3332
+ default_value = types.get_default_value_for_type(annotated_type)
3333
+ if default_value is None and not types.is_optional(annotated_type):
3334
+ annotated_type = annotated_type | None
3335
+ if types.is_immutable(default_value):
3336
+ self.default = default_value
3337
+ else:
3338
+ self.default_factory = functools.partial(
3339
+ copy.deepcopy, default_value
3340
+ )
3341
+ self.outer_type_ = self.annotated_type = annotated_type
3342
+
3343
+ if type_origin is Annotated:
3344
+ type_origin = annotated_type.__origin__ # pyright: ignore [reportAttributeAccessIssue]
3345
+
3346
+ self.type_ = self.type_origin = type_origin
3347
+ else:
3348
+ self.outer_type_ = self.annotated_type = self.type_ = self.type_origin = Any
3349
+
3350
+ def default_value(self) -> FIELD_TYPE:
3351
+ """Get the default value for the field.
3352
+
3353
+ Returns:
3354
+ The default value for the field.
3355
+
3356
+ Raises:
3357
+ ValueError: If no default value or factory is provided.
3358
+ """
3359
+ if self.default is not MISSING:
3360
+ return self.default
3361
+ if self.default_factory is not None:
3362
+ return self.default_factory()
3363
+ msg = "No default value or factory provided."
3364
+ raise ValueError(msg)
3365
+
3366
+ def __repr__(self) -> str:
3367
+ """Represent the field in a readable format.
3368
+
3369
+ Returns:
3370
+ The string representation of the field.
3397
3371
  """
3372
+ annotated_type_str = (
3373
+ f", annotated_type={self.annotated_type!r}"
3374
+ if self.annotated_type is not MISSING
3375
+ else ""
3376
+ )
3377
+ if self.default is not MISSING:
3378
+ return f"Field(default={self.default!r}, is_var={self.is_var}{annotated_type_str})"
3379
+ return f"Field(default_factory={self.default_factory!r}, is_var={self.is_var}{annotated_type_str})"
3380
+
3381
+ if TYPE_CHECKING:
3382
+
3383
+ def __set__(self, instance: Any, value: FIELD_TYPE):
3384
+ """Set the Var.
3385
+
3386
+ Args:
3387
+ instance: The instance of the class setting the Var.
3388
+ value: The value to set the Var to.
3389
+
3390
+ # noqa: DAR101 self
3391
+ """
3398
3392
 
3399
3393
  @overload
3400
3394
  def __get__(self: Field[None], instance: None, owner: Any) -> NoneVar: ...
@@ -3484,13 +3478,252 @@ class Field(Generic[FIELD_TYPE]):
3484
3478
  """
3485
3479
 
3486
3480
 
3487
- def field(value: FIELD_TYPE) -> Field[FIELD_TYPE]:
3488
- """Create a Field with a value.
3481
+ @overload
3482
+ def field(
3483
+ default: FIELD_TYPE | _MISSING_TYPE = MISSING,
3484
+ *,
3485
+ is_var: Literal[False],
3486
+ default_factory: Callable[[], FIELD_TYPE] | None = None,
3487
+ ) -> FIELD_TYPE: ...
3488
+
3489
+
3490
+ @overload
3491
+ def field(
3492
+ default: FIELD_TYPE | _MISSING_TYPE = MISSING,
3493
+ *,
3494
+ default_factory: Callable[[], FIELD_TYPE] | None = None,
3495
+ is_var: Literal[True] = True,
3496
+ ) -> Field[FIELD_TYPE]: ...
3497
+
3498
+
3499
+ def field(
3500
+ default: FIELD_TYPE | _MISSING_TYPE = MISSING,
3501
+ *,
3502
+ default_factory: Callable[[], FIELD_TYPE] | None = None,
3503
+ is_var: bool = True,
3504
+ ) -> Field[FIELD_TYPE] | FIELD_TYPE:
3505
+ """Create a field for a state.
3489
3506
 
3490
3507
  Args:
3491
- value: The value of the Field.
3508
+ default: The default value for the field.
3509
+ default_factory: The default factory for the field.
3510
+ is_var: Whether the field is a Var.
3492
3511
 
3493
3512
  Returns:
3494
- The Field.
3513
+ The field for the state.
3514
+
3515
+ Raises:
3516
+ ValueError: If both default and default_factory are specified.
3495
3517
  """
3496
- return value # pyright: ignore [reportReturnType]
3518
+ if default is not MISSING and default_factory is not None:
3519
+ msg = "cannot specify both default and default_factory"
3520
+ raise ValueError(msg)
3521
+ if default is not MISSING and not types.is_immutable(default):
3522
+ console.warn(
3523
+ "Mutable default values are not recommended. "
3524
+ "Use default_factory instead to avoid unexpected behavior."
3525
+ )
3526
+ return Field(
3527
+ default_factory=functools.partial(copy.deepcopy, default),
3528
+ is_var=is_var,
3529
+ )
3530
+ return Field(
3531
+ default=default,
3532
+ default_factory=default_factory,
3533
+ is_var=is_var,
3534
+ )
3535
+
3536
+
3537
+ @dataclass_transform(kw_only_default=True, field_specifiers=(field,))
3538
+ class BaseStateMeta(ABCMeta):
3539
+ """Meta class for BaseState."""
3540
+
3541
+ if TYPE_CHECKING:
3542
+ __inherited_fields__: Mapping[str, Field]
3543
+ __own_fields__: dict[str, Field]
3544
+ __fields__: dict[str, Field]
3545
+
3546
+ # Whether this state class is a mixin and should not be instantiated.
3547
+ _mixin: bool = False
3548
+
3549
+ def __new__(
3550
+ cls,
3551
+ name: str,
3552
+ bases: tuple[type],
3553
+ namespace: dict[str, Any],
3554
+ mixin: bool = False,
3555
+ ) -> type:
3556
+ """Create a new class.
3557
+
3558
+ Args:
3559
+ name: The name of the class.
3560
+ bases: The bases of the class.
3561
+ namespace: The namespace of the class.
3562
+ mixin: Whether the class is a mixin and should not be instantiated.
3563
+
3564
+ Returns:
3565
+ The new class.
3566
+ """
3567
+ state_bases = [
3568
+ base for base in bases if issubclass(base, EvenMoreBasicBaseState)
3569
+ ]
3570
+ mixin = mixin or (
3571
+ bool(state_bases) and all(base._mixin for base in state_bases)
3572
+ )
3573
+ # Add the field to the class
3574
+ inherited_fields: dict[str, Field] = {}
3575
+ own_fields: dict[str, Field] = {}
3576
+ resolved_annotations = types.resolve_annotations(
3577
+ namespace.get("__annotations__", {}), namespace["__module__"]
3578
+ )
3579
+
3580
+ for base in bases[::-1]:
3581
+ if hasattr(base, "__inherited_fields__"):
3582
+ inherited_fields.update(base.__inherited_fields__)
3583
+ for base in bases[::-1]:
3584
+ if hasattr(base, "__own_fields__"):
3585
+ inherited_fields.update(base.__own_fields__)
3586
+
3587
+ for key, value in [
3588
+ (key, value)
3589
+ for key, value in namespace.items()
3590
+ if key not in resolved_annotations
3591
+ ]:
3592
+ if isinstance(value, Field):
3593
+ if value.annotated_type is not Any:
3594
+ new_value = value
3595
+ elif value.default is not MISSING:
3596
+ new_value = Field(
3597
+ default=value.default,
3598
+ is_var=value.is_var,
3599
+ annotated_type=figure_out_type(value.default),
3600
+ )
3601
+ else:
3602
+ new_value = Field(
3603
+ default_factory=value.default_factory,
3604
+ is_var=value.is_var,
3605
+ annotated_type=Any,
3606
+ )
3607
+ elif (
3608
+ not key.startswith("__")
3609
+ and not callable(value)
3610
+ and not isinstance(value, (staticmethod, classmethod, property, Var))
3611
+ ):
3612
+ if types.is_immutable(value):
3613
+ new_value = Field(
3614
+ default=value,
3615
+ annotated_type=figure_out_type(value),
3616
+ )
3617
+ else:
3618
+ new_value = Field(
3619
+ default_factory=functools.partial(copy.deepcopy, value),
3620
+ annotated_type=figure_out_type(value),
3621
+ )
3622
+ else:
3623
+ continue
3624
+
3625
+ own_fields[key] = new_value
3626
+
3627
+ for key, annotation in resolved_annotations.items():
3628
+ value = namespace.get(key, MISSING)
3629
+
3630
+ if types.is_classvar(annotation):
3631
+ # If the annotation is a classvar, skip it.
3632
+ continue
3633
+
3634
+ if value is MISSING:
3635
+ value = Field(
3636
+ annotated_type=annotation,
3637
+ )
3638
+ elif not isinstance(value, Field):
3639
+ if types.is_immutable(value):
3640
+ value = Field(
3641
+ default=value,
3642
+ annotated_type=annotation,
3643
+ )
3644
+ else:
3645
+ value = Field(
3646
+ default_factory=functools.partial(copy.deepcopy, value),
3647
+ annotated_type=annotation,
3648
+ )
3649
+ else:
3650
+ value = Field(
3651
+ default=value.default,
3652
+ default_factory=value.default_factory,
3653
+ is_var=value.is_var,
3654
+ annotated_type=annotation,
3655
+ )
3656
+
3657
+ own_fields[key] = value
3658
+
3659
+ namespace["__own_fields__"] = own_fields
3660
+ namespace["__inherited_fields__"] = inherited_fields
3661
+ namespace["__fields__"] = inherited_fields | own_fields
3662
+ namespace["_mixin"] = mixin
3663
+ return super().__new__(cls, name, bases, namespace)
3664
+
3665
+
3666
+ class EvenMoreBasicBaseState(metaclass=BaseStateMeta):
3667
+ """A simplified base state class that provides basic functionality."""
3668
+
3669
+ def __init__(
3670
+ self,
3671
+ **kwargs,
3672
+ ):
3673
+ """Initialize the state with the given kwargs.
3674
+
3675
+ Args:
3676
+ **kwargs: The kwargs to pass to the state.
3677
+ """
3678
+ super().__init__()
3679
+ for key, value in kwargs.items():
3680
+ object.__setattr__(self, key, value)
3681
+ for name, value in type(self).get_fields().items():
3682
+ if name not in kwargs:
3683
+ default_value = value.default_value()
3684
+ object.__setattr__(self, name, default_value)
3685
+
3686
+ def set(self, **kwargs):
3687
+ """Mutate the state by setting the given kwargs. Returns the state.
3688
+
3689
+ Args:
3690
+ **kwargs: The kwargs to set.
3691
+
3692
+ Returns:
3693
+ The state with the fields set to the given kwargs.
3694
+ """
3695
+ for key, value in kwargs.items():
3696
+ setattr(self, key, value)
3697
+ return self
3698
+
3699
+ @classmethod
3700
+ def get_fields(cls) -> Mapping[str, Field]:
3701
+ """Get the fields of the component.
3702
+
3703
+ Returns:
3704
+ The fields of the component.
3705
+ """
3706
+ return cls.__fields__
3707
+
3708
+ @classmethod
3709
+ def add_field(cls, name: str, var: Var, default_value: Any):
3710
+ """Add a field to the class after class definition.
3711
+
3712
+ Used by State.add_var() to correctly handle the new variable.
3713
+
3714
+ Args:
3715
+ name: The name of the field to add.
3716
+ var: The variable to add a field for.
3717
+ default_value: The default value of the field.
3718
+ """
3719
+ if types.is_immutable(default_value):
3720
+ new_field = Field(
3721
+ default=default_value,
3722
+ annotated_type=var._var_type,
3723
+ )
3724
+ else:
3725
+ new_field = Field(
3726
+ default_factory=functools.partial(copy.deepcopy, default_value),
3727
+ annotated_type=var._var_type,
3728
+ )
3729
+ cls.__fields__[name] = new_field
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reflex
3
- Version: 0.7.14a5
3
+ Version: 0.8.0a1
4
4
  Summary: Web apps in pure Python.
5
5
  Project-URL: homepage, https://reflex.dev
6
6
  Project-URL: repository, https://github.com/reflex-dev/reflex
@@ -39,8 +39,7 @@ Requires-Dist: wrapt<2.0,>=1.17.0
39
39
  Description-Content-Type: text/markdown
40
40
 
41
41
  <div align="center">
42
- <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_dark.svg#gh-light-mode-only" alt="Reflex Logo" width="300px">
43
- <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_light.svg#gh-dark-mode-only" alt="Reflex Logo" width="300px">
42
+ <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex.svg" alt="Reflex Logo" width="300px">
44
43
 
45
44
  <hr>
46
45
 
@@ -60,7 +59,12 @@ Description-Content-Type: text/markdown
60
59
 
61
60
  ---
62
61
 
63
- # Reflex
62
+ > [!NOTE]
63
+ > 🚀 **Try [Reflex Build](https://build.reflex.dev/)** – our AI-powered app builder that generates full-stack Reflex applications in seconds.
64
+
65
+ ---
66
+
67
+ # Introduction
64
68
 
65
69
  Reflex is a library to build full-stack web apps in pure Python.
66
70
 
@@ -268,7 +272,10 @@ You can create a multi-page app by adding more pages.
268
272
 
269
273
  Reflex launched in December 2022 with the name Pynecone.
270
274
 
271
- Beginning in 2025, [Reflex Cloud](https://cloud.reflex.dev) has launched to provide the best hosting experience for Reflex apps. We will continue to develop it and implement more features.
275
+ 🚀 Introducing [Reflex Build](https://build.reflex.dev/) Our AI-Powered Builder
276
+ Reflex Build uses AI to generate complete full-stack Python applications. It helps you quickly create, customize, and refine your Reflex apps — from frontend components to backend logic — so you can focus on your ideas instead of boilerplate code. Whether you’re prototyping or scaling, Reflex Build accelerates development by intelligently scaffolding and optimizing your app’s entire stack.
277
+
278
+ Alongside this, [Reflex Cloud](https://cloud.reflex.dev) launched in 2025 to offer the best hosting experience for your Reflex apps. We’re continuously improving the platform with new features and capabilities.
272
279
 
273
280
  Reflex has new releases and features coming every week! Make sure to :star: star and :eyes: watch this repository to stay up to date.
274
281