reflex 0.6.4a2__py3-none-any.whl → 0.6.5__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 (228) hide show
  1. reflex/.templates/jinja/web/pages/custom_component.js.jinja2 +0 -14
  2. reflex/.templates/jinja/web/pages/utils.js.jinja2 +4 -8
  3. reflex/.templates/web/components/shiki/code.js +16 -11
  4. reflex/.templates/web/utils/state.js +29 -21
  5. reflex/__init__.py +4 -0
  6. reflex/__init__.pyi +4 -0
  7. reflex/app.py +148 -154
  8. reflex/app_mixins/lifespan.py +5 -1
  9. reflex/app_mixins/middleware.py +3 -1
  10. reflex/app_mixins/mixin.py +3 -2
  11. reflex/base.py +2 -4
  12. reflex/compiler/compiler.py +111 -37
  13. reflex/components/base/app_wrap.pyi +17 -17
  14. reflex/components/base/bare.py +72 -3
  15. reflex/components/base/body.pyi +17 -17
  16. reflex/components/base/document.pyi +81 -81
  17. reflex/components/base/error_boundary.pyi +25 -18
  18. reflex/components/base/fragment.pyi +17 -17
  19. reflex/components/base/head.pyi +33 -33
  20. reflex/components/base/link.pyi +33 -33
  21. reflex/components/base/meta.pyi +65 -65
  22. reflex/components/base/script.py +4 -4
  23. reflex/components/base/script.pyi +23 -20
  24. reflex/components/component.py +250 -31
  25. reflex/components/core/banner.py +1 -1
  26. reflex/components/core/banner.pyi +81 -81
  27. reflex/components/core/client_side_routing.pyi +33 -33
  28. reflex/components/core/clipboard.py +2 -2
  29. reflex/components/core/clipboard.pyi +24 -18
  30. reflex/components/core/debounce.py +2 -2
  31. reflex/components/core/debounce.pyi +18 -18
  32. reflex/components/core/html.pyi +17 -17
  33. reflex/components/core/upload.py +90 -28
  34. reflex/components/core/upload.pyi +128 -72
  35. reflex/components/datadisplay/code.py +55 -40
  36. reflex/components/datadisplay/code.pyi +46 -44
  37. reflex/components/datadisplay/dataeditor.py +21 -20
  38. reflex/components/datadisplay/dataeditor.pyi +103 -35
  39. reflex/components/datadisplay/shiki_code_block.py +60 -27
  40. reflex/components/datadisplay/shiki_code_block.pyi +86 -65
  41. reflex/components/dynamic.py +9 -5
  42. reflex/components/el/element.pyi +17 -17
  43. reflex/components/el/elements/base.pyi +17 -17
  44. reflex/components/el/elements/forms.py +12 -3
  45. reflex/components/el/elements/forms.pyi +293 -233
  46. reflex/components/el/elements/inline.pyi +449 -449
  47. reflex/components/el/elements/media.pyi +401 -401
  48. reflex/components/el/elements/metadata.pyi +97 -97
  49. reflex/components/el/elements/other.pyi +113 -113
  50. reflex/components/el/elements/scripts.pyi +49 -49
  51. reflex/components/el/elements/sectioning.pyi +241 -241
  52. reflex/components/el/elements/tables.pyi +161 -161
  53. reflex/components/el/elements/typography.pyi +241 -241
  54. reflex/components/gridjs/datatable.pyi +33 -33
  55. reflex/components/lucide/icon.py +1 -1
  56. reflex/components/lucide/icon.pyi +33 -33
  57. reflex/components/markdown/markdown.py +180 -49
  58. reflex/components/markdown/markdown.pyi +36 -19
  59. reflex/components/moment/moment.py +17 -21
  60. reflex/components/moment/moment.pyi +26 -21
  61. reflex/components/next/base.pyi +17 -17
  62. reflex/components/next/image.py +3 -3
  63. reflex/components/next/image.pyi +21 -19
  64. reflex/components/next/link.pyi +17 -17
  65. reflex/components/next/video.pyi +17 -17
  66. reflex/components/plotly/plotly.py +79 -78
  67. reflex/components/plotly/plotly.pyi +91 -41
  68. reflex/components/props.py +34 -0
  69. reflex/components/radix/primitives/accordion.py +15 -8
  70. reflex/components/radix/primitives/accordion.pyi +121 -118
  71. reflex/components/radix/primitives/base.pyi +33 -33
  72. reflex/components/radix/primitives/drawer.py +41 -20
  73. reflex/components/radix/primitives/drawer.pyi +279 -190
  74. reflex/components/radix/primitives/form.py +2 -2
  75. reflex/components/radix/primitives/form.pyi +200 -167
  76. reflex/components/radix/primitives/progress.pyi +81 -81
  77. reflex/components/radix/primitives/slider.pyi +89 -83
  78. reflex/components/radix/themes/base.py +30 -1
  79. reflex/components/radix/themes/base.pyi +286 -113
  80. reflex/components/radix/themes/color_mode.py +17 -9
  81. reflex/components/radix/themes/color_mode.pyi +68 -56
  82. reflex/components/radix/themes/components/alert_dialog.py +8 -5
  83. reflex/components/radix/themes/components/alert_dialog.pyi +125 -117
  84. reflex/components/radix/themes/components/aspect_ratio.pyi +17 -17
  85. reflex/components/radix/themes/components/avatar.py +1 -5
  86. reflex/components/radix/themes/components/avatar.pyi +17 -17
  87. reflex/components/radix/themes/components/badge.py +1 -5
  88. reflex/components/radix/themes/components/badge.pyi +17 -17
  89. reflex/components/radix/themes/components/button.pyi +18 -21
  90. reflex/components/radix/themes/components/callout.py +1 -4
  91. reflex/components/radix/themes/components/callout.pyi +81 -81
  92. reflex/components/radix/themes/components/card.py +1 -3
  93. reflex/components/radix/themes/components/card.pyi +17 -17
  94. reflex/components/radix/themes/components/checkbox.py +4 -8
  95. reflex/components/radix/themes/components/checkbox.pyi +61 -52
  96. reflex/components/radix/themes/components/checkbox_cards.pyi +33 -33
  97. reflex/components/radix/themes/components/checkbox_group.pyi +33 -33
  98. reflex/components/radix/themes/components/context_menu.py +121 -28
  99. reflex/components/radix/themes/components/context_menu.pyi +250 -147
  100. reflex/components/radix/themes/components/data_list.pyi +65 -65
  101. reflex/components/radix/themes/components/dialog.py +11 -11
  102. reflex/components/radix/themes/components/dialog.pyi +135 -120
  103. reflex/components/radix/themes/components/dropdown_menu.py +14 -25
  104. reflex/components/radix/themes/components/dropdown_menu.pyi +157 -145
  105. reflex/components/radix/themes/components/hover_card.py +19 -7
  106. reflex/components/radix/themes/components/hover_card.pyi +102 -67
  107. reflex/components/radix/themes/components/icon_button.pyi +18 -21
  108. reflex/components/radix/themes/components/inset.py +1 -3
  109. reflex/components/radix/themes/components/inset.pyi +17 -17
  110. reflex/components/radix/themes/components/popover.py +22 -13
  111. reflex/components/radix/themes/components/popover.pyi +98 -72
  112. reflex/components/radix/themes/components/progress.pyi +17 -17
  113. reflex/components/radix/themes/components/radio.pyi +17 -17
  114. reflex/components/radix/themes/components/radio_cards.py +2 -2
  115. reflex/components/radix/themes/components/radio_cards.pyi +37 -34
  116. reflex/components/radix/themes/components/radio_group.py +3 -7
  117. reflex/components/radix/themes/components/radio_group.pyi +69 -66
  118. reflex/components/radix/themes/components/scroll_area.py +1 -3
  119. reflex/components/radix/themes/components/scroll_area.pyi +17 -17
  120. reflex/components/radix/themes/components/segmented_control.pyi +37 -34
  121. reflex/components/radix/themes/components/select.py +7 -11
  122. reflex/components/radix/themes/components/select.pyi +175 -154
  123. reflex/components/radix/themes/components/separator.py +1 -4
  124. reflex/components/radix/themes/components/separator.pyi +17 -17
  125. reflex/components/radix/themes/components/skeleton.pyi +17 -17
  126. reflex/components/radix/themes/components/slider.py +12 -21
  127. reflex/components/radix/themes/components/slider.pyi +47 -25
  128. reflex/components/radix/themes/components/spinner.py +1 -4
  129. reflex/components/radix/themes/components/spinner.pyi +17 -17
  130. reflex/components/radix/themes/components/switch.py +3 -6
  131. reflex/components/radix/themes/components/switch.pyi +21 -18
  132. reflex/components/radix/themes/components/table.py +21 -5
  133. reflex/components/radix/themes/components/table.pyi +392 -116
  134. reflex/components/radix/themes/components/tabs.py +3 -6
  135. reflex/components/radix/themes/components/tabs.pyi +89 -83
  136. reflex/components/radix/themes/components/text_area.py +1 -5
  137. reflex/components/radix/themes/components/text_area.pyi +43 -20
  138. reflex/components/radix/themes/components/text_field.py +1 -5
  139. reflex/components/radix/themes/components/text_field.pyi +101 -55
  140. reflex/components/radix/themes/components/tooltip.py +5 -7
  141. reflex/components/radix/themes/components/tooltip.pyi +25 -22
  142. reflex/components/radix/themes/layout/base.py +2 -27
  143. reflex/components/radix/themes/layout/base.pyi +82 -82
  144. reflex/components/radix/themes/layout/box.pyi +17 -17
  145. reflex/components/radix/themes/layout/center.pyi +17 -17
  146. reflex/components/radix/themes/layout/container.pyi +17 -17
  147. reflex/components/radix/themes/layout/flex.py +1 -6
  148. reflex/components/radix/themes/layout/flex.pyi +17 -17
  149. reflex/components/radix/themes/layout/grid.py +1 -6
  150. reflex/components/radix/themes/layout/grid.pyi +17 -17
  151. reflex/components/radix/themes/layout/list.py +20 -15
  152. reflex/components/radix/themes/layout/list.pyi +175 -92
  153. reflex/components/radix/themes/layout/section.pyi +17 -17
  154. reflex/components/radix/themes/layout/spacer.pyi +17 -17
  155. reflex/components/radix/themes/layout/stack.py +6 -6
  156. reflex/components/radix/themes/layout/stack.pyi +91 -62
  157. reflex/components/radix/themes/typography/blockquote.py +2 -8
  158. reflex/components/radix/themes/typography/blockquote.pyi +17 -17
  159. reflex/components/radix/themes/typography/code.py +4 -10
  160. reflex/components/radix/themes/typography/code.pyi +19 -18
  161. reflex/components/radix/themes/typography/heading.py +4 -11
  162. reflex/components/radix/themes/typography/heading.pyi +19 -18
  163. reflex/components/radix/themes/typography/link.py +4 -10
  164. reflex/components/radix/themes/typography/link.pyi +19 -18
  165. reflex/components/radix/themes/typography/text.py +4 -11
  166. reflex/components/radix/themes/typography/text.pyi +115 -114
  167. reflex/components/react_player/audio.pyi +58 -33
  168. reflex/components/react_player/react_player.py +17 -17
  169. reflex/components/react_player/react_player.pyi +55 -33
  170. reflex/components/react_player/video.pyi +58 -33
  171. reflex/components/recharts/cartesian.py +45 -45
  172. reflex/components/recharts/cartesian.pyi +389 -304
  173. reflex/components/recharts/charts.py +22 -22
  174. reflex/components/recharts/charts.pyi +226 -179
  175. reflex/components/recharts/general.py +26 -27
  176. reflex/components/recharts/general.pyi +106 -99
  177. reflex/components/recharts/polar.py +33 -33
  178. reflex/components/recharts/polar.pyi +70 -64
  179. reflex/components/recharts/recharts.pyi +33 -33
  180. reflex/components/sonner/toast.py +9 -36
  181. reflex/components/sonner/toast.pyi +20 -24
  182. reflex/components/suneditor/editor.py +8 -8
  183. reflex/components/suneditor/editor.pyi +50 -25
  184. reflex/components/tags/iter_tag.py +1 -10
  185. reflex/components/tags/tag.py +1 -4
  186. reflex/config.py +252 -41
  187. reflex/constants/__init__.py +4 -16
  188. reflex/constants/base.py +7 -14
  189. reflex/constants/colors.py +0 -1
  190. reflex/constants/installer.py +12 -7
  191. reflex/constants/state.py +4 -0
  192. reflex/custom_components/custom_components.py +6 -6
  193. reflex/event.py +486 -241
  194. reflex/experimental/client_state.py +9 -9
  195. reflex/experimental/layout.py +2 -2
  196. reflex/experimental/layout.pyi +95 -87
  197. reflex/experimental/misc.py +1 -1
  198. reflex/istate/__init__.py +1 -0
  199. reflex/istate/proxy.py +33 -0
  200. reflex/istate/wrappers.py +27 -0
  201. reflex/model.py +7 -7
  202. reflex/page.py +2 -1
  203. reflex/reflex.py +142 -8
  204. reflex/state.py +133 -46
  205. reflex/testing.py +9 -7
  206. reflex/utils/console.py +0 -1
  207. reflex/utils/exceptions.py +31 -3
  208. reflex/utils/exec.py +33 -14
  209. reflex/utils/format.py +15 -12
  210. reflex/utils/net.py +1 -1
  211. reflex/utils/path_ops.py +2 -2
  212. reflex/utils/prerequisites.py +82 -46
  213. reflex/utils/pyi_generator.py +63 -20
  214. reflex/utils/registry.py +1 -1
  215. reflex/utils/serializers.py +75 -36
  216. reflex/utils/telemetry.py +3 -2
  217. reflex/utils/types.py +125 -10
  218. reflex/vars/base.py +131 -119
  219. reflex/vars/function.py +59 -12
  220. reflex/vars/number.py +3 -1
  221. reflex/vars/object.py +30 -24
  222. reflex/vars/sequence.py +7 -7
  223. {reflex-0.6.4a2.dist-info → reflex-0.6.5.dist-info}/METADATA +3 -3
  224. reflex-0.6.5.dist-info/RECORD +394 -0
  225. reflex-0.6.4a2.dist-info/RECORD +0 -391
  226. {reflex-0.6.4a2.dist-info → reflex-0.6.5.dist-info}/LICENSE +0 -0
  227. {reflex-0.6.4a2.dist-info → reflex-0.6.5.dist-info}/WHEEL +0 -0
  228. {reflex-0.6.4a2.dist-info → reflex-0.6.5.dist-info}/entry_points.txt +0 -0
reflex/config.py CHANGED
@@ -3,14 +3,26 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import dataclasses
6
+ import enum
6
7
  import importlib
8
+ import inspect
7
9
  import os
8
10
  import sys
9
11
  import urllib.parse
10
12
  from pathlib import Path
11
- from typing import Any, Dict, List, Optional, Set
12
-
13
- from typing_extensions import get_type_hints
13
+ from typing import (
14
+ TYPE_CHECKING,
15
+ Any,
16
+ Dict,
17
+ Generic,
18
+ List,
19
+ Optional,
20
+ Set,
21
+ TypeVar,
22
+ get_args,
23
+ )
24
+
25
+ from typing_extensions import Annotated, get_type_hints
14
26
 
15
27
  from reflex.utils.exceptions import ConfigError, EnvironmentVarValueError
16
28
  from reflex.utils.types import GenericType, is_union, value_inside_optional
@@ -202,8 +214,8 @@ def interpret_int_env(value: str, field_name: str) -> int:
202
214
  ) from ve
203
215
 
204
216
 
205
- def interpret_path_env(value: str, field_name: str) -> Path:
206
- """Interpret a path environment variable value.
217
+ def interpret_existing_path_env(value: str, field_name: str) -> ExistingPath:
218
+ """Interpret a path environment variable value as an existing path.
207
219
 
208
220
  Args:
209
221
  value: The environment variable value.
@@ -221,6 +233,41 @@ def interpret_path_env(value: str, field_name: str) -> Path:
221
233
  return path
222
234
 
223
235
 
236
+ def interpret_path_env(value: str, field_name: str) -> Path:
237
+ """Interpret a path environment variable value.
238
+
239
+ Args:
240
+ value: The environment variable value.
241
+ field_name: The field name.
242
+
243
+ Returns:
244
+ The interpreted value.
245
+ """
246
+ return Path(value)
247
+
248
+
249
+ def interpret_enum_env(value: str, field_type: GenericType, field_name: str) -> Any:
250
+ """Interpret an enum environment variable value.
251
+
252
+ Args:
253
+ value: The environment variable value.
254
+ field_type: The field type.
255
+ field_name: The field name.
256
+
257
+ Returns:
258
+ The interpreted value.
259
+
260
+ Raises:
261
+ EnvironmentVarValueError: If the value is invalid.
262
+ """
263
+ try:
264
+ return field_type(value)
265
+ except ValueError as ve:
266
+ raise EnvironmentVarValueError(
267
+ f"Invalid enum value: {value} for {field_name}"
268
+ ) from ve
269
+
270
+
224
271
  def interpret_env_var_value(
225
272
  value: str, field_type: GenericType, field_name: str
226
273
  ) -> Any:
@@ -252,6 +299,10 @@ def interpret_env_var_value(
252
299
  return interpret_int_env(value, field_name)
253
300
  elif field_type is Path:
254
301
  return interpret_path_env(value, field_name)
302
+ elif field_type is ExistingPath:
303
+ return interpret_existing_path_env(value, field_name)
304
+ elif inspect.isclass(field_type) and issubclass(field_type, enum.Enum):
305
+ return interpret_enum_env(value, field_type, field_name)
255
306
 
256
307
  else:
257
308
  raise ValueError(
@@ -259,83 +310,240 @@ def interpret_env_var_value(
259
310
  )
260
311
 
261
312
 
262
- @dataclasses.dataclass(init=False)
313
+ T = TypeVar("T")
314
+
315
+
316
+ class EnvVar(Generic[T]):
317
+ """Environment variable."""
318
+
319
+ name: str
320
+ default: Any
321
+ type_: T
322
+
323
+ def __init__(self, name: str, default: Any, type_: T) -> None:
324
+ """Initialize the environment variable.
325
+
326
+ Args:
327
+ name: The environment variable name.
328
+ default: The default value.
329
+ type_: The type of the value.
330
+ """
331
+ self.name = name
332
+ self.default = default
333
+ self.type_ = type_
334
+
335
+ def interpret(self, value: str) -> T:
336
+ """Interpret the environment variable value.
337
+
338
+ Args:
339
+ value: The environment variable value.
340
+
341
+ Returns:
342
+ The interpreted value.
343
+ """
344
+ return interpret_env_var_value(value, self.type_, self.name)
345
+
346
+ def getenv(self) -> Optional[T]:
347
+ """Get the interpreted environment variable value.
348
+
349
+ Returns:
350
+ The environment variable value.
351
+ """
352
+ env_value = os.getenv(self.name, None)
353
+ if env_value is not None:
354
+ return self.interpret(env_value)
355
+ return None
356
+
357
+ def is_set(self) -> bool:
358
+ """Check if the environment variable is set.
359
+
360
+ Returns:
361
+ True if the environment variable is set.
362
+ """
363
+ return self.name in os.environ
364
+
365
+ def get(self) -> T:
366
+ """Get the interpreted environment variable value or the default value if not set.
367
+
368
+ Returns:
369
+ The interpreted value.
370
+ """
371
+ env_value = self.getenv()
372
+ if env_value is not None:
373
+ return env_value
374
+ return self.default
375
+
376
+ def set(self, value: T | None) -> None:
377
+ """Set the environment variable. None unsets the variable.
378
+
379
+ Args:
380
+ value: The value to set.
381
+ """
382
+ if value is None:
383
+ _ = os.environ.pop(self.name, None)
384
+ else:
385
+ if isinstance(value, enum.Enum):
386
+ value = value.value
387
+ os.environ[self.name] = str(value)
388
+
389
+
390
+ class env_var: # type: ignore
391
+ """Descriptor for environment variables."""
392
+
393
+ name: str
394
+ default: Any
395
+ internal: bool = False
396
+
397
+ def __init__(self, default: Any, internal: bool = False) -> None:
398
+ """Initialize the descriptor.
399
+
400
+ Args:
401
+ default: The default value.
402
+ internal: Whether the environment variable is reflex internal.
403
+ """
404
+ self.default = default
405
+ self.internal = internal
406
+
407
+ def __set_name__(self, owner, name):
408
+ """Set the name of the descriptor.
409
+
410
+ Args:
411
+ owner: The owner class.
412
+ name: The name of the descriptor.
413
+ """
414
+ self.name = name
415
+
416
+ def __get__(self, instance, owner):
417
+ """Get the EnvVar instance.
418
+
419
+ Args:
420
+ instance: The instance.
421
+ owner: The owner class.
422
+
423
+ Returns:
424
+ The EnvVar instance.
425
+ """
426
+ type_ = get_args(get_type_hints(owner)[self.name])[0]
427
+ env_name = self.name
428
+ if self.internal:
429
+ env_name = f"__{env_name}"
430
+ return EnvVar(name=env_name, default=self.default, type_=type_)
431
+
432
+
433
+ if TYPE_CHECKING:
434
+
435
+ def env_var(default, internal=False) -> EnvVar:
436
+ """Typing helper for the env_var descriptor.
437
+
438
+ Args:
439
+ default: The default value.
440
+ internal: Whether the environment variable is reflex internal.
441
+
442
+ Returns:
443
+ The EnvVar instance.
444
+ """
445
+ return default
446
+
447
+
448
+ class PathExistsFlag:
449
+ """Flag to indicate that a path must exist."""
450
+
451
+
452
+ ExistingPath = Annotated[Path, PathExistsFlag]
453
+
454
+
263
455
  class EnvironmentVariables:
264
456
  """Environment variables class to instantiate environment variables."""
265
457
 
266
458
  # Whether to use npm over bun to install frontend packages.
267
- REFLEX_USE_NPM: bool = False
459
+ REFLEX_USE_NPM: EnvVar[bool] = env_var(False)
268
460
 
269
461
  # The npm registry to use.
270
- NPM_CONFIG_REGISTRY: Optional[str] = None
462
+ NPM_CONFIG_REGISTRY: EnvVar[Optional[str]] = env_var(None)
271
463
 
272
464
  # Whether to use Granian for the backend. Otherwise, use Uvicorn.
273
- REFLEX_USE_GRANIAN: bool = False
465
+ REFLEX_USE_GRANIAN: EnvVar[bool] = env_var(False)
274
466
 
275
467
  # The username to use for authentication on python package repository. Username and password must both be provided.
276
- TWINE_USERNAME: Optional[str] = None
468
+ TWINE_USERNAME: EnvVar[Optional[str]] = env_var(None)
277
469
 
278
470
  # The password to use for authentication on python package repository. Username and password must both be provided.
279
- TWINE_PASSWORD: Optional[str] = None
471
+ TWINE_PASSWORD: EnvVar[Optional[str]] = env_var(None)
280
472
 
281
473
  # Whether to use the system installed bun. If set to false, bun will be bundled with the app.
282
- REFLEX_USE_SYSTEM_BUN: bool = False
474
+ REFLEX_USE_SYSTEM_BUN: EnvVar[bool] = env_var(False)
283
475
 
284
476
  # Whether to use the system installed node and npm. If set to false, node and npm will be bundled with the app.
285
- REFLEX_USE_SYSTEM_NODE: bool = False
477
+ REFLEX_USE_SYSTEM_NODE: EnvVar[bool] = env_var(False)
286
478
 
287
479
  # The working directory for the next.js commands.
288
- REFLEX_WEB_WORKDIR: Path = Path(constants.Dirs.WEB)
480
+ REFLEX_WEB_WORKDIR: EnvVar[Path] = env_var(Path(constants.Dirs.WEB))
289
481
 
290
482
  # Path to the alembic config file
291
- ALEMBIC_CONFIG: Path = Path(constants.ALEMBIC_CONFIG)
483
+ ALEMBIC_CONFIG: EnvVar[ExistingPath] = env_var(Path(constants.ALEMBIC_CONFIG))
292
484
 
293
485
  # Disable SSL verification for HTTPX requests.
294
- SSL_NO_VERIFY: bool = False
486
+ SSL_NO_VERIFY: EnvVar[bool] = env_var(False)
295
487
 
296
488
  # The directory to store uploaded files.
297
- REFLEX_UPLOADED_FILES_DIR: Path = Path(constants.Dirs.UPLOADED_FILES)
489
+ REFLEX_UPLOADED_FILES_DIR: EnvVar[Path] = env_var(
490
+ Path(constants.Dirs.UPLOADED_FILES)
491
+ )
298
492
 
299
- # Whether to use seperate processes to compile the frontend and how many. If not set, defaults to thread executor.
300
- REFLEX_COMPILE_PROCESSES: Optional[int] = None
493
+ # Whether to use separate processes to compile the frontend and how many. If not set, defaults to thread executor.
494
+ REFLEX_COMPILE_PROCESSES: EnvVar[Optional[int]] = env_var(None)
301
495
 
302
- # Whether to use seperate threads to compile the frontend and how many. Defaults to `min(32, os.cpu_count() + 4)`.
303
- REFLEX_COMPILE_THREADS: Optional[int] = None
496
+ # Whether to use separate threads to compile the frontend and how many. Defaults to `min(32, os.cpu_count() + 4)`.
497
+ REFLEX_COMPILE_THREADS: EnvVar[Optional[int]] = env_var(None)
304
498
 
305
499
  # The directory to store reflex dependencies.
306
- REFLEX_DIR: Path = Path(constants.Reflex.DIR)
500
+ REFLEX_DIR: EnvVar[Path] = env_var(Path(constants.Reflex.DIR))
307
501
 
308
502
  # Whether to print the SQL queries if the log level is INFO or lower.
309
- SQLALCHEMY_ECHO: bool = False
503
+ SQLALCHEMY_ECHO: EnvVar[bool] = env_var(False)
310
504
 
311
505
  # Whether to ignore the redis config error. Some redis servers only allow out-of-band configuration.
312
- REFLEX_IGNORE_REDIS_CONFIG_ERROR: bool = False
506
+ REFLEX_IGNORE_REDIS_CONFIG_ERROR: EnvVar[bool] = env_var(False)
313
507
 
314
508
  # Whether to skip purging the web directory in dev mode.
315
- REFLEX_PERSIST_WEB_DIR: bool = False
509
+ REFLEX_PERSIST_WEB_DIR: EnvVar[bool] = env_var(False)
316
510
 
317
511
  # The reflex.build frontend host.
318
- REFLEX_BUILD_FRONTEND: str = constants.Templates.REFLEX_BUILD_FRONTEND
512
+ REFLEX_BUILD_FRONTEND: EnvVar[str] = env_var(
513
+ constants.Templates.REFLEX_BUILD_FRONTEND
514
+ )
319
515
 
320
516
  # The reflex.build backend host.
321
- REFLEX_BUILD_BACKEND: str = constants.Templates.REFLEX_BUILD_BACKEND
517
+ REFLEX_BUILD_BACKEND: EnvVar[str] = env_var(
518
+ constants.Templates.REFLEX_BUILD_BACKEND
519
+ )
322
520
 
323
- def __init__(self):
324
- """Initialize the environment variables."""
325
- type_hints = get_type_hints(type(self))
521
+ # This env var stores the execution mode of the app
522
+ REFLEX_ENV_MODE: EnvVar[constants.Env] = env_var(constants.Env.DEV)
326
523
 
327
- for field in dataclasses.fields(self):
328
- raw_value = os.getenv(field.name, None)
524
+ # Whether to run the backend only. Exclusive with REFLEX_FRONTEND_ONLY.
525
+ REFLEX_BACKEND_ONLY: EnvVar[bool] = env_var(False)
329
526
 
330
- field.type = type_hints.get(field.name) or field.type
527
+ # Whether to run the frontend only. Exclusive with REFLEX_BACKEND_ONLY.
528
+ REFLEX_FRONTEND_ONLY: EnvVar[bool] = env_var(False)
331
529
 
332
- value = (
333
- interpret_env_var_value(raw_value, field.type, field.name)
334
- if raw_value is not None
335
- else get_default_value_for_field(field)
336
- )
530
+ # Reflex internal env to reload the config.
531
+ RELOAD_CONFIG: EnvVar[bool] = env_var(False, internal=True)
532
+
533
+ # If this env var is set to "yes", App.compile will be a no-op
534
+ REFLEX_SKIP_COMPILE: EnvVar[bool] = env_var(False, internal=True)
535
+
536
+ # Whether to run app harness tests in headless mode.
537
+ APP_HARNESS_HEADLESS: EnvVar[bool] = env_var(False)
337
538
 
338
- setattr(self, field.name, value)
539
+ # Which app harness driver to use.
540
+ APP_HARNESS_DRIVER: EnvVar[str] = env_var("Chrome")
541
+
542
+ # Arguments to pass to the app harness driver.
543
+ APP_HARNESS_DRIVER_ARGS: EnvVar[str] = env_var("")
544
+
545
+ # Where to save screenshots when tests fail.
546
+ SCREENSHOT_DIR: EnvVar[Optional[Path]] = env_var(None)
339
547
 
340
548
 
341
549
  environment = EnvironmentVariables()
@@ -401,7 +609,10 @@ class Config(Base):
401
609
  telemetry_enabled: bool = True
402
610
 
403
611
  # The bun path
404
- bun_path: Path = constants.Bun.DEFAULT_PATH
612
+ bun_path: ExistingPath = constants.Bun.DEFAULT_PATH
613
+
614
+ # Timeout to do a production build of a frontend page.
615
+ static_page_generation_timeout: int = 60
405
616
 
406
617
  # List of origins that are allowed to connect to the backend API.
407
618
  cors_allowed_origins: List[str] = ["*"]
@@ -525,7 +736,7 @@ class Config(Base):
525
736
  )
526
737
 
527
738
  # Interpret the value.
528
- value = interpret_env_var_value(env_var, field.type_, field.name)
739
+ value = interpret_env_var_value(env_var, field.outer_type_, field.name)
529
740
 
530
741
  # Set the value.
531
742
  updated_values[key] = value
@@ -2,18 +2,15 @@
2
2
 
3
3
  from .base import (
4
4
  COOKIES,
5
- ENV_BACKEND_ONLY_ENV_VAR,
6
- ENV_FRONTEND_ONLY_ENV_VAR,
7
- ENV_MODE_ENV_VAR,
5
+ IS_LINUX,
6
+ IS_MACOS,
8
7
  IS_WINDOWS,
9
8
  LOCAL_STORAGE,
10
9
  POLLING_MAX_HTTP_BUFFER_SIZE,
11
10
  PYTEST_CURRENT_TEST,
12
11
  REFLEX_VAR_CLOSING_TAG,
13
12
  REFLEX_VAR_OPENING_TAG,
14
- RELOAD_CONFIG,
15
13
  SESSION_STORAGE,
16
- SKIP_COMPILE_ENV_VAR,
17
14
  ColorMode,
18
15
  Dirs,
19
16
  Env,
@@ -44,16 +41,9 @@ from .config import (
44
41
  GitIgnore,
45
42
  RequirementsTxt,
46
43
  )
47
- from .custom_components import (
48
- CustomComponents,
49
- )
44
+ from .custom_components import CustomComponents
50
45
  from .event import Endpoint, EventTriggers, SocketEvent
51
- from .installer import (
52
- Bun,
53
- Fnm,
54
- Node,
55
- PackageJson,
56
- )
46
+ from .installer import Bun, Fnm, Node, PackageJson
57
47
  from .route import (
58
48
  ROUTE_NOT_FOUND,
59
49
  ROUTER,
@@ -106,7 +96,6 @@ __ALL__ = [
106
96
  POLLING_MAX_HTTP_BUFFER_SIZE,
107
97
  PYTEST_CURRENT_TEST,
108
98
  Reflex,
109
- RELOAD_CONFIG,
110
99
  RequirementsTxt,
111
100
  RouteArgType,
112
101
  RouteRegex,
@@ -116,7 +105,6 @@ __ALL__ = [
116
105
  ROUTER_DATA_INCLUDE,
117
106
  ROUTE_NOT_FOUND,
118
107
  SETTER_PREFIX,
119
- SKIP_COMPILE_ENV_VAR,
120
108
  SocketEvent,
121
109
  StateManagerMode,
122
110
  Tailwind,
reflex/constants/base.py CHANGED
@@ -13,6 +13,8 @@ from platformdirs import PlatformDirs
13
13
  from .utils import classproperty
14
14
 
15
15
  IS_WINDOWS = platform.system() == "Windows"
16
+ IS_MACOS = platform.system() == "Darwin"
17
+ IS_LINUX = platform.system() == "Linux"
16
18
 
17
19
 
18
20
  class Dirs(SimpleNamespace):
@@ -76,7 +78,7 @@ class Reflex(SimpleNamespace):
76
78
  # The root directory of the reflex library.
77
79
  ROOT_DIR = Path(__file__).parents[2]
78
80
 
79
- RELEASES_URL = f"https://api.github.com/repos/reflex-dev/templates/releases"
81
+ RELEASES_URL = "https://api.github.com/repos/reflex-dev/templates/releases"
80
82
 
81
83
 
82
84
  class ReflexHostingCLI(SimpleNamespace):
@@ -112,7 +114,7 @@ class Templates(SimpleNamespace):
112
114
  from reflex.config import environment
113
115
 
114
116
  return (
115
- environment.REFLEX_BUILD_FRONTEND
117
+ environment.REFLEX_BUILD_FRONTEND.get()
116
118
  + "/gen?reflex_init_token={reflex_init_token}"
117
119
  )
118
120
 
@@ -126,7 +128,7 @@ class Templates(SimpleNamespace):
126
128
  """
127
129
  from reflex.config import environment
128
130
 
129
- return environment.REFLEX_BUILD_BACKEND + "/api/init/{reflex_init_token}"
131
+ return environment.REFLEX_BUILD_BACKEND.get() + "/api/init/{reflex_init_token}"
130
132
 
131
133
  @classproperty
132
134
  @classmethod
@@ -139,7 +141,8 @@ class Templates(SimpleNamespace):
139
141
  from reflex.config import environment
140
142
 
141
143
  return (
142
- environment.REFLEX_BUILD_BACKEND + "/api/gen/{generation_hash}/refactored"
144
+ environment.REFLEX_BUILD_BACKEND.get()
145
+ + "/api/gen/{generation_hash}/refactored"
143
146
  )
144
147
 
145
148
  class Dirs(SimpleNamespace):
@@ -239,19 +242,9 @@ COOKIES = "cookies"
239
242
  LOCAL_STORAGE = "local_storage"
240
243
  SESSION_STORAGE = "session_storage"
241
244
 
242
- # If this env var is set to "yes", App.compile will be a no-op
243
- SKIP_COMPILE_ENV_VAR = "__REFLEX_SKIP_COMPILE"
244
-
245
- # This env var stores the execution mode of the app
246
- ENV_MODE_ENV_VAR = "REFLEX_ENV_MODE"
247
-
248
- ENV_BACKEND_ONLY_ENV_VAR = "REFLEX_BACKEND_ONLY"
249
- ENV_FRONTEND_ONLY_ENV_VAR = "REFLEX_FRONTEND_ONLY"
250
-
251
245
  # Testing variables.
252
246
  # Testing os env set by pytest when running a test case.
253
247
  PYTEST_CURRENT_TEST = "PYTEST_CURRENT_TEST"
254
- RELOAD_CONFIG = "__REFLEX_RELOAD_CONFIG"
255
248
 
256
249
  REFLEX_VAR_OPENING_TAG = "<reflex.Var>"
257
250
  REFLEX_VAR_CLOSING_TAG = "</reflex.Var>"
@@ -35,7 +35,6 @@ ColorType = Literal[
35
35
  "amber",
36
36
  "gold",
37
37
  "bronze",
38
- "gray",
39
38
  "accent",
40
39
  "black",
41
40
  "white",
@@ -63,7 +63,7 @@ class Bun(SimpleNamespace):
63
63
  """
64
64
  from reflex.config import environment
65
65
 
66
- return environment.REFLEX_DIR / "bun"
66
+ return environment.REFLEX_DIR.get() / "bun"
67
67
 
68
68
  @classproperty
69
69
  @classmethod
@@ -75,6 +75,11 @@ class Bun(SimpleNamespace):
75
75
  """
76
76
  return cls.ROOT_PATH / "bin" / ("bun" if not IS_WINDOWS else "bun.exe")
77
77
 
78
+ DEFAULT_CONFIG = """
79
+ [install]
80
+ registry = "{registry}"
81
+ """
82
+
78
83
 
79
84
  # FNM config.
80
85
  class Fnm(SimpleNamespace):
@@ -100,7 +105,7 @@ class Fnm(SimpleNamespace):
100
105
  """
101
106
  from reflex.config import environment
102
107
 
103
- return environment.REFLEX_DIR / "fnm"
108
+ return environment.REFLEX_DIR.get() / "fnm"
104
109
 
105
110
  @classproperty
106
111
  @classmethod
@@ -118,9 +123,9 @@ class Node(SimpleNamespace):
118
123
  """Node/ NPM constants."""
119
124
 
120
125
  # The Node version.
121
- VERSION = "22.10.0"
126
+ VERSION = "22.11.0"
122
127
  # The minimum required node version.
123
- MIN_VERSION = "18.17.0"
128
+ MIN_VERSION = "18.18.0"
124
129
 
125
130
  @classproperty
126
131
  @classmethod
@@ -173,17 +178,17 @@ class PackageJson(SimpleNamespace):
173
178
  PATH = "package.json"
174
179
 
175
180
  DEPENDENCIES = {
176
- "@babel/standalone": "7.25.8",
181
+ "@babel/standalone": "7.26.0",
177
182
  "@emotion/react": "11.13.3",
178
183
  "axios": "1.7.7",
179
184
  "json5": "2.2.3",
180
- "next": "14.2.15",
185
+ "next": "14.2.16",
181
186
  "next-sitemap": "4.2.3",
182
187
  "next-themes": "0.3.0",
183
188
  "react": "18.3.1",
184
189
  "react-dom": "18.3.1",
185
190
  "react-focus-lock": "2.13.2",
186
- "socket.io-client": "4.8.0",
191
+ "socket.io-client": "4.8.1",
187
192
  "universal-cookie": "7.2.1",
188
193
  }
189
194
  DEV_DEPENDENCIES = {
reflex/constants/state.py CHANGED
@@ -9,3 +9,7 @@ class StateManagerMode(str, Enum):
9
9
  DISK = "disk"
10
10
  MEMORY = "memory"
11
11
  REDIS = "redis"
12
+
13
+
14
+ # Used for things like console_log, etc.
15
+ FRONTEND_EVENT_STATE = "__reflex_internal_frontend_event_state"
@@ -609,14 +609,14 @@ def publish(
609
609
  help="The API token to use for authentication on python package repository. If token is provided, no username/password should be provided at the same time",
610
610
  ),
611
611
  username: Optional[str] = typer.Option(
612
- environment.TWINE_USERNAME,
612
+ environment.TWINE_USERNAME.get(),
613
613
  "-u",
614
614
  "--username",
615
615
  show_default="TWINE_USERNAME environment variable value if set",
616
616
  help="The username to use for authentication on python package repository. Username and password must both be provided.",
617
617
  ),
618
618
  password: Optional[str] = typer.Option(
619
- environment.TWINE_PASSWORD,
619
+ environment.TWINE_PASSWORD.get(),
620
620
  "-p",
621
621
  "--password",
622
622
  show_default="TWINE_PASSWORD environment variable value if set",
@@ -779,8 +779,8 @@ def _validate_project_info():
779
779
  )
780
780
  # PyPI only shows the first author.
781
781
  author = project.get("authors", [{}])[0]
782
- author["name"] = console.ask(f"Author Name", default=author.get("name", ""))
783
- author["email"] = console.ask(f"Author Email", default=author.get("email", ""))
782
+ author["name"] = console.ask("Author Name", default=author.get("name", ""))
783
+ author["email"] = console.ask("Author Email", default=author.get("email", ""))
784
784
 
785
785
  console.print(f'Current keywords are: {project.get("keywords") or []}')
786
786
  keyword_action = console.ask(
@@ -923,7 +923,7 @@ def _get_file_from_prompt_in_loop() -> Tuple[bytes, str] | None:
923
923
  image_file = file_extension = None
924
924
  while image_file is None:
925
925
  image_filepath = console.ask(
926
- f"Upload a preview image of your demo app (enter to skip)"
926
+ "Upload a preview image of your demo app (enter to skip)"
927
927
  )
928
928
  if not image_filepath:
929
929
  break
@@ -973,6 +973,6 @@ def install(
973
973
  console.set_log_level(loglevel)
974
974
 
975
975
  if _pip_install_on_demand(package_name=".", install_args=["-e"]):
976
- console.info(f"Package installed successfully!")
976
+ console.info("Package installed successfully!")
977
977
  else:
978
978
  raise typer.Exit(code=1)