reflex 0.6.8a2__py3-none-any.whl → 0.7.0__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 (247) 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 +3 -3
  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 +286 -129
  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 +57 -18
  15. reflex/components/base/app_wrap.pyi +16 -16
  16. reflex/components/base/bare.py +1 -1
  17. reflex/components/base/body.pyi +16 -16
  18. reflex/components/base/document.pyi +76 -76
  19. reflex/components/base/error_boundary.py +2 -1
  20. reflex/components/base/error_boundary.pyi +19 -22
  21. reflex/components/base/fragment.pyi +16 -16
  22. reflex/components/base/head.pyi +31 -31
  23. reflex/components/base/link.pyi +31 -31
  24. reflex/components/base/meta.py +2 -2
  25. reflex/components/base/meta.pyi +61 -61
  26. reflex/components/base/script.pyi +19 -19
  27. reflex/components/base/strict_mode.py +10 -0
  28. reflex/components/base/strict_mode.pyi +57 -0
  29. reflex/components/component.py +38 -77
  30. reflex/components/core/banner.py +159 -4
  31. reflex/components/core/banner.pyi +162 -76
  32. reflex/components/core/breakpoints.py +3 -1
  33. reflex/components/core/client_side_routing.py +1 -1
  34. reflex/components/core/client_side_routing.pyi +32 -32
  35. reflex/components/core/clipboard.pyi +17 -20
  36. reflex/components/core/cond.py +9 -10
  37. reflex/components/core/debounce.py +1 -1
  38. reflex/components/core/debounce.pyi +17 -17
  39. reflex/components/core/foreach.py +28 -3
  40. reflex/components/core/html.py +1 -1
  41. reflex/components/core/html.pyi +16 -16
  42. reflex/components/core/match.py +5 -5
  43. reflex/components/core/sticky.py +134 -0
  44. reflex/components/core/sticky.pyi +449 -0
  45. reflex/components/core/upload.py +2 -2
  46. reflex/components/core/upload.pyi +80 -88
  47. reflex/components/datadisplay/code.py +5 -14
  48. reflex/components/datadisplay/code.pyi +31 -31
  49. reflex/components/datadisplay/dataeditor.py +7 -4
  50. reflex/components/datadisplay/dataeditor.pyi +40 -54
  51. reflex/components/datadisplay/logo.py +13 -8
  52. reflex/components/datadisplay/shiki_code_block.py +14 -9
  53. reflex/components/datadisplay/shiki_code_block.pyi +46 -46
  54. reflex/components/dynamic.py +22 -3
  55. reflex/components/el/constants/reflex.py +1 -1
  56. reflex/components/el/element.py +1 -1
  57. reflex/components/el/element.pyi +16 -16
  58. reflex/components/el/elements/base.pyi +16 -16
  59. reflex/components/el/elements/forms.py +4 -4
  60. reflex/components/el/elements/forms.pyi +224 -258
  61. reflex/components/el/elements/inline.pyi +421 -421
  62. reflex/components/el/elements/media.pyi +376 -376
  63. reflex/components/el/elements/metadata.pyi +91 -91
  64. reflex/components/el/elements/other.pyi +106 -106
  65. reflex/components/el/elements/scripts.pyi +46 -46
  66. reflex/components/el/elements/sectioning.pyi +226 -226
  67. reflex/components/el/elements/tables.pyi +151 -151
  68. reflex/components/el/elements/typography.pyi +226 -226
  69. reflex/components/gridjs/datatable.pyi +31 -31
  70. reflex/components/lucide/icon.py +46 -8
  71. reflex/components/lucide/icon.pyi +85 -31
  72. reflex/components/markdown/markdown.py +10 -8
  73. reflex/components/markdown/markdown.pyi +16 -16
  74. reflex/components/moment/moment.py +2 -2
  75. reflex/components/moment/moment.pyi +17 -19
  76. reflex/components/next/base.pyi +16 -16
  77. reflex/components/next/image.py +16 -4
  78. reflex/components/next/image.pyi +22 -20
  79. reflex/components/next/link.py +1 -1
  80. reflex/components/next/link.pyi +16 -16
  81. reflex/components/next/video.pyi +16 -16
  82. reflex/components/plotly/__init__.py +29 -2
  83. reflex/components/plotly/plotly.py +240 -5
  84. reflex/components/plotly/plotly.pyi +799 -44
  85. reflex/components/props.py +3 -3
  86. reflex/components/radix/__init__.pyi +1 -1
  87. reflex/components/radix/primitives/accordion.py +9 -5
  88. reflex/components/radix/primitives/accordion.pyi +110 -108
  89. reflex/components/radix/primitives/base.pyi +31 -31
  90. reflex/components/radix/primitives/drawer.py +5 -2
  91. reflex/components/radix/primitives/drawer.pyi +179 -187
  92. reflex/components/radix/primitives/form.pyi +160 -172
  93. reflex/components/radix/primitives/progress.py +1 -1
  94. reflex/components/radix/primitives/progress.pyi +76 -76
  95. reflex/components/radix/primitives/slider.py +1 -1
  96. reflex/components/radix/primitives/slider.pyi +78 -82
  97. reflex/components/radix/themes/base.pyi +121 -121
  98. reflex/components/radix/themes/color_mode.py +11 -9
  99. reflex/components/radix/themes/color_mode.pyi +47 -49
  100. reflex/components/radix/themes/components/alert_dialog.py +3 -0
  101. reflex/components/radix/themes/components/alert_dialog.pyi +110 -112
  102. reflex/components/radix/themes/components/aspect_ratio.pyi +16 -16
  103. reflex/components/radix/themes/components/avatar.pyi +16 -16
  104. reflex/components/radix/themes/components/badge.pyi +16 -16
  105. reflex/components/radix/themes/components/button.pyi +16 -16
  106. reflex/components/radix/themes/components/callout.pyi +76 -76
  107. reflex/components/radix/themes/components/card.py +1 -1
  108. reflex/components/radix/themes/components/card.pyi +17 -17
  109. reflex/components/radix/themes/components/checkbox.pyi +49 -55
  110. reflex/components/radix/themes/components/checkbox_cards.pyi +31 -31
  111. reflex/components/radix/themes/components/checkbox_group.pyi +31 -31
  112. reflex/components/radix/themes/components/context_menu.py +5 -0
  113. reflex/components/radix/themes/components/context_menu.pyi +149 -155
  114. reflex/components/radix/themes/components/data_list.pyi +61 -61
  115. reflex/components/radix/themes/components/dialog.py +3 -0
  116. reflex/components/radix/themes/components/dialog.pyi +113 -117
  117. reflex/components/radix/themes/components/dropdown_menu.py +5 -0
  118. reflex/components/radix/themes/components/dropdown_menu.pyi +133 -137
  119. reflex/components/radix/themes/components/hover_card.py +3 -0
  120. reflex/components/radix/themes/components/hover_card.pyi +63 -67
  121. reflex/components/radix/themes/components/icon_button.py +2 -2
  122. reflex/components/radix/themes/components/icon_button.pyi +17 -16
  123. reflex/components/radix/themes/components/inset.pyi +16 -16
  124. reflex/components/radix/themes/components/popover.py +3 -0
  125. reflex/components/radix/themes/components/popover.pyi +68 -70
  126. reflex/components/radix/themes/components/progress.pyi +16 -16
  127. reflex/components/radix/themes/components/radio.pyi +16 -16
  128. reflex/components/radix/themes/components/radio_cards.py +2 -0
  129. reflex/components/radix/themes/components/radio_cards.pyi +32 -34
  130. reflex/components/radix/themes/components/radio_group.py +1 -1
  131. reflex/components/radix/themes/components/radio_group.pyi +62 -64
  132. reflex/components/radix/themes/components/scroll_area.pyi +16 -16
  133. reflex/components/radix/themes/components/segmented_control.pyi +32 -35
  134. reflex/components/radix/themes/components/select.py +4 -0
  135. reflex/components/radix/themes/components/select.pyi +145 -157
  136. reflex/components/radix/themes/components/separator.pyi +16 -16
  137. reflex/components/radix/themes/components/skeleton.py +3 -0
  138. reflex/components/radix/themes/components/skeleton.pyi +16 -16
  139. reflex/components/radix/themes/components/slider.pyi +22 -28
  140. reflex/components/radix/themes/components/spinner.pyi +16 -16
  141. reflex/components/radix/themes/components/switch.pyi +17 -19
  142. reflex/components/radix/themes/components/table.pyi +106 -106
  143. reflex/components/radix/themes/components/tabs.py +3 -0
  144. reflex/components/radix/themes/components/tabs.pyi +78 -82
  145. reflex/components/radix/themes/components/text_area.py +12 -0
  146. reflex/components/radix/themes/components/text_area.pyi +21 -33
  147. reflex/components/radix/themes/components/text_field.py +1 -1
  148. reflex/components/radix/themes/components/text_field.pyi +52 -80
  149. reflex/components/radix/themes/components/tooltip.py +6 -1
  150. reflex/components/radix/themes/components/tooltip.pyi +20 -21
  151. reflex/components/radix/themes/layout/__init__.pyi +1 -1
  152. reflex/components/radix/themes/layout/base.pyi +16 -16
  153. reflex/components/radix/themes/layout/box.pyi +16 -16
  154. reflex/components/radix/themes/layout/center.pyi +16 -16
  155. reflex/components/radix/themes/layout/container.pyi +16 -16
  156. reflex/components/radix/themes/layout/flex.pyi +16 -16
  157. reflex/components/radix/themes/layout/grid.pyi +16 -16
  158. reflex/components/radix/themes/layout/list.py +2 -2
  159. reflex/components/radix/themes/layout/list.pyi +76 -76
  160. reflex/components/radix/themes/layout/section.pyi +16 -16
  161. reflex/components/radix/themes/layout/spacer.pyi +16 -16
  162. reflex/components/radix/themes/layout/stack.py +2 -2
  163. reflex/components/radix/themes/layout/stack.pyi +46 -46
  164. reflex/components/radix/themes/typography/blockquote.pyi +16 -16
  165. reflex/components/radix/themes/typography/code.pyi +16 -16
  166. reflex/components/radix/themes/typography/heading.pyi +16 -16
  167. reflex/components/radix/themes/typography/link.py +1 -1
  168. reflex/components/radix/themes/typography/link.pyi +16 -16
  169. reflex/components/radix/themes/typography/text.py +2 -2
  170. reflex/components/radix/themes/typography/text.pyi +106 -106
  171. reflex/components/react_player/audio.pyi +33 -39
  172. reflex/components/react_player/react_player.py +1 -1
  173. reflex/components/react_player/react_player.pyi +32 -38
  174. reflex/components/react_player/video.pyi +33 -39
  175. reflex/components/recharts/__init__.py +2 -0
  176. reflex/components/recharts/__init__.pyi +2 -0
  177. reflex/components/recharts/cartesian.pyi +282 -282
  178. reflex/components/recharts/charts.py +15 -15
  179. reflex/components/recharts/charts.pyi +164 -164
  180. reflex/components/recharts/general.py +19 -4
  181. reflex/components/recharts/general.pyi +132 -81
  182. reflex/components/recharts/polar.py +2 -2
  183. reflex/components/recharts/polar.pyi +55 -55
  184. reflex/components/recharts/recharts.py +4 -4
  185. reflex/components/recharts/recharts.pyi +31 -31
  186. reflex/components/sonner/toast.py +15 -13
  187. reflex/components/sonner/toast.pyi +22 -22
  188. reflex/components/suneditor/editor.py +6 -4
  189. reflex/components/suneditor/editor.pyi +26 -40
  190. reflex/components/tags/iter_tag.py +3 -3
  191. reflex/components/tags/tag.py +25 -3
  192. reflex/config.py +48 -15
  193. reflex/constants/__init__.py +1 -0
  194. reflex/constants/base.py +4 -1
  195. reflex/constants/compiler.py +5 -2
  196. reflex/constants/config.py +8 -1
  197. reflex/constants/installer.py +9 -9
  198. reflex/constants/style.py +1 -1
  199. reflex/custom_components/custom_components.py +18 -10
  200. reflex/event.py +221 -231
  201. reflex/experimental/__init__.py +19 -11
  202. reflex/experimental/client_state.py +53 -28
  203. reflex/experimental/hooks.py +5 -5
  204. reflex/experimental/layout.py +8 -5
  205. reflex/experimental/layout.pyi +79 -83
  206. reflex/experimental/misc.py +3 -3
  207. reflex/istate/wrappers.py +1 -1
  208. reflex/middleware/hydrate_middleware.py +2 -2
  209. reflex/model.py +11 -6
  210. reflex/page.py +5 -5
  211. reflex/reflex.py +104 -26
  212. reflex/route.py +1 -1
  213. reflex/state.py +358 -401
  214. reflex/style.py +27 -3
  215. reflex/testing.py +29 -23
  216. reflex/utils/build.py +6 -2
  217. reflex/utils/codespaces.py +1 -4
  218. reflex/utils/compat.py +6 -5
  219. reflex/utils/console.py +71 -16
  220. reflex/utils/exceptions.py +89 -26
  221. reflex/utils/exec.py +69 -74
  222. reflex/utils/export.py +6 -1
  223. reflex/utils/format.py +8 -40
  224. reflex/utils/imports.py +5 -2
  225. reflex/utils/lazy_loader.py +7 -1
  226. reflex/utils/path_ops.py +74 -14
  227. reflex/utils/prerequisites.py +345 -68
  228. reflex/utils/processes.py +45 -32
  229. reflex/utils/pyi_generator.py +39 -33
  230. reflex/utils/registry.py +4 -4
  231. reflex/utils/serializers.py +1 -1
  232. reflex/utils/telemetry.py +5 -4
  233. reflex/utils/types.py +42 -18
  234. reflex/vars/base.py +695 -330
  235. reflex/vars/datetime.py +6 -7
  236. reflex/vars/dep_tracking.py +344 -0
  237. reflex/vars/function.py +11 -5
  238. reflex/vars/number.py +31 -43
  239. reflex/vars/object.py +74 -64
  240. reflex/vars/sequence.py +79 -67
  241. {reflex-0.6.8a2.dist-info → reflex-0.7.0.dist-info}/METADATA +7 -8
  242. reflex-0.7.0.dist-info/RECORD +401 -0
  243. {reflex-0.6.8a2.dist-info → reflex-0.7.0.dist-info}/WHEEL +1 -1
  244. reflex/experimental/assets.py +0 -37
  245. reflex-0.6.8a2.dist-info/RECORD +0 -397
  246. {reflex-0.6.8a2.dist-info → reflex-0.7.0.dist-info}/LICENSE +0 -0
  247. {reflex-0.6.8a2.dist-info → reflex-0.7.0.dist-info}/entry_points.txt +0 -0
reflex/event.py CHANGED
@@ -4,7 +4,6 @@ from __future__ import annotations
4
4
 
5
5
  import dataclasses
6
6
  import inspect
7
- import sys
8
7
  import types
9
8
  import urllib.parse
10
9
  from base64 import b64encode
@@ -25,22 +24,27 @@ from typing import (
25
24
  overload,
26
25
  )
27
26
 
28
- import typing_extensions
29
27
  from typing_extensions import (
30
- Concatenate,
31
- ParamSpec,
32
28
  Protocol,
29
+ Self,
33
30
  TypeAliasType,
34
31
  TypedDict,
35
32
  TypeVar,
33
+ TypeVarTuple,
34
+ Unpack,
36
35
  get_args,
37
36
  get_origin,
38
37
  )
39
38
 
40
39
  from reflex import constants
40
+ from reflex.constants.compiler import CompileVars, Hooks, Imports
41
41
  from reflex.constants.state import FRONTEND_EVENT_STATE
42
42
  from reflex.utils import console, format
43
- from reflex.utils.exceptions import EventFnArgMismatch, EventHandlerArgTypeMismatch
43
+ from reflex.utils.exceptions import (
44
+ EventFnArgMismatchError,
45
+ EventHandlerArgTypeMismatchError,
46
+ MissingAnnotationError,
47
+ )
44
48
  from reflex.utils.types import ArgsSpec, GenericType, typehint_issubclass
45
49
  from reflex.vars import VarData
46
50
  from reflex.vars.base import LiteralVar, Var
@@ -91,33 +95,9 @@ class Event:
91
95
  return f"{self.token}_{substate}"
92
96
 
93
97
 
94
- BACKGROUND_TASK_MARKER = "_reflex_background_task"
95
-
96
-
97
- def background(fn, *, __internal_reflex_call: bool = False):
98
- """Decorator to mark event handler as running in the background.
99
-
100
- Args:
101
- fn: The function to decorate.
102
-
103
- Returns:
104
- The same function, but with a marker set.
105
-
98
+ _EVENT_FIELDS: set[str] = {f.name for f in dataclasses.fields(Event)}
106
99
 
107
- Raises:
108
- TypeError: If the function is not a coroutine function or async generator.
109
- """
110
- if not __internal_reflex_call:
111
- console.deprecate(
112
- "background-decorator",
113
- "Use `rx.event(background=True)` instead.",
114
- "0.6.5",
115
- "0.7.0",
116
- )
117
- if not inspect.iscoroutinefunction(fn) and not inspect.isasyncgenfunction(fn):
118
- raise TypeError("Background task must be async function or generator.")
119
- setattr(fn, BACKGROUND_TASK_MARKER, True)
120
- return fn
100
+ BACKGROUND_TASK_MARKER = "_reflex_background_task"
121
101
 
122
102
 
123
103
  @dataclasses.dataclass(
@@ -131,7 +111,7 @@ class EventActionsMixin:
131
111
  event_actions: Dict[str, Union[bool, int]] = dataclasses.field(default_factory=dict)
132
112
 
133
113
  @property
134
- def stop_propagation(self):
114
+ def stop_propagation(self) -> Self:
135
115
  """Stop the event from bubbling up the DOM tree.
136
116
 
137
117
  Returns:
@@ -143,7 +123,7 @@ class EventActionsMixin:
143
123
  )
144
124
 
145
125
  @property
146
- def prevent_default(self):
126
+ def prevent_default(self) -> Self:
147
127
  """Prevent the default behavior of the event.
148
128
 
149
129
  Returns:
@@ -154,7 +134,7 @@ class EventActionsMixin:
154
134
  event_actions={"preventDefault": True, **self.event_actions},
155
135
  )
156
136
 
157
- def throttle(self, limit_ms: int):
137
+ def throttle(self, limit_ms: int) -> Self:
158
138
  """Throttle the event handler.
159
139
 
160
140
  Args:
@@ -168,7 +148,7 @@ class EventActionsMixin:
168
148
  event_actions={"throttle": limit_ms, **self.event_actions},
169
149
  )
170
150
 
171
- def debounce(self, delay_ms: int):
151
+ def debounce(self, delay_ms: int) -> Self:
172
152
  """Debounce the event handler.
173
153
 
174
154
  Args:
@@ -183,7 +163,7 @@ class EventActionsMixin:
183
163
  )
184
164
 
185
165
  @property
186
- def temporal(self):
166
+ def temporal(self) -> Self:
187
167
  """Do not queue the event if the backend is down.
188
168
 
189
169
  Returns:
@@ -264,7 +244,7 @@ class EventHandler(EventActionsMixin):
264
244
  raise EventHandlerTypeError(
265
245
  f"Arguments to event handlers must be Vars or JSON-serializable. Got {arg} of type {type(arg)}."
266
246
  ) from e
267
- payload = tuple(zip(fn_args, values))
247
+ payload = tuple(zip(fn_args, values, strict=False))
268
248
 
269
249
  # Return the event spec.
270
250
  return EventSpec(
@@ -284,7 +264,7 @@ class EventSpec(EventActionsMixin):
284
264
  """
285
265
 
286
266
  # The event handler.
287
- handler: EventHandler = dataclasses.field(default=None) # type: ignore
267
+ handler: EventHandler = dataclasses.field(default=None) # pyright: ignore [reportAssignmentType]
288
268
 
289
269
  # The handler on the client to process event.
290
270
  client_handler_name: str = dataclasses.field(default="")
@@ -353,12 +333,12 @@ class EventSpec(EventActionsMixin):
353
333
  arg = None
354
334
  try:
355
335
  for arg in args:
356
- values.append(LiteralVar.create(value=arg)) # noqa: PERF401
336
+ values.append(LiteralVar.create(value=arg)) # noqa: PERF401, RUF100
357
337
  except TypeError as e:
358
338
  raise EventHandlerTypeError(
359
339
  f"Arguments to event handlers must be Vars or JSON-serializable. Got {arg} of type {type(arg)}."
360
340
  ) from e
361
- new_payload = tuple(zip(fn_args, values))
341
+ new_payload = tuple(zip(fn_args, values, strict=False))
362
342
  return self.with_args(self.args + new_payload)
363
343
 
364
344
 
@@ -555,13 +535,13 @@ class JavasciptKeyboardEvent:
555
535
  """Interface for a Javascript KeyboardEvent https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent."""
556
536
 
557
537
  key: str = ""
558
- altKey: bool = False
559
- ctrlKey: bool = False
560
- metaKey: bool = False
561
- shiftKey: bool = False
538
+ altKey: bool = False # noqa: N815
539
+ ctrlKey: bool = False # noqa: N815
540
+ metaKey: bool = False # noqa: N815
541
+ shiftKey: bool = False # noqa: N815
562
542
 
563
543
 
564
- def input_event(e: Var[JavascriptInputEvent]) -> Tuple[Var[str]]:
544
+ def input_event(e: ObjectVar[JavascriptInputEvent]) -> Tuple[Var[str]]:
565
545
  """Get the value from an input event.
566
546
 
567
547
  Args:
@@ -582,7 +562,9 @@ class KeyInputInfo(TypedDict):
582
562
  shift_key: bool
583
563
 
584
564
 
585
- def key_event(e: Var[JavasciptKeyboardEvent]) -> Tuple[Var[str], Var[KeyInputInfo]]:
565
+ def key_event(
566
+ e: ObjectVar[JavasciptKeyboardEvent],
567
+ ) -> Tuple[Var[str], Var[KeyInputInfo]]:
586
568
  """Get the key from a keyboard event.
587
569
 
588
570
  Args:
@@ -592,7 +574,7 @@ def key_event(e: Var[JavasciptKeyboardEvent]) -> Tuple[Var[str], Var[KeyInputInf
592
574
  The key from the keyboard event.
593
575
  """
594
576
  return (
595
- e.key,
577
+ e.key.to(str),
596
578
  Var.create(
597
579
  {
598
580
  "alt_key": e.altKey,
@@ -600,7 +582,7 @@ def key_event(e: Var[JavasciptKeyboardEvent]) -> Tuple[Var[str], Var[KeyInputInf
600
582
  "meta_key": e.metaKey,
601
583
  "shift_key": e.shiftKey,
602
584
  },
603
- ),
585
+ ).to(KeyInputInfo),
604
586
  )
605
587
 
606
588
 
@@ -610,7 +592,7 @@ def no_args_event_spec() -> Tuple[()]:
610
592
  Returns:
611
593
  An empty tuple.
612
594
  """
613
- return () # type: ignore
595
+ return ()
614
596
 
615
597
 
616
598
  # These chains can be used for their side effects when no other events are desired.
@@ -638,9 +620,9 @@ class IdentityEventReturn(Generic[T], Protocol):
638
620
 
639
621
 
640
622
  @overload
641
- def passthrough_event_spec(
623
+ def passthrough_event_spec( # pyright: ignore [reportOverlappingOverload]
642
624
  event_type: Type[T], /
643
- ) -> Callable[[Var[T]], Tuple[Var[T]]]: ... # type: ignore
625
+ ) -> Callable[[Var[T]], Tuple[Var[T]]]: ...
644
626
 
645
627
 
646
628
  @overload
@@ -653,7 +635,7 @@ def passthrough_event_spec(
653
635
  def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: ...
654
636
 
655
637
 
656
- def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: # type: ignore
638
+ def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: # pyright: ignore [reportInconsistentOverload]
657
639
  """A helper function that returns the input event as output.
658
640
 
659
641
  Args:
@@ -667,9 +649,9 @@ def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: #
667
649
  return values
668
650
 
669
651
  inner_type = tuple(Var[event_type] for event_type in event_types)
670
- return_annotation = Tuple[inner_type] # type: ignore
652
+ return_annotation = Tuple[inner_type]
671
653
 
672
- inner.__signature__ = inspect.signature(inner).replace( # type: ignore
654
+ inner.__signature__ = inspect.signature(inner).replace( # pyright: ignore [reportFunctionMemberAccess]
673
655
  parameters=[
674
656
  inspect.Parameter(
675
657
  f"ev_{i}",
@@ -751,7 +733,7 @@ class FileUpload:
751
733
  # Call the lambda to get the event chain.
752
734
  events = call_event_fn(
753
735
  on_upload_progress, self.on_upload_progress_args_spec
754
- ) # type: ignore
736
+ )
755
737
  else:
756
738
  raise ValueError(f"{on_upload_progress} is not a valid event handler.")
757
739
  if isinstance(events, Var):
@@ -798,7 +780,7 @@ def server_side(name: str, sig: inspect.Signature, **kwargs) -> EventSpec:
798
780
  return None
799
781
 
800
782
  fn.__qualname__ = name
801
- fn.__signature__ = sig
783
+ fn.__signature__ = sig # pyright: ignore [reportFunctionMemberAccess]
802
784
  return EventSpec(
803
785
  handler=EventHandler(fn=fn, state_full_name=FRONTEND_EVENT_STATE),
804
786
  args=tuple(
@@ -811,29 +793,10 @@ def server_side(name: str, sig: inspect.Signature, **kwargs) -> EventSpec:
811
793
  )
812
794
 
813
795
 
814
- @overload
815
796
  def redirect(
816
797
  path: str | Var[str],
817
- is_external: Optional[bool] = None,
798
+ is_external: bool = False,
818
799
  replace: bool = False,
819
- ) -> EventSpec: ...
820
-
821
-
822
- @overload
823
- @typing_extensions.deprecated("`external` is deprecated use `is_external` instead")
824
- def redirect(
825
- path: str | Var[str],
826
- is_external: Optional[bool] = None,
827
- replace: bool = False,
828
- external: Optional[bool] = None,
829
- ) -> EventSpec: ...
830
-
831
-
832
- def redirect(
833
- path: str | Var[str],
834
- is_external: Optional[bool] = None,
835
- replace: bool = False,
836
- external: Optional[bool] = None,
837
800
  ) -> EventSpec:
838
801
  """Redirect to a new path.
839
802
 
@@ -841,26 +804,10 @@ def redirect(
841
804
  path: The path to redirect to.
842
805
  is_external: Whether to open in new tab or not.
843
806
  replace: If True, the current page will not create a new history entry.
844
- external(Deprecated): Whether to open in new tab or not.
845
807
 
846
808
  Returns:
847
809
  An event to redirect to the path.
848
810
  """
849
- if external is not None:
850
- console.deprecate(
851
- "The `external` prop in `rx.redirect`",
852
- "use `is_external` instead.",
853
- "0.6.6",
854
- "0.7.0",
855
- )
856
-
857
- # is_external should take precedence over external.
858
- is_external = (
859
- (False if external is None else external)
860
- if is_external is None
861
- else is_external
862
- )
863
-
864
811
  return server_side(
865
812
  "_redirect",
866
813
  get_fn_signature(redirect),
@@ -1106,13 +1053,13 @@ def download(
1106
1053
 
1107
1054
  is_data_url = (data.js_type() == "string") & (
1108
1055
  data.to(str).startswith("data:")
1109
- ) # type: ignore
1056
+ )
1110
1057
 
1111
1058
  # If it's a data: URI, use it as is, otherwise convert the Var to JSON in a data: URI.
1112
- url = cond( # type: ignore
1059
+ url = cond(
1113
1060
  is_data_url,
1114
1061
  data.to(str),
1115
- "data:text/plain," + data.to_string(), # type: ignore
1062
+ "data:text/plain," + data.to_string(),
1116
1063
  )
1117
1064
  elif isinstance(data, bytes):
1118
1065
  # Caller provided bytes, so base64 encode it as a data: URI.
@@ -1131,7 +1078,8 @@ def download(
1131
1078
  )
1132
1079
 
1133
1080
 
1134
- def _callback_arg_spec(eval_result):
1081
+ # This function seems unused. Check if we still need it. If not, remove in 0.7.0
1082
+ def _callback_arg_spec(eval_result: Any):
1135
1083
  """ArgSpec for call_script callback function.
1136
1084
 
1137
1085
  Args:
@@ -1145,7 +1093,7 @@ def _callback_arg_spec(eval_result):
1145
1093
 
1146
1094
  def call_script(
1147
1095
  javascript_code: str | Var[str],
1148
- callback: EventType | None = None,
1096
+ callback: EventType[Any] | None = None,
1149
1097
  ) -> EventSpec:
1150
1098
  """Create an event handler that executes arbitrary javascript code.
1151
1099
 
@@ -1184,7 +1132,7 @@ def call_script(
1184
1132
 
1185
1133
  def call_function(
1186
1134
  javascript_code: str | Var,
1187
- callback: EventType | None = None,
1135
+ callback: EventType[Any] | None = None,
1188
1136
  ) -> EventSpec:
1189
1137
  """Create an event handler that executes arbitrary javascript code.
1190
1138
 
@@ -1218,7 +1166,7 @@ def call_function(
1218
1166
 
1219
1167
  def run_script(
1220
1168
  javascript_code: str | Var,
1221
- callback: EventType | None = None,
1169
+ callback: EventType[Any] | None = None,
1222
1170
  ) -> EventSpec:
1223
1171
  """Create an event handler that executes arbitrary javascript code.
1224
1172
 
@@ -1236,7 +1184,7 @@ def run_script(
1236
1184
  return call_function(ArgsFunctionOperation.create((), javascript_code), callback)
1237
1185
 
1238
1186
 
1239
- def get_event(state, event):
1187
+ def get_event(state: BaseState, event: str):
1240
1188
  """Get the event from the given state.
1241
1189
 
1242
1190
  Args:
@@ -1249,7 +1197,7 @@ def get_event(state, event):
1249
1197
  return f"{state.get_name()}.{event}"
1250
1198
 
1251
1199
 
1252
- def get_hydrate_event(state) -> str:
1200
+ def get_hydrate_event(state: BaseState) -> str:
1253
1201
  """Get the name of the hydrate event for the state.
1254
1202
 
1255
1203
  Args:
@@ -1277,13 +1225,16 @@ def call_event_handler(
1277
1225
  event_spec: The lambda that define the argument(s) to pass to the event handler.
1278
1226
  key: The key to pass to the event handler.
1279
1227
 
1228
+ Raises:
1229
+ EventHandlerArgTypeMismatchError: If the event handler arguments do not match the event spec. #noqa: DAR402
1230
+ TypeError: If the event handler arguments are invalid.
1231
+
1280
1232
  Returns:
1281
1233
  The event spec from calling the event handler.
1282
1234
 
1283
- # noqa: DAR401 failure
1284
-
1235
+ #noqa: DAR401
1285
1236
  """
1286
- event_spec_args = parse_args_spec(event_spec) # type: ignore
1237
+ event_spec_args = parse_args_spec(event_spec)
1287
1238
 
1288
1239
  if isinstance(event_callback, EventSpec):
1289
1240
  check_fn_match_arg_spec(
@@ -1318,10 +1269,15 @@ def call_event_handler(
1318
1269
  ),
1319
1270
  )
1320
1271
  )
1272
+ type_match_found: dict[str, bool] = {}
1273
+ delayed_exceptions: list[EventHandlerArgTypeMismatchError] = []
1321
1274
 
1322
- if event_spec_return_types:
1323
- failures = []
1275
+ try:
1276
+ type_hints_of_provided_callback = get_type_hints(event_callback.fn)
1277
+ except NameError:
1278
+ type_hints_of_provided_callback = {}
1324
1279
 
1280
+ if event_spec_return_types:
1325
1281
  event_callback_spec = inspect.getfullargspec(event_callback.fn)
1326
1282
 
1327
1283
  for event_spec_index, event_spec_return_type in enumerate(
@@ -1333,43 +1289,35 @@ def call_event_handler(
1333
1289
  arg if get_origin(arg) is not Var else get_args(arg)[0] for arg in args
1334
1290
  ]
1335
1291
 
1336
- try:
1337
- type_hints_of_provided_callback = get_type_hints(event_callback.fn)
1338
- except NameError:
1339
- type_hints_of_provided_callback = {}
1340
-
1341
- failed_type_check = False
1342
-
1343
1292
  # check that args of event handler are matching the spec if type hints are provided
1344
1293
  for i, arg in enumerate(event_callback_spec.args[1:]):
1345
1294
  if arg not in type_hints_of_provided_callback:
1346
1295
  continue
1347
1296
 
1297
+ type_match_found.setdefault(arg, False)
1298
+
1348
1299
  try:
1349
1300
  compare_result = typehint_issubclass(
1350
1301
  args_types_without_vars[i], type_hints_of_provided_callback[arg]
1351
1302
  )
1352
- except TypeError:
1353
- # TODO: In 0.7.0, remove this block and raise the exception
1354
- # raise TypeError(
1355
- # f"Could not compare types {args_types_without_vars[i]} and {type_hints_of_provided_callback[arg]} for argument {arg} of {event_handler.fn.__qualname__} provided for {key}." # noqa: ERA001
1356
- # ) from e
1357
- console.warn(
1303
+ except TypeError as te:
1304
+ raise TypeError(
1358
1305
  f"Could not compare types {args_types_without_vars[i]} and {type_hints_of_provided_callback[arg]} for argument {arg} of {event_callback.fn.__qualname__} provided for {key}."
1359
- )
1360
- compare_result = False
1306
+ ) from te
1361
1307
 
1362
1308
  if compare_result:
1309
+ type_match_found[arg] = True
1363
1310
  continue
1364
1311
  else:
1365
- failure = EventHandlerArgTypeMismatch(
1366
- f"Event handler {key} expects {args_types_without_vars[i]} for argument {arg} but got {type_hints_of_provided_callback[arg]} as annotated in {event_callback.fn.__qualname__} instead."
1312
+ type_match_found[arg] = False
1313
+ delayed_exceptions.append(
1314
+ EventHandlerArgTypeMismatchError(
1315
+ f"Event handler {key} expects {args_types_without_vars[i]} for argument {arg} but got {type_hints_of_provided_callback[arg]} as annotated in {event_callback.fn.__qualname__} instead."
1316
+ )
1367
1317
  )
1368
- failures.append(failure)
1369
- failed_type_check = True
1370
- break
1371
1318
 
1372
- if not failed_type_check:
1319
+ if all(type_match_found.values()):
1320
+ delayed_exceptions.clear()
1373
1321
  if event_spec_index:
1374
1322
  args = get_args(event_spec_return_types[0])
1375
1323
 
@@ -1391,17 +1339,12 @@ def call_event_handler(
1391
1339
  f"Event handler {key} expects ({expect_string}) -> () but got ({given_string}) -> () as annotated in {event_callback.fn.__qualname__} instead. "
1392
1340
  f"This may lead to unexpected behavior but is intentionally ignored for {key}."
1393
1341
  )
1394
- return event_callback(*event_spec_args)
1395
-
1396
- if failures:
1397
- console.deprecate(
1398
- "Mismatched event handler argument types",
1399
- "\n".join([str(f) for f in failures]),
1400
- "0.6.5",
1401
- "0.7.0",
1402
- )
1342
+ break
1343
+
1344
+ if delayed_exceptions:
1345
+ raise delayed_exceptions[0]
1403
1346
 
1404
- return event_callback(*event_spec_args) # type: ignore
1347
+ return event_callback(*event_spec_args)
1405
1348
 
1406
1349
 
1407
1350
  def unwrap_var_annotation(annotation: GenericType):
@@ -1413,31 +1356,31 @@ def unwrap_var_annotation(annotation: GenericType):
1413
1356
  Returns:
1414
1357
  The unwrapped annotation.
1415
1358
  """
1416
- if get_origin(annotation) is Var and (args := get_args(annotation)):
1359
+ if get_origin(annotation) in (Var, ObjectVar) and (args := get_args(annotation)):
1417
1360
  return args[0]
1418
1361
  return annotation
1419
1362
 
1420
1363
 
1421
- def resolve_annotation(annotations: dict[str, Any], arg_name: str):
1364
+ def resolve_annotation(annotations: dict[str, Any], arg_name: str, spec: ArgsSpec):
1422
1365
  """Resolve the annotation for the given argument name.
1423
1366
 
1424
1367
  Args:
1425
1368
  annotations: The annotations.
1426
1369
  arg_name: The argument name.
1370
+ spec: The specs which the annotations come from.
1371
+
1372
+ Raises:
1373
+ MissingAnnotationError: If the annotation is missing for non-lambda methods.
1427
1374
 
1428
1375
  Returns:
1429
1376
  The resolved annotation.
1430
1377
  """
1431
1378
  annotation = annotations.get(arg_name)
1432
1379
  if annotation is None:
1433
- console.deprecate(
1434
- feature_name="Unannotated event handler arguments",
1435
- reason="Provide type annotations for event handler arguments.",
1436
- deprecation_version="0.6.3",
1437
- removal_version="0.7.0",
1438
- )
1439
- # Allow arbitrary attribute access two levels deep until removed.
1440
- return Dict[str, dict]
1380
+ if not isinstance(spec, types.LambdaType):
1381
+ raise MissingAnnotationError(var_name=arg_name)
1382
+ else:
1383
+ return dict[str, dict]
1441
1384
  return annotation
1442
1385
 
1443
1386
 
@@ -1459,7 +1402,13 @@ def parse_args_spec(arg_spec: ArgsSpec | Sequence[ArgsSpec]):
1459
1402
  arg_spec(
1460
1403
  *[
1461
1404
  Var(f"_{l_arg}").to(
1462
- unwrap_var_annotation(resolve_annotation(annotations, l_arg))
1405
+ unwrap_var_annotation(
1406
+ resolve_annotation(
1407
+ annotations,
1408
+ l_arg,
1409
+ spec=arg_spec,
1410
+ )
1411
+ )
1463
1412
  )
1464
1413
  for l_arg in spec.args
1465
1414
  ]
@@ -1475,7 +1424,7 @@ def check_fn_match_arg_spec(
1475
1424
  func_name: str | None = None,
1476
1425
  ):
1477
1426
  """Ensures that the function signature matches the passed argument specification
1478
- or raises an EventFnArgMismatch if they do not.
1427
+ or raises an EventFnArgMismatchError if they do not.
1479
1428
 
1480
1429
  Args:
1481
1430
  user_func: The function to be validated.
@@ -1485,7 +1434,7 @@ def check_fn_match_arg_spec(
1485
1434
  func_name: The name of the function to be validated.
1486
1435
 
1487
1436
  Raises:
1488
- EventFnArgMismatch: Raised if the number of mandatory arguments do not match
1437
+ EventFnArgMismatchError: Raised if the number of mandatory arguments do not match
1489
1438
  """
1490
1439
  user_args = inspect.getfullargspec(user_func).args
1491
1440
  # Drop the first argument if it's a bound method
@@ -1501,7 +1450,7 @@ def check_fn_match_arg_spec(
1501
1450
  number_of_event_args = len(parsed_event_args)
1502
1451
 
1503
1452
  if number_of_user_args - number_of_user_default_args > number_of_event_args:
1504
- raise EventFnArgMismatch(
1453
+ raise EventFnArgMismatchError(
1505
1454
  f"Event {key} only provides {number_of_event_args} arguments, but "
1506
1455
  f"{func_name or user_func} requires at least {number_of_user_args - number_of_user_default_args} "
1507
1456
  "arguments to be passed to the event handler.\n"
@@ -1589,7 +1538,7 @@ def get_handler_args(
1589
1538
 
1590
1539
 
1591
1540
  def fix_events(
1592
- events: list[EventHandler | EventSpec] | None,
1541
+ events: list[EventSpec | EventHandler] | None,
1593
1542
  token: str,
1594
1543
  router_data: dict[str, Any] | None = None,
1595
1544
  ) -> list[Event]:
@@ -1629,7 +1578,7 @@ def fix_events(
1629
1578
  if not isinstance(e, EventSpec):
1630
1579
  raise ValueError(f"Unexpected event type, {type(e)}.")
1631
1580
  name = format.format_event_handler(e.handler)
1632
- payload = {k._js_expr: v._decode() for k, v in e.args} # type: ignore
1581
+ payload = {k._js_expr: v._decode() for k, v in e.args}
1633
1582
 
1634
1583
  # Filter router_data to reduce payload size
1635
1584
  event_router_data = {
@@ -1673,12 +1622,12 @@ class EventVar(ObjectVar, python_types=EventSpec):
1673
1622
  @dataclasses.dataclass(
1674
1623
  eq=False,
1675
1624
  frozen=True,
1676
- **{"slots": True} if sys.version_info >= (3, 10) else {},
1625
+ slots=True,
1677
1626
  )
1678
1627
  class LiteralEventVar(VarOperationCall, LiteralVar, EventVar):
1679
1628
  """A literal event var."""
1680
1629
 
1681
- _var_value: EventSpec = dataclasses.field(default=None) # type: ignore
1630
+ _var_value: EventSpec = dataclasses.field(default=None) # pyright: ignore [reportAssignmentType]
1682
1631
 
1683
1632
  def __hash__(self) -> int:
1684
1633
  """Get the hash of the var.
@@ -1734,7 +1683,7 @@ class EventChainVar(BuilderFunctionVar, python_types=EventChain):
1734
1683
  @dataclasses.dataclass(
1735
1684
  eq=False,
1736
1685
  frozen=True,
1737
- **{"slots": True} if sys.version_info >= (3, 10) else {},
1686
+ slots=True,
1738
1687
  )
1739
1688
  # Note: LiteralVar is second in the inheritance list allowing it act like a
1740
1689
  # CachedVarOperation (ArgsFunctionOperation) and get the _js_expr from the
@@ -1742,7 +1691,7 @@ class EventChainVar(BuilderFunctionVar, python_types=EventChain):
1742
1691
  class LiteralEventChainVar(ArgsFunctionOperationBuilder, LiteralVar, EventChainVar):
1743
1692
  """A literal event chain var."""
1744
1693
 
1745
- _var_value: EventChain = dataclasses.field(default=None) # type: ignore
1694
+ _var_value: EventChain = dataclasses.field(default=None) # pyright: ignore [reportAssignmentType]
1746
1695
 
1747
1696
  def __hash__(self) -> int:
1748
1697
  """Get the hash of the var.
@@ -1766,13 +1715,16 @@ class LiteralEventChainVar(ArgsFunctionOperationBuilder, LiteralVar, EventChainV
1766
1715
 
1767
1716
  Returns:
1768
1717
  The created LiteralEventChainVar instance.
1718
+
1719
+ Raises:
1720
+ ValueError: If the invocation is not a FunctionVar.
1769
1721
  """
1770
1722
  arg_spec = (
1771
1723
  value.args_spec[0]
1772
1724
  if isinstance(value.args_spec, Sequence)
1773
1725
  else value.args_spec
1774
1726
  )
1775
- sig = inspect.signature(arg_spec) # type: ignore
1727
+ sig = inspect.signature(arg_spec) # pyright: ignore [reportArgumentType]
1776
1728
  if sig.parameters:
1777
1729
  arg_def = tuple((f"_{p}" for p in sig.parameters))
1778
1730
  arg_def_expr = LiteralVar.create([Var(_js_expr=arg) for arg in arg_def])
@@ -1783,10 +1735,21 @@ class LiteralEventChainVar(ArgsFunctionOperationBuilder, LiteralVar, EventChainV
1783
1735
  arg_def_expr = Var(_js_expr="args")
1784
1736
 
1785
1737
  if value.invocation is None:
1786
- invocation = FunctionStringVar.create("addEvents")
1738
+ invocation = FunctionStringVar.create(
1739
+ CompileVars.ADD_EVENTS,
1740
+ _var_data=VarData(
1741
+ imports=Imports.EVENTS,
1742
+ hooks={Hooks.EVENTS: None},
1743
+ ),
1744
+ )
1787
1745
  else:
1788
1746
  invocation = value.invocation
1789
1747
 
1748
+ if invocation is not None and not isinstance(invocation, FunctionVar):
1749
+ raise ValueError(
1750
+ f"EventChain invocation must be a FunctionVar, got {invocation!s} of type {invocation._var_type!s}."
1751
+ )
1752
+
1790
1753
  return cls(
1791
1754
  _js_expr="",
1792
1755
  _var_type=EventChain,
@@ -1801,8 +1764,8 @@ class LiteralEventChainVar(ArgsFunctionOperationBuilder, LiteralVar, EventChainV
1801
1764
  )
1802
1765
 
1803
1766
 
1804
- P = ParamSpec("P")
1805
- Q = ParamSpec("Q")
1767
+ P = TypeVarTuple("P")
1768
+ Q = TypeVarTuple("Q")
1806
1769
  T = TypeVar("T")
1807
1770
  V = TypeVar("V")
1808
1771
  V2 = TypeVar("V2")
@@ -1810,13 +1773,11 @@ V3 = TypeVar("V3")
1810
1773
  V4 = TypeVar("V4")
1811
1774
  V5 = TypeVar("V5")
1812
1775
 
1813
- background_event_decorator = background
1814
1776
 
1815
-
1816
- class EventCallback(Generic[P, T]):
1777
+ class EventCallback(Generic[Unpack[P]], EventActionsMixin):
1817
1778
  """A descriptor that wraps a function to be used as an event."""
1818
1779
 
1819
- def __init__(self, func: Callable[Concatenate[Any, P], T]):
1780
+ def __init__(self, func: Callable[[Any, Unpack[P]], Any]):
1820
1781
  """Initialize the descriptor with the function to be wrapped.
1821
1782
 
1822
1783
  Args:
@@ -1824,59 +1785,41 @@ class EventCallback(Generic[P, T]):
1824
1785
  """
1825
1786
  self.func = func
1826
1787
 
1827
- @property
1828
- def prevent_default(self):
1829
- """Prevent default behavior.
1830
-
1831
- Returns:
1832
- The event callback with prevent default behavior.
1833
- """
1834
- return self
1835
-
1836
- @property
1837
- def stop_propagation(self):
1838
- """Stop event propagation.
1839
-
1840
- Returns:
1841
- The event callback with stop propagation behavior.
1842
- """
1843
- return self
1844
-
1845
1788
  @overload
1846
1789
  def __call__(
1847
- self: EventCallback[Q, T],
1848
- ) -> EventCallback[Q, T]: ...
1790
+ self: EventCallback[Unpack[Q]],
1791
+ ) -> EventCallback[Unpack[Q]]: ...
1849
1792
 
1850
1793
  @overload
1851
1794
  def __call__(
1852
- self: EventCallback[Concatenate[V, Q], T], value: V | Var[V]
1853
- ) -> EventCallback[Q, T]: ...
1795
+ self: EventCallback[V, Unpack[Q]], value: V | Var[V]
1796
+ ) -> EventCallback[Unpack[Q]]: ...
1854
1797
 
1855
1798
  @overload
1856
1799
  def __call__(
1857
- self: EventCallback[Concatenate[V, V2, Q], T],
1800
+ self: EventCallback[V, V2, Unpack[Q]],
1858
1801
  value: V | Var[V],
1859
1802
  value2: V2 | Var[V2],
1860
- ) -> EventCallback[Q, T]: ...
1803
+ ) -> EventCallback[Unpack[Q]]: ...
1861
1804
 
1862
1805
  @overload
1863
1806
  def __call__(
1864
- self: EventCallback[Concatenate[V, V2, V3, Q], T],
1807
+ self: EventCallback[V, V2, V3, Unpack[Q]],
1865
1808
  value: V | Var[V],
1866
1809
  value2: V2 | Var[V2],
1867
1810
  value3: V3 | Var[V3],
1868
- ) -> EventCallback[Q, T]: ...
1811
+ ) -> EventCallback[Unpack[Q]]: ...
1869
1812
 
1870
1813
  @overload
1871
1814
  def __call__(
1872
- self: EventCallback[Concatenate[V, V2, V3, V4, Q], T],
1815
+ self: EventCallback[V, V2, V3, V4, Unpack[Q]],
1873
1816
  value: V | Var[V],
1874
1817
  value2: V2 | Var[V2],
1875
1818
  value3: V3 | Var[V3],
1876
1819
  value4: V4 | Var[V4],
1877
- ) -> EventCallback[Q, T]: ...
1820
+ ) -> EventCallback[Unpack[Q]]: ...
1878
1821
 
1879
- def __call__(self, *values) -> EventCallback: # type: ignore
1822
+ def __call__(self, *values) -> EventCallback: # pyright: ignore [reportInconsistentOverload]
1880
1823
  """Call the function with the values.
1881
1824
 
1882
1825
  Args:
@@ -1885,17 +1828,17 @@ class EventCallback(Generic[P, T]):
1885
1828
  Returns:
1886
1829
  The function with the values.
1887
1830
  """
1888
- return self.func(*values) # type: ignore
1831
+ return self.func(*values) # pyright: ignore [reportArgumentType]
1889
1832
 
1890
1833
  @overload
1891
1834
  def __get__(
1892
- self: EventCallback[P, T], instance: None, owner
1893
- ) -> EventCallback[P, T]: ...
1835
+ self: EventCallback[Unpack[P]], instance: None, owner: Any
1836
+ ) -> EventCallback[Unpack[P]]: ...
1894
1837
 
1895
1838
  @overload
1896
- def __get__(self, instance, owner) -> Callable[P, T]: ...
1839
+ def __get__(self, instance: Any, owner: Any) -> Callable[[Unpack[P]]]: ...
1897
1840
 
1898
- def __get__(self, instance, owner) -> Callable: # type: ignore
1841
+ def __get__(self, instance: Any, owner: Any) -> Callable:
1899
1842
  """Get the function with the instance bound to it.
1900
1843
 
1901
1844
  Args:
@@ -1906,38 +1849,74 @@ class EventCallback(Generic[P, T]):
1906
1849
  The function with the instance bound to it
1907
1850
  """
1908
1851
  if instance is None:
1909
- return self.func # type: ignore
1852
+ return self.func
1910
1853
 
1911
- return partial(self.func, instance) # type: ignore
1854
+ return partial(self.func, instance)
1912
1855
 
1913
1856
 
1914
- G = ParamSpec("G")
1857
+ class LambdaEventCallback(Protocol[Unpack[P]]):
1858
+ """A protocol for a lambda event callback."""
1915
1859
 
1916
- if TYPE_CHECKING:
1917
- from reflex.state import BaseState
1860
+ @overload
1861
+ def __call__(self: LambdaEventCallback[()]) -> Any: ...
1918
1862
 
1919
- BASE_STATE = TypeVar("BASE_STATE", bound=BaseState)
1920
- else:
1921
- BASE_STATE = TypeVar("BASE_STATE")
1863
+ @overload
1864
+ def __call__(self: LambdaEventCallback[V], value: Var[V], /) -> Any: ...
1922
1865
 
1923
- StateCallable = TypeAliasType(
1924
- "StateCallable",
1925
- Callable[Concatenate[BASE_STATE, G], Any],
1926
- type_params=(G, BASE_STATE),
1866
+ @overload
1867
+ def __call__(
1868
+ self: LambdaEventCallback[V, V2], value: Var[V], value2: Var[V2], /
1869
+ ) -> Any: ...
1870
+
1871
+ @overload
1872
+ def __call__(
1873
+ self: LambdaEventCallback[V, V2, V3],
1874
+ value: Var[V],
1875
+ value2: Var[V2],
1876
+ value3: Var[V3],
1877
+ /,
1878
+ ) -> Any: ...
1879
+
1880
+ def __call__(self, *args: Var) -> Any:
1881
+ """Call the lambda with the args.
1882
+
1883
+ Args:
1884
+ *args: The args to call the lambda with.
1885
+ """
1886
+
1887
+
1888
+ ARGS = TypeVarTuple("ARGS")
1889
+
1890
+
1891
+ LAMBDA_OR_STATE = TypeAliasType(
1892
+ "LAMBDA_OR_STATE",
1893
+ LambdaEventCallback[Unpack[ARGS]] | EventCallback[Unpack[ARGS]],
1894
+ type_params=(ARGS,),
1895
+ )
1896
+
1897
+ ItemOrList = V | List[V]
1898
+
1899
+ BASIC_EVENT_TYPES = TypeAliasType(
1900
+ "BASIC_EVENT_TYPES", EventSpec | EventHandler | Var[Any], type_params=()
1927
1901
  )
1928
1902
 
1929
- IndividualEventType = Union[
1930
- EventSpec,
1931
- EventHandler,
1932
- Callable[G, Any],
1933
- StateCallable[G, BASE_STATE],
1934
- EventCallback[G, Any],
1935
- Var[Any],
1936
- ]
1903
+ IndividualEventType = TypeAliasType(
1904
+ "IndividualEventType",
1905
+ LAMBDA_OR_STATE[Unpack[ARGS]] | BASIC_EVENT_TYPES,
1906
+ type_params=(ARGS,),
1907
+ )
1937
1908
 
1938
- ItemOrList = Union[V, List[V]]
1909
+ EventType = TypeAliasType(
1910
+ "EventType", ItemOrList[IndividualEventType[Unpack[ARGS]]], type_params=(ARGS,)
1911
+ )
1939
1912
 
1940
- EventType = ItemOrList[IndividualEventType[G, BASE_STATE]]
1913
+
1914
+ if TYPE_CHECKING:
1915
+ from reflex.state import BaseState
1916
+
1917
+ BASE_STATE = TypeVar("BASE_STATE", bound=BaseState)
1918
+ else:
1919
+ BASE_STATE = TypeVar("BASE_STATE")
1941
1920
 
1942
1921
 
1943
1922
  class EventNamespace(types.SimpleNamespace):
@@ -1959,24 +1938,26 @@ class EventNamespace(types.SimpleNamespace):
1959
1938
  @staticmethod
1960
1939
  def __call__(
1961
1940
  func: None = None, *, background: bool | None = None
1962
- ) -> Callable[[Callable[Concatenate[BASE_STATE, P], T]], EventCallback[P, T]]: ...
1941
+ ) -> Callable[
1942
+ [Callable[[BASE_STATE, Unpack[P]], Any]], EventCallback[Unpack[P]] # pyright: ignore [reportInvalidTypeVarUse]
1943
+ ]: ...
1963
1944
 
1964
1945
  @overload
1965
1946
  @staticmethod
1966
1947
  def __call__(
1967
- func: Callable[Concatenate[BASE_STATE, P], T],
1948
+ func: Callable[[BASE_STATE, Unpack[P]], Any],
1968
1949
  *,
1969
1950
  background: bool | None = None,
1970
- ) -> EventCallback[P, T]: ...
1951
+ ) -> EventCallback[Unpack[P]]: ...
1971
1952
 
1972
1953
  @staticmethod
1973
1954
  def __call__(
1974
- func: Callable[Concatenate[BASE_STATE, P], T] | None = None,
1955
+ func: Callable[[BASE_STATE, Unpack[P]], Any] | None = None,
1975
1956
  *,
1976
1957
  background: bool | None = None,
1977
1958
  ) -> Union[
1978
- EventCallback[P, T],
1979
- Callable[[Callable[Concatenate[BASE_STATE, P], T]], EventCallback[P, T]],
1959
+ EventCallback[Unpack[P]],
1960
+ Callable[[Callable[[BASE_STATE, Unpack[P]], Any]], EventCallback[Unpack[P]]],
1980
1961
  ]:
1981
1962
  """Wrap a function to be used as an event.
1982
1963
 
@@ -1984,16 +1965,25 @@ class EventNamespace(types.SimpleNamespace):
1984
1965
  func: The function to wrap.
1985
1966
  background: Whether the event should be run in the background. Defaults to False.
1986
1967
 
1968
+ Raises:
1969
+ TypeError: If background is True and the function is not a coroutine or async generator. # noqa: DAR402
1970
+
1987
1971
  Returns:
1988
1972
  The wrapped function.
1989
1973
  """
1990
1974
 
1991
1975
  def wrapper(
1992
- func: Callable[Concatenate[BASE_STATE, P], T],
1993
- ) -> EventCallback[P, T]:
1976
+ func: Callable[[BASE_STATE, Unpack[P]], T],
1977
+ ) -> EventCallback[Unpack[P]]:
1994
1978
  if background is True:
1995
- return background_event_decorator(func, __internal_reflex_call=True) # type: ignore
1996
- return func # type: ignore
1979
+ if not inspect.iscoroutinefunction(
1980
+ func
1981
+ ) and not inspect.isasyncgenfunction(func):
1982
+ raise TypeError(
1983
+ "Background task must be async function or generator."
1984
+ )
1985
+ setattr(func, BACKGROUND_TASK_MARKER, True)
1986
+ return func # pyright: ignore [reportReturnType]
1997
1987
 
1998
1988
  if func is not None:
1999
1989
  return wrapper(func)