reflex 0.8.15a0__py3-none-any.whl → 0.8.15a2__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.

reflex/model.py CHANGED
@@ -71,6 +71,10 @@ if find_spec("sqlalchemy"):
71
71
  "echo": environment.SQLALCHEMY_ECHO.get(),
72
72
  # Check connections before returning them.
73
73
  "pool_pre_ping": environment.SQLALCHEMY_POOL_PRE_PING.get(),
74
+ "pool_size": environment.SQLALCHEMY_POOL_SIZE.get(),
75
+ "max_overflow": environment.SQLALCHEMY_MAX_OVERFLOW.get(),
76
+ "pool_recycle": environment.SQLALCHEMY_POOL_RECYCLE.get(),
77
+ "pool_timeout": environment.SQLALCHEMY_POOL_TIMEOUT.get(),
74
78
  }
75
79
  conf = get_config()
76
80
  url = url or conf.db_url
@@ -363,7 +367,7 @@ if find_spec("sqlmodel") and find_spec("sqlalchemy") and find_spec("pydantic"):
363
367
  reason=(
364
368
  "Register sqlmodel.SQLModel classes with `@rx.ModelRegistry.register`"
365
369
  ),
366
- deprecation_version="0.8.0",
370
+ deprecation_version="0.8.15",
367
371
  removal_version="0.9.0",
368
372
  )
369
373
  super().__pydantic_init_subclass__()
reflex/state.py CHANGED
@@ -16,6 +16,7 @@ import time
16
16
  import typing
17
17
  import warnings
18
18
  from collections.abc import AsyncIterator, Callable, Sequence
19
+ from enum import Enum
19
20
  from hashlib import md5
20
21
  from importlib.util import find_spec
21
22
  from types import FunctionType
@@ -246,7 +247,7 @@ class EventHandlerSetVar(EventHandler):
246
247
  msg = f"Variable `{args[0]}` cannot be set on `{self.state_cls.get_full_name()}`"
247
248
  raise AttributeError(msg)
248
249
 
249
- if asyncio.iscoroutinefunction(handler.fn):
250
+ if inspect.iscoroutinefunction(handler.fn):
250
251
  msg = f"Setter for {args[0]} is async, which is not supported."
251
252
  raise NotImplementedError(msg)
252
253
 
@@ -287,7 +288,7 @@ async def _resolve_delta(delta: Delta) -> Delta:
287
288
  tasks = {}
288
289
  for state_name, state_delta in delta.items():
289
290
  for var_name, value in state_delta.items():
290
- if asyncio.iscoroutine(value):
291
+ if inspect.iscoroutine(value):
291
292
  tasks[state_name, var_name] = asyncio.create_task(
292
293
  value,
293
294
  name=f"reflex_resolve_delta|{state_name}|{var_name}|{time.time()}",
@@ -852,7 +853,7 @@ class BaseState(EvenMoreBasicBaseState):
852
853
  ComputedVarShadowsBaseVarsError: When a computed var shadows a base var.
853
854
  """
854
855
  for name, computed_var_ in cls._get_computed_vars():
855
- if name in cls.__annotations__:
856
+ if name in get_type_hints(cls):
856
857
  msg = f"The computed var name `{computed_var_._js_expr}` shadows a base var in {cls.__module__}.{cls.__name__}; use a different name instead"
857
858
  raise ComputedVarShadowsBaseVarsError(msg)
858
859
 
@@ -1554,6 +1555,8 @@ class BaseState(EvenMoreBasicBaseState):
1554
1555
  RuntimeError: If redis is not used in this backend process.
1555
1556
  StateMismatchError: If the state instance is not of the expected type.
1556
1557
  """
1558
+ from reflex.istate.manager.redis import StateManagerRedis
1559
+
1557
1560
  # Then get the target state and all its substates.
1558
1561
  state_manager = get_state_manager()
1559
1562
  if not isinstance(state_manager, StateManagerRedis):
@@ -1733,7 +1736,7 @@ class BaseState(EvenMoreBasicBaseState):
1733
1736
  except TypeError:
1734
1737
  pass
1735
1738
 
1736
- coroutines = [e for e in events if asyncio.iscoroutine(e)]
1739
+ coroutines = [e for e in events if inspect.iscoroutine(e)]
1737
1740
 
1738
1741
  for coroutine in coroutines:
1739
1742
  coroutine_name = coroutine.__qualname__
@@ -1878,6 +1881,12 @@ class BaseState(EvenMoreBasicBaseState):
1878
1881
  hinted_args is tuple or hinted_args is tuple
1879
1882
  ):
1880
1883
  payload[arg] = tuple(value)
1884
+ elif isinstance(hinted_args, type) and issubclass(hinted_args, Enum):
1885
+ try:
1886
+ payload[arg] = hinted_args(value)
1887
+ except ValueError:
1888
+ msg = f"Received an invalid enum value ({value}) for {arg} of type {hinted_args}"
1889
+ raise ValueError(msg) from None
1881
1890
  elif (
1882
1891
  isinstance(value, str)
1883
1892
  and (deserializer := _deserializers.get(hinted_args)) is not None
@@ -1895,7 +1904,7 @@ class BaseState(EvenMoreBasicBaseState):
1895
1904
  # Wrap the function in a try/except block.
1896
1905
  try:
1897
1906
  # Handle async functions.
1898
- if asyncio.iscoroutinefunction(fn.func):
1907
+ if inspect.iscoroutinefunction(fn.func):
1899
1908
  events = await fn(**payload)
1900
1909
 
1901
1910
  # Handle regular functions.
@@ -2738,11 +2747,7 @@ def reload_state_module(
2738
2747
  state.get_class_substate.cache_clear()
2739
2748
 
2740
2749
 
2741
- from reflex.istate.manager import LockExpiredError as LockExpiredError # noqa: E402
2742
2750
  from reflex.istate.manager import StateManager as StateManager # noqa: E402
2743
- from reflex.istate.manager import StateManagerDisk as StateManagerDisk # noqa: E402
2744
- from reflex.istate.manager import StateManagerMemory as StateManagerMemory # noqa: E402
2745
- from reflex.istate.manager import StateManagerRedis as StateManagerRedis # noqa: E402
2746
2751
  from reflex.istate.manager import get_state_manager as get_state_manager # noqa: E402
2747
2752
  from reflex.istate.manager import ( # noqa: E402
2748
2753
  reset_disk_state_manager as reset_disk_state_manager,
reflex/testing.py CHANGED
@@ -38,14 +38,10 @@ import reflex.utils.processes
38
38
  from reflex.components.component import CustomComponent
39
39
  from reflex.config import get_config
40
40
  from reflex.environment import environment
41
- from reflex.state import (
42
- BaseState,
43
- StateManager,
44
- StateManagerDisk,
45
- StateManagerMemory,
46
- StateManagerRedis,
47
- reload_state_module,
48
- )
41
+ from reflex.istate.manager.disk import StateManagerDisk
42
+ from reflex.istate.manager.memory import StateManagerMemory
43
+ from reflex.istate.manager.redis import StateManagerRedis
44
+ from reflex.state import BaseState, StateManager, reload_state_module
49
45
  from reflex.utils import console, js_runtimes
50
46
  from reflex.utils.export import export
51
47
  from reflex.utils.token_manager import TokenManager
@@ -26,11 +26,40 @@ def redirect_script() -> str:
26
26
  const thisUrl = new URL(window.location.href);
27
27
  const params = new URLSearchParams(thisUrl.search)
28
28
 
29
+ function sameHostnameDifferentPort(one, two) {{
30
+ const hostnameOne = one.hostname;
31
+ const hostnameTwo = two.hostname;
32
+ const partsOne = hostnameOne.split(".");
33
+ const partsTwo = hostnameTwo.split(".");
34
+ if (partsOne.length !== partsTwo.length) {{ return false; }}
35
+ for (let i = 1; i < partsOne.length; i++) {{
36
+ if (partsOne[i] !== partsTwo[i]) {{ return false; }}
37
+ }}
38
+ const uniqueNameOne = partsOne[0];
39
+ const uniqueNameTwo = partsTwo[0];
40
+ const uniqueNamePartsOne = uniqueNameOne.split("-");
41
+ const uniqueNamePartsTwo = uniqueNameTwo.split("-");
42
+ if (uniqueNamePartsOne.length !== uniqueNamePartsTwo.length) {{ return false; }}
43
+ for (let i = 0; i < uniqueNamePartsOne.length - 1; i++) {{
44
+ if (uniqueNamePartsOne[i] !== uniqueNamePartsTwo[i]) {{ return false; }}
45
+ }}
46
+ return true;
47
+ }}
48
+
29
49
  function doRedirect(url) {{
30
50
  if (!window.sessionStorage.getItem("authenticated_github_codespaces")) {{
31
51
  const a = document.createElement("a");
32
52
  if (params.has("redirect_to")) {{
33
- a.href = params.get("redirect_to")
53
+ const redirect_to = new URL(params.get("redirect_to"));
54
+ if (!sameHostnameDifferentPort(thisUrl, redirect_to)) {{
55
+ console.warn("Reflex: Not redirecting to different hostname");
56
+ return;
57
+ }}
58
+ if (!redirect_to.hostname.endsWith(".app.github.dev")) {{
59
+ console.warn("Reflex: Not redirecting to non .app.github.dev hostname");
60
+ return;
61
+ }}
62
+ a.href = redirect_to.href;
34
63
  }} else if (!window.location.href.startsWith(url)) {{
35
64
  a.href = url + `?redirect_to=${{window.location.href}}`
36
65
  }} else {{
reflex/utils/compat.py CHANGED
@@ -1,6 +1,9 @@
1
1
  """Compatibility hacks and helpers."""
2
2
 
3
- from typing import TYPE_CHECKING
3
+ import sys
4
+ from collections.abc import Mapping
5
+ from importlib.util import find_spec
6
+ from typing import TYPE_CHECKING, Any
4
7
 
5
8
  if TYPE_CHECKING:
6
9
  from pydantic.fields import FieldInfo
@@ -30,6 +33,51 @@ async def windows_hot_reload_lifespan_hack():
30
33
  pass
31
34
 
32
35
 
36
+ def annotations_from_namespace(namespace: Mapping[str, Any]) -> dict[str, Any]:
37
+ """Get the annotations from a class namespace.
38
+
39
+ Args:
40
+ namespace: The class namespace.
41
+
42
+ Returns:
43
+ The (forward-ref) annotations from the class namespace.
44
+ """
45
+ if sys.version_info >= (3, 14) and "__annotations__" not in namespace:
46
+ from annotationlib import (
47
+ Format,
48
+ call_annotate_function,
49
+ get_annotate_from_class_namespace,
50
+ )
51
+
52
+ if annotate := get_annotate_from_class_namespace(namespace):
53
+ return call_annotate_function(annotate, format=Format.FORWARDREF)
54
+ return namespace.get("__annotations__", {})
55
+
56
+
57
+ if find_spec("pydantic") and find_spec("pydantic.v1"):
58
+ from pydantic.v1.main import ModelMetaclass
59
+
60
+ class ModelMetaclassLazyAnnotations(ModelMetaclass):
61
+ """Compatibility metaclass to resolve python3.14 style lazy annotations."""
62
+
63
+ def __new__(mcs, name: str, bases: tuple, namespace: dict, **kwargs):
64
+ """Resolve python3.14 style lazy annotations before passing off to pydantic v1.
65
+
66
+ Args:
67
+ name: The class name.
68
+ bases: The base classes.
69
+ namespace: The class namespace.
70
+ **kwargs: Additional keyword arguments.
71
+
72
+ Returns:
73
+ The created class.
74
+ """
75
+ namespace["__annotations__"] = annotations_from_namespace(namespace)
76
+ return super().__new__(mcs, name, bases, namespace, **kwargs)
77
+ else:
78
+ ModelMetaclassLazyAnnotations = type # type: ignore[assignment]
79
+
80
+
33
81
  def sqlmodel_field_has_primary_key(field_info: "FieldInfo") -> bool:
34
82
  """Determines if a field is a primary.
35
83
 
reflex/utils/misc.py CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  import asyncio
4
4
  import contextlib
5
+ import inspect
5
6
  import sys
6
7
  import threading
7
8
  from collections.abc import Callable
@@ -62,7 +63,7 @@ async def run_in_thread(func: Callable) -> Any:
62
63
  Returns:
63
64
  Any: The return value of the function.
64
65
  """
65
- if asyncio.coroutines.iscoroutinefunction(func):
66
+ if inspect.iscoroutinefunction(func):
66
67
  msg = "func must be a non-async function"
67
68
  raise ValueError(msg)
68
69
  return await asyncio.get_event_loop().run_in_executor(None, func)
@@ -1,6 +1,5 @@
1
1
  """PyLeak integration for monitoring event loop blocking and resource leaks in Reflex applications."""
2
2
 
3
- import asyncio
4
3
  import contextlib
5
4
  import functools
6
5
  import inspect
@@ -154,7 +153,7 @@ def monitor_loopblocks(func: Callable) -> Callable:
154
153
 
155
154
  return async_gen_wrapper
156
155
 
157
- if asyncio.iscoroutinefunction(func):
156
+ if inspect.iscoroutinefunction(func):
158
157
 
159
158
  @functools.wraps(func)
160
159
  async def async_wrapper(*args, **kwargs):
@@ -16,9 +16,6 @@ from types import ModuleType
16
16
  from typing import NamedTuple
17
17
 
18
18
  from packaging import version
19
- from redis import Redis as RedisSync
20
- from redis.asyncio import Redis
21
- from redis.exceptions import RedisError
22
19
 
23
20
  from reflex import constants, model
24
21
  from reflex.config import Config, get_config
@@ -28,6 +25,9 @@ from reflex.utils.decorator import once
28
25
  from reflex.utils.misc import get_module_path
29
26
 
30
27
  if typing.TYPE_CHECKING:
28
+ from redis import Redis as RedisSync
29
+ from redis.asyncio import Redis
30
+
31
31
  from reflex.app import App
32
32
 
33
33
 
@@ -369,6 +369,12 @@ def get_redis() -> Redis | None:
369
369
  Returns:
370
370
  The asynchronous redis client.
371
371
  """
372
+ try:
373
+ from redis.asyncio import Redis
374
+ from redis.exceptions import RedisError
375
+ except ImportError:
376
+ console.debug("Redis package not installed.")
377
+ return None
372
378
  if (redis_url := parse_redis_url()) is not None:
373
379
  return Redis.from_url(
374
380
  redis_url,
@@ -383,6 +389,12 @@ def get_redis_sync() -> RedisSync | None:
383
389
  Returns:
384
390
  The synchronous redis client.
385
391
  """
392
+ try:
393
+ from redis import Redis as RedisSync
394
+ from redis.exceptions import RedisError
395
+ except ImportError:
396
+ console.debug("Redis package not installed.")
397
+ return None
386
398
  if (redis_url := parse_redis_url()) is not None:
387
399
  return RedisSync.from_url(
388
400
  redis_url,
@@ -417,6 +429,8 @@ async def get_redis_status() -> dict[str, bool | None]:
417
429
  Returns:
418
430
  The status of the Redis connection.
419
431
  """
432
+ from redis.exceptions import RedisError
433
+
420
434
  try:
421
435
  status = True
422
436
  redis_client = get_redis()
reflex/utils/processes.py CHANGED
@@ -16,7 +16,6 @@ from pathlib import Path
16
16
  from typing import Any, Literal, overload
17
17
 
18
18
  import rich.markup
19
- from redis.exceptions import RedisError
20
19
  from rich.progress import Progress
21
20
 
22
21
  from reflex import constants
@@ -45,6 +44,9 @@ def get_num_workers() -> int:
45
44
  """
46
45
  if (redis_client := prerequisites.get_redis_sync()) is None:
47
46
  return 1
47
+
48
+ from redis.exceptions import RedisError
49
+
48
50
  try:
49
51
  redis_client.ping()
50
52
  except RedisError as re:
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))
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
@@ -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
 
@@ -442,6 +443,13 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None
442
443
 
443
444
  from reflex.model import Model
444
445
 
446
+ if find_spec("sqlmodel"):
447
+ from sqlmodel import SQLModel
448
+
449
+ sqlmodel_types = (Model, SQLModel)
450
+ else:
451
+ sqlmodel_types = (Model,)
452
+
445
453
  if isinstance(cls, type) and issubclass(cls, DeclarativeBase):
446
454
  insp = sqlalchemy.inspect(cls)
447
455
  if name in insp.columns:
@@ -485,7 +493,7 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None
485
493
  elif (
486
494
  isinstance(cls, type)
487
495
  and not is_generic_alias(cls)
488
- and issubclass(cls, Model)
496
+ and issubclass(cls, sqlmodel_types)
489
497
  ):
490
498
  # Check in the annotations directly (for sqlmodel.Relationship)
491
499
  hints = get_type_hints(cls) # pyright: ignore [reportArgumentType]
reflex/vars/base.py CHANGED
@@ -43,6 +43,7 @@ from reflex import constants
43
43
  from reflex.constants.compiler import Hooks
44
44
  from reflex.constants.state import FIELD_MARKER
45
45
  from reflex.utils import console, exceptions, imports, serializers, types
46
+ from reflex.utils.compat import annotations_from_namespace
46
47
  from reflex.utils.decorator import once
47
48
  from reflex.utils.exceptions import (
48
49
  ComputedVarSignatureError,
@@ -1526,6 +1527,82 @@ class LiteralVar(Var):
1526
1527
  def __post_init__(self):
1527
1528
  """Post-initialize the var."""
1528
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
+
1529
1606
  @property
1530
1607
  def _var_value(self) -> Any:
1531
1608
  msg = "LiteralVar subclasses must implement the _var_value property."
@@ -1687,30 +1764,30 @@ def figure_out_type(value: Any) -> types.GenericType:
1687
1764
  Returns:
1688
1765
  The type of the value.
1689
1766
  """
1690
- if isinstance(value, Var):
1691
- return value._var_type
1692
- type_ = type(value)
1693
- if has_args(type_):
1694
- return type_
1695
- if isinstance(value, list):
1696
- if not value:
1697
- return Sequence[NoReturn]
1698
- return Sequence[unionize(*(figure_out_type(v) for v in value))]
1699
- if isinstance(value, set):
1700
- return set[unionize(*(figure_out_type(v) for v in value))]
1701
- if isinstance(value, tuple):
1702
- if not value:
1703
- return tuple[NoReturn, ...]
1704
- if len(value) <= 5:
1705
- return tuple[tuple(figure_out_type(v) for v in value)]
1706
- return tuple[unionize(*(figure_out_type(v) for v in value)), ...]
1707
- if isinstance(value, Mapping):
1708
- if not value:
1709
- return Mapping[NoReturn, NoReturn]
1710
- return Mapping[
1711
- unionize(*(figure_out_type(k) for k in value)),
1712
- unionize(*(figure_out_type(v) for v in value.values())),
1713
- ]
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
+ ]
1714
1791
  return type(value)
1715
1792
 
1716
1793
 
@@ -2882,6 +2959,10 @@ class LiteralNoneVar(LiteralVar, NoneVar):
2882
2959
  """
2883
2960
  return "null"
2884
2961
 
2962
+ @classmethod
2963
+ def _get_all_var_data_without_creating_var(cls, value: None) -> VarData | None:
2964
+ return None
2965
+
2885
2966
  @classmethod
2886
2967
  def create(
2887
2968
  cls,
@@ -3478,7 +3559,7 @@ class BaseStateMeta(ABCMeta):
3478
3559
  inherited_fields: dict[str, Field] = {}
3479
3560
  own_fields: dict[str, Field] = {}
3480
3561
  resolved_annotations = types.resolve_annotations(
3481
- namespace.get("__annotations__", {}), namespace["__module__"]
3562
+ annotations_from_namespace(namespace), namespace["__module__"]
3482
3563
  )
3483
3564
 
3484
3565
  for base in bases[::-1]: