reflex 0.8.3a3__py3-none-any.whl → 0.8.4__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.

@@ -21,6 +21,7 @@ export function ThemeProvider({ children, defaultTheme = "system" }) {
21
21
  const [systemTheme, setSystemTheme] = useState(
22
22
  defaultTheme !== "system" ? defaultTheme : "light",
23
23
  );
24
+ const [isInitialized, setIsInitialized] = useState(false);
24
25
 
25
26
  const firstRender = useRef(true);
26
27
 
@@ -36,6 +37,7 @@ export function ThemeProvider({ children, defaultTheme = "system" }) {
36
37
  if (lastCompiledTheme !== defaultColorMode) {
37
38
  // on app startup, make sure the application color mode is persisted correctly.
38
39
  localStorage.setItem("last_compiled_theme", defaultColorMode);
40
+ setIsInitialized(true);
39
41
  return;
40
42
  }
41
43
  }
@@ -43,6 +45,7 @@ export function ThemeProvider({ children, defaultTheme = "system" }) {
43
45
  // Load saved theme from localStorage
44
46
  const savedTheme = localStorage.getItem("theme") || defaultTheme;
45
47
  setTheme(savedTheme);
48
+ setIsInitialized(true);
46
49
  });
47
50
 
48
51
  const resolvedTheme = useMemo(
@@ -69,16 +72,20 @@ export function ThemeProvider({ children, defaultTheme = "system" }) {
69
72
  });
70
73
 
71
74
  // Save theme to localStorage whenever it changes
75
+ // Skip saving only if theme key already exists and we haven't initialized yet
72
76
  useEffect(() => {
77
+ const existingTheme = localStorage.getItem("theme");
78
+ if (!isInitialized && existingTheme !== null) return;
73
79
  localStorage.setItem("theme", theme);
74
80
  }, [theme]);
75
81
 
76
82
  useEffect(() => {
83
+ if (!isInitialized) return;
77
84
  const root = window.document.documentElement;
78
85
  root.classList.remove("light", "dark");
79
86
  root.classList.add(resolvedTheme);
80
87
  root.style.colorScheme = resolvedTheme;
81
- }, [resolvedTheme]);
88
+ }, [resolvedTheme, isInitialized]);
82
89
 
83
90
  return createElement(
84
91
  ThemeContext.Provider,
@@ -791,9 +791,9 @@ export const hydrateClientStorage = (client_storage) => {
791
791
  for (const state_key in client_storage.cookies) {
792
792
  const cookie_options = client_storage.cookies[state_key];
793
793
  const cookie_name = cookie_options.name || state_key;
794
- const cookie_value = cookies.get(cookie_name);
794
+ const cookie_value = cookies.get(cookie_name, { doNotParse: true });
795
795
  if (cookie_value !== undefined) {
796
- client_storage_values[state_key] = cookies.get(cookie_name);
796
+ client_storage_values[state_key] = cookie_value;
797
797
  }
798
798
  }
799
799
  }
reflex/app.py CHANGED
@@ -28,7 +28,6 @@ from timeit import default_timer as timer
28
28
  from types import SimpleNamespace
29
29
  from typing import TYPE_CHECKING, Any, BinaryIO, ParamSpec, get_args, get_type_hints
30
30
 
31
- from fastapi import FastAPI
32
31
  from rich.progress import MofNCompleteColumn, Progress, TimeElapsedColumn
33
32
  from socketio import ASGIApp as EngineIOApp
34
33
  from socketio import AsyncNamespace, AsyncServer
@@ -441,9 +440,6 @@ class App(MiddlewareMixin, LifespanMixin):
441
440
  | None
442
441
  ) = None
443
442
 
444
- # FastAPI app for compatibility with FastAPI.
445
- _cached_fastapi_app: FastAPI | None = None
446
-
447
443
  @property
448
444
  def event_namespace(self) -> EventNamespace | None:
449
445
  """Get the event namespace.
@@ -598,32 +594,22 @@ class App(MiddlewareMixin, LifespanMixin):
598
594
  Returns:
599
595
  The backend api.
600
596
  """
597
+ from reflex.vars.base import GLOBAL_CACHE
598
+
601
599
  # For py3.9 compatibility when redis is used, we MUST add any decorator pages
602
600
  # before compiling the app in a thread to avoid event loop error (REF-2172).
603
601
  self._apply_decorated_pages()
604
602
 
605
- compile_future = concurrent.futures.ThreadPoolExecutor(max_workers=1).submit(
606
- self._compile, prerender_routes=is_prod_mode()
607
- )
603
+ self._compile(prerender_routes=is_prod_mode())
608
604
 
609
- def callback(f: concurrent.futures.Future):
610
- # Force background compile errors to print eagerly
611
- return f.result()
612
-
613
- compile_future.add_done_callback(callback)
614
- # Wait for the compile to finish to ensure all optional endpoints are mounted.
615
- compile_future.result()
605
+ # We will not be making more vars, so we can clear the global cache to free up memory.
606
+ GLOBAL_CACHE.clear()
616
607
 
617
608
  if not self._api:
618
609
  msg = "The app has not been initialized."
619
610
  raise ValueError(msg)
620
611
 
621
- if self._cached_fastapi_app is not None:
622
- asgi_app = self._cached_fastapi_app
623
- asgi_app.mount("", self._api)
624
- App._add_cors(asgi_app)
625
- else:
626
- asgi_app = self._api
612
+ asgi_app = self._api
627
613
 
628
614
  if self.api_transformer is not None:
629
615
  api_transformers: Sequence[Starlette | Callable[[ASGIApp], ASGIApp]] = (
reflex/compiler/utils.py CHANGED
@@ -359,6 +359,8 @@ def create_document_root(
359
359
  Returns:
360
360
  The document root.
361
361
  """
362
+ from reflex.utils.misc import preload_color_theme
363
+
362
364
  existing_meta_types = set()
363
365
 
364
366
  for component in head_components or []:
@@ -385,7 +387,11 @@ def create_document_root(
385
387
  Meta.create(name="viewport", content="width=device-width, initial-scale=1")
386
388
  )
387
389
 
390
+ # Add theme preload script as the very first component to prevent FOUC
391
+ theme_preload_components = [preload_color_theme()]
392
+
388
393
  head_components = [
394
+ *theme_preload_components,
389
395
  *(head_components or []),
390
396
  *maybe_head_components,
391
397
  *always_head_components,
@@ -14,7 +14,7 @@ class Bun(SimpleNamespace):
14
14
  """Bun constants."""
15
15
 
16
16
  # The Bun version.
17
- VERSION = "1.2.18"
17
+ VERSION = "1.2.19"
18
18
 
19
19
  # Min Bun Version
20
20
  MIN_VERSION = "1.2.17"
@@ -75,7 +75,7 @@ fetch-retries=0
75
75
 
76
76
 
77
77
  def _determine_react_router_version() -> str:
78
- default_version = "7.6.3"
78
+ default_version = "7.7.0"
79
79
  if (version := os.getenv("REACT_ROUTER_VERSION")) and version != default_version:
80
80
  from reflex.utils import console
81
81
 
@@ -143,11 +143,11 @@ class PackageJson(SimpleNamespace):
143
143
  "postcss-import": "16.1.1",
144
144
  "@react-router/dev": _react_router_version,
145
145
  "@react-router/fs-routes": _react_router_version,
146
- "rolldown-vite": "7.0.9",
146
+ "rolldown-vite": "7.0.11",
147
147
  }
148
148
  OVERRIDES = {
149
149
  # This should always match the `react` version in DEPENDENCIES for recharts compatibility.
150
150
  "react-is": _react_version,
151
151
  "cookie": "1.0.2",
152
- "rollup": "4.44.2",
152
+ "rollup": "4.45.1",
153
153
  }
@@ -12,7 +12,6 @@ from pathlib import Path
12
12
  from typing import Any
13
13
 
14
14
  import click
15
- import httpx
16
15
 
17
16
  from reflex import constants
18
17
  from reflex.constants import CustomComponents
@@ -467,6 +466,7 @@ def _collect_details_for_gallery():
467
466
  Raises:
468
467
  Exit: If pyproject.toml file is ill-formed or the request to the backend services fails.
469
468
  """
469
+ import httpx
470
470
  from reflex_cli.utils import hosting
471
471
 
472
472
  console.rule("[bold]Authentication with Reflex Services")
reflex/istate/data.py CHANGED
@@ -3,7 +3,7 @@
3
3
  import dataclasses
4
4
  from collections.abc import Mapping
5
5
  from typing import TYPE_CHECKING
6
- from urllib.parse import _NetlocResultMixinStr, urlsplit
6
+ from urllib.parse import _NetlocResultMixinStr, parse_qsl, urlsplit
7
7
 
8
8
  from reflex import constants
9
9
  from reflex.utils import console, format
@@ -102,8 +102,10 @@ class ReflexURL(str, _NetlocResultMixinStr):
102
102
  if TYPE_CHECKING:
103
103
  scheme: str
104
104
  netloc: str
105
+ origin: str
105
106
  path: str
106
107
  query: str
108
+ query_parameters: Mapping[str, str]
107
109
  fragment: str
108
110
 
109
111
  def __new__(cls, url: str):
@@ -121,6 +123,10 @@ class ReflexURL(str, _NetlocResultMixinStr):
121
123
  object.__setattr__(obj, "netloc", netloc)
122
124
  object.__setattr__(obj, "path", path)
123
125
  object.__setattr__(obj, "query", query)
126
+ object.__setattr__(obj, "origin", f"{scheme}://{netloc}")
127
+ object.__setattr__(
128
+ obj, "query_parameters", _FrozenDictStrStr(**dict(parse_qsl(query)))
129
+ )
124
130
  object.__setattr__(obj, "fragment", fragment)
125
131
  return obj
126
132
 
reflex/utils/console.py CHANGED
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import contextlib
6
+ import datetime
6
7
  import inspect
7
8
  import os
8
9
  import shutil
@@ -136,7 +137,7 @@ def print_to_log_file(msg: str, *, dedupe: bool = False, **kwargs):
136
137
  dedupe: If True, suppress multiple console logs of print message.
137
138
  kwargs: Keyword arguments to pass to the print function.
138
139
  """
139
- log_file_console().print(msg, **kwargs)
140
+ log_file_console().print(f"[{datetime.datetime.now()}] {msg}", **kwargs)
140
141
 
141
142
 
142
143
  def debug(msg: str, *, dedupe: bool = False, **kwargs):
reflex/utils/decorator.py CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  import functools
4
4
  from collections.abc import Callable
5
- from typing import ParamSpec, TypeVar
5
+ from pathlib import Path
6
+ from typing import ParamSpec, TypeVar, cast
6
7
 
7
8
  T = TypeVar("T")
8
9
 
@@ -70,3 +71,77 @@ def debug(f: Callable[P, T]) -> Callable[P, T]:
70
71
  return result
71
72
 
72
73
  return wrapper
74
+
75
+
76
+ def _write_cached_procedure_file(payload: str, cache_file: Path, value: object):
77
+ import pickle
78
+
79
+ cache_file.write_bytes(pickle.dumps((payload, value)))
80
+
81
+
82
+ def _read_cached_procedure_file(cache_file: Path) -> tuple[str | None, object]:
83
+ import pickle
84
+
85
+ if cache_file.exists():
86
+ with cache_file.open("rb") as f:
87
+ return pickle.loads(f.read())
88
+
89
+ return None, None
90
+
91
+
92
+ P = ParamSpec("P")
93
+ Picklable = TypeVar("Picklable")
94
+
95
+
96
+ def cached_procedure(
97
+ cache_file_path: Callable[[], Path],
98
+ payload_fn: Callable[P, str],
99
+ ) -> Callable[[Callable[P, Picklable]], Callable[P, Picklable]]:
100
+ """Decorator to cache the result of a function based on its arguments.
101
+
102
+ Args:
103
+ cache_file_path: Function that computes the cache file path.
104
+ payload_fn: Function that computes cache payload from function args.
105
+
106
+ Returns:
107
+ The decorated function.
108
+ """
109
+
110
+ def _inner_decorator(func: Callable[P, Picklable]) -> Callable[P, Picklable]:
111
+ def _inner(*args: P.args, **kwargs: P.kwargs) -> Picklable:
112
+ _cache_file = cache_file_path()
113
+
114
+ payload, value = _read_cached_procedure_file(_cache_file)
115
+ new_payload = payload_fn(*args, **kwargs)
116
+
117
+ if payload != new_payload:
118
+ new_value = func(*args, **kwargs)
119
+ _write_cached_procedure_file(new_payload, _cache_file, new_value)
120
+ return new_value
121
+
122
+ from reflex.utils import console
123
+
124
+ console.debug(
125
+ f"Using cached value for {func.__name__} with payload: {new_payload}"
126
+ )
127
+ return cast("Picklable", value)
128
+
129
+ return _inner
130
+
131
+ return _inner_decorator
132
+
133
+
134
+ def cache_result_in_disk(
135
+ cache_file_path: Callable[[], Path],
136
+ ) -> Callable[[Callable[[], Picklable]], Callable[[], Picklable]]:
137
+ """Decorator to cache the result of a function on disk.
138
+
139
+ Args:
140
+ cache_file_path: Function that computes the cache file path.
141
+
142
+ Returns:
143
+ The decorated function.
144
+ """
145
+ return cached_procedure(
146
+ cache_file_path=cache_file_path, payload_fn=lambda: "constant"
147
+ )
reflex/utils/misc.py CHANGED
@@ -90,3 +90,43 @@ def with_cwd_in_syspath():
90
90
  yield
91
91
  finally:
92
92
  sys.path[:] = orig_sys_path
93
+
94
+
95
+ def preload_color_theme():
96
+ """Create a script component that preloads the color theme to prevent FOUC.
97
+
98
+ This script runs immediately in the document head before React hydration,
99
+ reading the saved theme from localStorage and applying the correct CSS classes
100
+ to prevent flash of unstyled content.
101
+
102
+ Returns:
103
+ Script: A script component to add to App.head_components
104
+ """
105
+ from reflex.components.el.elements.scripts import Script
106
+
107
+ # Create direct inline script content (like next-themes dangerouslySetInnerHTML)
108
+ script_content = """
109
+ // Only run in browser environment, not during SSR
110
+ if (typeof document !== 'undefined') {
111
+ try {
112
+ const theme = localStorage.getItem("theme") || "system";
113
+ const systemPreference = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
114
+ const resolvedTheme = theme === "system" ? systemPreference : theme;
115
+
116
+ // Apply theme immediately - blocks until complete
117
+ // Use classList to avoid overwriting other classes
118
+ document.documentElement.classList.remove("light", "dark");
119
+ document.documentElement.classList.add(resolvedTheme);
120
+ document.documentElement.style.colorScheme = resolvedTheme;
121
+
122
+ } catch (e) {
123
+ // Fallback to system preference on any error (resolve "system" to actual theme)
124
+ const fallbackTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
125
+ document.documentElement.classList.remove("light", "dark");
126
+ document.documentElement.classList.add(fallbackTheme);
127
+ document.documentElement.style.colorScheme = fallbackTheme;
128
+ }
129
+ }
130
+ """
131
+
132
+ return Script.create(script_content)
reflex/utils/net.py CHANGED
@@ -5,8 +5,6 @@ import time
5
5
  from collections.abc import Callable
6
6
  from typing import ParamSpec, TypeVar
7
7
 
8
- import httpx
9
-
10
8
  from reflex.utils.decorator import once
11
9
  from reflex.utils.types import Unset
12
10
 
@@ -42,6 +40,8 @@ def _wrap_https_func(
42
40
 
43
41
  @functools.wraps(func)
44
42
  def wrapper(*args: _P.args, **kwargs: _P.kwargs) -> _T:
43
+ import httpx
44
+
45
45
  url = args[0]
46
46
  console.debug(f"Sending HTTPS request to {args[0]}")
47
47
  initial_time = time.time()
@@ -94,6 +94,8 @@ def _is_ipv4_supported() -> bool:
94
94
  Returns:
95
95
  True if the system supports IPv4, False otherwise.
96
96
  """
97
+ import httpx
98
+
97
99
  try:
98
100
  httpx.head("http://1.1.1.1", timeout=3)
99
101
  except httpx.RequestError:
@@ -108,6 +110,8 @@ def _is_ipv6_supported() -> bool:
108
110
  Returns:
109
111
  True if the system supports IPv6, False otherwise.
110
112
  """
113
+ import httpx
114
+
111
115
  try:
112
116
  httpx.head("http://[2606:4700:4700::1111]", timeout=3)
113
117
  except httpx.RequestError:
@@ -139,12 +143,13 @@ def _httpx_local_address_kwarg() -> str:
139
143
 
140
144
 
141
145
  @once
142
- def _httpx_client() -> httpx.Client:
146
+ def _httpx_client():
143
147
  """Get an HTTPX client.
144
148
 
145
149
  Returns:
146
150
  An HTTPX client.
147
151
  """
152
+ import httpx
148
153
  from httpx._utils import get_environment_proxies
149
154
 
150
155
  return httpx.Client(
@@ -19,7 +19,7 @@ import sys
19
19
  import tempfile
20
20
  import typing
21
21
  import zipfile
22
- from collections.abc import Callable, Sequence
22
+ from collections.abc import Sequence
23
23
  from datetime import datetime
24
24
  from pathlib import Path
25
25
  from types import ModuleType
@@ -27,7 +27,6 @@ from typing import NamedTuple
27
27
  from urllib.parse import urlparse
28
28
 
29
29
  import click
30
- import httpx
31
30
  from alembic.util.exc import CommandError
32
31
  from packaging import version
33
32
  from redis import Redis as RedisSync
@@ -39,6 +38,7 @@ from reflex.compiler import templates
39
38
  from reflex.config import Config, get_config
40
39
  from reflex.environment import environment
41
40
  from reflex.utils import console, net, path_ops, processes, redir
41
+ from reflex.utils.decorator import cached_procedure
42
42
  from reflex.utils.exceptions import SystemPackageMissingError
43
43
  from reflex.utils.misc import get_module_path
44
44
  from reflex.utils.registry import get_npm_registry
@@ -1170,6 +1170,8 @@ def download_and_run(url: str, *args, show_status: bool = False, **env):
1170
1170
  Raises:
1171
1171
  Exit: If the script fails to download.
1172
1172
  """
1173
+ import httpx
1174
+
1173
1175
  # Download the script
1174
1176
  console.debug(f"Downloading {url}")
1175
1177
  try:
@@ -1177,7 +1179,7 @@ def download_and_run(url: str, *args, show_status: bool = False, **env):
1177
1179
  response.raise_for_status()
1178
1180
  except httpx.HTTPError as e:
1179
1181
  console.error(
1180
- f"Failed to download bun install script. You can install or update bun manually from https://bun.sh \n{e}"
1182
+ f"Failed to download bun install script. You can install or update bun manually from https://bun.com \n{e}"
1181
1183
  )
1182
1184
  raise click.exceptions.Exit(1) from None
1183
1185
 
@@ -1251,71 +1253,9 @@ def install_bun():
1251
1253
  )
1252
1254
 
1253
1255
 
1254
- def _write_cached_procedure_file(payload: str, cache_file: str | Path):
1255
- cache_file = Path(cache_file)
1256
- cache_file.write_text(payload)
1257
-
1258
-
1259
- def _read_cached_procedure_file(cache_file: str | Path) -> str | None:
1260
- cache_file = Path(cache_file)
1261
- if cache_file.exists():
1262
- return cache_file.read_text()
1263
- return None
1264
-
1265
-
1266
- def _clear_cached_procedure_file(cache_file: str | Path):
1267
- cache_file = Path(cache_file)
1268
- if cache_file.exists():
1269
- cache_file.unlink()
1270
-
1271
-
1272
- def cached_procedure(
1273
- cache_file: str | None,
1274
- payload_fn: Callable[..., str],
1275
- cache_file_fn: Callable[[], str] | None = None,
1276
- ):
1277
- """Decorator to cache the runs of a procedure on disk. Procedures should not have
1278
- a return value.
1279
-
1280
- Args:
1281
- cache_file: The file to store the cache payload in.
1282
- payload_fn: Function that computes cache payload from function args.
1283
- cache_file_fn: Function that computes the cache file name at runtime.
1284
-
1285
- Returns:
1286
- The decorated function.
1287
-
1288
- Raises:
1289
- ValueError: If both cache_file and cache_file_fn are provided.
1290
- """
1291
- if cache_file and cache_file_fn is not None:
1292
- msg = "cache_file and cache_file_fn cannot both be provided."
1293
- raise ValueError(msg)
1294
-
1295
- def _inner_decorator(func: Callable):
1296
- def _inner(*args, **kwargs):
1297
- _cache_file = cache_file_fn() if cache_file_fn is not None else cache_file
1298
- if not _cache_file:
1299
- msg = "Unknown cache file, cannot cache result."
1300
- raise ValueError(msg)
1301
- payload = _read_cached_procedure_file(_cache_file)
1302
- new_payload = payload_fn(*args, **kwargs)
1303
- if payload != new_payload:
1304
- _clear_cached_procedure_file(_cache_file)
1305
- func(*args, **kwargs)
1306
- _write_cached_procedure_file(new_payload, _cache_file)
1307
-
1308
- return _inner
1309
-
1310
- return _inner_decorator
1311
-
1312
-
1313
1256
  @cached_procedure(
1314
- cache_file_fn=lambda: str(
1315
- get_web_dir() / "reflex.install_frontend_packages.cached"
1316
- ),
1317
- payload_fn=lambda p, c: f"{sorted(p)!r},{c.json()}",
1318
- cache_file=None,
1257
+ cache_file_path=lambda: get_web_dir() / "reflex.install_frontend_packages.cached",
1258
+ payload_fn=lambda packages, config: f"{sorted(packages)!r},{config.json()}",
1319
1259
  )
1320
1260
  def install_frontend_packages(packages: set[str], config: Config):
1321
1261
  """Installs the base and custom frontend packages.
@@ -1725,6 +1665,8 @@ def create_config_init_app_from_remote_template(app_name: str, template_url: str
1725
1665
  Exit: If any download, file operations fail or unexpected zip file format.
1726
1666
 
1727
1667
  """
1668
+ import httpx
1669
+
1728
1670
  # Create a temp directory for the zip download.
1729
1671
  try:
1730
1672
  temp_dir = tempfile.mkdtemp()
reflex/utils/processes.py CHANGED
@@ -78,19 +78,41 @@ def _can_bind_at_port(
78
78
  return True
79
79
 
80
80
 
81
- def is_process_on_port(port: int) -> bool:
81
+ def _can_bind_at_any_port(address_family: socket.AddressFamily | int) -> bool:
82
+ """Check if any port is available for binding.
83
+
84
+ Args:
85
+ address_family: The address family (e.g., socket.AF_INET or socket.AF_INET6).
86
+
87
+ Returns:
88
+ Whether any port is available for binding.
89
+ """
90
+ with closing(socket.socket(address_family, socket.SOCK_STREAM)) as sock:
91
+ try:
92
+ sock.bind(("", 0)) # Bind to any available port
93
+ except (OverflowError, PermissionError, OSError) as e:
94
+ console.debug(f"Unable to bind to any port for {address_family}: {e}")
95
+ return False
96
+ return True
97
+
98
+
99
+ def is_process_on_port(
100
+ port: int,
101
+ address_families: Sequence[socket.AddressFamily | int] = (
102
+ socket.AF_INET,
103
+ socket.AF_INET6,
104
+ ),
105
+ ) -> bool:
82
106
  """Check if a process is running on the given port.
83
107
 
84
108
  Args:
85
109
  port: The port.
110
+ address_families: The address families to check (default: IPv4 and IPv6).
86
111
 
87
112
  Returns:
88
113
  Whether a process is running on the given port.
89
114
  """
90
- return (
91
- not _can_bind_at_port(socket.AF_INET, "", port) # Test IPv4 local network
92
- or not _can_bind_at_port(socket.AF_INET6, "", port) # Test IPv6 local network
93
- )
115
+ return any(not _can_bind_at_port(family, "", port) for family in address_families)
94
116
 
95
117
 
96
118
  MAXIMUM_PORT = 2**16 - 1
@@ -113,13 +135,30 @@ def handle_port(service_name: str, port: int, auto_increment: bool) -> int:
113
135
  """
114
136
  console.debug(f"Checking if {service_name.capitalize()} port: {port} is in use.")
115
137
 
116
- if not is_process_on_port(port):
138
+ families = [
139
+ address_family
140
+ for address_family in (socket.AF_INET, socket.AF_INET6)
141
+ if _can_bind_at_any_port(address_family)
142
+ ]
143
+
144
+ if not families:
145
+ console.error(
146
+ f"Unable to bind to any port for {service_name}. "
147
+ "Please check your network configuration."
148
+ )
149
+ raise click.exceptions.Exit(1)
150
+
151
+ console.debug(
152
+ f"Checking if {service_name.capitalize()} port: {port} is in use for families: {families}."
153
+ )
154
+
155
+ if not is_process_on_port(port, families):
117
156
  console.debug(f"{service_name.capitalize()} port: {port} is not in use.")
118
157
  return port
119
158
 
120
159
  if auto_increment:
121
160
  for new_port in range(port + 1, MAXIMUM_PORT + 1):
122
- if not is_process_on_port(new_port):
161
+ if not is_process_on_port(new_port, families):
123
162
  console.info(
124
163
  f"The {service_name} will run on port [bold underline]{new_port}[/bold underline]."
125
164
  )
reflex/utils/redir.py CHANGED
@@ -3,8 +3,6 @@
3
3
  import time
4
4
  import webbrowser
5
5
 
6
- import httpx
7
-
8
6
  from reflex import constants
9
7
  from reflex.utils import net
10
8
 
@@ -25,9 +23,7 @@ def open_browser(target_url: str) -> None:
25
23
  console.info(f"Opening browser to {target_url}.")
26
24
 
27
25
 
28
- def open_browser_and_wait(
29
- target_url: str, poll_url: str, interval: int = 2
30
- ) -> httpx.Response:
26
+ def open_browser_and_wait(target_url: str, poll_url: str, interval: int = 2):
31
27
  """Open a browser window to target_url and request poll_url until it returns successfully.
32
28
 
33
29
  Args:
@@ -38,6 +34,8 @@ def open_browser_and_wait(
38
34
  Returns:
39
35
  The response from the poll_url.
40
36
  """
37
+ import httpx
38
+
41
39
  open_browser(target_url)
42
40
  console.info("[b]Complete the workflow in the browser to continue.[/b]")
43
41
  while True:
reflex/utils/registry.py CHANGED
@@ -1,10 +1,10 @@
1
1
  """Utilities for working with registries."""
2
2
 
3
- import httpx
3
+ from pathlib import Path
4
4
 
5
5
  from reflex.environment import environment
6
6
  from reflex.utils import console, net
7
- from reflex.utils.decorator import once
7
+ from reflex.utils.decorator import cache_result_in_disk, once
8
8
 
9
9
 
10
10
  def latency(registry: str) -> int:
@@ -16,6 +16,8 @@ def latency(registry: str) -> int:
16
16
  Returns:
17
17
  int: The latency of the registry in microseconds.
18
18
  """
19
+ import httpx
20
+
19
21
  try:
20
22
  time_to_respond = net.get(registry, timeout=2).elapsed.microseconds
21
23
  except httpx.HTTPError:
@@ -41,6 +43,16 @@ def average_latency(registry: str, attempts: int = 3) -> int:
41
43
  return registry_latency
42
44
 
43
45
 
46
+ def _best_registry_file_path() -> Path:
47
+ """Get the file path for the best registry cache.
48
+
49
+ Returns:
50
+ The file path for the best registry cache.
51
+ """
52
+ return environment.REFLEX_DIR.get() / "reflex_best_registry.cached"
53
+
54
+
55
+ @cache_result_in_disk(cache_file_path=_best_registry_file_path)
44
56
  def _get_best_registry() -> str:
45
57
  """Get the best registry based on latency.
46
58
 
reflex/utils/telemetry.py CHANGED
@@ -12,8 +12,6 @@ from contextlib import suppress
12
12
  from datetime import datetime, timezone
13
13
  from typing import TypedDict
14
14
 
15
- import httpx
16
-
17
15
  from reflex import constants
18
16
  from reflex.environment import environment
19
17
  from reflex.utils import console
@@ -218,6 +216,8 @@ def _prepare_event(event: str, **kwargs) -> _Event | None:
218
216
 
219
217
 
220
218
  def _send_event(event_data: _Event) -> bool:
219
+ import httpx
220
+
221
221
  try:
222
222
  httpx.post(POSTHOG_API_URL, json=event_data)
223
223
  except Exception:
@@ -7,6 +7,7 @@ import dataclasses
7
7
  import dis
8
8
  import enum
9
9
  import inspect
10
+ import sys
10
11
  from types import CellType, CodeType, FunctionType
11
12
  from typing import TYPE_CHECKING, Any, ClassVar, cast
12
13
 
@@ -60,9 +61,7 @@ class DependencyTracker:
60
61
  tracked_locals: dict[str, type[BaseState]] = dataclasses.field(default_factory=dict)
61
62
 
62
63
  _getting_state_class: type[BaseState] | None = dataclasses.field(default=None)
63
- _getting_var_instructions: list[dis.Instruction] = dataclasses.field(
64
- default_factory=list
65
- )
64
+ _get_var_value_positions: dis.Positions | None = dataclasses.field(default=None)
66
65
 
67
66
  INVALID_NAMES: ClassVar[list[str]] = ["parent_state", "substates", "get_substate"]
68
67
 
@@ -114,6 +113,8 @@ class DependencyTracker:
114
113
  return
115
114
  if instruction.argval == "get_var_value":
116
115
  # Special case: arbitrary var access requested.
116
+ if sys.version_info >= (3, 11):
117
+ self._get_var_value_positions = instruction.positions
117
118
  self.scan_status = ScanStatus.GETTING_VAR
118
119
  return
119
120
 
@@ -222,9 +223,12 @@ class DependencyTracker:
222
223
  self.scan_status = ScanStatus.SCANNING
223
224
  self._getting_state_class = None
224
225
 
225
- def _eval_var(self) -> Var:
226
+ def _eval_var(self, positions: dis.Positions) -> Var:
226
227
  """Evaluate instructions from the wrapped function to get the Var object.
227
228
 
229
+ Args:
230
+ positions: The disassembly positions of the get_var_value call.
231
+
228
232
  Returns:
229
233
  The Var object.
230
234
 
@@ -233,15 +237,13 @@ class DependencyTracker:
233
237
  """
234
238
  # Get the original source code and eval it to get the Var.
235
239
  module = inspect.getmodule(self.func)
236
- positions0 = self._getting_var_instructions[0].positions
237
- positions1 = self._getting_var_instructions[-1].positions
238
- if module is None or positions0 is None or positions1 is None:
240
+ if module is None or self._get_var_value_positions is None:
239
241
  msg = f"Cannot determine the source code for the var in {self.func!r}."
240
242
  raise VarValueError(msg)
241
- start_line = positions0.lineno
242
- start_column = positions0.col_offset
243
- end_line = positions1.end_lineno
244
- end_column = positions1.end_col_offset
243
+ start_line = self._get_var_value_positions.end_lineno
244
+ start_column = self._get_var_value_positions.end_col_offset
245
+ end_line = positions.end_lineno
246
+ end_column = positions.end_col_offset
245
247
  if (
246
248
  start_line is None
247
249
  or start_column is None
@@ -254,14 +256,10 @@ class DependencyTracker:
254
256
  # Create a python source string snippet.
255
257
  if len(source) > 1:
256
258
  snipped_source = "".join(
257
- [
258
- *source[0][start_column:],
259
- *(source[1:-2] if len(source) > 2 else []),
260
- *source[-1][: end_column - 1],
261
- ]
259
+ [*source[0][start_column:], *source[1:-1], *source[-1][:end_column]]
262
260
  )
263
261
  else:
264
- snipped_source = source[0][start_column : end_column - 1]
262
+ snipped_source = source[0][start_column:end_column]
265
263
  # Evaluate the string in the context of the function's globals and closure.
266
264
  return eval(f"({snipped_source})", self._get_globals(), self._get_closure())
267
265
 
@@ -279,20 +277,19 @@ class DependencyTracker:
279
277
  Raises:
280
278
  VarValueError: if the source code for the var cannot be determined.
281
279
  """
282
- if instruction.opname == "CALL" and self._getting_var_instructions:
283
- if self._getting_var_instructions:
284
- the_var = self._eval_var()
285
- the_var_data = the_var._get_all_var_data()
286
- if the_var_data is None:
287
- msg = f"Cannot determine the source code for the var in {self.func!r}."
288
- raise VarValueError(msg)
289
- self.dependencies.setdefault(the_var_data.state, set()).add(
290
- the_var_data.field_name
291
- )
292
- self._getting_var_instructions.clear()
280
+ if instruction.opname == "CALL":
281
+ if instruction.positions is None:
282
+ msg = f"Cannot determine the source code for the var in {self.func!r}."
283
+ raise VarValueError(msg)
284
+ the_var = self._eval_var(instruction.positions)
285
+ the_var_data = the_var._get_all_var_data()
286
+ if the_var_data is None:
287
+ msg = f"Cannot determine the source code for the var in {self.func!r}."
288
+ raise VarValueError(msg)
289
+ self.dependencies.setdefault(the_var_data.state, set()).add(
290
+ the_var_data.field_name
291
+ )
293
292
  self.scan_status = ScanStatus.SCANNING
294
- else:
295
- self._getting_var_instructions.append(instruction)
296
293
 
297
294
  def _populate_dependencies(self) -> None:
298
295
  """Update self.dependencies based on the disassembly of self.func.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reflex
3
- Version: 0.8.3a3
3
+ Version: 0.8.4
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
@@ -20,7 +20,6 @@ Classifier: Programming Language :: Python :: 3.13
20
20
  Requires-Python: <4.0,>=3.10
21
21
  Requires-Dist: alembic<2.0,>=1.15.2
22
22
  Requires-Dist: click>=8.2
23
- Requires-Dist: fastapi>=0.115.0
24
23
  Requires-Dist: granian[reload]>=2.4.0
25
24
  Requires-Dist: httpx<1.0,>=0.28.0
26
25
  Requires-Dist: jinja2<4.0,>=3.1.2
@@ -34,6 +33,7 @@ Requires-Dist: redis<7.0,>=5.2.1
34
33
  Requires-Dist: reflex-hosting-cli>=0.1.51
35
34
  Requires-Dist: rich<15,>=13
36
35
  Requires-Dist: sqlmodel<0.1,>=0.0.24
36
+ Requires-Dist: starlette>=0.47.0
37
37
  Requires-Dist: typing-extensions>=4.13.0
38
38
  Requires-Dist: wrapt<2.0,>=1.17.0
39
39
  Description-Content-Type: text/markdown
@@ -2,7 +2,7 @@ reflex/__init__.py,sha256=xGw7ZbGlWsa-OShPv-I81RuUOACxHGTQFlX17x5n9Hg,10328
2
2
  reflex/__init__.pyi,sha256=GfoYvxYXK1GFGbUsMA8Su7IFoqupV_xxG6__KSgnitA,10097
3
3
  reflex/__main__.py,sha256=6cVrGEyT3j3tEvlEVUatpaYfbB5EF3UVY-6vc_Z7-hw,108
4
4
  reflex/admin.py,sha256=Nbc38y-M8iaRBvh1W6DQu_D3kEhO8JFvxrog4q2cB_E,434
5
- reflex/app.py,sha256=xrP6jq5D5tILtNzNluhRJ_kkWuRIekj8NFA5plA-Spc,75596
5
+ reflex/app.py,sha256=w2VOaN8ZwxQgW8AXnXnXy1Yubcks2DgbPt3Z8n_MTHM,75036
6
6
  reflex/assets.py,sha256=l5O_mlrTprC0lF7Rc_McOe3a0OtSLnRdNl_PqCpDCBA,3431
7
7
  reflex/base.py,sha256=Oh664QL3fZEHErhUasFqP7fE4olYf1y-9Oj6uZI2FCU,1173
8
8
  reflex/config.py,sha256=HgJ57Op-glTro23GoQKmyXwUplvGYgZFKjvClYpD27s,19359
@@ -51,8 +51,8 @@ reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js,sha2
51
51
  reflex/.templates/web/components/shiki/code.js,sha256=4Es1pxsr-lX4hTQ5mglrwwC6O_SI-z-O60k03z8VFzQ,1144
52
52
  reflex/.templates/web/styles/__reflex_style_reset.css,sha256=qbC6JIT643YEsvSQ0D7xBmWE5vXy94JGrKNihRuEjnA,8913
53
53
  reflex/.templates/web/utils/client_side_routing.js,sha256=lRNgEGCLfTejh8W3aCuBdFuko6UI2vetk64j8wLT5Uk,1650
54
- reflex/.templates/web/utils/react-theme.js,sha256=4CNLOcjLS5tiRp0TIgKK7trf8bSLWtmeDVhFP6BLe80,2349
55
- reflex/.templates/web/utils/state.js,sha256=Ibr-o2RIjWaalsy5xQS3j9DOwY1-U6hGsSOaUAHwd8c,36152
54
+ reflex/.templates/web/utils/react-theme.js,sha256=Aa-RND3ooGCXW6Zavzitc-v0ciKlcQDTFlDtE4mPkFI,2713
55
+ reflex/.templates/web/utils/state.js,sha256=Z9NeC1sjePtIg03kvxILng-1ri_PNZFAM_t64K4d5Dg,36162
56
56
  reflex/.templates/web/utils/helpers/dataeditor.js,sha256=pG6MgsHuStDR7-qPipzfiK32j9bKDBa-4hZ0JSUo4JM,1623
57
57
  reflex/.templates/web/utils/helpers/debounce.js,sha256=xGhtTRtS_xIcaeqnYVvYJNseLgQVk-DW-eFiHJYO9As,528
58
58
  reflex/.templates/web/utils/helpers/paste.js,sha256=ef30HsR83jRzzvZnl8yV79yqFP8TC_u8SlN99cCS_OM,1799
@@ -65,7 +65,7 @@ reflex/app_mixins/mixin.py,sha256=R1YncalqDrbdPZvpKVbm72ZKmQZxYAWfuFq9JknzTqQ,30
65
65
  reflex/compiler/__init__.py,sha256=r8jqmDSFf09iV2lHlNhfc9XrTLjNxfDNwPYlxS4cmHE,27
66
66
  reflex/compiler/compiler.py,sha256=r-qvhlz0I7Gw__rIFRjt2vCbUYW2yl-rHvznyO7SS4Q,28835
67
67
  reflex/compiler/templates.py,sha256=mQifVgvE7cKyzMFL9F5jxdJb9KFxucWJa7nuOp09ZUo,6002
68
- reflex/compiler/utils.py,sha256=v2LGz6WAFOSRpn3H0l215E94R7r7hB3s9vseWrQiXUQ,19045
68
+ reflex/compiler/utils.py,sha256=Eo0-zLCj4rFhkVZQNWSMoMSGTSAkHIivoNwoAgMBYi8,19266
69
69
  reflex/components/__init__.py,sha256=eWpgWFbSQDj2TpGp6StEbxU7roQgzY7ZM0XIcIc5RE8,588
70
70
  reflex/components/__init__.pyi,sha256=7VFHtJGIjvGtD3IiPk848IPWYSCcPRT1EyPGljLhYlU,736
71
71
  reflex/components/component.py,sha256=0ZouhQgfO5hAbKu3Z4ytM0jvaz70U0Uab9SrIewdUbQ,99431
@@ -344,17 +344,17 @@ reflex/constants/compiler.py,sha256=VoA1vWZpl-2EdIOhAiOLwSX4S-bFLbkiESlNBmN08NQ,
344
344
  reflex/constants/config.py,sha256=8OIjiBdZZJrRVHsNBheMwopE9AwBFFzau0SXqXKcrPg,1715
345
345
  reflex/constants/custom_components.py,sha256=joJt4CEt1yKy7wsBH6vYo7_QRW0O_fWXrrTf0VY2q14,1317
346
346
  reflex/constants/event.py,sha256=tgoynWQi2L0_Kqc3XhXo7XXL76A-OKhJGHRrNjm7gFw,2885
347
- reflex/constants/installer.py,sha256=hPfNCA3HiFf67-BBYL-KK4Fi71c-EZXF71mrQNCojfs,4141
347
+ reflex/constants/installer.py,sha256=i0CUcOCPTGLqNdVEwDxU-UKkaDtEh9ImT5rqmI9Ly90,4142
348
348
  reflex/constants/route.py,sha256=UBjqaAOxiUxlDZCSY4O2JJChKvA4MZrhUU0E5rNvKbM,2682
349
349
  reflex/constants/state.py,sha256=uF_7-M9Gid-P3DjAOq4F1ERplyZhiNccowo_jLrdJrg,323
350
350
  reflex/constants/utils.py,sha256=e1ChEvbHfmE_V2UJvCSUhD_qTVAIhEGPpRJSqdSd6PA,780
351
351
  reflex/custom_components/__init__.py,sha256=R4zsvOi4dfPmHc18KEphohXnQFBPnUCb50cMR5hSLDE,36
352
- reflex/custom_components/custom_components.py,sha256=fSsPqqYv0T81B8LTL6yeol0Qx1edW96o-2ibrW5ujNo,20206
352
+ reflex/custom_components/custom_components.py,sha256=IPW7Kbtyr8vjk1FzXRsCyCaLJTlaLQMYjOxgf1WK_jg,20210
353
353
  reflex/experimental/__init__.py,sha256=P8fe8S2e2gy2HCwHFGQzr3lPMmh7qN5Ii2e8ukoPHuQ,1664
354
354
  reflex/experimental/client_state.py,sha256=1VOe6rYhpOBOZi7-tZwfOnSNPPdX3tsXzlfgNs7aDrg,10020
355
355
  reflex/experimental/hooks.py,sha256=CHYGrAE5t8riltrJmDFgJ4D2Vhmhw-y3B3MSGNlOQow,2366
356
356
  reflex/istate/__init__.py,sha256=afq_pCS5B_REC-Kl3Rbaa538uWi59xNz4INeuENcWnk,2039
357
- reflex/istate/data.py,sha256=Q8HGjViQu3teVcwo1V1X6uWBxGr05ABTqAdeCoLUxic,7287
357
+ reflex/istate/data.py,sha256=KrANpAQFTZcfFWnxyykgK1FRNuXTwTin1WYpyqymV-U,7547
358
358
  reflex/istate/dynamic.py,sha256=xOQ9upZVPf6ngqcLQZ9HdAAYmoWwJ8kRFPH34Q5HTiM,91
359
359
  reflex/istate/manager.py,sha256=te5uQN6n-ctOGrf6NbZUVy6BKgWapLlMtCzDaO6RthU,30412
360
360
  reflex/istate/proxy.py,sha256=Q8JrV1m6drVcTNJL9JuN-nKUXclazs96OHl_fhR0UBk,25928
@@ -373,36 +373,36 @@ reflex/utils/__init__.py,sha256=y-AHKiRQAhk2oAkvn7W8cRVTZVK625ff8tTwvZtO7S4,24
373
373
  reflex/utils/build.py,sha256=lk8hE69onG95dv-LxRhjtEugct1g-KcWPUDorzqeGIE,7964
374
374
  reflex/utils/codespaces.py,sha256=kEQ-j-jclTukFpXDlYgNp95kYMGDrQmP3VNEoYGZ1u4,3052
375
375
  reflex/utils/compat.py,sha256=aSJH_M6iomgHPQ4onQ153xh1MWqPi3HSYDzE68N6gZM,2635
376
- reflex/utils/console.py,sha256=_qC1KxqmIThrQnoCqIr4AMGgXfnByeF97YbA77PPuTQ,11531
377
- reflex/utils/decorator.py,sha256=DVrlVGljV5OchMs-5_y1CbbqnCWlH6lv-dFko8yHxVY,1738
376
+ reflex/utils/console.py,sha256=QIOgyElaxSVM1Bbvz0zx77-MqkDZkfpu1d6l26VRkQ0,11580
377
+ reflex/utils/decorator.py,sha256=P5xP2kZsJnNdc91x2dou9_Z8U3q4YkPDB-vpfE3CZtU,3900
378
378
  reflex/utils/exceptions.py,sha256=Wwu7Ji2xgq521bJKtU2NgjwhmFfnG8erirEVN2h8S-g,8884
379
379
  reflex/utils/exec.py,sha256=KQ5tS5vz3wuu9zDGPR6clSE0IoY_vcIbJGCB5bqiDJM,21987
380
380
  reflex/utils/export.py,sha256=Z2AHuhkxGQzOi9I90BejQ4qEcD0URr2i-ZU5qTJt7eQ,2562
381
381
  reflex/utils/format.py,sha256=FZe5NA0U3K0n0k7r8RIGcx-eHpN7sf8eQX9w1C8_uR8,21120
382
382
  reflex/utils/imports.py,sha256=Ov-lqv-PfsPl3kTEW13r5aDauIfn6TqzEMyv42RKLOA,3761
383
383
  reflex/utils/lazy_loader.py,sha256=BiY9OvmAJDCz10qpuyTYv9duXgMFQa6RXKQmTO9hqKU,4453
384
- reflex/utils/misc.py,sha256=zbYIl7mI08is9enr851sj7PnDaNeVVvq5jDmQ4wdlCE,2879
385
- reflex/utils/net.py,sha256=HEHA8L5g7L9s0fFG4dTiZzB9PFO_0WRrlbMgpZr_GAQ,4093
384
+ reflex/utils/misc.py,sha256=folEweZVCrhHNkkqut9KqQdTJ80HxwL_gI41m40FnNM,4592
385
+ reflex/utils/net.py,sha256=GXq5KNmYowT-BP4o9HmEqKthm-N9nj82KH8es3EeTWI,4138
386
386
  reflex/utils/path_ops.py,sha256=_RS17IQDNr5vcoLLGZx2-z1E5WP-JgDHvaRAOgqrZiU,8154
387
- reflex/utils/prerequisites.py,sha256=L2tCFqqiYqygRbQ0JMMBduMdsMkKJLDvzGKZnvI1Enc,66001
388
- reflex/utils/processes.py,sha256=q9RwI82t4zaVs7_xUGC8HNk9x6QCY9rcgEGitfqzG10,16918
387
+ reflex/utils/prerequisites.py,sha256=8S_Yn3n2ojiqwDkpVmTqbxnTY7ILobFSm4f2MjYXtAw,64129
388
+ reflex/utils/processes.py,sha256=szY-jWXVdpMF48q5sVaxTW_KiJOUKgTVPhl-C519NsQ,18182
389
389
  reflex/utils/pyi_generator.py,sha256=HdmUVs50Bk7MAMFSvpATRhH--_50w-9URMFnjLlwT40,46086
390
- reflex/utils/redir.py,sha256=3JG0cRdfIZnFIBHHN32ynD5cfbUZa7gLRxzrxRGGl5I,1751
391
- reflex/utils/registry.py,sha256=DEF7csYQ5VnrZhy6ULVfMlceh7XVH0pks96lIyyThuc,1882
390
+ reflex/utils/redir.py,sha256=E6lJ6UYGQs_uCyQAKHT_dDMplo5IRZ9JarWfvgGAgGo,1731
391
+ reflex/utils/registry.py,sha256=omKh5rrsybDuuKmh4K88lwdwwcpGsu3Vc4pCko_djKY,2239
392
392
  reflex/utils/serializers.py,sha256=sVLfbWIBKPpmo0CVVxoxXGu0K3R9mYMWgaI02LXZmcM,13952
393
- reflex/utils/telemetry.py,sha256=9k5S6dST_6rylhKyLMlnwzsxZ4p_Q0oikxOBpTckQxw,7448
393
+ reflex/utils/telemetry.py,sha256=XpPbFmlFdEh5uJl5vXoLyCCFv1choJN8EMko0MujigQ,7452
394
394
  reflex/utils/types.py,sha256=jFHfd2-yHWV61L7YP2gc9Zj2ZLwdthHOOfRIc_PAWH0,38390
395
395
  reflex/vars/__init__.py,sha256=85eXMt32bFoKtMdH3KxYRMD8mtnKyYiQcThPxJLoW1k,1359
396
396
  reflex/vars/base.py,sha256=IGCU5iwZSsVMPVQqODEjmHJrskqfpfMIQ2yzcVFMoSQ,112940
397
397
  reflex/vars/datetime.py,sha256=F2Jv_bfydipFSkIQ1F6x5MnSgFEyES9Vq5RG_uGH81E,5118
398
- reflex/vars/dep_tracking.py,sha256=aCIPJwCagl87hpszYI2uihFy3Xg2-RVzanaUxt5Kt7o,13775
398
+ reflex/vars/dep_tracking.py,sha256=LfDGgAGlqfC0DeiVcitRBcA1uCe1C3fNRARRekLgCz4,13738
399
399
  reflex/vars/function.py,sha256=0i-VkxHkDJmZtfQUwUfaF0rlS6WM8azjwQ8k7rEOkyk,13944
400
400
  reflex/vars/number.py,sha256=tO7pnvFaBsedq1HWT4skytnSqHWMluGEhUbjAUMx8XQ,28190
401
401
  reflex/vars/object.py,sha256=BDmeiwG8v97s_BnR1Egq3NxOKVjv9TfnREB3cz0zZtk,17322
402
402
  reflex/vars/sequence.py,sha256=1kBrqihspyjyQ1XDqFPC8OpVGtZs_EVkOdIKBro5ilA,55249
403
403
  scripts/hatch_build.py,sha256=-4pxcLSFmirmujGpQX9UUxjhIC03tQ_fIQwVbHu9kc0,1861
404
- reflex-0.8.3a3.dist-info/METADATA,sha256=z4r4mAqtN5umJxNbaXQGmMl__HnItjgvmO_E2N3MiIM,12371
405
- reflex-0.8.3a3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
406
- reflex-0.8.3a3.dist-info/entry_points.txt,sha256=Rxt4dXc7MLBNt5CSHTehVPuSe9Xqow4HLX55nD9tQQ0,45
407
- reflex-0.8.3a3.dist-info/licenses/LICENSE,sha256=dw3zLrp9f5ObD7kqS32vWfhcImfO52PMmRqvtxq_YEE,11358
408
- reflex-0.8.3a3.dist-info/RECORD,,
404
+ reflex-0.8.4.dist-info/METADATA,sha256=Er3WQwPS4PhuNR_O2Up0hp_xtmn_waWIN2iWkV8ge28,12370
405
+ reflex-0.8.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
406
+ reflex-0.8.4.dist-info/entry_points.txt,sha256=Rxt4dXc7MLBNt5CSHTehVPuSe9Xqow4HLX55nD9tQQ0,45
407
+ reflex-0.8.4.dist-info/licenses/LICENSE,sha256=dw3zLrp9f5ObD7kqS32vWfhcImfO52PMmRqvtxq_YEE,11358
408
+ reflex-0.8.4.dist-info/RECORD,,