reflex 0.6.8a1__py3-none-any.whl → 0.7.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 (155) hide show
  1. reflex/.templates/jinja/custom_components/pyproject.toml.jinja2 +1 -1
  2. reflex/.templates/jinja/web/pages/_app.js.jinja2 +7 -7
  3. reflex/.templates/jinja/web/pages/utils.js.jinja2 +2 -2
  4. reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +1 -4
  5. reflex/.templates/web/utils/state.js +65 -36
  6. reflex/__init__.py +4 -17
  7. reflex/__init__.pyi +1 -2
  8. reflex/app.py +244 -115
  9. reflex/app_mixins/lifespan.py +9 -9
  10. reflex/app_mixins/middleware.py +6 -6
  11. reflex/app_module_for_backend.py +3 -7
  12. reflex/base.py +7 -7
  13. reflex/compiler/compiler.py +8 -0
  14. reflex/compiler/utils.py +35 -6
  15. reflex/components/base/bare.py +1 -1
  16. reflex/components/base/error_boundary.py +2 -1
  17. reflex/components/base/error_boundary.pyi +2 -1
  18. reflex/components/base/meta.py +2 -2
  19. reflex/components/base/strict_mode.py +10 -0
  20. reflex/components/base/strict_mode.pyi +57 -0
  21. reflex/components/component.py +38 -77
  22. reflex/components/core/banner.py +83 -4
  23. reflex/components/core/banner.pyi +86 -0
  24. reflex/components/core/breakpoints.py +3 -1
  25. reflex/components/core/client_side_routing.py +1 -1
  26. reflex/components/core/client_side_routing.pyi +1 -1
  27. reflex/components/core/cond.py +9 -10
  28. reflex/components/core/debounce.py +1 -1
  29. reflex/components/core/foreach.py +23 -3
  30. reflex/components/core/html.py +1 -1
  31. reflex/components/core/match.py +5 -5
  32. reflex/components/core/sticky.py +160 -0
  33. reflex/components/core/sticky.pyi +449 -0
  34. reflex/components/core/upload.py +2 -2
  35. reflex/components/datadisplay/code.py +5 -14
  36. reflex/components/datadisplay/dataeditor.py +7 -4
  37. reflex/components/datadisplay/logo.py +13 -8
  38. reflex/components/datadisplay/shiki_code_block.py +14 -9
  39. reflex/components/dynamic.py +22 -3
  40. reflex/components/el/constants/reflex.py +1 -1
  41. reflex/components/el/element.py +1 -1
  42. reflex/components/el/elements/forms.py +4 -4
  43. reflex/components/el/elements/forms.pyi +4 -4
  44. reflex/components/lucide/icon.py +46 -8
  45. reflex/components/lucide/icon.pyi +54 -0
  46. reflex/components/markdown/markdown.py +10 -8
  47. reflex/components/moment/moment.py +2 -2
  48. reflex/components/next/image.py +16 -4
  49. reflex/components/next/image.pyi +4 -2
  50. reflex/components/next/link.py +1 -1
  51. reflex/components/plotly/plotly.py +5 -5
  52. reflex/components/props.py +3 -3
  53. reflex/components/radix/__init__.pyi +1 -1
  54. reflex/components/radix/primitives/accordion.py +9 -5
  55. reflex/components/radix/primitives/accordion.pyi +3 -1
  56. reflex/components/radix/primitives/drawer.py +5 -2
  57. reflex/components/radix/primitives/drawer.pyi +4 -4
  58. reflex/components/radix/primitives/form.pyi +6 -6
  59. reflex/components/radix/primitives/progress.py +1 -1
  60. reflex/components/radix/primitives/slider.py +1 -1
  61. reflex/components/radix/themes/color_mode.py +11 -9
  62. reflex/components/radix/themes/components/alert_dialog.py +3 -0
  63. reflex/components/radix/themes/components/card.py +1 -1
  64. reflex/components/radix/themes/components/card.pyi +1 -1
  65. reflex/components/radix/themes/components/context_menu.py +5 -0
  66. reflex/components/radix/themes/components/dialog.py +3 -0
  67. reflex/components/radix/themes/components/dropdown_menu.py +5 -0
  68. reflex/components/radix/themes/components/hover_card.py +3 -0
  69. reflex/components/radix/themes/components/icon_button.py +2 -2
  70. reflex/components/radix/themes/components/icon_button.pyi +1 -0
  71. reflex/components/radix/themes/components/popover.py +3 -0
  72. reflex/components/radix/themes/components/radio_cards.py +2 -0
  73. reflex/components/radix/themes/components/radio_group.py +1 -1
  74. reflex/components/radix/themes/components/select.py +3 -0
  75. reflex/components/radix/themes/components/tabs.py +3 -0
  76. reflex/components/radix/themes/components/text_area.py +12 -0
  77. reflex/components/radix/themes/components/text_area.pyi +2 -0
  78. reflex/components/radix/themes/components/text_field.py +1 -1
  79. reflex/components/radix/themes/components/tooltip.py +3 -1
  80. reflex/components/radix/themes/components/tooltip.pyi +1 -0
  81. reflex/components/radix/themes/layout/__init__.pyi +1 -1
  82. reflex/components/radix/themes/layout/list.py +2 -2
  83. reflex/components/radix/themes/layout/stack.py +2 -2
  84. reflex/components/radix/themes/typography/link.py +1 -1
  85. reflex/components/radix/themes/typography/text.py +2 -2
  86. reflex/components/react_player/react_player.py +1 -1
  87. reflex/components/recharts/__init__.py +2 -0
  88. reflex/components/recharts/__init__.pyi +2 -0
  89. reflex/components/recharts/charts.py +15 -15
  90. reflex/components/recharts/general.py +19 -4
  91. reflex/components/recharts/general.pyi +55 -4
  92. reflex/components/recharts/polar.py +2 -2
  93. reflex/components/recharts/recharts.py +4 -4
  94. reflex/components/sonner/toast.py +15 -13
  95. reflex/components/sonner/toast.pyi +6 -6
  96. reflex/components/suneditor/editor.py +6 -4
  97. reflex/components/suneditor/editor.pyi +2 -2
  98. reflex/components/tags/iter_tag.py +3 -3
  99. reflex/components/tags/tag.py +25 -3
  100. reflex/config.py +48 -20
  101. reflex/constants/__init__.py +1 -0
  102. reflex/constants/base.py +4 -1
  103. reflex/constants/compiler.py +5 -2
  104. reflex/constants/config.py +8 -1
  105. reflex/constants/installer.py +9 -9
  106. reflex/constants/style.py +1 -1
  107. reflex/custom_components/custom_components.py +9 -7
  108. reflex/event.py +137 -163
  109. reflex/experimental/__init__.py +19 -11
  110. reflex/experimental/client_state.py +53 -28
  111. reflex/experimental/hooks.py +5 -5
  112. reflex/experimental/layout.py +8 -5
  113. reflex/experimental/layout.pyi +1 -1
  114. reflex/experimental/misc.py +3 -3
  115. reflex/istate/wrappers.py +1 -1
  116. reflex/middleware/hydrate_middleware.py +2 -2
  117. reflex/model.py +11 -6
  118. reflex/page.py +3 -3
  119. reflex/reflex.py +90 -19
  120. reflex/route.py +1 -1
  121. reflex/state.py +358 -401
  122. reflex/style.py +27 -3
  123. reflex/testing.py +34 -39
  124. reflex/utils/build.py +6 -2
  125. reflex/utils/codespaces.py +1 -4
  126. reflex/utils/compat.py +6 -5
  127. reflex/utils/console.py +52 -21
  128. reflex/utils/exceptions.py +76 -26
  129. reflex/utils/exec.py +69 -74
  130. reflex/utils/export.py +6 -1
  131. reflex/utils/format.py +7 -39
  132. reflex/utils/imports.py +2 -2
  133. reflex/utils/lazy_loader.py +7 -1
  134. reflex/utils/path_ops.py +28 -14
  135. reflex/utils/prerequisites.py +324 -65
  136. reflex/utils/processes.py +45 -32
  137. reflex/utils/pyi_generator.py +30 -25
  138. reflex/utils/registry.py +4 -4
  139. reflex/utils/serializers.py +1 -1
  140. reflex/utils/telemetry.py +5 -4
  141. reflex/utils/types.py +42 -18
  142. reflex/vars/base.py +650 -333
  143. reflex/vars/datetime.py +6 -7
  144. reflex/vars/dep_tracking.py +344 -0
  145. reflex/vars/function.py +11 -5
  146. reflex/vars/number.py +31 -43
  147. reflex/vars/object.py +63 -62
  148. reflex/vars/sequence.py +79 -67
  149. {reflex-0.6.8a1.dist-info → reflex-0.7.0a1.dist-info}/METADATA +7 -10
  150. {reflex-0.6.8a1.dist-info → reflex-0.7.0a1.dist-info}/RECORD +153 -150
  151. {reflex-0.6.8a1.dist-info → reflex-0.7.0a1.dist-info}/WHEEL +1 -1
  152. reflex/experimental/assets.py +0 -37
  153. reflex/proxy.py +0 -119
  154. {reflex-0.6.8a1.dist-info → reflex-0.7.0a1.dist-info}/LICENSE +0 -0
  155. {reflex-0.6.8a1.dist-info → reflex-0.7.0a1.dist-info}/entry_points.txt +0 -0
reflex/vars/number.py CHANGED
@@ -5,7 +5,6 @@ from __future__ import annotations
5
5
  import dataclasses
6
6
  import json
7
7
  import math
8
- import sys
9
8
  from typing import (
10
9
  TYPE_CHECKING,
11
10
  Any,
@@ -18,9 +17,8 @@ from typing import (
18
17
  )
19
18
 
20
19
  from reflex.constants.base import Dirs
21
- from reflex.utils.exceptions import PrimitiveUnserializableToJSON, VarTypeError
20
+ from reflex.utils.exceptions import PrimitiveUnserializableToJSONError, VarTypeError
22
21
  from reflex.utils.imports import ImportDict, ImportVar
23
- from reflex.utils.types import is_optional
24
22
 
25
23
  from .base import (
26
24
  CustomVarOperationReturn,
@@ -32,7 +30,7 @@ from .base import (
32
30
  var_operation_return,
33
31
  )
34
32
 
35
- NUMBER_T = TypeVar("NUMBER_T", int, float, Union[int, float], bool)
33
+ NUMBER_T = TypeVar("NUMBER_T", int, float, bool)
36
34
 
37
35
  if TYPE_CHECKING:
38
36
  from .sequence import ArrayVar
@@ -62,7 +60,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
62
60
  def __add__(self, other: number_types) -> NumberVar: ...
63
61
 
64
62
  @overload
65
- def __add__(self, other: NoReturn) -> NoReturn: ...
63
+ def __add__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
66
64
 
67
65
  def __add__(self, other: Any):
68
66
  """Add two numbers.
@@ -81,7 +79,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
81
79
  def __radd__(self, other: number_types) -> NumberVar: ...
82
80
 
83
81
  @overload
84
- def __radd__(self, other: NoReturn) -> NoReturn: ...
82
+ def __radd__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
85
83
 
86
84
  def __radd__(self, other: Any):
87
85
  """Add two numbers.
@@ -100,7 +98,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
100
98
  def __sub__(self, other: number_types) -> NumberVar: ...
101
99
 
102
100
  @overload
103
- def __sub__(self, other: NoReturn) -> NoReturn: ...
101
+ def __sub__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
104
102
 
105
103
  def __sub__(self, other: Any):
106
104
  """Subtract two numbers.
@@ -120,7 +118,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
120
118
  def __rsub__(self, other: number_types) -> NumberVar: ...
121
119
 
122
120
  @overload
123
- def __rsub__(self, other: NoReturn) -> NoReturn: ...
121
+ def __rsub__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
124
122
 
125
123
  def __rsub__(self, other: Any):
126
124
  """Subtract two numbers.
@@ -161,7 +159,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
161
159
  """
162
160
  from .sequence import ArrayVar, LiteralArrayVar
163
161
 
164
- if isinstance(other, (list, tuple, set, ArrayVar)):
162
+ if isinstance(other, (list, tuple, ArrayVar)):
165
163
  if isinstance(other, ArrayVar):
166
164
  return other * self
167
165
  return LiteralArrayVar.create(other) * self
@@ -188,7 +186,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
188
186
  """
189
187
  from .sequence import ArrayVar, LiteralArrayVar
190
188
 
191
- if isinstance(other, (list, tuple, set, ArrayVar)):
189
+ if isinstance(other, (list, tuple, ArrayVar)):
192
190
  if isinstance(other, ArrayVar):
193
191
  return other * self
194
192
  return LiteralArrayVar.create(other) * self
@@ -202,7 +200,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
202
200
  def __truediv__(self, other: number_types) -> NumberVar: ...
203
201
 
204
202
  @overload
205
- def __truediv__(self, other: NoReturn) -> NoReturn: ...
203
+ def __truediv__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
206
204
 
207
205
  def __truediv__(self, other: Any):
208
206
  """Divide two numbers.
@@ -222,7 +220,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
222
220
  def __rtruediv__(self, other: number_types) -> NumberVar: ...
223
221
 
224
222
  @overload
225
- def __rtruediv__(self, other: NoReturn) -> NoReturn: ...
223
+ def __rtruediv__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
226
224
 
227
225
  def __rtruediv__(self, other: Any):
228
226
  """Divide two numbers.
@@ -242,7 +240,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
242
240
  def __floordiv__(self, other: number_types) -> NumberVar: ...
243
241
 
244
242
  @overload
245
- def __floordiv__(self, other: NoReturn) -> NoReturn: ...
243
+ def __floordiv__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
246
244
 
247
245
  def __floordiv__(self, other: Any):
248
246
  """Floor divide two numbers.
@@ -262,7 +260,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
262
260
  def __rfloordiv__(self, other: number_types) -> NumberVar: ...
263
261
 
264
262
  @overload
265
- def __rfloordiv__(self, other: NoReturn) -> NoReturn: ...
263
+ def __rfloordiv__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
266
264
 
267
265
  def __rfloordiv__(self, other: Any):
268
266
  """Floor divide two numbers.
@@ -282,7 +280,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
282
280
  def __mod__(self, other: number_types) -> NumberVar: ...
283
281
 
284
282
  @overload
285
- def __mod__(self, other: NoReturn) -> NoReturn: ...
283
+ def __mod__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
286
284
 
287
285
  def __mod__(self, other: Any):
288
286
  """Modulo two numbers.
@@ -302,7 +300,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
302
300
  def __rmod__(self, other: number_types) -> NumberVar: ...
303
301
 
304
302
  @overload
305
- def __rmod__(self, other: NoReturn) -> NoReturn: ...
303
+ def __rmod__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
306
304
 
307
305
  def __rmod__(self, other: Any):
308
306
  """Modulo two numbers.
@@ -322,7 +320,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
322
320
  def __pow__(self, other: number_types) -> NumberVar: ...
323
321
 
324
322
  @overload
325
- def __pow__(self, other: NoReturn) -> NoReturn: ...
323
+ def __pow__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
326
324
 
327
325
  def __pow__(self, other: Any):
328
326
  """Exponentiate two numbers.
@@ -342,7 +340,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
342
340
  def __rpow__(self, other: number_types) -> NumberVar: ...
343
341
 
344
342
  @overload
345
- def __rpow__(self, other: NoReturn) -> NoReturn: ...
343
+ def __rpow__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
346
344
 
347
345
  def __rpow__(self, other: Any):
348
346
  """Exponentiate two numbers.
@@ -418,7 +416,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
418
416
  def __lt__(self, other: number_types) -> BooleanVar: ...
419
417
 
420
418
  @overload
421
- def __lt__(self, other: NoReturn) -> NoReturn: ...
419
+ def __lt__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
422
420
 
423
421
  def __lt__(self, other: Any):
424
422
  """Less than comparison.
@@ -431,13 +429,13 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
431
429
  """
432
430
  if not isinstance(other, NUMBER_TYPES):
433
431
  raise_unsupported_operand_types("<", (type(self), type(other)))
434
- return less_than_operation(self, +other)
432
+ return less_than_operation(+self, +other)
435
433
 
436
434
  @overload
437
435
  def __le__(self, other: number_types) -> BooleanVar: ...
438
436
 
439
437
  @overload
440
- def __le__(self, other: NoReturn) -> NoReturn: ...
438
+ def __le__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
441
439
 
442
440
  def __le__(self, other: Any):
443
441
  """Less than or equal comparison.
@@ -450,7 +448,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
450
448
  """
451
449
  if not isinstance(other, NUMBER_TYPES):
452
450
  raise_unsupported_operand_types("<=", (type(self), type(other)))
453
- return less_than_or_equal_operation(self, +other)
451
+ return less_than_or_equal_operation(+self, +other)
454
452
 
455
453
  def __eq__(self, other: Any):
456
454
  """Equal comparison.
@@ -462,7 +460,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
462
460
  The result of the comparison.
463
461
  """
464
462
  if isinstance(other, NUMBER_TYPES):
465
- return equal_operation(self, +other)
463
+ return equal_operation(+self, +other)
466
464
  return equal_operation(self, other)
467
465
 
468
466
  def __ne__(self, other: Any):
@@ -475,14 +473,14 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
475
473
  The result of the comparison.
476
474
  """
477
475
  if isinstance(other, NUMBER_TYPES):
478
- return not_equal_operation(self, +other)
476
+ return not_equal_operation(+self, +other)
479
477
  return not_equal_operation(self, other)
480
478
 
481
479
  @overload
482
480
  def __gt__(self, other: number_types) -> BooleanVar: ...
483
481
 
484
482
  @overload
485
- def __gt__(self, other: NoReturn) -> NoReturn: ...
483
+ def __gt__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
486
484
 
487
485
  def __gt__(self, other: Any):
488
486
  """Greater than comparison.
@@ -495,13 +493,13 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
495
493
  """
496
494
  if not isinstance(other, NUMBER_TYPES):
497
495
  raise_unsupported_operand_types(">", (type(self), type(other)))
498
- return greater_than_operation(self, +other)
496
+ return greater_than_operation(+self, +other)
499
497
 
500
498
  @overload
501
499
  def __ge__(self, other: number_types) -> BooleanVar: ...
502
500
 
503
501
  @overload
504
- def __ge__(self, other: NoReturn) -> NoReturn: ...
502
+ def __ge__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload]
505
503
 
506
504
  def __ge__(self, other: Any):
507
505
  """Greater than or equal comparison.
@@ -514,17 +512,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)):
514
512
  """
515
513
  if not isinstance(other, NUMBER_TYPES):
516
514
  raise_unsupported_operand_types(">=", (type(self), type(other)))
517
- return greater_than_or_equal_operation(self, +other)
518
-
519
- def bool(self):
520
- """Boolean conversion.
521
-
522
- Returns:
523
- The boolean value of the number.
524
- """
525
- if is_optional(self._var_type):
526
- return boolify((self != None) & (self != 0)) # noqa: E711
527
- return self != 0
515
+ return greater_than_or_equal_operation(+self, +other)
528
516
 
529
517
  def _is_strict_float(self) -> bool:
530
518
  """Check if the number is a float.
@@ -572,7 +560,7 @@ def binary_number_operation(
572
560
  Returns:
573
561
  The binary number operation.
574
562
  """
575
- return operation(lhs, rhs) # type: ignore
563
+ return operation(lhs, rhs) # pyright: ignore [reportReturnType, reportArgumentType]
576
564
 
577
565
  return wrapper
578
566
 
@@ -984,7 +972,7 @@ def boolean_not_operation(value: BooleanVar):
984
972
  @dataclasses.dataclass(
985
973
  eq=False,
986
974
  frozen=True,
987
- **{"slots": True} if sys.version_info >= (3, 10) else {},
975
+ slots=True,
988
976
  )
989
977
  class LiteralNumberVar(LiteralVar, NumberVar):
990
978
  """Base class for immutable literal number vars."""
@@ -998,10 +986,10 @@ class LiteralNumberVar(LiteralVar, NumberVar):
998
986
  The JSON representation of the var.
999
987
 
1000
988
  Raises:
1001
- PrimitiveUnserializableToJSON: If the var is unserializable to JSON.
989
+ PrimitiveUnserializableToJSONError: If the var is unserializable to JSON.
1002
990
  """
1003
991
  if math.isinf(self._var_value) or math.isnan(self._var_value):
1004
- raise PrimitiveUnserializableToJSON(
992
+ raise PrimitiveUnserializableToJSONError(
1005
993
  f"No valid JSON representation for {self}"
1006
994
  )
1007
995
  return json.dumps(self._var_value)
@@ -1043,7 +1031,7 @@ class LiteralNumberVar(LiteralVar, NumberVar):
1043
1031
  @dataclasses.dataclass(
1044
1032
  eq=False,
1045
1033
  frozen=True,
1046
- **{"slots": True} if sys.version_info >= (3, 10) else {},
1034
+ slots=True,
1047
1035
  )
1048
1036
  class LiteralBooleanVar(LiteralVar, BooleanVar):
1049
1037
  """Base class for immutable literal boolean vars."""
reflex/vars/object.py CHANGED
@@ -3,13 +3,12 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import dataclasses
6
- import sys
7
6
  import typing
8
7
  from inspect import isclass
9
8
  from typing import (
10
9
  Any,
11
- Dict,
12
10
  List,
11
+ Mapping,
13
12
  NoReturn,
14
13
  Tuple,
15
14
  Type,
@@ -19,6 +18,8 @@ from typing import (
19
18
  overload,
20
19
  )
21
20
 
21
+ from typing_extensions import is_typeddict
22
+
22
23
  from reflex.utils import types
23
24
  from reflex.utils.exceptions import VarAttributeError
24
25
  from reflex.utils.types import GenericType, get_attribute_access_type, get_origin
@@ -36,7 +37,7 @@ from .base import (
36
37
  from .number import BooleanVar, NumberVar, raise_unsupported_operand_types
37
38
  from .sequence import ArrayVar, StringVar
38
39
 
39
- OBJECT_TYPE = TypeVar("OBJECT_TYPE")
40
+ OBJECT_TYPE = TypeVar("OBJECT_TYPE", covariant=True)
40
41
 
41
42
  KEY_TYPE = TypeVar("KEY_TYPE")
42
43
  VALUE_TYPE = TypeVar("VALUE_TYPE")
@@ -46,7 +47,7 @@ ARRAY_INNER_TYPE = TypeVar("ARRAY_INNER_TYPE")
46
47
  OTHER_KEY_TYPE = TypeVar("OTHER_KEY_TYPE")
47
48
 
48
49
 
49
- class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
50
+ class ObjectVar(Var[OBJECT_TYPE], python_types=Mapping):
50
51
  """Base class for immutable object vars."""
51
52
 
52
53
  def _key_type(self) -> Type:
@@ -59,7 +60,7 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
59
60
 
60
61
  @overload
61
62
  def _value_type(
62
- self: ObjectVar[Dict[Any, VALUE_TYPE]],
63
+ self: ObjectVar[Mapping[Any, VALUE_TYPE]],
63
64
  ) -> Type[VALUE_TYPE]: ...
64
65
 
65
66
  @overload
@@ -73,9 +74,9 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
73
74
  """
74
75
  fixed_type = get_origin(self._var_type) or self._var_type
75
76
  if not isclass(fixed_type):
76
- return Any
77
- args = get_args(self._var_type) if issubclass(fixed_type, dict) else ()
78
- return args[1] if args else Any
77
+ return Any # pyright: ignore [reportReturnType]
78
+ args = get_args(self._var_type) if issubclass(fixed_type, Mapping) else ()
79
+ return args[1] if args else Any # pyright: ignore [reportReturnType]
79
80
 
80
81
  def keys(self) -> ArrayVar[List[str]]:
81
82
  """Get the keys of the object.
@@ -87,7 +88,7 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
87
88
 
88
89
  @overload
89
90
  def values(
90
- self: ObjectVar[Dict[Any, VALUE_TYPE]],
91
+ self: ObjectVar[Mapping[Any, VALUE_TYPE]],
91
92
  ) -> ArrayVar[List[VALUE_TYPE]]: ...
92
93
 
93
94
  @overload
@@ -103,7 +104,7 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
103
104
 
104
105
  @overload
105
106
  def entries(
106
- self: ObjectVar[Dict[Any, VALUE_TYPE]],
107
+ self: ObjectVar[Mapping[Any, VALUE_TYPE]],
107
108
  ) -> ArrayVar[List[Tuple[str, VALUE_TYPE]]]: ...
108
109
 
109
110
  @overload
@@ -132,50 +133,50 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
132
133
 
133
134
  # NoReturn is used here to catch when key value is Any
134
135
  @overload
135
- def __getitem__(
136
- self: ObjectVar[Dict[Any, NoReturn]],
136
+ def __getitem__( # pyright: ignore [reportOverlappingOverload]
137
+ self: ObjectVar[Mapping[Any, NoReturn]],
137
138
  key: Var | Any,
138
139
  ) -> Var: ...
139
140
 
141
+ @overload
142
+ def __getitem__(
143
+ self: (ObjectVar[Mapping[Any, bool]]),
144
+ key: Var | Any,
145
+ ) -> BooleanVar: ...
146
+
140
147
  @overload
141
148
  def __getitem__(
142
149
  self: (
143
- ObjectVar[Dict[Any, int]]
144
- | ObjectVar[Dict[Any, float]]
145
- | ObjectVar[Dict[Any, int | float]]
150
+ ObjectVar[Mapping[Any, int]]
151
+ | ObjectVar[Mapping[Any, float]]
152
+ | ObjectVar[Mapping[Any, int | float]]
146
153
  ),
147
154
  key: Var | Any,
148
155
  ) -> NumberVar: ...
149
156
 
150
157
  @overload
151
158
  def __getitem__(
152
- self: ObjectVar[Dict[Any, str]],
159
+ self: ObjectVar[Mapping[Any, str]],
153
160
  key: Var | Any,
154
161
  ) -> StringVar: ...
155
162
 
156
163
  @overload
157
164
  def __getitem__(
158
- self: ObjectVar[Dict[Any, list[ARRAY_INNER_TYPE]]],
165
+ self: ObjectVar[Mapping[Any, list[ARRAY_INNER_TYPE]]],
159
166
  key: Var | Any,
160
167
  ) -> ArrayVar[list[ARRAY_INNER_TYPE]]: ...
161
168
 
162
169
  @overload
163
170
  def __getitem__(
164
- self: ObjectVar[Dict[Any, set[ARRAY_INNER_TYPE]]],
165
- key: Var | Any,
166
- ) -> ArrayVar[set[ARRAY_INNER_TYPE]]: ...
167
-
168
- @overload
169
- def __getitem__(
170
- self: ObjectVar[Dict[Any, tuple[ARRAY_INNER_TYPE, ...]]],
171
+ self: ObjectVar[Mapping[Any, tuple[ARRAY_INNER_TYPE, ...]]],
171
172
  key: Var | Any,
172
173
  ) -> ArrayVar[tuple[ARRAY_INNER_TYPE, ...]]: ...
173
174
 
174
175
  @overload
175
176
  def __getitem__(
176
- self: ObjectVar[Dict[Any, dict[OTHER_KEY_TYPE, VALUE_TYPE]]],
177
+ self: ObjectVar[Mapping[Any, Mapping[OTHER_KEY_TYPE, VALUE_TYPE]]],
177
178
  key: Var | Any,
178
- ) -> ObjectVar[dict[OTHER_KEY_TYPE, VALUE_TYPE]]: ...
179
+ ) -> ObjectVar[Mapping[OTHER_KEY_TYPE, VALUE_TYPE]]: ...
179
180
 
180
181
  def __getitem__(self, key: Var | Any) -> Var:
181
182
  """Get an item from the object.
@@ -194,50 +195,44 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
194
195
 
195
196
  # NoReturn is used here to catch when key value is Any
196
197
  @overload
197
- def __getattr__(
198
- self: ObjectVar[Dict[Any, NoReturn]],
198
+ def __getattr__( # pyright: ignore [reportOverlappingOverload]
199
+ self: ObjectVar[Mapping[Any, NoReturn]],
199
200
  name: str,
200
201
  ) -> Var: ...
201
202
 
202
203
  @overload
203
204
  def __getattr__(
204
205
  self: (
205
- ObjectVar[Dict[Any, int]]
206
- | ObjectVar[Dict[Any, float]]
207
- | ObjectVar[Dict[Any, int | float]]
206
+ ObjectVar[Mapping[Any, int]]
207
+ | ObjectVar[Mapping[Any, float]]
208
+ | ObjectVar[Mapping[Any, int | float]]
208
209
  ),
209
210
  name: str,
210
211
  ) -> NumberVar: ...
211
212
 
212
213
  @overload
213
214
  def __getattr__(
214
- self: ObjectVar[Dict[Any, str]],
215
+ self: ObjectVar[Mapping[Any, str]],
215
216
  name: str,
216
217
  ) -> StringVar: ...
217
218
 
218
219
  @overload
219
220
  def __getattr__(
220
- self: ObjectVar[Dict[Any, list[ARRAY_INNER_TYPE]]],
221
+ self: ObjectVar[Mapping[Any, list[ARRAY_INNER_TYPE]]],
221
222
  name: str,
222
223
  ) -> ArrayVar[list[ARRAY_INNER_TYPE]]: ...
223
224
 
224
225
  @overload
225
226
  def __getattr__(
226
- self: ObjectVar[Dict[Any, set[ARRAY_INNER_TYPE]]],
227
- name: str,
228
- ) -> ArrayVar[set[ARRAY_INNER_TYPE]]: ...
229
-
230
- @overload
231
- def __getattr__(
232
- self: ObjectVar[Dict[Any, tuple[ARRAY_INNER_TYPE, ...]]],
227
+ self: ObjectVar[Mapping[Any, tuple[ARRAY_INNER_TYPE, ...]]],
233
228
  name: str,
234
229
  ) -> ArrayVar[tuple[ARRAY_INNER_TYPE, ...]]: ...
235
230
 
236
231
  @overload
237
232
  def __getattr__(
238
- self: ObjectVar[Dict[Any, dict[OTHER_KEY_TYPE, VALUE_TYPE]]],
233
+ self: ObjectVar[Mapping[Any, Mapping[OTHER_KEY_TYPE, VALUE_TYPE]]],
239
234
  name: str,
240
- ) -> ObjectVar[dict[OTHER_KEY_TYPE, VALUE_TYPE]]: ...
235
+ ) -> ObjectVar[Mapping[OTHER_KEY_TYPE, VALUE_TYPE]]: ...
241
236
 
242
237
  @overload
243
238
  def __getattr__(
@@ -245,7 +240,7 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
245
240
  name: str,
246
241
  ) -> ObjectItemOperation: ...
247
242
 
248
- def __getattr__(self, name) -> Var:
243
+ def __getattr__(self, name: str) -> Var:
249
244
  """Get an attribute of the var.
250
245
 
251
246
  Args:
@@ -266,8 +261,11 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
266
261
  var_type = get_args(var_type)[0]
267
262
 
268
263
  fixed_type = var_type if isclass(var_type) else get_origin(var_type)
269
- if (isclass(fixed_type) and not issubclass(fixed_type, dict)) or (
270
- fixed_type in types.UnionTypes
264
+
265
+ if (
266
+ (isclass(fixed_type) and not issubclass(fixed_type, Mapping))
267
+ or (fixed_type in types.UnionTypes)
268
+ or is_typeddict(fixed_type)
271
269
  ):
272
270
  attribute_type = get_attribute_access_type(var_type, name)
273
271
  if attribute_type is None:
@@ -294,12 +292,12 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=dict):
294
292
  @dataclasses.dataclass(
295
293
  eq=False,
296
294
  frozen=True,
297
- **{"slots": True} if sys.version_info >= (3, 10) else {},
295
+ slots=True,
298
296
  )
299
297
  class LiteralObjectVar(CachedVarOperation, ObjectVar[OBJECT_TYPE], LiteralVar):
300
298
  """Base class for immutable literal object vars."""
301
299
 
302
- _var_value: Dict[Union[Var, Any], Union[Var, Any]] = dataclasses.field(
300
+ _var_value: Mapping[Union[Var, Any], Union[Var, Any]] = dataclasses.field(
303
301
  default_factory=dict
304
302
  )
305
303
 
@@ -310,7 +308,7 @@ class LiteralObjectVar(CachedVarOperation, ObjectVar[OBJECT_TYPE], LiteralVar):
310
308
  The type of the keys of the object.
311
309
  """
312
310
  args_list = typing.get_args(self._var_type)
313
- return args_list[0] if args_list else Any
311
+ return args_list[0] if args_list else Any # pyright: ignore [reportReturnType]
314
312
 
315
313
  def _value_type(self) -> Type:
316
314
  """Get the type of the values of the object.
@@ -319,7 +317,7 @@ class LiteralObjectVar(CachedVarOperation, ObjectVar[OBJECT_TYPE], LiteralVar):
319
317
  The type of the values of the object.
320
318
  """
321
319
  args_list = typing.get_args(self._var_type)
322
- return args_list[1] if args_list else Any
320
+ return args_list[1] if args_list else Any # pyright: ignore [reportReturnType]
323
321
 
324
322
  @cached_property_no_lock
325
323
  def _cached_var_name(self) -> str:
@@ -344,17 +342,20 @@ class LiteralObjectVar(CachedVarOperation, ObjectVar[OBJECT_TYPE], LiteralVar):
344
342
 
345
343
  Returns:
346
344
  The JSON representation of the object.
345
+
346
+ Raises:
347
+ TypeError: The keys and values of the object must be literal vars to get the JSON representation
347
348
  """
348
- return (
349
- "{"
350
- + ", ".join(
351
- [
352
- f"{LiteralVar.create(key).json()}:{LiteralVar.create(value).json()}"
353
- for key, value in self._var_value.items()
354
- ]
355
- )
356
- + "}"
357
- )
349
+ keys_and_values = []
350
+ for key, value in self._var_value.items():
351
+ key = LiteralVar.create(key)
352
+ value = LiteralVar.create(value)
353
+ if not isinstance(key, LiteralVar) or not isinstance(value, LiteralVar):
354
+ raise TypeError(
355
+ "The keys and values of the object must be literal vars to get the JSON representation."
356
+ )
357
+ keys_and_values.append(f"{key.json()}:{value.json()}")
358
+ return "{" + ", ".join(keys_and_values) + "}"
358
359
 
359
360
  def __hash__(self) -> int:
360
361
  """Get the hash of the var.
@@ -383,7 +384,7 @@ class LiteralObjectVar(CachedVarOperation, ObjectVar[OBJECT_TYPE], LiteralVar):
383
384
  @classmethod
384
385
  def create(
385
386
  cls,
386
- _var_value: dict,
387
+ _var_value: Mapping,
387
388
  _var_type: Type[OBJECT_TYPE] | None = None,
388
389
  _var_data: VarData | None = None,
389
390
  ) -> LiteralObjectVar[OBJECT_TYPE]:
@@ -466,7 +467,7 @@ def object_merge_operation(lhs: ObjectVar, rhs: ObjectVar):
466
467
  """
467
468
  return var_operation_return(
468
469
  js_expression=f"({{...{lhs}, ...{rhs}}})",
469
- var_type=Dict[
470
+ var_type=Mapping[
470
471
  Union[lhs._key_type(), rhs._key_type()],
471
472
  Union[lhs._value_type(), rhs._value_type()],
472
473
  ],
@@ -476,7 +477,7 @@ def object_merge_operation(lhs: ObjectVar, rhs: ObjectVar):
476
477
  @dataclasses.dataclass(
477
478
  eq=False,
478
479
  frozen=True,
479
- **{"slots": True} if sys.version_info >= (3, 10) else {},
480
+ slots=True,
480
481
  )
481
482
  class ObjectItemOperation(CachedVarOperation, Var):
482
483
  """Operation to get an item from an object."""