reflex 0.7.2a2__py3-none-any.whl → 0.7.3__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 (45) hide show
  1. reflex/.templates/jinja/web/pages/custom_component.js.jinja2 +6 -3
  2. reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +1 -1
  3. reflex/.templates/web/components/shiki/code.js +26 -21
  4. reflex/.templates/web/postcss.config.js +1 -1
  5. reflex/.templates/web/utils/client_side_routing.js +18 -16
  6. reflex/.templates/web/utils/helpers/dataeditor.js +1 -1
  7. reflex/.templates/web/utils/helpers/range.js +30 -30
  8. reflex/.templates/web/utils/state.js +44 -22
  9. reflex/app_mixins/middleware.py +9 -10
  10. reflex/compiler/compiler.py +7 -0
  11. reflex/components/core/banner.py +1 -1
  12. reflex/components/core/foreach.py +3 -2
  13. reflex/components/datadisplay/logo.py +1 -1
  14. reflex/components/el/__init__.pyi +22 -0
  15. reflex/components/el/elements/__init__.py +20 -1
  16. reflex/components/el/elements/__init__.pyi +42 -1
  17. reflex/components/el/elements/media.py +11 -0
  18. reflex/components/el/elements/media.pyi +11 -0
  19. reflex/components/lucide/icon.py +8 -6
  20. reflex/components/lucide/icon.pyi +0 -1
  21. reflex/components/radix/themes/components/slider.py +2 -1
  22. reflex/config.py +13 -7
  23. reflex/custom_components/custom_components.py +23 -25
  24. reflex/event.py +7 -2
  25. reflex/istate/data.py +59 -7
  26. reflex/reflex.py +75 -32
  27. reflex/state.py +3 -3
  28. reflex/style.py +3 -3
  29. reflex/testing.py +4 -10
  30. reflex/utils/exceptions.py +31 -1
  31. reflex/utils/exec.py +4 -8
  32. reflex/utils/export.py +2 -2
  33. reflex/utils/prerequisites.py +3 -45
  34. reflex/utils/pyi_generator.py +2 -2
  35. reflex/utils/redir.py +3 -12
  36. reflex/vars/base.py +26 -3
  37. reflex/vars/number.py +22 -21
  38. reflex/vars/object.py +29 -0
  39. reflex/vars/sequence.py +37 -0
  40. {reflex-0.7.2a2.dist-info → reflex-0.7.3.dist-info}/METADATA +52 -59
  41. {reflex-0.7.2a2.dist-info → reflex-0.7.3.dist-info}/RECORD +64 -64
  42. {reflex-0.7.2a2.dist-info → reflex-0.7.3.dist-info}/WHEEL +1 -1
  43. reflex-0.7.3.dist-info/entry_points.txt +2 -0
  44. reflex-0.7.2a2.dist-info/entry_points.txt +0 -3
  45. {reflex-0.7.2a2.dist-info → reflex-0.7.3.dist-info/licenses}/LICENSE +0 -0
reflex/reflex.py CHANGED
@@ -13,7 +13,7 @@ from reflex import constants
13
13
  from reflex.config import environment, get_config
14
14
  from reflex.custom_components.custom_components import custom_components_cli
15
15
  from reflex.state import reset_disk_state_manager
16
- from reflex.utils import console, telemetry
16
+ from reflex.utils import console, redir, telemetry
17
17
 
18
18
  # Disable typer+rich integration for help panels
19
19
  typer.core.rich = None # pyright: ignore [reportPrivateImportUsage]
@@ -22,10 +22,6 @@ typer.core.rich = None # pyright: ignore [reportPrivateImportUsage]
22
22
  cli = typer.Typer(add_completion=False, pretty_exceptions_enable=False)
23
23
 
24
24
 
25
- # Get the config.
26
- config = get_config()
27
-
28
-
29
25
  def version(value: bool):
30
26
  """Get the Reflex version.
31
27
 
@@ -58,18 +54,28 @@ def main(
58
54
  def _init(
59
55
  name: str,
60
56
  template: str | None = None,
61
- loglevel: constants.LogLevel = config.loglevel,
57
+ loglevel: constants.LogLevel | None = None,
62
58
  ai: bool = False,
63
59
  ):
64
60
  """Initialize a new Reflex app in the given directory."""
65
61
  from reflex.utils import exec, prerequisites
66
62
 
63
+ if loglevel is not None:
64
+ console.set_log_level(loglevel)
65
+
66
+ config = get_config()
67
+
67
68
  # Set the log level.
69
+ loglevel = loglevel or config.loglevel
68
70
  console.set_log_level(loglevel)
69
71
 
70
72
  # Show system info
71
73
  exec.output_system_info()
72
74
 
75
+ if ai:
76
+ redir.reflex_build_redirect()
77
+ return
78
+
73
79
  # Validate the app name.
74
80
  app_name = prerequisites.validate_app_name(name)
75
81
  console.rule(f"[bold]Initializing {app_name}")
@@ -83,7 +89,7 @@ def _init(
83
89
  prerequisites.initialize_frontend_dependencies()
84
90
 
85
91
  # Initialize the app.
86
- template = prerequisites.initialize_app(app_name, template, ai)
92
+ template = prerequisites.initialize_app(app_name, template)
87
93
 
88
94
  # Initialize the .gitignore.
89
95
  prerequisites.initialize_gitignore()
@@ -105,8 +111,8 @@ def init(
105
111
  None,
106
112
  help="The template to initialize the app with.",
107
113
  ),
108
- loglevel: constants.LogLevel = typer.Option(
109
- config.loglevel, help="The log level to use."
114
+ loglevel: constants.LogLevel | None = typer.Option(
115
+ None, help="The log level to use."
110
116
  ),
111
117
  ai: bool = typer.Option(
112
118
  False,
@@ -123,12 +129,20 @@ def _run(
123
129
  backend: bool = True,
124
130
  frontend_port: int | None = None,
125
131
  backend_port: int | None = None,
126
- backend_host: str = config.backend_host,
127
- loglevel: constants.LogLevel = config.loglevel,
132
+ backend_host: str | None = None,
133
+ loglevel: constants.LogLevel | None = None,
128
134
  ):
129
135
  """Run the app in the given directory."""
130
136
  from reflex.utils import build, exec, prerequisites, processes
131
137
 
138
+ if loglevel is not None:
139
+ console.set_log_level(loglevel)
140
+
141
+ config = get_config()
142
+
143
+ loglevel = loglevel or config.loglevel
144
+ backend_host = backend_host or config.backend_host
145
+
132
146
  # Set the log level.
133
147
  console.set_log_level(loglevel)
134
148
 
@@ -270,21 +284,19 @@ def run(
270
284
  help="Execute only backend.",
271
285
  envvar=environment.REFLEX_BACKEND_ONLY.name,
272
286
  ),
273
- frontend_port: int = typer.Option(
274
- config.frontend_port,
287
+ frontend_port: int | None = typer.Option(
288
+ None,
275
289
  help="Specify a different frontend port.",
276
290
  envvar=environment.REFLEX_FRONTEND_PORT.name,
277
291
  ),
278
- backend_port: int = typer.Option(
279
- config.backend_port,
292
+ backend_port: int | None = typer.Option(
293
+ None,
280
294
  help="Specify a different backend port.",
281
295
  envvar=environment.REFLEX_BACKEND_PORT.name,
282
296
  ),
283
- backend_host: str = typer.Option(
284
- config.backend_host, help="Specify the backend host."
285
- ),
286
- loglevel: constants.LogLevel = typer.Option(
287
- config.loglevel, help="The log level to use."
297
+ backend_host: str | None = typer.Option(None, help="Specify the backend host."),
298
+ loglevel: constants.LogLevel | None = typer.Option(
299
+ None, help="The log level to use."
288
300
  ),
289
301
  ):
290
302
  """Run the app in the current directory."""
@@ -292,6 +304,16 @@ def run(
292
304
  console.error("Cannot use both --frontend-only and --backend-only options.")
293
305
  raise typer.Exit(1)
294
306
 
307
+ if loglevel is not None:
308
+ console.set_log_level(loglevel)
309
+
310
+ config = get_config()
311
+
312
+ frontend_port = frontend_port or config.frontend_port
313
+ backend_port = backend_port or config.backend_port
314
+ backend_host = backend_host or config.backend_host
315
+ loglevel = loglevel or config.loglevel
316
+
295
317
  environment.REFLEX_COMPILE_CONTEXT.set(constants.CompileContext.RUN)
296
318
  environment.REFLEX_BACKEND_ONLY.set(backend)
297
319
  environment.REFLEX_FRONTEND_ONLY.set(frontend)
@@ -331,8 +353,8 @@ def export(
331
353
  env: constants.Env = typer.Option(
332
354
  constants.Env.PROD, help="The environment to export the app in."
333
355
  ),
334
- loglevel: constants.LogLevel = typer.Option(
335
- config.loglevel, help="The log level to use."
356
+ loglevel: constants.LogLevel | None = typer.Option(
357
+ None, help="The log level to use."
336
358
  ),
337
359
  ):
338
360
  """Export the app to a zip file."""
@@ -343,8 +365,11 @@ def export(
343
365
 
344
366
  frontend, backend = prerequisites.check_running_mode(frontend, backend)
345
367
 
368
+ loglevel = loglevel or get_config().loglevel
369
+ console.set_log_level(loglevel)
370
+
346
371
  if prerequisites.needs_reinit(frontend=frontend or not backend):
347
- _init(name=config.app_name, loglevel=loglevel)
372
+ _init(name=get_config().app_name, loglevel=loglevel)
348
373
 
349
374
  export_utils.export(
350
375
  zipping=zipping,
@@ -358,10 +383,14 @@ def export(
358
383
 
359
384
 
360
385
  @cli.command()
361
- def login(loglevel: constants.LogLevel = typer.Option(config.loglevel)):
386
+ def login(loglevel: constants.LogLevel | None = typer.Option(None)):
362
387
  """Authenticate with experimental Reflex hosting service."""
363
388
  from reflex_cli.v2 import cli as hosting_cli
364
389
 
390
+ loglevel = loglevel or get_config().loglevel
391
+
392
+ console.set_log_level(loglevel)
393
+
365
394
  check_version()
366
395
 
367
396
  validated_info = hosting_cli.login()
@@ -372,8 +401,8 @@ def login(loglevel: constants.LogLevel = typer.Option(config.loglevel)):
372
401
 
373
402
  @cli.command()
374
403
  def logout(
375
- loglevel: constants.LogLevel = typer.Option(
376
- config.loglevel, help="The log level to use."
404
+ loglevel: constants.LogLevel | None = typer.Option(
405
+ None, help="The log level to use."
377
406
  ),
378
407
  ):
379
408
  """Log out of access to Reflex hosting service."""
@@ -381,6 +410,8 @@ def logout(
381
410
 
382
411
  check_version()
383
412
 
413
+ loglevel = loglevel or get_config().loglevel
414
+
384
415
  logout(loglevel) # pyright: ignore [reportArgumentType]
385
416
 
386
417
 
@@ -399,6 +430,8 @@ def db_init():
399
430
  from reflex import model
400
431
  from reflex.utils import prerequisites
401
432
 
433
+ config = get_config()
434
+
402
435
  # Check the database url.
403
436
  if config.db_url is None:
404
437
  console.error("db_url is not configured, cannot initialize.")
@@ -466,8 +499,8 @@ def makemigrations(
466
499
 
467
500
  @cli.command()
468
501
  def deploy(
469
- app_name: str = typer.Option(
470
- config.app_name,
502
+ app_name: str | None = typer.Option(
503
+ None,
471
504
  "--app-name",
472
505
  help="The name of the App to deploy under.",
473
506
  ),
@@ -506,8 +539,8 @@ def deploy(
506
539
  "--envfile",
507
540
  help="The path to an env file to use. Will override any envs set manually.",
508
541
  ),
509
- loglevel: constants.LogLevel = typer.Option(
510
- config.loglevel, help="The log level to use."
542
+ loglevel: constants.LogLevel | None = typer.Option(
543
+ None, help="The log level to use."
511
544
  ),
512
545
  project: str | None = typer.Option(
513
546
  None,
@@ -538,6 +571,14 @@ def deploy(
538
571
  from reflex.utils import export as export_utils
539
572
  from reflex.utils import prerequisites
540
573
 
574
+ if loglevel is not None:
575
+ console.set_log_level(loglevel)
576
+
577
+ config = get_config()
578
+
579
+ loglevel = loglevel or config.loglevel
580
+ app_name = app_name or config.app_name
581
+
541
582
  check_version()
542
583
 
543
584
  environment.REFLEX_COMPILE_CONTEXT.set(constants.CompileContext.DEPLOY)
@@ -604,13 +645,15 @@ def deploy(
604
645
  @cli.command()
605
646
  def rename(
606
647
  new_name: str = typer.Argument(..., help="The new name for the app."),
607
- loglevel: constants.LogLevel = typer.Option(
608
- config.loglevel, help="The log level to use."
648
+ loglevel: constants.LogLevel | None = typer.Option(
649
+ None, help="The log level to use."
609
650
  ),
610
651
  ):
611
652
  """Rename the app in the current directory."""
612
653
  from reflex.utils import prerequisites
613
654
 
655
+ loglevel = loglevel or get_config().loglevel
656
+
614
657
  prerequisites.validate_app_name(new_name)
615
658
  prerequisites.rename_app(new_name, loglevel)
616
659
 
reflex/state.py CHANGED
@@ -1013,9 +1013,9 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
1013
1013
 
1014
1014
  if not types.is_valid_var_type(prop._var_type):
1015
1015
  raise VarTypeError(
1016
- "State vars must be primitive Python types, "
1017
- "Plotly figures, Pandas dataframes, "
1018
- "or subclasses of rx.Base. "
1016
+ "State vars must be of a serializable type. "
1017
+ "Valid types include strings, numbers, booleans, lists, "
1018
+ "dictionaries, dataclasses, datetime objects, and pydantic models. "
1019
1019
  f'Found var "{prop._js_expr}" with type {prop._var_type}.'
1020
1020
  )
1021
1021
  cls._set_var(prop)
reflex/style.py CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Any, Literal, Type
5
+ from typing import Any, Literal, Mapping, Type
6
6
 
7
7
  from reflex import constants
8
8
  from reflex.components.core.breakpoints import Breakpoints, breakpoints_values
@@ -10,7 +10,7 @@ from reflex.event import EventChain, EventHandler, EventSpec, run_script
10
10
  from reflex.utils import format
11
11
  from reflex.utils.exceptions import ReflexError
12
12
  from reflex.utils.imports import ImportVar
13
- from reflex.utils.types import get_origin
13
+ from reflex.utils.types import typehint_issubclass
14
14
  from reflex.vars import VarData
15
15
  from reflex.vars.base import LiteralVar, Var
16
16
  from reflex.vars.function import FunctionVar
@@ -189,7 +189,7 @@ def convert(
189
189
  or (isinstance(value, list) and all(not isinstance(v, dict) for v in value))
190
190
  or (
191
191
  isinstance(value, ObjectVar)
192
- and not issubclass(get_origin(value._var_type) or value._var_type, dict)
192
+ and not typehint_issubclass(value._var_type, Mapping)
193
193
  )
194
194
  else (key,)
195
195
  )
reflex/testing.py CHANGED
@@ -54,18 +54,12 @@ from reflex.state import (
54
54
  from reflex.utils import console
55
55
 
56
56
  try:
57
- from selenium import webdriver # pyright: ignore [reportMissingImports]
58
- from selenium.webdriver.remote.webdriver import ( # pyright: ignore [reportMissingImports]
59
- WebDriver,
60
- )
57
+ from selenium import webdriver
58
+ from selenium.webdriver.remote.webdriver import WebDriver
61
59
 
62
60
  if TYPE_CHECKING:
63
- from selenium.webdriver.common.options import (
64
- ArgOptions, # pyright: ignore [reportMissingImports]
65
- )
66
- from selenium.webdriver.remote.webelement import ( # pyright: ignore [reportMissingImports]
67
- WebElement,
68
- )
61
+ from selenium.webdriver.common.options import ArgOptions
62
+ from selenium.webdriver.remote.webelement import WebElement
69
63
 
70
64
  has_selenium = True
71
65
  except ImportError:
@@ -1,6 +1,11 @@
1
1
  """Custom Exceptions."""
2
2
 
3
- from typing import Any
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+ if TYPE_CHECKING:
8
+ from reflex.vars import Var
4
9
 
5
10
 
6
11
  class ReflexError(Exception):
@@ -78,6 +83,31 @@ class VarAttributeError(ReflexError, AttributeError):
78
83
  class UntypedVarError(ReflexError, TypeError):
79
84
  """Custom TypeError for untyped var errors."""
80
85
 
86
+ def __init__(self, var: Var, action: str, doc_link: str = ""):
87
+ """Create an UntypedVarError from a var.
88
+
89
+ Args:
90
+ var: The var.
91
+ action: The action that caused the error.
92
+ doc_link: The link to the documentation.
93
+ """
94
+ var_data = var._get_all_var_data()
95
+ is_state_var = (
96
+ var_data
97
+ and var_data.state
98
+ and var_data.field_name
99
+ and var_data.state + "." + var_data.field_name == str(var)
100
+ )
101
+ super().__init__(
102
+ f"Cannot {action} on untyped var '{var!s}' of type '{var._var_type!s}'."
103
+ + (
104
+ " Please add a type annotation to the var in the state class."
105
+ if is_state_var
106
+ else " You can call the var's .to(desired_type) method to convert it to the desired type."
107
+ )
108
+ + (f" See {doc_link}" if doc_link else "")
109
+ )
110
+
81
111
 
82
112
  class UntypedComputedVarError(ReflexError, TypeError):
83
113
  """Custom TypeError for untyped computed var errors."""
reflex/utils/exec.py CHANGED
@@ -332,11 +332,9 @@ def run_granian_backend(host: str, port: int, loglevel: LogLevel):
332
332
  """
333
333
  console.debug("Using Granian for backend")
334
334
  try:
335
- from granian import Granian # pyright: ignore [reportMissingImports]
336
- from granian.constants import ( # pyright: ignore [reportMissingImports]
337
- Interfaces,
338
- )
339
- from granian.log import LogLevels # pyright: ignore [reportMissingImports]
335
+ from granian.constants import Interfaces
336
+ from granian.log import LogLevels
337
+ from granian.server import Server as Granian
340
338
 
341
339
  Granian(
342
340
  target=get_granian_target(),
@@ -466,9 +464,7 @@ def run_granian_backend_prod(host: str, port: int, loglevel: LogLevel):
466
464
  from reflex.utils import processes
467
465
 
468
466
  try:
469
- from granian.constants import ( # pyright: ignore [reportMissingImports]
470
- Interfaces,
471
- )
467
+ from granian.constants import Interfaces
472
468
 
473
469
  command = [
474
470
  "granian",
reflex/utils/export.py CHANGED
@@ -6,8 +6,6 @@ from reflex import constants
6
6
  from reflex.config import environment, get_config
7
7
  from reflex.utils import build, console, exec, prerequisites, telemetry
8
8
 
9
- config = get_config()
10
-
11
9
 
12
10
  def export(
13
11
  zipping: bool = True,
@@ -33,6 +31,8 @@ def export(
33
31
  env: The environment to use. Defaults to constants.Env.PROD.
34
32
  loglevel: The log level to use. Defaults to console._LOG_LEVEL.
35
33
  """
34
+ config = get_config()
35
+
36
36
  # Set the log level.
37
37
  console.set_log_level(loglevel)
38
38
 
@@ -37,7 +37,7 @@ from redis.exceptions import RedisError
37
37
  from reflex import constants, model
38
38
  from reflex.compiler import templates
39
39
  from reflex.config import Config, environment, get_config
40
- from reflex.utils import console, net, path_ops, processes, redir
40
+ from reflex.utils import console, net, path_ops, processes
41
41
  from reflex.utils.exceptions import (
42
42
  GeneratedCodeHasNoFunctionDefsError,
43
43
  SystemPackageMissingError,
@@ -1695,31 +1695,6 @@ def validate_and_create_app_using_remote_template(
1695
1695
  )
1696
1696
 
1697
1697
 
1698
- def generate_template_using_ai(template: str | None = None) -> str:
1699
- """Generate a template using AI(Flexgen).
1700
-
1701
- Args:
1702
- template: The name of the template.
1703
-
1704
- Returns:
1705
- The generation hash.
1706
-
1707
- Raises:
1708
- Exit: If the template and ai flags are used.
1709
- """
1710
- if template is None:
1711
- # If AI is requested and no template specified, redirect the user to reflex.build.
1712
- return redir.reflex_build_redirect()
1713
- elif is_generation_hash(template):
1714
- # Otherwise treat the template as a generation hash.
1715
- return template
1716
- else:
1717
- console.error(
1718
- "Cannot use `--template` option with `--ai` option. Please remove `--template` option."
1719
- )
1720
- raise typer.Exit(2)
1721
-
1722
-
1723
1698
  def fetch_remote_templates(
1724
1699
  template: str,
1725
1700
  ) -> tuple[str, dict[str, Template]]:
@@ -1744,15 +1719,12 @@ def fetch_remote_templates(
1744
1719
  return template, available_templates
1745
1720
 
1746
1721
 
1747
- def initialize_app(
1748
- app_name: str, template: str | None = None, ai: bool = False
1749
- ) -> str | None:
1722
+ def initialize_app(app_name: str, template: str | None = None) -> str | None:
1750
1723
  """Initialize the app either from a remote template or a blank app. If the config file exists, it is considered as reinit.
1751
1724
 
1752
1725
  Args:
1753
1726
  app_name: The name of the app.
1754
1727
  template: The name of the template to use.
1755
- ai: Whether to use AI to generate the template.
1756
1728
 
1757
1729
  Returns:
1758
1730
  The name of the template.
@@ -1768,11 +1740,6 @@ def initialize_app(
1768
1740
  telemetry.send("reinit")
1769
1741
  return
1770
1742
 
1771
- generation_hash = None
1772
- if ai:
1773
- generation_hash = generate_template_using_ai(template)
1774
- template = constants.Templates.DEFAULT
1775
-
1776
1743
  templates: dict[str, Template] = {}
1777
1744
 
1778
1745
  # Don't fetch app templates if the user directly asked for DEFAULT.
@@ -1781,11 +1748,7 @@ def initialize_app(
1781
1748
 
1782
1749
  if template is None:
1783
1750
  template = prompt_for_template_options(get_init_cli_prompt_options())
1784
- if template == constants.Templates.AI:
1785
- generation_hash = generate_template_using_ai()
1786
- # change to the default to allow creation of default app
1787
- template = constants.Templates.DEFAULT
1788
- elif template == constants.Templates.CHOOSE_TEMPLATES:
1751
+ if template == constants.Templates.CHOOSE_TEMPLATES:
1789
1752
  console.print(
1790
1753
  f"Go to the templates page ({constants.Templates.REFLEX_TEMPLATES_URL}) and copy the command to init with a template."
1791
1754
  )
@@ -1800,11 +1763,6 @@ def initialize_app(
1800
1763
  app_name=app_name, template=template, templates=templates
1801
1764
  )
1802
1765
 
1803
- # If a reflex.build generation hash is available, download the code and apply it to the main module.
1804
- if generation_hash:
1805
- initialize_main_module_index_from_generation(
1806
- app_name, generation_hash=generation_hash
1807
- )
1808
1766
  telemetry.send("init", template=template)
1809
1767
 
1810
1768
  return template
@@ -348,7 +348,7 @@ def _extract_class_props_as_ast_nodes(
348
348
  all_props = []
349
349
  kwargs = []
350
350
  for target_class in clzs:
351
- event_triggers = target_class().get_event_triggers()
351
+ event_triggers = target_class._create([]).get_event_triggers()
352
352
  # Import from the target class to ensure type hints are resolvable.
353
353
  exec(f"from {target_class.__module__} import *", type_hint_globals)
354
354
  for name, value in target_class.__annotations__.items():
@@ -575,7 +575,7 @@ def _generate_component_create_functiondef(
575
575
  return ast.Name(id=f"{' | '.join(map(ast.unparse, all_count_args_type))}")
576
576
  return ast.Name(id="EventType[Any]")
577
577
 
578
- event_triggers = clz().get_event_triggers()
578
+ event_triggers = clz._create([]).get_event_triggers()
579
579
 
580
580
  # event handler kwargs
581
581
  kwargs.extend(
reflex/utils/redir.py CHANGED
@@ -1,7 +1,6 @@
1
1
  """Utilities to handle redirection to browser UI."""
2
2
 
3
3
  import time
4
- import uuid
5
4
  import webbrowser
6
5
 
7
6
  import httpx
@@ -48,14 +47,6 @@ def open_browser_and_wait(
48
47
  return response
49
48
 
50
49
 
51
- def reflex_build_redirect() -> str:
52
- """Open the browser window to reflex.build and wait for the user to select a generation.
53
-
54
- Returns:
55
- The selected generation hash.
56
- """
57
- token = str(uuid.uuid4())
58
- target_url = constants.Templates.REFLEX_BUILD_URL.format(reflex_init_token=token)
59
- poll_url = constants.Templates.REFLEX_BUILD_POLL_URL.format(reflex_init_token=token)
60
- response = open_browser_and_wait(target_url, poll_url)
61
- return response.json()["generation_hash"]
50
+ def reflex_build_redirect() -> None:
51
+ """Open the browser window to reflex.build."""
52
+ open_browser(constants.Templates.REFLEX_BUILD_FRONTEND)
reflex/vars/base.py CHANGED
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import contextlib
6
+ import copy
6
7
  import dataclasses
7
8
  import datetime
8
9
  import functools
@@ -1255,6 +1256,27 @@ class Var(Generic[VAR_TYPE]):
1255
1256
 
1256
1257
  if not TYPE_CHECKING:
1257
1258
 
1259
+ def __getitem__(self, key: Any) -> Var:
1260
+ """Get the item from the var.
1261
+
1262
+ Args:
1263
+ key: The key to get.
1264
+
1265
+ Raises:
1266
+ UntypedVarError: If the var type is Any.
1267
+ TypeError: If the var type is Any.
1268
+
1269
+ # noqa: DAR101 self
1270
+ """
1271
+ if self._var_type is Any:
1272
+ raise exceptions.UntypedVarError(
1273
+ self,
1274
+ f"access the item '{key}'",
1275
+ )
1276
+ raise TypeError(
1277
+ f"Var of type {self._var_type} does not support item access."
1278
+ )
1279
+
1258
1280
  def __getattr__(self, name: str):
1259
1281
  """Get an attribute of the var.
1260
1282
 
@@ -1280,7 +1302,8 @@ class Var(Generic[VAR_TYPE]):
1280
1302
 
1281
1303
  if self._var_type is Any:
1282
1304
  raise exceptions.UntypedVarError(
1283
- f"You must provide an annotation for the state var `{self!s}`. Annotation cannot be `{self._var_type}`."
1305
+ self,
1306
+ f"access the attribute '{name}'",
1284
1307
  )
1285
1308
 
1286
1309
  raise VarAttributeError(
@@ -2146,7 +2169,7 @@ class ComputedVar(Var[RETURN_TYPE]):
2146
2169
  "fget": kwargs.pop("fget", self._fget),
2147
2170
  "initial_value": kwargs.pop("initial_value", self._initial_value),
2148
2171
  "cache": kwargs.pop("cache", self._cache),
2149
- "deps": kwargs.pop("deps", self._static_deps),
2172
+ "deps": kwargs.pop("deps", copy.copy(self._static_deps)),
2150
2173
  "auto_deps": kwargs.pop("auto_deps", self._auto_deps),
2151
2174
  "interval": kwargs.pop("interval", self._update_interval),
2152
2175
  "backend": kwargs.pop("backend", self._backend),
@@ -2318,7 +2341,7 @@ class ComputedVar(Var[RETURN_TYPE]):
2318
2341
  if not _isinstance(value, self._var_type, nested=1, treat_var_as_type=False):
2319
2342
  console.error(
2320
2343
  f"Computed var '{type(instance).__name__}.{self._js_expr}' must return"
2321
- f" type '{self._var_type}', got '{type(value)}'."
2344
+ f" a value of type '{self._var_type}', got '{value}' of type {type(value)}."
2322
2345
  )
2323
2346
 
2324
2347
  def _deps(