reflex 0.7.1a4__py3-none-any.whl → 0.7.2a2__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 (227) hide show
  1. reflex/.templates/jinja/web/utils/context.js.jinja2 +8 -8
  2. reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +3 -3
  3. reflex/.templates/web/utils/state.js +18 -18
  4. reflex/admin.py +1 -2
  5. reflex/app.py +46 -49
  6. reflex/app_mixins/lifespan.py +2 -2
  7. reflex/app_mixins/middleware.py +1 -2
  8. reflex/assets.py +1 -2
  9. reflex/base.py +2 -2
  10. reflex/compiler/compiler.py +51 -16
  11. reflex/compiler/utils.py +4 -13
  12. reflex/components/base/app_wrap.pyi +7 -7
  13. reflex/components/base/bare.py +3 -3
  14. reflex/components/base/body.pyi +7 -7
  15. reflex/components/base/document.py +1 -3
  16. reflex/components/base/document.pyi +32 -32
  17. reflex/components/base/error_boundary.py +2 -4
  18. reflex/components/base/error_boundary.pyi +11 -13
  19. reflex/components/base/fragment.pyi +7 -7
  20. reflex/components/base/head.pyi +13 -13
  21. reflex/components/base/link.pyi +22 -22
  22. reflex/components/base/meta.py +5 -7
  23. reflex/components/base/meta.pyi +40 -40
  24. reflex/components/base/script.pyi +11 -14
  25. reflex/components/base/strict_mode.pyi +7 -7
  26. reflex/components/component.py +188 -113
  27. reflex/components/core/auto_scroll.py +8 -1
  28. reflex/components/core/auto_scroll.pyi +183 -210
  29. reflex/components/core/banner.py +2 -4
  30. reflex/components/core/banner.pyi +390 -444
  31. reflex/components/core/breakpoints.py +5 -5
  32. reflex/components/core/client_side_routing.pyi +14 -14
  33. reflex/components/core/clipboard.py +4 -4
  34. reflex/components/core/clipboard.pyi +12 -14
  35. reflex/components/core/cond.py +17 -25
  36. reflex/components/core/debounce.py +3 -3
  37. reflex/components/core/debounce.pyi +14 -14
  38. reflex/components/core/foreach.py +7 -2
  39. reflex/components/core/html.py +1 -3
  40. reflex/components/core/html.pyi +184 -213
  41. reflex/components/core/match.py +15 -19
  42. reflex/components/core/sticky.pyi +930 -1078
  43. reflex/components/core/upload.py +4 -4
  44. reflex/components/core/upload.pyi +62 -62
  45. reflex/components/datadisplay/code.py +6 -6
  46. reflex/components/datadisplay/code.pyi +1159 -1165
  47. reflex/components/datadisplay/dataeditor.py +49 -49
  48. reflex/components/datadisplay/dataeditor.pyi +95 -123
  49. reflex/components/datadisplay/logo.py +1 -3
  50. reflex/components/datadisplay/shiki_code_block.py +8 -10
  51. reflex/components/datadisplay/shiki_code_block.pyi +1678 -1720
  52. reflex/components/el/element.pyi +7 -7
  53. reflex/components/el/elements/base.pyi +183 -210
  54. reflex/components/el/elements/forms.py +24 -24
  55. reflex/components/el/elements/forms.pyi +2572 -2934
  56. reflex/components/el/elements/inline.py +4 -4
  57. reflex/components/el/elements/inline.pyi +5191 -5953
  58. reflex/components/el/elements/media.py +47 -47
  59. reflex/components/el/elements/media.pyi +4802 -5500
  60. reflex/components/el/elements/metadata.py +1 -3
  61. reflex/components/el/elements/metadata.pyi +782 -896
  62. reflex/components/el/elements/other.pyi +1278 -1467
  63. reflex/components/el/elements/scripts.pyi +580 -667
  64. reflex/components/el/elements/sectioning.pyi +2761 -3166
  65. reflex/components/el/elements/tables.pyi +1840 -2119
  66. reflex/components/el/elements/typography.pyi +2772 -3179
  67. reflex/components/gridjs/datatable.py +7 -7
  68. reflex/components/gridjs/datatable.pyi +19 -19
  69. reflex/components/lucide/icon.pyi +21 -21
  70. reflex/components/markdown/markdown.py +2 -2
  71. reflex/components/markdown/markdown.pyi +9 -9
  72. reflex/components/moment/moment.py +11 -12
  73. reflex/components/moment/moment.pyi +44 -47
  74. reflex/components/next/base.pyi +7 -7
  75. reflex/components/next/image.py +3 -3
  76. reflex/components/next/image.pyi +19 -21
  77. reflex/components/next/link.pyi +9 -9
  78. reflex/components/next/video.py +1 -3
  79. reflex/components/next/video.pyi +9 -9
  80. reflex/components/plotly/plotly.py +22 -45
  81. reflex/components/plotly/plotly.pyi +164 -164
  82. reflex/components/radix/primitives/accordion.py +14 -14
  83. reflex/components/radix/primitives/accordion.pyi +439 -487
  84. reflex/components/radix/primitives/base.py +1 -3
  85. reflex/components/radix/primitives/base.pyi +15 -15
  86. reflex/components/radix/primitives/drawer.py +3 -3
  87. reflex/components/radix/primitives/drawer.pyi +110 -116
  88. reflex/components/radix/primitives/form.py +1 -1
  89. reflex/components/radix/primitives/form.pyi +668 -752
  90. reflex/components/radix/primitives/progress.py +6 -6
  91. reflex/components/radix/primitives/progress.pyi +225 -243
  92. reflex/components/radix/primitives/slider.py +6 -6
  93. reflex/components/radix/primitives/slider.pyi +52 -55
  94. reflex/components/radix/themes/base.py +3 -6
  95. reflex/components/radix/themes/base.pyi +197 -303
  96. reflex/components/radix/themes/color_mode.py +5 -5
  97. reflex/components/radix/themes/color_mode.pyi +366 -436
  98. reflex/components/radix/themes/components/alert_dialog.pyi +229 -262
  99. reflex/components/radix/themes/components/aspect_ratio.py +1 -3
  100. reflex/components/radix/themes/components/aspect_ratio.pyi +8 -8
  101. reflex/components/radix/themes/components/avatar.pyi +79 -94
  102. reflex/components/radix/themes/components/badge.pyi +252 -295
  103. reflex/components/radix/themes/components/button.pyi +269 -314
  104. reflex/components/radix/themes/components/callout.py +2 -2
  105. reflex/components/radix/themes/components/callout.pyi +1116 -1290
  106. reflex/components/radix/themes/components/card.pyi +194 -229
  107. reflex/components/radix/themes/components/checkbox.pyi +243 -278
  108. reflex/components/radix/themes/components/checkbox_cards.py +3 -7
  109. reflex/components/radix/themes/components/checkbox_cards.pyi +101 -135
  110. reflex/components/radix/themes/components/checkbox_group.py +2 -2
  111. reflex/components/radix/themes/components/checkbox_group.pyi +83 -96
  112. reflex/components/radix/themes/components/context_menu.py +18 -15
  113. reflex/components/radix/themes/components/context_menu.pyi +408 -458
  114. reflex/components/radix/themes/components/data_list.pyi +122 -147
  115. reflex/components/radix/themes/components/dialog.pyi +231 -264
  116. reflex/components/radix/themes/components/dropdown_menu.py +16 -13
  117. reflex/components/radix/themes/components/dropdown_menu.pyi +223 -246
  118. reflex/components/radix/themes/components/hover_card.py +2 -2
  119. reflex/components/radix/themes/components/hover_card.pyi +237 -282
  120. reflex/components/radix/themes/components/icon_button.pyi +269 -314
  121. reflex/components/radix/themes/components/inset.py +8 -8
  122. reflex/components/radix/themes/components/inset.pyi +232 -292
  123. reflex/components/radix/themes/components/popover.py +2 -2
  124. reflex/components/radix/themes/components/popover.pyi +229 -271
  125. reflex/components/radix/themes/components/progress.pyi +80 -96
  126. reflex/components/radix/themes/components/radio.pyi +73 -86
  127. reflex/components/radix/themes/components/radio_cards.py +4 -8
  128. reflex/components/radix/themes/components/radio_cards.pyi +117 -154
  129. reflex/components/radix/themes/components/radio_group.py +3 -3
  130. reflex/components/radix/themes/components/radio_group.pyi +250 -291
  131. reflex/components/radix/themes/components/scroll_area.pyi +14 -20
  132. reflex/components/radix/themes/components/segmented_control.py +6 -6
  133. reflex/components/radix/themes/components/segmented_control.pyi +89 -108
  134. reflex/components/radix/themes/components/select.py +7 -7
  135. reflex/components/radix/themes/components/select.pyi +376 -444
  136. reflex/components/radix/themes/components/separator.pyi +79 -93
  137. reflex/components/radix/themes/components/skeleton.pyi +32 -26
  138. reflex/components/radix/themes/components/slider.py +8 -8
  139. reflex/components/radix/themes/components/slider.pyi +99 -122
  140. reflex/components/radix/themes/components/spinner.pyi +12 -19
  141. reflex/components/radix/themes/components/switch.pyi +84 -99
  142. reflex/components/radix/themes/components/table.py +9 -9
  143. reflex/components/radix/themes/components/table.pyi +1440 -1794
  144. reflex/components/radix/themes/components/tabs.py +4 -4
  145. reflex/components/radix/themes/components/tabs.pyi +120 -132
  146. reflex/components/radix/themes/components/text_area.pyi +281 -331
  147. reflex/components/radix/themes/components/text_field.py +2 -2
  148. reflex/components/radix/themes/components/text_field.pyi +639 -734
  149. reflex/components/radix/themes/components/tooltip.py +6 -6
  150. reflex/components/radix/themes/components/tooltip.pyi +34 -43
  151. reflex/components/radix/themes/layout/base.pyi +85 -182
  152. reflex/components/radix/themes/layout/box.pyi +183 -210
  153. reflex/components/radix/themes/layout/center.pyi +225 -286
  154. reflex/components/radix/themes/layout/container.pyi +191 -224
  155. reflex/components/radix/themes/layout/flex.py +2 -2
  156. reflex/components/radix/themes/layout/flex.pyi +225 -286
  157. reflex/components/radix/themes/layout/grid.py +2 -2
  158. reflex/components/radix/themes/layout/grid.pyi +245 -315
  159. reflex/components/radix/themes/layout/list.py +2 -2
  160. reflex/components/radix/themes/layout/list.pyi +712 -815
  161. reflex/components/radix/themes/layout/section.pyi +187 -221
  162. reflex/components/radix/themes/layout/spacer.pyi +225 -286
  163. reflex/components/radix/themes/layout/stack.pyi +625 -768
  164. reflex/components/radix/themes/typography/blockquote.pyi +257 -299
  165. reflex/components/radix/themes/typography/code.pyi +259 -304
  166. reflex/components/radix/themes/typography/heading.pyi +272 -324
  167. reflex/components/radix/themes/typography/link.pyi +302 -358
  168. reflex/components/radix/themes/typography/text.pyi +1669 -1945
  169. reflex/components/react_player/audio.pyi +20 -22
  170. reflex/components/react_player/react_player.pyi +19 -19
  171. reflex/components/react_player/video.pyi +20 -22
  172. reflex/components/recharts/cartesian.py +100 -97
  173. reflex/components/recharts/cartesian.pyi +891 -1007
  174. reflex/components/recharts/charts.py +42 -42
  175. reflex/components/recharts/charts.pyi +212 -249
  176. reflex/components/recharts/general.py +22 -21
  177. reflex/components/recharts/general.pyi +198 -223
  178. reflex/components/recharts/polar.py +42 -45
  179. reflex/components/recharts/polar.pyi +254 -288
  180. reflex/components/recharts/recharts.pyi +13 -13
  181. reflex/components/sonner/toast.py +20 -20
  182. reflex/components/sonner/toast.pyi +58 -61
  183. reflex/components/suneditor/editor.py +9 -9
  184. reflex/components/suneditor/editor.pyi +78 -83
  185. reflex/components/tags/cond_tag.py +2 -2
  186. reflex/components/tags/iter_tag.py +10 -14
  187. reflex/components/tags/match_tag.py +2 -2
  188. reflex/components/tags/tag.py +10 -10
  189. reflex/config.py +36 -35
  190. reflex/constants/__init__.py +56 -53
  191. reflex/custom_components/custom_components.py +6 -7
  192. reflex/event.py +38 -42
  193. reflex/experimental/client_state.py +2 -4
  194. reflex/experimental/layout.py +2 -2
  195. reflex/experimental/layout.pyi +579 -663
  196. reflex/istate/data.py +4 -5
  197. reflex/middleware/hydrate_middleware.py +2 -2
  198. reflex/middleware/middleware.py +2 -2
  199. reflex/model.py +3 -5
  200. reflex/page.py +2 -2
  201. reflex/reflex.py +9 -10
  202. reflex/state.py +77 -49
  203. reflex/style.py +9 -3
  204. reflex/testing.py +21 -24
  205. reflex/utils/console.py +1 -1
  206. reflex/utils/decorator.py +26 -1
  207. reflex/utils/exec.py +6 -11
  208. reflex/utils/export.py +2 -3
  209. reflex/utils/format.py +4 -4
  210. reflex/utils/imports.py +12 -12
  211. reflex/utils/prerequisites.py +35 -84
  212. reflex/utils/processes.py +5 -5
  213. reflex/utils/pyi_generator.py +33 -22
  214. reflex/utils/serializers.py +60 -15
  215. reflex/utils/types.py +237 -56
  216. reflex/vars/base.py +122 -72
  217. reflex/vars/datetime.py +2 -2
  218. reflex/vars/function.py +52 -55
  219. reflex/vars/number.py +59 -5
  220. reflex/vars/object.py +57 -26
  221. reflex/vars/sequence.py +983 -958
  222. {reflex-0.7.1a4.dist-info → reflex-0.7.2a2.dist-info}/METADATA +3 -6
  223. reflex-0.7.2a2.dist-info/RECORD +405 -0
  224. {reflex-0.7.1a4.dist-info → reflex-0.7.2a2.dist-info}/WHEEL +1 -1
  225. reflex-0.7.1a4.dist-info/RECORD +0 -405
  226. {reflex-0.7.1a4.dist-info → reflex-0.7.2a2.dist-info}/LICENSE +0 -0
  227. {reflex-0.7.1a4.dist-info → reflex-0.7.2a2.dist-info}/entry_points.txt +0 -0
@@ -78,9 +78,9 @@ export function UploadFilesProvider({ children }) {
78
78
  return newFilesById
79
79
  })
80
80
  return (
81
- <UploadFilesContext.Provider value={[filesById, setFilesById]}>
81
+ <UploadFilesContext value={[filesById, setFilesById]}>
82
82
  {children}
83
- </UploadFilesContext.Provider>
83
+ </UploadFilesContext>
84
84
  )
85
85
  }
86
86
 
@@ -92,9 +92,9 @@ export function EventLoopProvider({ children }) {
92
92
  clientStorage,
93
93
  )
94
94
  return (
95
- <EventLoopContext.Provider value={[addEvents, connectErrors]}>
95
+ <EventLoopContext value={[addEvents, connectErrors]}>
96
96
  {children}
97
- </EventLoopContext.Provider>
97
+ </EventLoopContext>
98
98
  )
99
99
  }
100
100
 
@@ -112,13 +112,13 @@ export function StateProvider({ children }) {
112
112
 
113
113
  return (
114
114
  {% for state_name in initial_state %}
115
- <StateContexts.{{state_name|var_name}}.Provider value={ {{state_name|var_name}} }>
115
+ <StateContexts.{{state_name|var_name}} value={ {{state_name|var_name}} }>
116
116
  {% endfor %}
117
- <DispatchContext.Provider value={dispatchers}>
117
+ <DispatchContext value={dispatchers}>
118
118
  {children}
119
- </DispatchContext.Provider>
119
+ </DispatchContext>
120
120
  {% for state_name in initial_state|reverse %}
121
- </StateContexts.{{state_name|var_name}}.Provider>
121
+ </StateContexts.{{state_name|var_name}}>
122
122
  {% endfor %}
123
123
  )
124
124
  }
@@ -36,17 +36,17 @@ export default function RadixThemesColorModeProvider({ children }) {
36
36
  const allowedModes = ["light", "dark", "system"];
37
37
  if (!allowedModes.includes(mode)) {
38
38
  console.error(
39
- `Invalid color mode "${mode}". Defaulting to "${defaultColorMode}".`
39
+ `Invalid color mode "${mode}". Defaulting to "${defaultColorMode}".`,
40
40
  );
41
41
  mode = defaultColorMode;
42
42
  }
43
43
  setTheme(mode);
44
44
  };
45
45
  return (
46
- <ColorModeContext.Provider
46
+ <ColorModeContext
47
47
  value={{ rawColorMode, resolvedColorMode, toggleColorMode, setColorMode }}
48
48
  >
49
49
  {children}
50
- </ColorModeContext.Provider>
50
+ </ColorModeContext>
51
51
  );
52
52
  }
@@ -179,7 +179,7 @@ export const applyEvent = async (event, socket) => {
179
179
  // Handle special events
180
180
  if (event.name == "_redirect") {
181
181
  if (event.payload.external) {
182
- window.open(event.payload.path, "_blank");
182
+ window.open(event.payload.path, "_blank", "noopener");
183
183
  } else if (event.payload.replace) {
184
184
  Router.replace(event.payload.path);
185
185
  } else {
@@ -227,8 +227,8 @@ export const applyEvent = async (event, socket) => {
227
227
  a.href = eval?.(
228
228
  event.payload.url.replace(
229
229
  "getBackendURL(env.UPLOAD)",
230
- `"${getBackendURL(env.UPLOAD)}"`,
231
- ),
230
+ `"${getBackendURL(env.UPLOAD)}"`
231
+ )
232
232
  );
233
233
  }
234
234
  a.download = event.payload.filename;
@@ -341,7 +341,7 @@ export const applyRestEvent = async (event, socket) => {
341
341
  event.payload.files,
342
342
  event.payload.upload_id,
343
343
  event.payload.on_upload_progress,
344
- socket,
344
+ socket
345
345
  );
346
346
  return false;
347
347
  }
@@ -408,7 +408,7 @@ export const connect = async (
408
408
  dispatch,
409
409
  transports,
410
410
  setConnectErrors,
411
- client_storage = {},
411
+ client_storage = {}
412
412
  ) => {
413
413
  // Get backend URL object from the endpoint.
414
414
  const endpoint = getBackendURL(EVENTURL);
@@ -499,7 +499,7 @@ export const uploadFiles = async (
499
499
  files,
500
500
  upload_id,
501
501
  on_upload_progress,
502
- socket,
502
+ socket
503
503
  ) => {
504
504
  // return if there's no file to upload
505
505
  if (files === undefined || files.length === 0) {
@@ -604,7 +604,7 @@ export const Event = (
604
604
  name,
605
605
  payload = {},
606
606
  event_actions = {},
607
- handler = null,
607
+ handler = null
608
608
  ) => {
609
609
  return { name, payload, handler, event_actions };
610
610
  };
@@ -631,7 +631,7 @@ export const hydrateClientStorage = (client_storage) => {
631
631
  for (const state_key in client_storage.local_storage) {
632
632
  const options = client_storage.local_storage[state_key];
633
633
  const local_storage_value = localStorage.getItem(
634
- options.name || state_key,
634
+ options.name || state_key
635
635
  );
636
636
  if (local_storage_value !== null) {
637
637
  client_storage_values[state_key] = local_storage_value;
@@ -642,7 +642,7 @@ export const hydrateClientStorage = (client_storage) => {
642
642
  for (const state_key in client_storage.session_storage) {
643
643
  const session_options = client_storage.session_storage[state_key];
644
644
  const session_storage_value = sessionStorage.getItem(
645
- session_options.name || state_key,
645
+ session_options.name || state_key
646
646
  );
647
647
  if (session_storage_value != null) {
648
648
  client_storage_values[state_key] = session_storage_value;
@@ -667,7 +667,7 @@ export const hydrateClientStorage = (client_storage) => {
667
667
  const applyClientStorageDelta = (client_storage, delta) => {
668
668
  // find the main state and check for is_hydrated
669
669
  const unqualified_states = Object.keys(delta).filter(
670
- (key) => key.split(".").length === 1,
670
+ (key) => key.split(".").length === 1
671
671
  );
672
672
  if (unqualified_states.length === 1) {
673
673
  const main_state = delta[unqualified_states[0]];
@@ -701,7 +701,7 @@ const applyClientStorageDelta = (client_storage, delta) => {
701
701
  const session_options = client_storage.session_storage[state_key];
702
702
  sessionStorage.setItem(
703
703
  session_options.name || state_key,
704
- delta[substate][key],
704
+ delta[substate][key]
705
705
  );
706
706
  }
707
707
  }
@@ -721,7 +721,7 @@ const applyClientStorageDelta = (client_storage, delta) => {
721
721
  export const useEventLoop = (
722
722
  dispatch,
723
723
  initial_events = () => [],
724
- client_storage = {},
724
+ client_storage = {}
725
725
  ) => {
726
726
  const socket = useRef(null);
727
727
  const router = useRouter();
@@ -735,7 +735,7 @@ export const useEventLoop = (
735
735
 
736
736
  event_actions = events.reduce(
737
737
  (acc, e) => ({ ...acc, ...e.event_actions }),
738
- event_actions ?? {},
738
+ event_actions ?? {}
739
739
  );
740
740
 
741
741
  const _e = args.filter((o) => o?.preventDefault !== undefined)[0];
@@ -763,7 +763,7 @@ export const useEventLoop = (
763
763
  debounce(
764
764
  combined_name,
765
765
  () => queueEvents(events, socket),
766
- event_actions.debounce,
766
+ event_actions.debounce
767
767
  );
768
768
  } else {
769
769
  queueEvents(events, socket);
@@ -782,7 +782,7 @@ export const useEventLoop = (
782
782
  query,
783
783
  asPath,
784
784
  }))(router),
785
- })),
785
+ }))
786
786
  );
787
787
  sentHydrate.current = true;
788
788
  }
@@ -828,7 +828,7 @@ export const useEventLoop = (
828
828
  dispatch,
829
829
  ["websocket"],
830
830
  setConnectErrors,
831
- client_storage,
831
+ client_storage
832
832
  );
833
833
  }
834
834
  }
@@ -876,7 +876,7 @@ export const useEventLoop = (
876
876
  vars[storage_to_state_map[e.key]] = e.newValue;
877
877
  const event = Event(
878
878
  `${state_name}.reflex___state____update_vars_internal_state.update_vars_internal`,
879
- { vars: vars },
879
+ { vars: vars }
880
880
  );
881
881
  addEvents([event], e);
882
882
  }
@@ -969,7 +969,7 @@ export const getRefValues = (refs) => {
969
969
  return refs.map((ref) =>
970
970
  ref.current
971
971
  ? ref.current.value || ref.current.getAttribute("aria-valuenow")
972
- : null,
972
+ : null
973
973
  );
974
974
  };
975
975
 
reflex/admin.py CHANGED
@@ -1,7 +1,6 @@
1
1
  """The Reflex Admin Dashboard."""
2
2
 
3
3
  from dataclasses import dataclass, field
4
- from typing import Optional
5
4
 
6
5
  from starlette_admin.base import BaseAdmin as Admin
7
6
 
@@ -12,4 +11,4 @@ class AdminDash:
12
11
 
13
12
  models: list = field(default_factory=list)
14
13
  view_overrides: dict = field(default_factory=dict)
15
- admin: Optional[Admin] = None
14
+ admin: Admin | None = None
reflex/app.py CHANGED
@@ -25,12 +25,8 @@ from typing import (
25
25
  Callable,
26
26
  Coroutine,
27
27
  Dict,
28
- List,
29
28
  MutableMapping,
30
- Optional,
31
- Set,
32
29
  Type,
33
- Union,
34
30
  get_args,
35
31
  get_type_hints,
36
32
  )
@@ -167,7 +163,7 @@ def default_backend_exception_handler(exception: Exception) -> EventSpec:
167
163
  )
168
164
 
169
165
 
170
- def extra_overlay_function() -> Optional[Component]:
166
+ def extra_overlay_function() -> Component | None:
171
167
  """Extra overlay function to add to the overlay component.
172
168
 
173
169
  Returns:
@@ -250,16 +246,16 @@ class UploadFile(StarletteUploadFile):
250
246
 
251
247
  file: BinaryIO
252
248
 
253
- path: Optional[Path] = dataclasses.field(default=None)
249
+ path: Path | None = dataclasses.field(default=None)
254
250
 
255
- _deprecated_filename: Optional[str] = dataclasses.field(default=None)
251
+ _deprecated_filename: str | None = dataclasses.field(default=None)
256
252
 
257
- size: Optional[int] = dataclasses.field(default=None)
253
+ size: int | None = dataclasses.field(default=None)
258
254
 
259
255
  headers: Headers = dataclasses.field(default_factory=Headers)
260
256
 
261
257
  @property
262
- def name(self) -> Optional[str]:
258
+ def name(self) -> str | None:
263
259
  """Get the name of the uploaded file.
264
260
 
265
261
  Returns:
@@ -269,7 +265,7 @@ class UploadFile(StarletteUploadFile):
269
265
  return self.path.name
270
266
 
271
267
  @property
272
- def filename(self) -> Optional[str]:
268
+ def filename(self) -> str | None:
273
269
  """Get the filename of the uploaded file.
274
270
 
275
271
  Returns:
@@ -290,13 +286,13 @@ class UploadFile(StarletteUploadFile):
290
286
  class UnevaluatedPage:
291
287
  """An uncompiled page."""
292
288
 
293
- component: Union[Component, ComponentCallable]
289
+ component: Component | ComponentCallable
294
290
  route: str
295
- title: Union[Var, str, None]
296
- description: Union[Var, str, None]
291
+ title: Var | str | None
292
+ description: Var | str | None
297
293
  image: str
298
- on_load: Union[EventType[()], None]
299
- meta: List[Dict[str, str]]
294
+ on_load: EventType[()] | None
295
+ meta: list[dict[str, str]]
300
296
 
301
297
 
302
298
  @dataclasses.dataclass()
@@ -322,7 +318,7 @@ class App(MiddlewareMixin, LifespanMixin):
322
318
  """
323
319
 
324
320
  # The global [theme](https://reflex.dev/docs/styling/theming/#theme) for the entire app.
325
- theme: Optional[Component] = dataclasses.field(
321
+ theme: Component | None = dataclasses.field(
326
322
  default_factory=lambda: themes.theme(accent_color="blue")
327
323
  )
328
324
 
@@ -330,18 +326,18 @@ class App(MiddlewareMixin, LifespanMixin):
330
326
  style: ComponentStyle = dataclasses.field(default_factory=dict)
331
327
 
332
328
  # A list of URLs to [stylesheets](https://reflex.dev/docs/styling/custom-stylesheets/) to include in the app.
333
- stylesheets: List[str] = dataclasses.field(default_factory=list)
329
+ stylesheets: list[str] = dataclasses.field(default_factory=list)
334
330
 
335
331
  # A component that is present on every page (defaults to the Connection Error banner).
336
- overlay_component: Optional[Union[Component, ComponentCallable]] = (
337
- dataclasses.field(default=None)
332
+ overlay_component: Component | ComponentCallable | None = dataclasses.field(
333
+ default=None
338
334
  )
339
335
 
340
336
  # Error boundary component to wrap the app with.
341
- error_boundary: Optional[ComponentCallable] = dataclasses.field(default=None)
337
+ error_boundary: ComponentCallable | None = dataclasses.field(default=None)
342
338
 
343
339
  # App wraps to be applied to the whole app. Expected to be a dictionary of (order, name) to a function that takes whether the state is enabled and optionally returns a component.
344
- app_wraps: Dict[tuple[int, str], Callable[[bool], Optional[Component]]] = (
340
+ app_wraps: dict[tuple[int, str], Callable[[bool], Component | None]] = (
345
341
  dataclasses.field(
346
342
  default_factory=lambda: {
347
343
  (55, "ErrorBoundary"): (
@@ -356,24 +352,24 @@ class App(MiddlewareMixin, LifespanMixin):
356
352
  )
357
353
 
358
354
  # Components to add to the head of every page.
359
- head_components: List[Component] = dataclasses.field(default_factory=list)
355
+ head_components: list[Component] = dataclasses.field(default_factory=list)
360
356
 
361
357
  # The Socket.IO AsyncServer instance.
362
- sio: Optional[AsyncServer] = None
358
+ sio: AsyncServer | None = None
363
359
 
364
360
  # The language to add to the html root tag of every page.
365
- html_lang: Optional[str] = None
361
+ html_lang: str | None = None
366
362
 
367
363
  # Attributes to add to the html root tag of every page.
368
- html_custom_attrs: Optional[Dict[str, str]] = None
364
+ html_custom_attrs: dict[str, str] | None = None
369
365
 
370
366
  # A map from a route to an unevaluated page.
371
- _unevaluated_pages: Dict[str, UnevaluatedPage] = dataclasses.field(
367
+ _unevaluated_pages: dict[str, UnevaluatedPage] = dataclasses.field(
372
368
  default_factory=dict
373
369
  )
374
370
 
375
371
  # A map from a page route to the component to render. Users should use `add_page`.
376
- _pages: Dict[str, Component] = dataclasses.field(default_factory=dict)
372
+ _pages: dict[str, Component] = dataclasses.field(default_factory=dict)
377
373
 
378
374
  # A mapping of pages which created states as they were being evaluated.
379
375
  _stateful_pages: Dict[str, None] = dataclasses.field(default_factory=dict)
@@ -382,24 +378,24 @@ class App(MiddlewareMixin, LifespanMixin):
382
378
  _api: FastAPI | None = None
383
379
 
384
380
  # The state class to use for the app.
385
- _state: Optional[Type[BaseState]] = None
381
+ _state: Type[BaseState] | None = None
386
382
 
387
383
  # Class to manage many client states.
388
- _state_manager: Optional[StateManager] = None
384
+ _state_manager: StateManager | None = None
389
385
 
390
386
  # Mapping from a route to event handlers to trigger when the page loads.
391
- _load_events: Dict[str, List[IndividualEventType[()]]] = dataclasses.field(
387
+ _load_events: dict[str, list[IndividualEventType[()]]] = dataclasses.field(
392
388
  default_factory=dict
393
389
  )
394
390
 
395
391
  # Admin dashboard to view and manage the database.
396
- admin_dash: Optional[AdminDash] = None
392
+ admin_dash: AdminDash | None = None
397
393
 
398
394
  # The async server name space.
399
- _event_namespace: Optional[EventNamespace] = None
395
+ _event_namespace: EventNamespace | None = None
400
396
 
401
397
  # Background tasks that are currently running.
402
- _background_tasks: Set[asyncio.Task] = dataclasses.field(default_factory=set)
398
+ _background_tasks: set[asyncio.Task] = dataclasses.field(default_factory=set)
403
399
 
404
400
  # Frontend Error Handler Function
405
401
  frontend_exception_handler: Callable[[Exception], None] = (
@@ -408,7 +404,7 @@ class App(MiddlewareMixin, LifespanMixin):
408
404
 
409
405
  # Backend Error Handler Function
410
406
  backend_exception_handler: Callable[
411
- [Exception], Union[EventSpec, List[EventSpec], None]
407
+ [Exception], EventSpec | list[EventSpec] | None
412
408
  ] = default_backend_exception_handler
413
409
 
414
410
  # Put the toast provider in the app wrap.
@@ -895,7 +891,7 @@ class App(MiddlewareMixin, LifespanMixin):
895
891
 
896
892
  admin.mount_to(self.api)
897
893
 
898
- def _get_frontend_packages(self, imports: Dict[str, set[ImportVar]]):
894
+ def _get_frontend_packages(self, imports: dict[str, set[ImportVar]]):
899
895
  """Gets the frontend packages to be installed and filters out the unnecessary ones.
900
896
 
901
897
  Args:
@@ -986,12 +982,15 @@ class App(MiddlewareMixin, LifespanMixin):
986
982
 
987
983
  def _setup_sticky_badge(self):
988
984
  """Add the sticky badge to the app."""
989
- for k, component in self._pages.items():
990
- # Would be nice to share single sticky_badge across all pages, but
991
- # it bungles the StatefulComponent compile step.
985
+ from reflex.components.component import memo
986
+
987
+ @memo
988
+ def memoized_badge():
992
989
  sticky_badge = sticky()
993
990
  sticky_badge._add_style_recursive({})
994
- self._pages[k] = Fragment.create(sticky_badge, component)
991
+ return sticky_badge
992
+
993
+ self.app_wraps[(0, "StickyBadge")] = lambda _: memoized_badge()
995
994
 
996
995
  def _apply_decorated_pages(self):
997
996
  """Add @rx.page decorated pages to the app.
@@ -1006,9 +1005,7 @@ class App(MiddlewareMixin, LifespanMixin):
1006
1005
  for render, kwargs in DECORATED_PAGES[get_config().app_name]:
1007
1006
  self.add_page(render, **kwargs)
1008
1007
 
1009
- def _validate_var_dependencies(
1010
- self, state: Optional[Type[BaseState]] = None
1011
- ) -> None:
1008
+ def _validate_var_dependencies(self, state: Type[BaseState] | None = None) -> None:
1012
1009
  """Validate the dependencies of the vars in the app.
1013
1010
 
1014
1011
  Args:
@@ -1080,7 +1077,7 @@ class App(MiddlewareMixin, LifespanMixin):
1080
1077
  self.style = evaluate_style_namespaces(self.style)
1081
1078
 
1082
1079
  # Add the app wrappers.
1083
- app_wrappers: Dict[tuple[int, str], Component] = {
1080
+ app_wrappers: dict[tuple[int, str], Component] = {
1084
1081
  # Default app wrap component renders {children}
1085
1082
  (0, "AppWrap"): AppWrap.create()
1086
1083
  }
@@ -1547,8 +1544,8 @@ class App(MiddlewareMixin, LifespanMixin):
1547
1544
 
1548
1545
  valid = bool(
1549
1546
  return_type == EventSpec
1550
- or return_type == Optional[EventSpec]
1551
- or return_type == List[EventSpec]
1547
+ or return_type == EventSpec | None
1548
+ or return_type == list[EventSpec]
1552
1549
  or return_type == inspect.Signature.empty
1553
1550
  or return_type is None
1554
1551
  )
@@ -1556,7 +1553,7 @@ class App(MiddlewareMixin, LifespanMixin):
1556
1553
  if not valid:
1557
1554
  raise ValueError(
1558
1555
  f"Provided custom {handler_domain} exception handler `{_fn_name}` has the wrong return type."
1559
- f"Expected `Union[EventSpec, List[EventSpec], None]` but got `{return_type}`"
1556
+ f"Expected `EventSpec | list[EventSpec] | None` but got `{return_type}`"
1560
1557
  )
1561
1558
 
1562
1559
 
@@ -1696,7 +1693,7 @@ def upload(app: App):
1696
1693
  The upload function.
1697
1694
  """
1698
1695
 
1699
- async def upload_file(request: Request, files: List[FastAPIUploadFile]):
1696
+ async def upload_file(request: Request, files: list[FastAPIUploadFile]):
1700
1697
  """Upload a file.
1701
1698
 
1702
1699
  Args:
@@ -1736,7 +1733,7 @@ def upload(app: App):
1736
1733
  # get handler function
1737
1734
  func = getattr(type(current_state), handler.split(".")[-1])
1738
1735
 
1739
- # check if there exists any handler args with annotation, List[UploadFile]
1736
+ # check if there exists any handler args with annotation, list[UploadFile]
1740
1737
  if isinstance(func, EventHandler):
1741
1738
  if func.is_background:
1742
1739
  raise UploadTypeError(
@@ -1756,7 +1753,7 @@ def upload(app: App):
1756
1753
  if not handler_upload_param:
1757
1754
  raise UploadValueError(
1758
1755
  f"`{handler}` handler should have a parameter annotated as "
1759
- "List[rx.UploadFile]"
1756
+ "list[rx.UploadFile]"
1760
1757
  )
1761
1758
 
1762
1759
  # Make a copy of the files as they are closed after the request.
@@ -7,7 +7,7 @@ import contextlib
7
7
  import dataclasses
8
8
  import functools
9
9
  import inspect
10
- from typing import Callable, Coroutine, Set, Union
10
+ from typing import Callable, Coroutine
11
11
 
12
12
  from fastapi import FastAPI
13
13
 
@@ -22,7 +22,7 @@ class LifespanMixin(AppMixin):
22
22
  """A Mixin that allow tasks to run during the whole app lifespan."""
23
23
 
24
24
  # Lifespan tasks that are planned to run.
25
- lifespan_tasks: Set[Union[asyncio.Task, Callable]] = dataclasses.field(
25
+ lifespan_tasks: set[asyncio.Task | Callable] = dataclasses.field(
26
26
  default_factory=set
27
27
  )
28
28
 
@@ -4,7 +4,6 @@ from __future__ import annotations
4
4
 
5
5
  import asyncio
6
6
  import dataclasses
7
- from typing import List
8
7
 
9
8
  from reflex.event import Event
10
9
  from reflex.middleware import HydrateMiddleware, Middleware
@@ -18,7 +17,7 @@ class MiddlewareMixin(AppMixin):
18
17
  """Middleware Mixin that allow to add middleware to the app."""
19
18
 
20
19
  # Middleware to add to the app. Users should use `add_middleware`. PRIVATE.
21
- middleware: List[Middleware] = dataclasses.field(default_factory=list)
20
+ middleware: list[Middleware] = dataclasses.field(default_factory=list)
22
21
 
23
22
  def _init_mixin(self):
24
23
  self.middleware.append(HydrateMiddleware())
reflex/assets.py CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  import inspect
4
4
  from pathlib import Path
5
- from typing import Optional
6
5
 
7
6
  from reflex import constants
8
7
  from reflex.config import EnvironmentVariables
@@ -11,7 +10,7 @@ from reflex.config import EnvironmentVariables
11
10
  def asset(
12
11
  path: str,
13
12
  shared: bool = False,
14
- subfolder: Optional[str] = None,
13
+ subfolder: str | None = None,
15
14
  _stack_level: int = 1,
16
15
  ) -> str:
17
16
  """Add an asset to the app, either shared as a symlink or local.
reflex/base.py CHANGED
@@ -3,14 +3,14 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import os
6
- from typing import TYPE_CHECKING, Any, List, Type
6
+ from typing import TYPE_CHECKING, Any, Type
7
7
 
8
8
  import pydantic.v1.main as pydantic_main
9
9
  from pydantic.v1 import BaseModel
10
10
  from pydantic.v1.fields import ModelField
11
11
 
12
12
 
13
- def validate_field_name(bases: List[Type["BaseModel"]], field_name: str) -> None:
13
+ def validate_field_name(bases: list[Type["BaseModel"]], field_name: str) -> None:
14
14
  """Ensure that the field's name does not shadow an existing attribute of the model.
15
15
 
16
16
  Args: