reflex 0.7.5a1__py3-none-any.whl → 0.7.6a0__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/.templates/jinja/web/pages/_app.js.jinja2 +1 -1
- reflex/__init__.py +1 -1
- reflex/admin.py +6 -2
- reflex/app.py +9 -3
- reflex/compiler/compiler.py +83 -44
- reflex/components/core/cond.py +1 -1
- reflex/components/core/foreach.py +4 -1
- reflex/config.py +0 -6
- reflex/constants/base.py +13 -1
- reflex/constants/compiler.py +1 -1
- reflex/constants/installer.py +2 -4
- reflex/custom_components/custom_components.py +17 -387
- reflex/event.py +17 -9
- reflex/reflex.py +9 -2
- reflex/state.py +13 -3
- reflex/utils/codespaces.py +12 -3
- reflex/utils/exec.py +2 -2
- reflex/utils/lazy_loader.py +63 -12
- reflex/utils/prerequisites.py +39 -33
- reflex/utils/processes.py +13 -4
- reflex/utils/pyi_generator.py +96 -13
- reflex/utils/types.py +11 -1
- {reflex-0.7.5a1.dist-info → reflex-0.7.6a0.dist-info}/METADATA +2 -11
- {reflex-0.7.5a1.dist-info → reflex-0.7.6a0.dist-info}/RECORD +27 -27
- {reflex-0.7.5a1.dist-info → reflex-0.7.6a0.dist-info}/WHEEL +0 -0
- {reflex-0.7.5a1.dist-info → reflex-0.7.6a0.dist-info}/entry_points.txt +0 -0
- {reflex-0.7.5a1.dist-info → reflex-0.7.6a0.dist-info}/licenses/LICENSE +0 -0
reflex/__init__.py
CHANGED
reflex/admin.py
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
"""The Reflex Admin Dashboard."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
3
5
|
from dataclasses import dataclass, field
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from starlette_admin.base import BaseAdmin as Admin
|
|
6
10
|
|
|
7
11
|
|
|
8
12
|
@dataclass
|
|
@@ -11,4 +15,4 @@ class AdminDash:
|
|
|
11
15
|
|
|
12
16
|
models: list = field(default_factory=list)
|
|
13
17
|
view_overrides: dict = field(default_factory=dict)
|
|
14
|
-
admin: Admin | None = None
|
|
18
|
+
admin: "Admin | None" = None
|
reflex/app.py
CHANGED
|
@@ -40,8 +40,6 @@ from rich.progress import MofNCompleteColumn, Progress, TimeElapsedColumn
|
|
|
40
40
|
from socketio import ASGIApp, AsyncNamespace, AsyncServer
|
|
41
41
|
from starlette.datastructures import Headers
|
|
42
42
|
from starlette.datastructures import UploadFile as StarletteUploadFile
|
|
43
|
-
from starlette_admin.contrib.sqla.admin import Admin
|
|
44
|
-
from starlette_admin.contrib.sqla.view import ModelView
|
|
45
43
|
|
|
46
44
|
from reflex import constants
|
|
47
45
|
from reflex.admin import AdminDash
|
|
@@ -445,6 +443,8 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
445
443
|
"rx.BaseState cannot be subclassed directly. Use rx.State instead"
|
|
446
444
|
)
|
|
447
445
|
|
|
446
|
+
get_config(reload=True)
|
|
447
|
+
|
|
448
448
|
if "breakpoints" in self.style:
|
|
449
449
|
set_breakpoints(self.style.pop("breakpoints"))
|
|
450
450
|
|
|
@@ -885,6 +885,12 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
885
885
|
|
|
886
886
|
def _setup_admin_dash(self):
|
|
887
887
|
"""Setup the admin dash."""
|
|
888
|
+
try:
|
|
889
|
+
from starlette_admin.contrib.sqla.admin import Admin
|
|
890
|
+
from starlette_admin.contrib.sqla.view import ModelView
|
|
891
|
+
except ImportError:
|
|
892
|
+
return
|
|
893
|
+
|
|
888
894
|
# Get the admin dash.
|
|
889
895
|
if not self.api:
|
|
890
896
|
return
|
|
@@ -1427,7 +1433,7 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
1427
1433
|
async with self.state_manager.modify_state(token) as state:
|
|
1428
1434
|
# No other event handler can modify the state while in this context.
|
|
1429
1435
|
yield state
|
|
1430
|
-
delta = state.
|
|
1436
|
+
delta = await state._get_resolved_delta()
|
|
1431
1437
|
if delta:
|
|
1432
1438
|
# When the state is modified reset dirty status and emit the delta to the frontend.
|
|
1433
1439
|
state._clean()
|
reflex/compiler/compiler.py
CHANGED
|
@@ -17,6 +17,7 @@ from reflex.components.component import (
|
|
|
17
17
|
StatefulComponent,
|
|
18
18
|
)
|
|
19
19
|
from reflex.config import environment, get_config
|
|
20
|
+
from reflex.constants.compiler import PageNames
|
|
20
21
|
from reflex.state import BaseState
|
|
21
22
|
from reflex.style import SYSTEM_COLOR_MODE
|
|
22
23
|
from reflex.utils import console, path_ops
|
|
@@ -174,6 +175,42 @@ def compile_root_stylesheet(stylesheets: list[str]) -> tuple[str, str]:
|
|
|
174
175
|
return output_path, code
|
|
175
176
|
|
|
176
177
|
|
|
178
|
+
def _validate_stylesheet(stylesheet_full_path: Path, assets_app_path: Path) -> None:
|
|
179
|
+
"""Validate the stylesheet.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
stylesheet_full_path: The stylesheet to validate.
|
|
183
|
+
assets_app_path: The path to the assets directory.
|
|
184
|
+
|
|
185
|
+
Raises:
|
|
186
|
+
ValueError: If the stylesheet is not supported.
|
|
187
|
+
FileNotFoundError: If the stylesheet is not found.
|
|
188
|
+
"""
|
|
189
|
+
suffix = stylesheet_full_path.suffix[1:] if stylesheet_full_path.suffix else ""
|
|
190
|
+
if suffix not in constants.Reflex.STYLESHEETS_SUPPORTED:
|
|
191
|
+
raise ValueError(f"Stylesheet file {stylesheet_full_path} is not supported.")
|
|
192
|
+
if not stylesheet_full_path.absolute().is_relative_to(assets_app_path.absolute()):
|
|
193
|
+
raise FileNotFoundError(
|
|
194
|
+
f"Cannot include stylesheets from outside the assets directory: {stylesheet_full_path}"
|
|
195
|
+
)
|
|
196
|
+
if not stylesheet_full_path.name:
|
|
197
|
+
raise ValueError(
|
|
198
|
+
f"Stylesheet file name cannot be empty: {stylesheet_full_path}"
|
|
199
|
+
)
|
|
200
|
+
if (
|
|
201
|
+
len(
|
|
202
|
+
stylesheet_full_path.absolute()
|
|
203
|
+
.relative_to(assets_app_path.absolute())
|
|
204
|
+
.parts
|
|
205
|
+
)
|
|
206
|
+
== 1
|
|
207
|
+
and stylesheet_full_path.stem == PageNames.STYLESHEET_ROOT
|
|
208
|
+
):
|
|
209
|
+
raise ValueError(
|
|
210
|
+
f"Stylesheet file name cannot be '{PageNames.STYLESHEET_ROOT}': {stylesheet_full_path}"
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
|
|
177
214
|
def _compile_root_stylesheet(stylesheets: list[str]) -> str:
|
|
178
215
|
"""Compile the root stylesheet.
|
|
179
216
|
|
|
@@ -194,10 +231,14 @@ def _compile_root_stylesheet(stylesheets: list[str]) -> str:
|
|
|
194
231
|
)
|
|
195
232
|
|
|
196
233
|
failed_to_import_sass = False
|
|
234
|
+
assets_app_path = Path.cwd() / constants.Dirs.APP_ASSETS
|
|
235
|
+
|
|
236
|
+
stylesheets_files: list[Path] = []
|
|
237
|
+
stylesheets_urls = []
|
|
238
|
+
|
|
197
239
|
for stylesheet in stylesheets:
|
|
198
240
|
if not utils.is_valid_url(stylesheet):
|
|
199
241
|
# check if stylesheet provided exists.
|
|
200
|
-
assets_app_path = Path.cwd() / constants.Dirs.APP_ASSETS
|
|
201
242
|
stylesheet_full_path = assets_app_path / stylesheet.strip("/")
|
|
202
243
|
|
|
203
244
|
if not stylesheet_full_path.exists():
|
|
@@ -206,53 +247,51 @@ def _compile_root_stylesheet(stylesheets: list[str]) -> str:
|
|
|
206
247
|
)
|
|
207
248
|
|
|
208
249
|
if stylesheet_full_path.is_dir():
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
# | dir_b/
|
|
214
|
-
# so to avoid the infinite loop, we don't include symbolic links
|
|
215
|
-
stylesheets += [
|
|
216
|
-
str(p.relative_to(assets_app_path))
|
|
217
|
-
for p in stylesheet_full_path.iterdir()
|
|
218
|
-
if not (p.is_symlink() and p.is_dir())
|
|
219
|
-
]
|
|
220
|
-
continue
|
|
221
|
-
|
|
222
|
-
if (
|
|
223
|
-
stylesheet_full_path.suffix[1:].lower()
|
|
224
|
-
in constants.Reflex.STYLESHEETS_SUPPORTED
|
|
225
|
-
):
|
|
226
|
-
target = (
|
|
227
|
-
get_web_dir()
|
|
228
|
-
/ constants.Dirs.STYLES
|
|
229
|
-
/ (stylesheet.rsplit(".", 1)[0].strip("/") + ".css")
|
|
250
|
+
all_files = (
|
|
251
|
+
file
|
|
252
|
+
for ext in constants.Reflex.STYLESHEETS_SUPPORTED
|
|
253
|
+
for file in stylesheet_full_path.rglob("*." + ext)
|
|
230
254
|
)
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
target.write_text(
|
|
240
|
-
data=sass_compile(
|
|
241
|
-
filename=str(stylesheet_full_path),
|
|
242
|
-
output_style="compressed",
|
|
243
|
-
),
|
|
244
|
-
encoding="utf8",
|
|
245
|
-
)
|
|
246
|
-
except ImportError:
|
|
247
|
-
failed_to_import_sass = True
|
|
255
|
+
for file in all_files:
|
|
256
|
+
if file.is_dir():
|
|
257
|
+
continue
|
|
258
|
+
# Validate the stylesheet.
|
|
259
|
+
_validate_stylesheet(file, assets_app_path)
|
|
260
|
+
stylesheets_files.append(file)
|
|
261
|
+
|
|
248
262
|
else:
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
)
|
|
263
|
+
# Validate the stylesheet.
|
|
264
|
+
_validate_stylesheet(stylesheet_full_path, assets_app_path)
|
|
265
|
+
stylesheets_files.append(stylesheet_full_path)
|
|
266
|
+
else:
|
|
267
|
+
stylesheets_urls.append(stylesheet)
|
|
252
268
|
|
|
253
|
-
|
|
269
|
+
sheets.extend(dict.fromkeys(stylesheets_urls))
|
|
270
|
+
|
|
271
|
+
for stylesheet in stylesheets_files:
|
|
272
|
+
target_path = stylesheet.relative_to(assets_app_path).with_suffix(".css")
|
|
273
|
+
target = get_web_dir() / constants.Dirs.STYLES / target_path
|
|
274
|
+
|
|
275
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
276
|
+
|
|
277
|
+
if stylesheet.suffix == ".css":
|
|
278
|
+
path_ops.cp(src=stylesheet, dest=target, overwrite=True)
|
|
279
|
+
else:
|
|
280
|
+
try:
|
|
281
|
+
from sass import compile as sass_compile
|
|
282
|
+
|
|
283
|
+
target.write_text(
|
|
284
|
+
data=sass_compile(
|
|
285
|
+
filename=str(stylesheet),
|
|
286
|
+
output_style="compressed",
|
|
287
|
+
),
|
|
288
|
+
encoding="utf8",
|
|
289
|
+
)
|
|
290
|
+
except ImportError:
|
|
291
|
+
failed_to_import_sass = True
|
|
254
292
|
|
|
255
|
-
|
|
293
|
+
str_target_path = "./" + str(target_path)
|
|
294
|
+
sheets.append(str_target_path) if str_target_path not in sheets else None
|
|
256
295
|
|
|
257
296
|
if failed_to_import_sass:
|
|
258
297
|
console.error(
|
reflex/components/core/cond.py
CHANGED
|
@@ -151,7 +151,7 @@ def cond(condition: Any, c1: Any, c2: Any = types.Unset(), /) -> Component | Var
|
|
|
151
151
|
c1_var = Var.create(c1)
|
|
152
152
|
c2_var = Var.create(c2)
|
|
153
153
|
|
|
154
|
-
if
|
|
154
|
+
if c1_var is cond_var or c1_var.equals(cond_var):
|
|
155
155
|
c1_var = c1_var.to(types.value_inside_optional(c1_var._var_type))
|
|
156
156
|
|
|
157
157
|
# Create the conditional var.
|
|
@@ -55,6 +55,9 @@ class Foreach(Component):
|
|
|
55
55
|
ForeachVarError: If the iterable is of type Any.
|
|
56
56
|
TypeError: If the render function is a ComponentState.
|
|
57
57
|
UntypedVarError: If the iterable is of type Any without a type annotation.
|
|
58
|
+
|
|
59
|
+
# noqa: DAR401 with_traceback
|
|
60
|
+
# noqa: DAR402 UntypedVarError
|
|
58
61
|
"""
|
|
59
62
|
from reflex.vars import ArrayVar, ObjectVar, StringVar
|
|
60
63
|
|
|
@@ -107,7 +110,7 @@ class Foreach(Component):
|
|
|
107
110
|
iterable,
|
|
108
111
|
"foreach",
|
|
109
112
|
"https://reflex.dev/docs/library/dynamic-rendering/foreach/",
|
|
110
|
-
) from
|
|
113
|
+
).with_traceback(e.__traceback__) from None
|
|
111
114
|
return component
|
|
112
115
|
|
|
113
116
|
def _render(self) -> IterTag:
|
reflex/config.py
CHANGED
|
@@ -604,12 +604,6 @@ class EnvironmentVariables:
|
|
|
604
604
|
# Whether to use Granian for the backend. By default, the backend uses Uvicorn if available.
|
|
605
605
|
REFLEX_USE_GRANIAN: EnvVar[bool] = env_var(False)
|
|
606
606
|
|
|
607
|
-
# The username to use for authentication on python package repository. Username and password must both be provided.
|
|
608
|
-
TWINE_USERNAME: EnvVar[str | None] = env_var(None)
|
|
609
|
-
|
|
610
|
-
# The password to use for authentication on python package repository. Username and password must both be provided.
|
|
611
|
-
TWINE_PASSWORD: EnvVar[str | None] = env_var(None)
|
|
612
|
-
|
|
613
607
|
# Whether to use the system installed bun. If set to false, bun will be bundled with the app.
|
|
614
608
|
REFLEX_USE_SYSTEM_BUN: EnvVar[bool] = env_var(False)
|
|
615
609
|
|
reflex/constants/base.py
CHANGED
|
@@ -61,6 +61,18 @@ class Dirs(SimpleNamespace):
|
|
|
61
61
|
UPLOAD_IS_USED = "upload_is_used"
|
|
62
62
|
|
|
63
63
|
|
|
64
|
+
def _reflex_version() -> str:
|
|
65
|
+
"""Get the Reflex version.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
The Reflex version.
|
|
69
|
+
"""
|
|
70
|
+
try:
|
|
71
|
+
return metadata.version("reflex")
|
|
72
|
+
except metadata.PackageNotFoundError:
|
|
73
|
+
return "unknown"
|
|
74
|
+
|
|
75
|
+
|
|
64
76
|
class Reflex(SimpleNamespace):
|
|
65
77
|
"""Base constants concerning Reflex."""
|
|
66
78
|
|
|
@@ -68,7 +80,7 @@ class Reflex(SimpleNamespace):
|
|
|
68
80
|
# The name of the Reflex package.
|
|
69
81
|
MODULE_NAME = "reflex"
|
|
70
82
|
# The current version of Reflex.
|
|
71
|
-
VERSION =
|
|
83
|
+
VERSION = _reflex_version()
|
|
72
84
|
|
|
73
85
|
# The reflex json file.
|
|
74
86
|
JSON = "reflex.json"
|
reflex/constants/compiler.py
CHANGED
|
@@ -85,7 +85,7 @@ class PageNames(SimpleNamespace):
|
|
|
85
85
|
# The name of the app root page.
|
|
86
86
|
APP_ROOT = "_app"
|
|
87
87
|
# The root stylesheet filename.
|
|
88
|
-
STYLESHEET_ROOT = "
|
|
88
|
+
STYLESHEET_ROOT = "__reflex_global_styles"
|
|
89
89
|
# The name of the document root page.
|
|
90
90
|
DOCUMENT_ROOT = "_document"
|
|
91
91
|
# The name of the theme page.
|
reflex/constants/installer.py
CHANGED
|
@@ -14,10 +14,10 @@ class Bun(SimpleNamespace):
|
|
|
14
14
|
"""Bun constants."""
|
|
15
15
|
|
|
16
16
|
# The Bun version.
|
|
17
|
-
VERSION = "1.2.
|
|
17
|
+
VERSION = "1.2.8"
|
|
18
18
|
|
|
19
19
|
# Min Bun Version
|
|
20
|
-
MIN_VERSION = "1.2.
|
|
20
|
+
MIN_VERSION = "1.2.8"
|
|
21
21
|
|
|
22
22
|
# URL to bun install script.
|
|
23
23
|
INSTALL_URL = "https://raw.githubusercontent.com/reflex-dev/reflex/main/scripts/bun_install.sh"
|
|
@@ -62,8 +62,6 @@ registry = "{registry}"
|
|
|
62
62
|
class Node(SimpleNamespace):
|
|
63
63
|
"""Node/ NPM constants."""
|
|
64
64
|
|
|
65
|
-
# The Node version.
|
|
66
|
-
VERSION = "22.11.0"
|
|
67
65
|
# The minimum required node version.
|
|
68
66
|
MIN_VERSION = "18.18.0"
|
|
69
67
|
|