reflex 0.8.14.post1__py3-none-any.whl → 0.8.15__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 (51) hide show
  1. reflex/.templates/web/utils/state.js +68 -8
  2. reflex/__init__.py +12 -7
  3. reflex/__init__.pyi +11 -3
  4. reflex/app.py +10 -7
  5. reflex/base.py +58 -33
  6. reflex/components/datadisplay/dataeditor.py +17 -2
  7. reflex/components/datadisplay/dataeditor.pyi +6 -2
  8. reflex/components/field.py +3 -1
  9. reflex/components/lucide/icon.py +2 -1
  10. reflex/components/lucide/icon.pyi +2 -1
  11. reflex/components/markdown/markdown.py +101 -27
  12. reflex/components/sonner/toast.py +3 -2
  13. reflex/components/sonner/toast.pyi +3 -2
  14. reflex/constants/base.py +5 -0
  15. reflex/constants/installer.py +3 -3
  16. reflex/environment.py +9 -1
  17. reflex/event.py +3 -0
  18. reflex/istate/manager/__init__.py +120 -0
  19. reflex/istate/manager/disk.py +210 -0
  20. reflex/istate/manager/memory.py +76 -0
  21. reflex/istate/{manager.py → manager/redis.py} +5 -372
  22. reflex/istate/proxy.py +35 -24
  23. reflex/model.py +534 -511
  24. reflex/plugins/tailwind_v4.py +2 -2
  25. reflex/reflex.py +16 -10
  26. reflex/state.py +35 -34
  27. reflex/testing.py +12 -14
  28. reflex/utils/build.py +11 -1
  29. reflex/utils/codespaces.py +30 -1
  30. reflex/utils/compat.py +51 -48
  31. reflex/utils/misc.py +2 -1
  32. reflex/utils/monitoring.py +1 -2
  33. reflex/utils/prerequisites.py +19 -4
  34. reflex/utils/processes.py +3 -1
  35. reflex/utils/redir.py +21 -37
  36. reflex/utils/serializers.py +21 -20
  37. reflex/utils/telemetry.py +0 -2
  38. reflex/utils/templates.py +4 -4
  39. reflex/utils/types.py +89 -90
  40. reflex/vars/base.py +108 -41
  41. reflex/vars/color.py +28 -8
  42. reflex/vars/datetime.py +6 -2
  43. reflex/vars/dep_tracking.py +2 -2
  44. reflex/vars/number.py +26 -0
  45. reflex/vars/object.py +51 -7
  46. reflex/vars/sequence.py +32 -1
  47. {reflex-0.8.14.post1.dist-info → reflex-0.8.15.dist-info}/METADATA +8 -3
  48. {reflex-0.8.14.post1.dist-info → reflex-0.8.15.dist-info}/RECORD +51 -48
  49. {reflex-0.8.14.post1.dist-info → reflex-0.8.15.dist-info}/WHEEL +0 -0
  50. {reflex-0.8.14.post1.dist-info → reflex-0.8.15.dist-info}/entry_points.txt +0 -0
  51. {reflex-0.8.14.post1.dist-info → reflex-0.8.15.dist-info}/licenses/LICENSE +0 -0
reflex/utils/redir.py CHANGED
@@ -1,59 +1,43 @@
1
1
  """Utilities to handle redirection to browser UI."""
2
2
 
3
- import time
4
- import webbrowser
3
+ from typing import TYPE_CHECKING
5
4
 
6
- from reflex import constants
7
- from reflex.utils import net
5
+ if TYPE_CHECKING:
6
+ from urllib.parse import SplitResult
8
7
 
9
- from . import console
10
8
 
11
-
12
- def open_browser(target_url: str) -> None:
9
+ def open_browser(target_url: "SplitResult") -> None:
13
10
  """Open a browser window to target_url.
14
11
 
15
12
  Args:
16
13
  target_url: The URL to open in the browser.
17
14
  """
18
- if not webbrowser.open(target_url):
15
+ import webbrowser
16
+
17
+ from reflex.utils import console
18
+
19
+ if not webbrowser.open(target_url.geturl()):
19
20
  console.warn(
20
21
  f"Unable to automatically open the browser. Please navigate to {target_url} in your browser."
21
22
  )
22
23
  else:
23
- console.info(f"Opening browser to {target_url}.")
24
-
25
-
26
- def open_browser_and_wait(target_url: str, poll_url: str, interval: int = 2):
27
- """Open a browser window to target_url and request poll_url until it returns successfully.
28
-
29
- Args:
30
- target_url: The URL to open in the browser.
31
- poll_url: The URL to poll for success.
32
- interval: The interval in seconds to wait between polling.
33
-
34
- Returns:
35
- The response from the poll_url.
36
- """
37
- import httpx
38
-
39
- open_browser(target_url)
40
- console.info("[b]Complete the workflow in the browser to continue.[/b]")
41
- while True:
42
- try:
43
- response = net.get(poll_url, follow_redirects=True)
44
- if response.is_success:
45
- break
46
- except httpx.RequestError as err:
47
- console.info(f"Will retry after error occurred while polling: {err}.")
48
- time.sleep(interval)
49
- return response
24
+ simplified_url = target_url._replace(path="", query="", fragment="").geturl()
25
+ console.info(f"Opened browser to {simplified_url}")
50
26
 
51
27
 
52
28
  def reflex_build_redirect() -> None:
53
29
  """Open the browser window to reflex.build."""
54
- open_browser(constants.Templates.REFLEX_BUILD_FRONTEND)
30
+ from urllib.parse import urlsplit
31
+
32
+ from reflex import constants
33
+
34
+ open_browser(urlsplit(constants.Templates.REFLEX_BUILD_FRONTEND_WITH_REFERRER))
55
35
 
56
36
 
57
37
  def reflex_templates():
58
38
  """Open the browser window to reflex.build/templates."""
59
- open_browser(constants.Templates.REFLEX_TEMPLATES_URL)
39
+ from urllib.parse import urlsplit
40
+
41
+ from reflex import constants
42
+
43
+ open_browser(urlsplit(constants.Templates.REFLEX_TEMPLATES_URL))
@@ -12,13 +12,11 @@ import warnings
12
12
  from collections.abc import Callable, Mapping, Sequence
13
13
  from datetime import date, datetime, time, timedelta
14
14
  from enum import Enum
15
+ from importlib.util import find_spec
15
16
  from pathlib import Path
16
17
  from typing import Any, Literal, TypeVar, get_type_hints, overload
17
18
  from uuid import UUID
18
19
 
19
- from pydantic import BaseModel as BaseModelV2
20
- from pydantic.v1 import BaseModel as BaseModelV1
21
-
22
20
  from reflex.base import Base
23
21
  from reflex.constants.colors import Color
24
22
  from reflex.utils import console, types
@@ -281,24 +279,13 @@ def serialize_base(value: Base) -> dict:
281
279
  }
282
280
 
283
281
 
284
- @serializer(to=dict)
285
- def serialize_base_model_v1(model: BaseModelV1) -> dict:
286
- """Serialize a pydantic v1 BaseModel instance.
287
-
288
- Args:
289
- model: The BaseModel to serialize.
290
-
291
- Returns:
292
- The serialized BaseModel.
293
- """
294
- return model.dict()
295
-
296
-
297
- if BaseModelV1 is not BaseModelV2:
282
+ if find_spec("pydantic"):
283
+ from pydantic import BaseModel as BaseModelV2
284
+ from pydantic.v1 import BaseModel as BaseModelV1
298
285
 
299
286
  @serializer(to=dict)
300
- def serialize_base_model_v2(model: BaseModelV2) -> dict:
301
- """Serialize a pydantic v2 BaseModel instance.
287
+ def serialize_base_model_v1(model: BaseModelV1) -> dict:
288
+ """Serialize a pydantic v1 BaseModel instance.
302
289
 
303
290
  Args:
304
291
  model: The BaseModel to serialize.
@@ -306,7 +293,21 @@ if BaseModelV1 is not BaseModelV2:
306
293
  Returns:
307
294
  The serialized BaseModel.
308
295
  """
309
- return model.model_dump()
296
+ return model.dict()
297
+
298
+ if BaseModelV1 is not BaseModelV2:
299
+
300
+ @serializer(to=dict)
301
+ def serialize_base_model_v2(model: BaseModelV2) -> dict:
302
+ """Serialize a pydantic v2 BaseModel instance.
303
+
304
+ Args:
305
+ model: The BaseModel to serialize.
306
+
307
+ Returns:
308
+ The serialized BaseModel.
309
+ """
310
+ return model.model_dump()
310
311
 
311
312
 
312
313
  @serializer
reflex/utils/telemetry.py CHANGED
@@ -1,7 +1,5 @@
1
1
  """Anonymous telemetry for Reflex."""
2
2
 
3
- from __future__ import annotations
4
-
5
3
  import asyncio
6
4
  import dataclasses
7
5
  import importlib.metadata
reflex/utils/templates.py CHANGED
@@ -419,13 +419,13 @@ def get_init_cli_prompt_options() -> list[Template]:
419
419
  """
420
420
  return [
421
421
  Template(
422
- name=constants.Templates.DEFAULT,
423
- description="A blank Reflex app.",
422
+ name=constants.Templates.AI,
423
+ description="[bold]Try our free AI builder.",
424
424
  code_url="",
425
425
  ),
426
426
  Template(
427
- name=constants.Templates.AI,
428
- description="[bold]Try our free AI builder.",
427
+ name=constants.Templates.DEFAULT,
428
+ description="A blank Reflex app.",
429
429
  code_url="",
430
430
  ),
431
431
  Template(
reflex/utils/types.py CHANGED
@@ -8,6 +8,7 @@ import types
8
8
  from collections.abc import Callable, Iterable, Mapping, Sequence
9
9
  from enum import Enum
10
10
  from functools import cached_property, lru_cache
11
+ from importlib.util import find_spec
11
12
  from types import GenericAlias
12
13
  from typing import ( # noqa: UP035
13
14
  TYPE_CHECKING,
@@ -33,7 +34,6 @@ from typing import ( # noqa: UP035
33
34
  from typing import get_origin as get_origin_og
34
35
  from typing import get_type_hints as get_type_hints_og
35
36
 
36
- from pydantic.v1.fields import ModelField
37
37
  from typing_extensions import Self as Self
38
38
  from typing_extensions import override as override
39
39
 
@@ -291,6 +291,7 @@ def is_literal(cls: GenericType) -> bool:
291
291
  return getattr(cls, "__origin__", None) is Literal
292
292
 
293
293
 
294
+ @lru_cache
294
295
  def has_args(cls: type) -> bool:
295
296
  """Check if the class has generic parameters.
296
297
 
@@ -346,33 +347,6 @@ def is_classvar(a_type: Any) -> bool:
346
347
  )
347
348
 
348
349
 
349
- def true_type_for_pydantic_field(f: ModelField):
350
- """Get the type for a pydantic field.
351
-
352
- Args:
353
- f: The field to get the type for.
354
-
355
- Returns:
356
- The type for the field.
357
- """
358
- if not isinstance(f.annotation, (str, ForwardRef)):
359
- return f.annotation
360
-
361
- type_ = f.outer_type_
362
-
363
- if (
364
- f.field_info.default is None
365
- or (isinstance(f.annotation, str) and f.annotation.startswith("Optional"))
366
- or (
367
- isinstance(f.annotation, ForwardRef)
368
- and f.annotation.__forward_arg__.startswith("Optional")
369
- )
370
- ) and not is_optional(type_):
371
- return type_ | None
372
-
373
- return type_
374
-
375
-
376
350
  def value_inside_optional(cls: GenericType) -> GenericType:
377
351
  """Get the value inside an Optional type or the original type.
378
352
 
@@ -412,6 +386,13 @@ def get_field_type(cls: GenericType, field_name: str) -> GenericType | None:
412
386
  return type_hints.get(field_name, None)
413
387
 
414
388
 
389
+ PROPERTY_CLASSES = (property,)
390
+ if find_spec("sqlalchemy") and find_spec("sqlalchemy.ext"):
391
+ from sqlalchemy.ext.hybrid import hybrid_property
392
+
393
+ PROPERTY_CLASSES += (hybrid_property,)
394
+
395
+
415
396
  def get_property_hint(attr: Any | None) -> GenericType | None:
416
397
  """Check if an attribute is a property and return its type hint.
417
398
 
@@ -421,9 +402,7 @@ def get_property_hint(attr: Any | None) -> GenericType | None:
421
402
  Returns:
422
403
  The type hint of the property, if it is a property, else None.
423
404
  """
424
- from sqlalchemy.ext.hybrid import hybrid_property
425
-
426
- if not isinstance(attr, (property, hybrid_property)):
405
+ if not isinstance(attr, PROPERTY_CLASSES):
427
406
  return None
428
407
  hints = get_type_hints(attr.fget)
429
408
  return hints.get("return", None)
@@ -441,12 +420,6 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None
441
420
  Returns:
442
421
  The type of the attribute, if accessible, or None
443
422
  """
444
- import sqlalchemy
445
- from sqlalchemy.ext.associationproxy import AssociationProxyInstance
446
- from sqlalchemy.orm import DeclarativeBase, Mapped, QueryableAttribute, Relationship
447
-
448
- from reflex.model import Model
449
-
450
423
  try:
451
424
  attr = getattr(cls, name, None)
452
425
  except NotImplementedError:
@@ -458,67 +431,93 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None
458
431
  if hasattr(cls, "__fields__") and name in cls.__fields__:
459
432
  # pydantic models
460
433
  return get_field_type(cls, name)
461
- if isinstance(cls, type) and issubclass(cls, DeclarativeBase):
462
- insp = sqlalchemy.inspect(cls)
463
- if name in insp.columns:
464
- # check for list types
465
- column = insp.columns[name]
466
- column_type = column.type
467
- try:
468
- type_ = insp.columns[name].type.python_type
469
- except NotImplementedError:
470
- type_ = None
471
- if type_ is not None:
472
- if hasattr(column_type, "item_type"):
473
- try:
474
- item_type = column_type.item_type.python_type # pyright: ignore [reportAttributeAccessIssue]
475
- except NotImplementedError:
476
- item_type = None
477
- if item_type is not None:
478
- if type_ in PrimitiveToAnnotation:
479
- type_ = PrimitiveToAnnotation[type_]
480
- type_ = type_[item_type] # pyright: ignore [reportIndexIssue]
481
- if hasattr(column, "nullable") and column.nullable:
482
- type_ = type_ | None
434
+ if find_spec("sqlalchemy") and find_spec("sqlalchemy.orm"):
435
+ import sqlalchemy
436
+ from sqlalchemy.ext.associationproxy import AssociationProxyInstance
437
+ from sqlalchemy.orm import (
438
+ DeclarativeBase,
439
+ Mapped,
440
+ QueryableAttribute,
441
+ Relationship,
442
+ )
443
+
444
+ from reflex.model import Model
445
+
446
+ if find_spec("sqlmodel"):
447
+ from sqlmodel import SQLModel
448
+
449
+ sqlmodel_types = (Model, SQLModel)
450
+ else:
451
+ sqlmodel_types = (Model,)
452
+
453
+ if isinstance(cls, type) and issubclass(cls, DeclarativeBase):
454
+ insp = sqlalchemy.inspect(cls)
455
+ if name in insp.columns:
456
+ # check for list types
457
+ column = insp.columns[name]
458
+ column_type = column.type
459
+ try:
460
+ type_ = insp.columns[name].type.python_type
461
+ except NotImplementedError:
462
+ type_ = None
463
+ if type_ is not None:
464
+ if hasattr(column_type, "item_type"):
465
+ try:
466
+ item_type = column_type.item_type.python_type # pyright: ignore [reportAttributeAccessIssue]
467
+ except NotImplementedError:
468
+ item_type = None
469
+ if item_type is not None:
470
+ if type_ in PrimitiveToAnnotation:
471
+ type_ = PrimitiveToAnnotation[type_]
472
+ type_ = type_[item_type] # pyright: ignore [reportIndexIssue]
473
+ if hasattr(column, "nullable") and column.nullable:
474
+ type_ = type_ | None
475
+ return type_
476
+ if name in insp.all_orm_descriptors:
477
+ descriptor = insp.all_orm_descriptors[name]
478
+ if hint := get_property_hint(descriptor):
479
+ return hint
480
+ if isinstance(descriptor, QueryableAttribute):
481
+ prop = descriptor.property
482
+ if isinstance(prop, Relationship):
483
+ type_ = prop.mapper.class_
484
+ # TODO: check for nullable?
485
+ return list[type_] if prop.uselist else type_ | None
486
+ if isinstance(attr, AssociationProxyInstance):
487
+ return list[
488
+ get_attribute_access_type(
489
+ attr.target_class,
490
+ attr.remote_attr.key, # pyright: ignore [reportAttributeAccessIssue]
491
+ )
492
+ ]
493
+ elif (
494
+ isinstance(cls, type)
495
+ and not is_generic_alias(cls)
496
+ and issubclass(cls, sqlmodel_types)
497
+ ):
498
+ # Check in the annotations directly (for sqlmodel.Relationship)
499
+ hints = get_type_hints(cls) # pyright: ignore [reportArgumentType]
500
+ if name in hints:
501
+ type_ = hints[name]
502
+ type_origin = get_origin(type_)
503
+ if isinstance(type_origin, type) and issubclass(type_origin, Mapped):
504
+ return get_args(type_)[0] # SQLAlchemy v2
505
+ if find_spec("pydantic"):
506
+ from pydantic.v1.fields import ModelField
507
+
508
+ if isinstance(type_, ModelField):
509
+ return type_.type_ # SQLAlchemy v1.4
483
510
  return type_
484
- if name in insp.all_orm_descriptors:
485
- descriptor = insp.all_orm_descriptors[name]
486
- if hint := get_property_hint(descriptor):
487
- return hint
488
- if isinstance(descriptor, QueryableAttribute):
489
- prop = descriptor.property
490
- if isinstance(prop, Relationship):
491
- type_ = prop.mapper.class_
492
- # TODO: check for nullable?
493
- return list[type_] if prop.uselist else type_ | None
494
- if isinstance(attr, AssociationProxyInstance):
495
- return list[
496
- get_attribute_access_type(
497
- attr.target_class,
498
- attr.remote_attr.key, # pyright: ignore [reportAttributeAccessIssue]
499
- )
500
- ]
501
- elif isinstance(cls, type) and not is_generic_alias(cls) and issubclass(cls, Model):
502
- # Check in the annotations directly (for sqlmodel.Relationship)
503
- hints = get_type_hints(cls)
504
- if name in hints:
505
- type_ = hints[name]
506
- type_origin = get_origin(type_)
507
- if isinstance(type_origin, type) and issubclass(type_origin, Mapped):
508
- return get_args(type_)[0] # SQLAlchemy v2
509
- if isinstance(type_, ModelField):
510
- return type_.type_ # SQLAlchemy v1.4
511
- return type_
512
- elif is_union(cls):
511
+ if is_union(cls):
513
512
  # Check in each arg of the annotation.
514
513
  return unionize(
515
514
  *(get_attribute_access_type(arg, name) for arg in get_args(cls))
516
515
  )
517
- elif isinstance(cls, type):
516
+ if isinstance(cls, type):
518
517
  # Bare class
519
518
  exceptions = NameError
520
519
  try:
521
- hints = get_type_hints(cls)
520
+ hints = get_type_hints(cls) # pyright: ignore [reportArgumentType]
522
521
  if name in hints:
523
522
  return hints[name]
524
523
  except exceptions as e:
reflex/vars/base.py CHANGED
@@ -40,10 +40,10 @@ from rich.markup import escape
40
40
  from typing_extensions import dataclass_transform, override
41
41
 
42
42
  from reflex import constants
43
- from reflex.base import Base
44
43
  from reflex.constants.compiler import Hooks
45
44
  from reflex.constants.state import FIELD_MARKER
46
45
  from reflex.utils import console, exceptions, imports, serializers, types
46
+ from reflex.utils.compat import annotations_from_namespace
47
47
  from reflex.utils.decorator import once
48
48
  from reflex.utils.exceptions import (
49
49
  ComputedVarSignatureError,
@@ -1505,21 +1505,6 @@ class LiteralVar(Var):
1505
1505
  )
1506
1506
  return LiteralVar.create(serialized_value, _var_data=_var_data)
1507
1507
 
1508
- if isinstance(value, Base):
1509
- # get the fields of the pydantic class
1510
- fields = value.__fields__.keys()
1511
- one_level_dict = {field: getattr(value, field) for field in fields}
1512
-
1513
- return LiteralObjectVar.create(
1514
- {
1515
- field: value
1516
- for field, value in one_level_dict.items()
1517
- if not callable(value)
1518
- },
1519
- _var_type=type(value),
1520
- _var_data=_var_data,
1521
- )
1522
-
1523
1508
  if dataclasses.is_dataclass(value) and not isinstance(value, type):
1524
1509
  return LiteralObjectVar.create(
1525
1510
  {
@@ -1542,6 +1527,82 @@ class LiteralVar(Var):
1542
1527
  def __post_init__(self):
1543
1528
  """Post-initialize the var."""
1544
1529
 
1530
+ @classmethod
1531
+ def _get_all_var_data_without_creating_var(
1532
+ cls,
1533
+ value: Any,
1534
+ ) -> VarData | None:
1535
+ return cls.create(value)._get_all_var_data()
1536
+
1537
+ @classmethod
1538
+ def _get_all_var_data_without_creating_var_dispatch(
1539
+ cls,
1540
+ value: Any,
1541
+ ) -> VarData | None:
1542
+ """Get all the var data without creating a var.
1543
+
1544
+ Args:
1545
+ value: The value to get the var data from.
1546
+
1547
+ Returns:
1548
+ The var data or None.
1549
+
1550
+ Raises:
1551
+ TypeError: If the value is not a supported type for LiteralVar.
1552
+ """
1553
+ from .object import LiteralObjectVar
1554
+ from .sequence import LiteralStringVar
1555
+
1556
+ if isinstance(value, Var):
1557
+ return value._get_all_var_data()
1558
+
1559
+ for literal_subclass, var_subclass in _var_literal_subclasses[::-1]:
1560
+ if isinstance(value, var_subclass.python_types):
1561
+ return literal_subclass._get_all_var_data_without_creating_var(value)
1562
+
1563
+ if (
1564
+ (as_var_method := getattr(value, "_as_var", None)) is not None
1565
+ and callable(as_var_method)
1566
+ and isinstance((resulting_var := as_var_method()), Var)
1567
+ ):
1568
+ return resulting_var._get_all_var_data()
1569
+
1570
+ from reflex.event import EventHandler
1571
+ from reflex.utils.format import get_event_handler_parts
1572
+
1573
+ if isinstance(value, EventHandler):
1574
+ return Var(
1575
+ _js_expr=".".join(filter(None, get_event_handler_parts(value)))
1576
+ )._get_all_var_data()
1577
+
1578
+ serialized_value = serializers.serialize(value)
1579
+ if serialized_value is not None:
1580
+ if isinstance(serialized_value, Mapping):
1581
+ return LiteralObjectVar._get_all_var_data_without_creating_var(
1582
+ serialized_value
1583
+ )
1584
+ if isinstance(serialized_value, str):
1585
+ return LiteralStringVar._get_all_var_data_without_creating_var(
1586
+ serialized_value
1587
+ )
1588
+ return LiteralVar._get_all_var_data_without_creating_var_dispatch(
1589
+ serialized_value
1590
+ )
1591
+
1592
+ if dataclasses.is_dataclass(value) and not isinstance(value, type):
1593
+ return LiteralObjectVar._get_all_var_data_without_creating_var(
1594
+ {
1595
+ k: (None if callable(v) else v)
1596
+ for k, v in dataclasses.asdict(value).items()
1597
+ }
1598
+ )
1599
+
1600
+ if isinstance(value, range):
1601
+ return None
1602
+
1603
+ msg = f"Unsupported type {type(value)} for LiteralVar. Tried to create a LiteralVar from {value}."
1604
+ raise TypeError(msg)
1605
+
1545
1606
  @property
1546
1607
  def _var_value(self) -> Any:
1547
1608
  msg = "LiteralVar subclasses must implement the _var_value property."
@@ -1703,30 +1764,30 @@ def figure_out_type(value: Any) -> types.GenericType:
1703
1764
  Returns:
1704
1765
  The type of the value.
1705
1766
  """
1706
- if isinstance(value, Var):
1707
- return value._var_type
1708
- type_ = type(value)
1709
- if has_args(type_):
1710
- return type_
1711
- if isinstance(value, list):
1712
- if not value:
1713
- return Sequence[NoReturn]
1714
- return Sequence[unionize(*(figure_out_type(v) for v in value))]
1715
- if isinstance(value, set):
1716
- return set[unionize(*(figure_out_type(v) for v in value))]
1717
- if isinstance(value, tuple):
1718
- if not value:
1719
- return tuple[NoReturn, ...]
1720
- if len(value) <= 5:
1721
- return tuple[tuple(figure_out_type(v) for v in value)]
1722
- return tuple[unionize(*(figure_out_type(v) for v in value)), ...]
1723
- if isinstance(value, Mapping):
1724
- if not value:
1725
- return Mapping[NoReturn, NoReturn]
1726
- return Mapping[
1727
- unionize(*(figure_out_type(k) for k in value)),
1728
- unionize(*(figure_out_type(v) for v in value.values())),
1729
- ]
1767
+ if isinstance(value, (list, set, tuple, Mapping, Var)):
1768
+ if isinstance(value, Var):
1769
+ return value._var_type
1770
+ if has_args(value_type := type(value)):
1771
+ return value_type
1772
+ if isinstance(value, list):
1773
+ if not value:
1774
+ return Sequence[NoReturn]
1775
+ return Sequence[unionize(*{figure_out_type(v) for v in value[:100]})]
1776
+ if isinstance(value, set):
1777
+ return set[unionize(*{figure_out_type(v) for v in value})]
1778
+ if isinstance(value, tuple):
1779
+ if not value:
1780
+ return tuple[NoReturn, ...]
1781
+ if len(value) <= 5:
1782
+ return tuple[tuple(figure_out_type(v) for v in value)]
1783
+ return tuple[unionize(*{figure_out_type(v) for v in value[:100]}), ...]
1784
+ if isinstance(value, Mapping):
1785
+ if not value:
1786
+ return Mapping[NoReturn, NoReturn]
1787
+ return Mapping[
1788
+ unionize(*{figure_out_type(k) for k in list(value.keys())[:100]}),
1789
+ unionize(*{figure_out_type(v) for v in list(value.values())[:100]}),
1790
+ ]
1730
1791
  return type(value)
1731
1792
 
1732
1793
 
@@ -2898,6 +2959,10 @@ class LiteralNoneVar(LiteralVar, NoneVar):
2898
2959
  """
2899
2960
  return "null"
2900
2961
 
2962
+ @classmethod
2963
+ def _get_all_var_data_without_creating_var(cls, value: None) -> VarData | None:
2964
+ return None
2965
+
2901
2966
  @classmethod
2902
2967
  def create(
2903
2968
  cls,
@@ -3201,6 +3266,8 @@ if TYPE_CHECKING:
3201
3266
  from _typeshed import DataclassInstance
3202
3267
  from sqlalchemy.orm import DeclarativeBase
3203
3268
 
3269
+ from reflex.base import Base
3270
+
3204
3271
  SQLA_TYPE = TypeVar("SQLA_TYPE", bound=DeclarativeBase | None)
3205
3272
  BASE_TYPE = TypeVar("BASE_TYPE", bound=Base | None)
3206
3273
  DATACLASS_TYPE = TypeVar("DATACLASS_TYPE", bound=DataclassInstance | None)
@@ -3492,7 +3559,7 @@ class BaseStateMeta(ABCMeta):
3492
3559
  inherited_fields: dict[str, Field] = {}
3493
3560
  own_fields: dict[str, Field] = {}
3494
3561
  resolved_annotations = types.resolve_annotations(
3495
- namespace.get("__annotations__", {}), namespace["__module__"]
3562
+ annotations_from_namespace(namespace), namespace["__module__"]
3496
3563
  )
3497
3564
 
3498
3565
  for base in bases[::-1]:
reflex/vars/color.py CHANGED
@@ -29,6 +29,23 @@ class LiteralColorVar(CachedVarOperation, LiteralVar, ColorVar):
29
29
 
30
30
  _var_value: Color = dataclasses.field(default_factory=lambda: Color(color="black"))
31
31
 
32
+ @classmethod
33
+ def _get_all_var_data_without_creating_var(
34
+ cls,
35
+ value: Color,
36
+ ) -> VarData | None:
37
+ return VarData.merge(
38
+ LiteralStringVar._get_all_var_data_without_creating_var(value.color)
39
+ if isinstance(value.color, str)
40
+ else value.color._get_all_var_data(),
41
+ value.alpha._get_all_var_data()
42
+ if not isinstance(value.alpha, bool)
43
+ else None,
44
+ value.shade._get_all_var_data()
45
+ if not isinstance(value.shade, int)
46
+ else None,
47
+ )
48
+
32
49
  @classmethod
33
50
  def create(
34
51
  cls,
@@ -111,14 +128,17 @@ class LiteralColorVar(CachedVarOperation, LiteralVar, ColorVar):
111
128
  The var data.
112
129
  """
113
130
  return VarData.merge(
114
- *[
115
- LiteralVar.create(var)._get_all_var_data()
116
- for var in (
117
- self._var_value.color,
118
- self._var_value.alpha,
119
- self._var_value.shade,
120
- )
121
- ],
131
+ LiteralStringVar._get_all_var_data_without_creating_var(
132
+ self._var_value.color
133
+ )
134
+ if isinstance(self._var_value.color, str)
135
+ else self._var_value.color._get_all_var_data(),
136
+ self._var_value.alpha._get_all_var_data()
137
+ if not isinstance(self._var_value.alpha, bool)
138
+ else None,
139
+ self._var_value.shade._get_all_var_data()
140
+ if not isinstance(self._var_value.shade, int)
141
+ else None,
122
142
  self._var_data,
123
143
  )
124
144