reflex 0.8.15a0__py3-none-any.whl → 0.8.15a1__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/__init__.py +11 -6
- reflex/__init__.pyi +9 -2
- reflex/base.py +8 -11
- reflex/components/field.py +3 -1
- reflex/components/markdown/markdown.py +101 -27
- reflex/constants/base.py +5 -0
- reflex/constants/installer.py +2 -2
- reflex/event.py +3 -0
- reflex/istate/manager/__init__.py +120 -0
- reflex/istate/manager/disk.py +210 -0
- reflex/istate/manager/memory.py +76 -0
- reflex/istate/{manager.py → manager/redis.py} +5 -372
- reflex/model.py +5 -1
- reflex/state.py +14 -9
- reflex/testing.py +4 -8
- reflex/utils/compat.py +49 -1
- reflex/utils/misc.py +2 -1
- reflex/utils/monitoring.py +1 -2
- reflex/utils/prerequisites.py +17 -3
- reflex/utils/processes.py +3 -1
- reflex/utils/redir.py +21 -37
- reflex/utils/templates.py +4 -4
- reflex/utils/types.py +1 -0
- reflex/vars/base.py +106 -25
- reflex/vars/color.py +28 -8
- reflex/vars/datetime.py +6 -2
- reflex/vars/dep_tracking.py +2 -2
- reflex/vars/number.py +26 -0
- reflex/vars/object.py +23 -6
- reflex/vars/sequence.py +32 -1
- {reflex-0.8.15a0.dist-info → reflex-0.8.15a1.dist-info}/METADATA +4 -3
- {reflex-0.8.15a0.dist-info → reflex-0.8.15a1.dist-info}/RECORD +35 -32
- {reflex-0.8.15a0.dist-info → reflex-0.8.15a1.dist-info}/WHEEL +0 -0
- {reflex-0.8.15a0.dist-info → reflex-0.8.15a1.dist-info}/entry_points.txt +0 -0
- {reflex-0.8.15a0.dist-info → reflex-0.8.15a1.dist-info}/licenses/LICENSE +0 -0
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
|
|
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)
|
reflex/utils/monitoring.py
CHANGED
|
@@ -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
|
|
156
|
+
if inspect.iscoroutinefunction(func):
|
|
158
157
|
|
|
159
158
|
@functools.wraps(func)
|
|
160
159
|
async def async_wrapper(*args, **kwargs):
|
reflex/utils/prerequisites.py
CHANGED
|
@@ -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
|
|
4
|
-
import webbrowser
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
from
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
423
|
-
description="
|
|
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.
|
|
428
|
-
description="
|
|
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
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
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
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
|
|
3562
|
+
annotations_from_namespace(namespace), namespace["__module__"]
|
|
3482
3563
|
)
|
|
3483
3564
|
|
|
3484
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
|
reflex/vars/datetime.py
CHANGED
|
@@ -174,10 +174,14 @@ def date_compare_operation(
|
|
|
174
174
|
class LiteralDatetimeVar(LiteralVar, DateTimeVar):
|
|
175
175
|
"""Base class for immutable datetime and date vars."""
|
|
176
176
|
|
|
177
|
-
_var_value:
|
|
177
|
+
_var_value: date = dataclasses.field(default=datetime.now())
|
|
178
178
|
|
|
179
179
|
@classmethod
|
|
180
|
-
def
|
|
180
|
+
def _get_all_var_data_without_creating_var(cls, value: date) -> VarData | None:
|
|
181
|
+
return None
|
|
182
|
+
|
|
183
|
+
@classmethod
|
|
184
|
+
def create(cls, value: date, _var_data: VarData | None = None):
|
|
181
185
|
"""Create a new instance of the class.
|
|
182
186
|
|
|
183
187
|
Args:
|
reflex/vars/dep_tracking.py
CHANGED
|
@@ -192,7 +192,7 @@ class DependencyTracker:
|
|
|
192
192
|
"""
|
|
193
193
|
from reflex.state import BaseState
|
|
194
194
|
|
|
195
|
-
if instruction.opname
|
|
195
|
+
if instruction.opname in ("LOAD_FAST", "LOAD_FAST_BORROW"):
|
|
196
196
|
msg = f"Dependency detection cannot identify get_state class from local var {instruction.argval}."
|
|
197
197
|
raise VarValueError(msg)
|
|
198
198
|
if isinstance(self.func, CodeType):
|
|
@@ -305,7 +305,7 @@ class DependencyTracker:
|
|
|
305
305
|
elif self.scan_status == ScanStatus.GETTING_VAR:
|
|
306
306
|
self.handle_getting_var(instruction)
|
|
307
307
|
elif (
|
|
308
|
-
instruction.opname in ("LOAD_FAST", "LOAD_DEREF")
|
|
308
|
+
instruction.opname in ("LOAD_FAST", "LOAD_DEREF", "LOAD_FAST_BORROW")
|
|
309
309
|
and instruction.argval in self.tracked_locals
|
|
310
310
|
):
|
|
311
311
|
# bytecode loaded the class instance to the top of stack, next load instruction
|
reflex/vars/number.py
CHANGED
|
@@ -973,6 +973,20 @@ class LiteralNumberVar(LiteralVar, NumberVar[NUMBER_T]):
|
|
|
973
973
|
"""
|
|
974
974
|
return hash((type(self).__name__, self._var_value))
|
|
975
975
|
|
|
976
|
+
@classmethod
|
|
977
|
+
def _get_all_var_data_without_creating_var(
|
|
978
|
+
cls, value: float | int | decimal.Decimal
|
|
979
|
+
) -> VarData | None:
|
|
980
|
+
"""Get all the var data without creating the var.
|
|
981
|
+
|
|
982
|
+
Args:
|
|
983
|
+
value: The value of the var.
|
|
984
|
+
|
|
985
|
+
Returns:
|
|
986
|
+
The var data.
|
|
987
|
+
"""
|
|
988
|
+
return None
|
|
989
|
+
|
|
976
990
|
@classmethod
|
|
977
991
|
def create(
|
|
978
992
|
cls, value: float | int | decimal.Decimal, _var_data: VarData | None = None
|
|
@@ -1027,6 +1041,18 @@ class LiteralBooleanVar(LiteralVar, BooleanVar):
|
|
|
1027
1041
|
"""
|
|
1028
1042
|
return hash((type(self).__name__, self._var_value))
|
|
1029
1043
|
|
|
1044
|
+
@classmethod
|
|
1045
|
+
def _get_all_var_data_without_creating_var(cls, value: bool) -> VarData | None:
|
|
1046
|
+
"""Get all the var data without creating the var.
|
|
1047
|
+
|
|
1048
|
+
Args:
|
|
1049
|
+
value: The value of the var.
|
|
1050
|
+
|
|
1051
|
+
Returns:
|
|
1052
|
+
The var data.
|
|
1053
|
+
"""
|
|
1054
|
+
return None
|
|
1055
|
+
|
|
1030
1056
|
@classmethod
|
|
1031
1057
|
def create(cls, value: bool, _var_data: VarData | None = None):
|
|
1032
1058
|
"""Create the boolean var.
|
reflex/vars/object.py
CHANGED
|
@@ -40,7 +40,7 @@ from .base import (
|
|
|
40
40
|
var_operation_return,
|
|
41
41
|
)
|
|
42
42
|
from .number import BooleanVar, NumberVar, raise_unsupported_operand_types
|
|
43
|
-
from .sequence import ArrayVar, StringVar
|
|
43
|
+
from .sequence import ArrayVar, LiteralArrayVar, StringVar
|
|
44
44
|
|
|
45
45
|
OBJECT_TYPE = TypeVar("OBJECT_TYPE", covariant=True)
|
|
46
46
|
|
|
@@ -437,6 +437,24 @@ class LiteralObjectVar(CachedVarOperation, ObjectVar[OBJECT_TYPE], LiteralVar):
|
|
|
437
437
|
"""
|
|
438
438
|
return hash((type(self).__name__, self._js_expr))
|
|
439
439
|
|
|
440
|
+
@classmethod
|
|
441
|
+
def _get_all_var_data_without_creating_var(
|
|
442
|
+
cls,
|
|
443
|
+
value: Mapping,
|
|
444
|
+
) -> VarData | None:
|
|
445
|
+
"""Get all the var data without creating a var.
|
|
446
|
+
|
|
447
|
+
Args:
|
|
448
|
+
value: The value to get the var data from.
|
|
449
|
+
|
|
450
|
+
Returns:
|
|
451
|
+
The var data.
|
|
452
|
+
"""
|
|
453
|
+
return VarData.merge(
|
|
454
|
+
LiteralArrayVar._get_all_var_data_without_creating_var(value),
|
|
455
|
+
LiteralArrayVar._get_all_var_data_without_creating_var(value.values()),
|
|
456
|
+
)
|
|
457
|
+
|
|
440
458
|
@cached_property_no_lock
|
|
441
459
|
def _cached_get_all_var_data(self) -> VarData | None:
|
|
442
460
|
"""Get all the var data.
|
|
@@ -445,11 +463,10 @@ class LiteralObjectVar(CachedVarOperation, ObjectVar[OBJECT_TYPE], LiteralVar):
|
|
|
445
463
|
The var data.
|
|
446
464
|
"""
|
|
447
465
|
return VarData.merge(
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
],
|
|
466
|
+
LiteralArrayVar._get_all_var_data_without_creating_var(self._var_value),
|
|
467
|
+
LiteralArrayVar._get_all_var_data_without_creating_var(
|
|
468
|
+
self._var_value.values()
|
|
469
|
+
),
|
|
453
470
|
self._var_data,
|
|
454
471
|
)
|
|
455
472
|
|
reflex/vars/sequence.py
CHANGED
|
@@ -495,6 +495,23 @@ class LiteralArrayVar(CachedVarOperation, LiteralVar, ArrayVar[ARRAY_VAR_TYPE]):
|
|
|
495
495
|
+ "]"
|
|
496
496
|
)
|
|
497
497
|
|
|
498
|
+
@classmethod
|
|
499
|
+
def _get_all_var_data_without_creating_var(cls, value: Iterable) -> VarData | None:
|
|
500
|
+
"""Get all the VarData associated with the Var without creating a Var.
|
|
501
|
+
|
|
502
|
+
Args:
|
|
503
|
+
value: The value to get the VarData for.
|
|
504
|
+
|
|
505
|
+
Returns:
|
|
506
|
+
The VarData associated with the Var.
|
|
507
|
+
"""
|
|
508
|
+
return VarData.merge(
|
|
509
|
+
*[
|
|
510
|
+
LiteralVar._get_all_var_data_without_creating_var_dispatch(element)
|
|
511
|
+
for element in value
|
|
512
|
+
]
|
|
513
|
+
)
|
|
514
|
+
|
|
498
515
|
@cached_property_no_lock
|
|
499
516
|
def _cached_get_all_var_data(self) -> VarData | None:
|
|
500
517
|
"""Get all the VarData associated with the Var.
|
|
@@ -504,7 +521,7 @@ class LiteralArrayVar(CachedVarOperation, LiteralVar, ArrayVar[ARRAY_VAR_TYPE]):
|
|
|
504
521
|
"""
|
|
505
522
|
return VarData.merge(
|
|
506
523
|
*[
|
|
507
|
-
LiteralVar.
|
|
524
|
+
LiteralVar._get_all_var_data_without_creating_var_dispatch(element)
|
|
508
525
|
for element in self._var_value
|
|
509
526
|
],
|
|
510
527
|
self._var_data,
|
|
@@ -1147,6 +1164,20 @@ class LiteralStringVar(LiteralVar, StringVar[str]):
|
|
|
1147
1164
|
|
|
1148
1165
|
_var_value: str = dataclasses.field(default="")
|
|
1149
1166
|
|
|
1167
|
+
@classmethod
|
|
1168
|
+
def _get_all_var_data_without_creating_var(cls, value: str) -> VarData | None:
|
|
1169
|
+
"""Get all the VarData associated with the Var without creating a Var.
|
|
1170
|
+
|
|
1171
|
+
Args:
|
|
1172
|
+
value: The value to get the VarData for.
|
|
1173
|
+
|
|
1174
|
+
Returns:
|
|
1175
|
+
The VarData associated with the Var.
|
|
1176
|
+
"""
|
|
1177
|
+
if REFLEX_VAR_OPENING_TAG not in value:
|
|
1178
|
+
return None
|
|
1179
|
+
return cls.create(value)._get_all_var_data()
|
|
1180
|
+
|
|
1150
1181
|
@classmethod
|
|
1151
1182
|
def create(
|
|
1152
1183
|
cls,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: reflex
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.15a1
|
|
4
4
|
Summary: Web apps in pure Python.
|
|
5
5
|
Project-URL: homepage, https://reflex.dev
|
|
6
6
|
Project-URL: repository, https://github.com/reflex-dev/reflex
|
|
@@ -18,10 +18,11 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
22
|
Requires-Python: <4.0,>=3.10
|
|
22
23
|
Requires-Dist: alembic<2.0,>=1.15.2
|
|
23
24
|
Requires-Dist: click>=8.2
|
|
24
|
-
Requires-Dist: granian[reload]>=2.
|
|
25
|
+
Requires-Dist: granian[reload]>=2.5.5
|
|
25
26
|
Requires-Dist: httpx<1.0,>=0.23.3
|
|
26
27
|
Requires-Dist: packaging<26,>=24.2
|
|
27
28
|
Requires-Dist: platformdirs<5.0,>=4.3.7
|
|
@@ -32,7 +33,7 @@ Requires-Dist: python-socketio<6.0,>=5.12.0
|
|
|
32
33
|
Requires-Dist: redis<7.0,>=5.2.1
|
|
33
34
|
Requires-Dist: reflex-hosting-cli>=0.1.55
|
|
34
35
|
Requires-Dist: rich<15,>=13
|
|
35
|
-
Requires-Dist: sqlmodel<0.1,>=0.0.
|
|
36
|
+
Requires-Dist: sqlmodel<0.1,>=0.0.27
|
|
36
37
|
Requires-Dist: starlette>=0.47.0
|
|
37
38
|
Requires-Dist: typing-extensions>=4.13.0
|
|
38
39
|
Requires-Dist: wrapt<2.0,>=1.17.0
|