reflex 0.7.3a2__py3-none-any.whl → 0.7.4a0__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/app.py +1 -1
- reflex/compiler/compiler.py +61 -4
- reflex/components/core/upload.py +1 -1
- reflex/components/plotly/plotly.py +9 -9
- reflex/components/recharts/recharts.py +2 -2
- reflex/components/sonner/toast.py +1 -1
- reflex/config.py +2 -5
- reflex/constants/__init__.py +1 -2
- reflex/constants/base.py +3 -0
- reflex/constants/installer.py +8 -105
- reflex/state.py +8 -1
- reflex/testing.py +7 -1
- reflex/utils/build.py +3 -4
- reflex/utils/exec.py +10 -11
- reflex/utils/path_ops.py +15 -25
- reflex/utils/prerequisites.py +113 -181
- reflex/utils/processes.py +21 -18
- reflex/utils/registry.py +5 -5
- {reflex-0.7.3a2.dist-info → reflex-0.7.4a0.dist-info}/METADATA +1 -1
- {reflex-0.7.3a2.dist-info → reflex-0.7.4a0.dist-info}/RECORD +23 -23
- {reflex-0.7.3a2.dist-info → reflex-0.7.4a0.dist-info}/WHEEL +0 -0
- {reflex-0.7.3a2.dist-info → reflex-0.7.4a0.dist-info}/entry_points.txt +0 -0
- {reflex-0.7.3a2.dist-info → reflex-0.7.4a0.dist-info}/licenses/LICENSE +0 -0
reflex/app.py
CHANGED
|
@@ -1063,7 +1063,7 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
1063
1063
|
with stateful_pages_marker.open("r") as f:
|
|
1064
1064
|
stateful_pages = json.load(f)
|
|
1065
1065
|
for route in stateful_pages:
|
|
1066
|
-
console.
|
|
1066
|
+
console.debug(f"BE Evaluating stateful page: {route}")
|
|
1067
1067
|
self._compile_page(route, save_page=False)
|
|
1068
1068
|
self._enable_state()
|
|
1069
1069
|
self._add_optional_endpoints()
|
reflex/compiler/compiler.py
CHANGED
|
@@ -19,6 +19,7 @@ from reflex.components.component import (
|
|
|
19
19
|
from reflex.config import environment, get_config
|
|
20
20
|
from reflex.state import BaseState
|
|
21
21
|
from reflex.style import SYSTEM_COLOR_MODE
|
|
22
|
+
from reflex.utils import console, path_ops
|
|
22
23
|
from reflex.utils.exec import is_prod_mode
|
|
23
24
|
from reflex.utils.imports import ImportVar
|
|
24
25
|
from reflex.utils.prerequisites import get_web_dir
|
|
@@ -190,18 +191,74 @@ def _compile_root_stylesheet(stylesheets: list[str]) -> str:
|
|
|
190
191
|
if get_config().tailwind is not None
|
|
191
192
|
else []
|
|
192
193
|
)
|
|
194
|
+
|
|
195
|
+
failed_to_import_sass = False
|
|
193
196
|
for stylesheet in stylesheets:
|
|
194
197
|
if not utils.is_valid_url(stylesheet):
|
|
195
198
|
# check if stylesheet provided exists.
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
+
assets_app_path = Path.cwd() / constants.Dirs.APP_ASSETS
|
|
200
|
+
stylesheet_full_path = assets_app_path / stylesheet.strip("/")
|
|
201
|
+
|
|
199
202
|
if not stylesheet_full_path.exists():
|
|
200
203
|
raise FileNotFoundError(
|
|
201
204
|
f"The stylesheet file {stylesheet_full_path} does not exist."
|
|
202
205
|
)
|
|
203
|
-
|
|
206
|
+
|
|
207
|
+
if stylesheet_full_path.is_dir():
|
|
208
|
+
# NOTE: this can create an infinite loop, for example:
|
|
209
|
+
# assets/
|
|
210
|
+
# | dir_a/
|
|
211
|
+
# | | dir_c/ (symlink to "assets/dir_a")
|
|
212
|
+
# | dir_b/
|
|
213
|
+
# so to avoid the infinite loop, we don't include symbolic links
|
|
214
|
+
stylesheets += [
|
|
215
|
+
str(p.relative_to(assets_app_path))
|
|
216
|
+
for p in stylesheet_full_path.iterdir()
|
|
217
|
+
if not (p.is_symlink() and p.is_dir())
|
|
218
|
+
]
|
|
219
|
+
continue
|
|
220
|
+
|
|
221
|
+
if (
|
|
222
|
+
stylesheet_full_path.suffix[1:].lower()
|
|
223
|
+
in constants.Reflex.STYLESHEETS_SUPPORTED
|
|
224
|
+
):
|
|
225
|
+
target = (
|
|
226
|
+
Path.cwd()
|
|
227
|
+
/ constants.Dirs.WEB
|
|
228
|
+
/ constants.Dirs.STYLES
|
|
229
|
+
/ (stylesheet.rsplit(".", 1)[0].strip("/") + ".css")
|
|
230
|
+
)
|
|
231
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
232
|
+
|
|
233
|
+
if stylesheet_full_path.suffix == ".css":
|
|
234
|
+
path_ops.cp(src=stylesheet_full_path, dest=target, overwrite=True)
|
|
235
|
+
else:
|
|
236
|
+
try:
|
|
237
|
+
from sass import compile as sass_compile
|
|
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
|
|
248
|
+
else:
|
|
249
|
+
raise FileNotFoundError(
|
|
250
|
+
f'The stylesheet file "{stylesheet_full_path}" is not a valid file.'
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
stylesheet = f"./{stylesheet.rsplit('.', 1)[0].strip('/')}.css"
|
|
254
|
+
|
|
204
255
|
sheets.append(stylesheet) if stylesheet not in sheets else None
|
|
256
|
+
|
|
257
|
+
if failed_to_import_sass:
|
|
258
|
+
console.error(
|
|
259
|
+
'The `libsass` package is required to compile sass/scss stylesheet files. Run `pip install "libsass>=0.23.0"`.'
|
|
260
|
+
)
|
|
261
|
+
|
|
205
262
|
return templates.STYLE.render(stylesheets=sheets)
|
|
206
263
|
|
|
207
264
|
|
reflex/components/core/upload.py
CHANGED
|
@@ -71,7 +71,7 @@ class Plotly(NoSSRComponent):
|
|
|
71
71
|
|
|
72
72
|
library = "react-plotly.js@2.6.0"
|
|
73
73
|
|
|
74
|
-
lib_dependencies: list[str] = ["plotly.js@
|
|
74
|
+
lib_dependencies: list[str] = ["plotly.js@3.0.1"]
|
|
75
75
|
|
|
76
76
|
tag = "Plot"
|
|
77
77
|
|
|
@@ -289,7 +289,7 @@ class PlotlyBasic(Plotly):
|
|
|
289
289
|
|
|
290
290
|
library = "react-plotly.js@2.6.0"
|
|
291
291
|
|
|
292
|
-
lib_dependencies: list[str] = ["plotly.js-basic-dist-min@3.0.
|
|
292
|
+
lib_dependencies: list[str] = ["plotly.js-basic-dist-min@3.0.1"]
|
|
293
293
|
|
|
294
294
|
def add_imports(self) -> ImportDict | list[ImportDict]:
|
|
295
295
|
"""Add imports for the plotly basic component.
|
|
@@ -315,7 +315,7 @@ class PlotlyCartesian(Plotly):
|
|
|
315
315
|
|
|
316
316
|
library = "react-plotly.js@2.6.0"
|
|
317
317
|
|
|
318
|
-
lib_dependencies: list[str] = ["plotly.js-cartesian-dist-min@3.0.
|
|
318
|
+
lib_dependencies: list[str] = ["plotly.js-cartesian-dist-min@3.0.1"]
|
|
319
319
|
|
|
320
320
|
def add_imports(self) -> ImportDict | list[ImportDict]:
|
|
321
321
|
"""Add imports for the plotly cartesian component.
|
|
@@ -341,7 +341,7 @@ class PlotlyGeo(Plotly):
|
|
|
341
341
|
|
|
342
342
|
library = "react-plotly.js@2.6.0"
|
|
343
343
|
|
|
344
|
-
lib_dependencies: list[str] = ["plotly.js-geo-dist-min@3.0.
|
|
344
|
+
lib_dependencies: list[str] = ["plotly.js-geo-dist-min@3.0.1"]
|
|
345
345
|
|
|
346
346
|
def add_imports(self) -> ImportDict | list[ImportDict]:
|
|
347
347
|
"""Add imports for the plotly geo component.
|
|
@@ -367,7 +367,7 @@ class PlotlyGl3d(Plotly):
|
|
|
367
367
|
|
|
368
368
|
library = "react-plotly.js@2.6.0"
|
|
369
369
|
|
|
370
|
-
lib_dependencies: list[str] = ["plotly.js-gl3d-dist-min@3.0.
|
|
370
|
+
lib_dependencies: list[str] = ["plotly.js-gl3d-dist-min@3.0.1"]
|
|
371
371
|
|
|
372
372
|
def add_imports(self) -> ImportDict | list[ImportDict]:
|
|
373
373
|
"""Add imports for the plotly 3d component.
|
|
@@ -393,7 +393,7 @@ class PlotlyGl2d(Plotly):
|
|
|
393
393
|
|
|
394
394
|
library = "react-plotly.js@2.6.0"
|
|
395
395
|
|
|
396
|
-
lib_dependencies: list[str] = ["plotly.js-gl2d-dist-min@3.0.
|
|
396
|
+
lib_dependencies: list[str] = ["plotly.js-gl2d-dist-min@3.0.1"]
|
|
397
397
|
|
|
398
398
|
def add_imports(self) -> ImportDict | list[ImportDict]:
|
|
399
399
|
"""Add imports for the plotly 2d component.
|
|
@@ -419,7 +419,7 @@ class PlotlyMapbox(Plotly):
|
|
|
419
419
|
|
|
420
420
|
library = "react-plotly.js@2.6.0"
|
|
421
421
|
|
|
422
|
-
lib_dependencies: list[str] = ["plotly.js-mapbox-dist-min@3.0.
|
|
422
|
+
lib_dependencies: list[str] = ["plotly.js-mapbox-dist-min@3.0.1"]
|
|
423
423
|
|
|
424
424
|
def add_imports(self) -> ImportDict | list[ImportDict]:
|
|
425
425
|
"""Add imports for the plotly mapbox component.
|
|
@@ -445,7 +445,7 @@ class PlotlyFinance(Plotly):
|
|
|
445
445
|
|
|
446
446
|
library = "react-plotly.js@2.6.0"
|
|
447
447
|
|
|
448
|
-
lib_dependencies: list[str] = ["plotly.js-finance-dist-min@3.0.
|
|
448
|
+
lib_dependencies: list[str] = ["plotly.js-finance-dist-min@3.0.1"]
|
|
449
449
|
|
|
450
450
|
def add_imports(self) -> ImportDict | list[ImportDict]:
|
|
451
451
|
"""Add imports for the plotly finance component.
|
|
@@ -471,7 +471,7 @@ class PlotlyStrict(Plotly):
|
|
|
471
471
|
|
|
472
472
|
library = "react-plotly.js@2.6.0"
|
|
473
473
|
|
|
474
|
-
lib_dependencies: list[str] = ["plotly.js-strict-dist-min@3.0.
|
|
474
|
+
lib_dependencies: list[str] = ["plotly.js-strict-dist-min@3.0.1"]
|
|
475
475
|
|
|
476
476
|
def add_imports(self) -> ImportDict | list[ImportDict]:
|
|
477
477
|
"""Add imports for the plotly strict component.
|
|
@@ -8,7 +8,7 @@ from reflex.components.component import Component, MemoizationLeaf, NoSSRCompone
|
|
|
8
8
|
class Recharts(Component):
|
|
9
9
|
"""A component that wraps a recharts lib."""
|
|
10
10
|
|
|
11
|
-
library = "recharts@2.15.
|
|
11
|
+
library = "recharts@2.15.1"
|
|
12
12
|
|
|
13
13
|
def _get_style(self) -> dict:
|
|
14
14
|
return {"wrapperStyle": self.style}
|
|
@@ -17,7 +17,7 @@ class Recharts(Component):
|
|
|
17
17
|
class RechartsCharts(NoSSRComponent, MemoizationLeaf):
|
|
18
18
|
"""A component that wraps a recharts lib."""
|
|
19
19
|
|
|
20
|
-
library = "recharts@2.15.
|
|
20
|
+
library = "recharts@2.15.1"
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
LiteralAnimationEasing = Literal["ease", "ease-in", "ease-out", "ease-in-out", "linear"]
|
|
@@ -172,7 +172,7 @@ class ToastProps(PropsBase, NoExtrasAllowedProps):
|
|
|
172
172
|
class Toaster(Component):
|
|
173
173
|
"""A Toaster Component for displaying toast notifications."""
|
|
174
174
|
|
|
175
|
-
library: str | None = "sonner@
|
|
175
|
+
library: str | None = "sonner@2.0.1"
|
|
176
176
|
|
|
177
177
|
tag = "Toaster"
|
|
178
178
|
|
reflex/config.py
CHANGED
|
@@ -596,7 +596,7 @@ class EnvironmentVariables:
|
|
|
596
596
|
constants.CompileContext.UNDEFINED, internal=True
|
|
597
597
|
)
|
|
598
598
|
|
|
599
|
-
# Whether to use npm over bun to install frontend
|
|
599
|
+
# Whether to use npm over bun to install and run the frontend.
|
|
600
600
|
REFLEX_USE_NPM: EnvVar[bool] = env_var(False)
|
|
601
601
|
|
|
602
602
|
# The npm registry to use.
|
|
@@ -614,9 +614,6 @@ class EnvironmentVariables:
|
|
|
614
614
|
# Whether to use the system installed bun. If set to false, bun will be bundled with the app.
|
|
615
615
|
REFLEX_USE_SYSTEM_BUN: EnvVar[bool] = env_var(False)
|
|
616
616
|
|
|
617
|
-
# Whether to use the system installed node and npm. If set to false, node and npm will be bundled with the app.
|
|
618
|
-
REFLEX_USE_SYSTEM_NODE: EnvVar[bool] = env_var(False)
|
|
619
|
-
|
|
620
617
|
# The working directory for the next.js commands.
|
|
621
618
|
REFLEX_WEB_WORKDIR: EnvVar[Path] = env_var(Path(constants.Dirs.WEB))
|
|
622
619
|
|
|
@@ -964,7 +961,7 @@ class Config(Base):
|
|
|
964
961
|
env_var = "***"
|
|
965
962
|
|
|
966
963
|
if value != getattr(self, key):
|
|
967
|
-
console.
|
|
964
|
+
console.debug(
|
|
968
965
|
f"Overriding config value {key} with env var {key.upper()}={env_var}",
|
|
969
966
|
dedupe=True,
|
|
970
967
|
)
|
reflex/constants/__init__.py
CHANGED
|
@@ -45,7 +45,7 @@ from .config import (
|
|
|
45
45
|
)
|
|
46
46
|
from .custom_components import CustomComponents
|
|
47
47
|
from .event import Endpoint, EventTriggers, SocketEvent
|
|
48
|
-
from .installer import Bun,
|
|
48
|
+
from .installer import Bun, Node, PackageJson
|
|
49
49
|
from .route import (
|
|
50
50
|
ROUTE_NOT_FOUND,
|
|
51
51
|
ROUTER,
|
|
@@ -94,7 +94,6 @@ __all__ = [
|
|
|
94
94
|
"EventTriggers",
|
|
95
95
|
"Expiration",
|
|
96
96
|
"Ext",
|
|
97
|
-
"Fnm",
|
|
98
97
|
"GitIgnore",
|
|
99
98
|
"Hooks",
|
|
100
99
|
"Imports",
|
reflex/constants/base.py
CHANGED
|
@@ -88,6 +88,9 @@ class Reflex(SimpleNamespace):
|
|
|
88
88
|
|
|
89
89
|
RELEASES_URL = "https://api.github.com/repos/reflex-dev/templates/releases"
|
|
90
90
|
|
|
91
|
+
# The reflex stylesheet language supported
|
|
92
|
+
STYLESHEETS_SUPPORTED = ["css", "sass", "scss"]
|
|
93
|
+
|
|
91
94
|
|
|
92
95
|
class ReflexHostingCLI(SimpleNamespace):
|
|
93
96
|
"""Base constants concerning Reflex Hosting CLI."""
|
reflex/constants/installer.py
CHANGED
|
@@ -1,46 +1,22 @@
|
|
|
1
|
-
"""File for constants related to the installation process. (Bun/
|
|
1
|
+
"""File for constants related to the installation process. (Bun/Node)."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import platform
|
|
6
|
-
from pathlib import Path
|
|
7
5
|
from types import SimpleNamespace
|
|
8
6
|
|
|
9
7
|
from .base import IS_WINDOWS
|
|
10
8
|
from .utils import classproperty
|
|
11
9
|
|
|
12
10
|
|
|
13
|
-
def get_fnm_name() -> str | None:
|
|
14
|
-
"""Get the appropriate fnm executable name based on the current platform.
|
|
15
|
-
|
|
16
|
-
Returns:
|
|
17
|
-
The fnm executable name for the current platform.
|
|
18
|
-
"""
|
|
19
|
-
platform_os = platform.system()
|
|
20
|
-
|
|
21
|
-
if platform_os == "Windows":
|
|
22
|
-
return "fnm-windows"
|
|
23
|
-
elif platform_os == "Darwin":
|
|
24
|
-
return "fnm-macos"
|
|
25
|
-
elif platform_os == "Linux":
|
|
26
|
-
machine = platform.machine()
|
|
27
|
-
if machine == "arm" or machine.startswith("armv7"):
|
|
28
|
-
return "fnm-arm32"
|
|
29
|
-
elif machine.startswith("aarch") or machine.startswith("armv8"):
|
|
30
|
-
return "fnm-arm64"
|
|
31
|
-
return "fnm-linux"
|
|
32
|
-
return None
|
|
33
|
-
|
|
34
|
-
|
|
35
11
|
# Bun config.
|
|
36
12
|
class Bun(SimpleNamespace):
|
|
37
13
|
"""Bun constants."""
|
|
38
14
|
|
|
39
15
|
# The Bun version.
|
|
40
|
-
VERSION = "1.2.
|
|
16
|
+
VERSION = "1.2.4"
|
|
41
17
|
|
|
42
18
|
# Min Bun Version
|
|
43
|
-
MIN_VERSION = "1.
|
|
19
|
+
MIN_VERSION = "1.2.4"
|
|
44
20
|
|
|
45
21
|
# URL to bun install script.
|
|
46
22
|
INSTALL_URL = "https://raw.githubusercontent.com/reflex-dev/reflex/main/scripts/bun_install.sh"
|
|
@@ -81,43 +57,6 @@ registry = "{registry}"
|
|
|
81
57
|
"""
|
|
82
58
|
|
|
83
59
|
|
|
84
|
-
# FNM config.
|
|
85
|
-
class Fnm(SimpleNamespace):
|
|
86
|
-
"""FNM constants."""
|
|
87
|
-
|
|
88
|
-
# The FNM version.
|
|
89
|
-
VERSION = "1.35.1"
|
|
90
|
-
|
|
91
|
-
FILENAME = get_fnm_name()
|
|
92
|
-
|
|
93
|
-
# The URL to the fnm release binary
|
|
94
|
-
INSTALL_URL = (
|
|
95
|
-
f"https://github.com/Schniz/fnm/releases/download/v{VERSION}/{FILENAME}.zip"
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
@classproperty
|
|
99
|
-
@classmethod
|
|
100
|
-
def DIR(cls) -> Path:
|
|
101
|
-
"""The directory to store fnm.
|
|
102
|
-
|
|
103
|
-
Returns:
|
|
104
|
-
The directory to store fnm.
|
|
105
|
-
"""
|
|
106
|
-
from reflex.config import environment
|
|
107
|
-
|
|
108
|
-
return environment.REFLEX_DIR.get() / "fnm"
|
|
109
|
-
|
|
110
|
-
@classproperty
|
|
111
|
-
@classmethod
|
|
112
|
-
def EXE(cls):
|
|
113
|
-
"""The fnm executable binary.
|
|
114
|
-
|
|
115
|
-
Returns:
|
|
116
|
-
The fnm executable binary.
|
|
117
|
-
"""
|
|
118
|
-
return cls.DIR / ("fnm.exe" if IS_WINDOWS else "fnm")
|
|
119
|
-
|
|
120
|
-
|
|
121
60
|
# Node / NPM config
|
|
122
61
|
class Node(SimpleNamespace):
|
|
123
62
|
"""Node/ NPM constants."""
|
|
@@ -127,42 +66,6 @@ class Node(SimpleNamespace):
|
|
|
127
66
|
# The minimum required node version.
|
|
128
67
|
MIN_VERSION = "18.18.0"
|
|
129
68
|
|
|
130
|
-
@classproperty
|
|
131
|
-
@classmethod
|
|
132
|
-
def BIN_PATH(cls):
|
|
133
|
-
"""The node bin path.
|
|
134
|
-
|
|
135
|
-
Returns:
|
|
136
|
-
The node bin path.
|
|
137
|
-
"""
|
|
138
|
-
return (
|
|
139
|
-
Fnm.DIR
|
|
140
|
-
/ "node-versions"
|
|
141
|
-
/ f"v{cls.VERSION}"
|
|
142
|
-
/ "installation"
|
|
143
|
-
/ ("bin" if not IS_WINDOWS else "")
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
@classproperty
|
|
147
|
-
@classmethod
|
|
148
|
-
def PATH(cls):
|
|
149
|
-
"""The default path where node is installed.
|
|
150
|
-
|
|
151
|
-
Returns:
|
|
152
|
-
The default path where node is installed.
|
|
153
|
-
"""
|
|
154
|
-
return cls.BIN_PATH / ("node.exe" if IS_WINDOWS else "node")
|
|
155
|
-
|
|
156
|
-
@classproperty
|
|
157
|
-
@classmethod
|
|
158
|
-
def NPM_PATH(cls):
|
|
159
|
-
"""The default path where npm is installed.
|
|
160
|
-
|
|
161
|
-
Returns:
|
|
162
|
-
The default path where npm is installed.
|
|
163
|
-
"""
|
|
164
|
-
return cls.BIN_PATH / "npm"
|
|
165
|
-
|
|
166
69
|
|
|
167
70
|
class PackageJson(SimpleNamespace):
|
|
168
71
|
"""Constants used to build the package.json file."""
|
|
@@ -179,11 +82,11 @@ class PackageJson(SimpleNamespace):
|
|
|
179
82
|
|
|
180
83
|
DEPENDENCIES = {
|
|
181
84
|
"@emotion/react": "11.14.0",
|
|
182
|
-
"axios": "1.
|
|
85
|
+
"axios": "1.8.3",
|
|
183
86
|
"json5": "2.2.3",
|
|
184
|
-
"next": "15.
|
|
87
|
+
"next": "15.0.4",
|
|
185
88
|
"next-sitemap": "4.2.3",
|
|
186
|
-
"next-themes": "0.4.
|
|
89
|
+
"next-themes": "0.4.6",
|
|
187
90
|
"react": "19.0.0",
|
|
188
91
|
"react-dom": "19.0.0",
|
|
189
92
|
"react-focus-lock": "2.13.6",
|
|
@@ -191,8 +94,8 @@ class PackageJson(SimpleNamespace):
|
|
|
191
94
|
"universal-cookie": "7.2.2",
|
|
192
95
|
}
|
|
193
96
|
DEV_DEPENDENCIES = {
|
|
194
|
-
"autoprefixer": "10.4.
|
|
195
|
-
"postcss": "8.5.
|
|
97
|
+
"autoprefixer": "10.4.21",
|
|
98
|
+
"postcss": "8.5.3",
|
|
196
99
|
"postcss-import": "16.1.0",
|
|
197
100
|
}
|
|
198
101
|
OVERRIDES = {
|
reflex/state.py
CHANGED
|
@@ -905,7 +905,14 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
905
905
|
]
|
|
906
906
|
if len(parent_states) >= 2:
|
|
907
907
|
raise ValueError(f"Only one parent state is allowed {parent_states}.")
|
|
908
|
-
|
|
908
|
+
# The first non-mixin state in the mro is our parent.
|
|
909
|
+
for base in cls.mro()[1:]:
|
|
910
|
+
if base._mixin or not issubclass(base, BaseState):
|
|
911
|
+
continue
|
|
912
|
+
if base is BaseState:
|
|
913
|
+
break
|
|
914
|
+
return base
|
|
915
|
+
return None # No known parent
|
|
909
916
|
|
|
910
917
|
@classmethod
|
|
911
918
|
@functools.lru_cache()
|
reflex/testing.py
CHANGED
|
@@ -371,7 +371,13 @@ class AppHarness:
|
|
|
371
371
|
|
|
372
372
|
# Start the frontend.
|
|
373
373
|
self.frontend_process = reflex.utils.processes.new_process(
|
|
374
|
-
[
|
|
374
|
+
[
|
|
375
|
+
*reflex.utils.prerequisites.get_js_package_executor(raise_on_none=True)[
|
|
376
|
+
0
|
|
377
|
+
],
|
|
378
|
+
"run",
|
|
379
|
+
"dev",
|
|
380
|
+
],
|
|
375
381
|
cwd=self.app_path / reflex.utils.prerequisites.get_web_dir(),
|
|
376
382
|
env={"PORT": "0"},
|
|
377
383
|
**FRONTEND_POPEN_ARGS,
|
reflex/utils/build.py
CHANGED
|
@@ -212,7 +212,7 @@ def build(
|
|
|
212
212
|
|
|
213
213
|
# Start the subprocess with the progress bar.
|
|
214
214
|
process = processes.new_process(
|
|
215
|
-
[prerequisites.
|
|
215
|
+
[*prerequisites.get_js_package_executor(raise_on_none=True)[0], "run", command],
|
|
216
216
|
cwd=wdir,
|
|
217
217
|
shell=constants.IS_WINDOWS,
|
|
218
218
|
)
|
|
@@ -231,11 +231,10 @@ def setup_frontend(
|
|
|
231
231
|
"""
|
|
232
232
|
# Create the assets dir if it doesn't exist.
|
|
233
233
|
path_ops.mkdir(constants.Dirs.APP_ASSETS)
|
|
234
|
-
|
|
235
|
-
# Copy asset files to public folder.
|
|
236
234
|
path_ops.cp(
|
|
237
235
|
src=str(root / constants.Dirs.APP_ASSETS),
|
|
238
236
|
dest=str(root / prerequisites.get_web_dir() / constants.Dirs.PUBLIC),
|
|
237
|
+
ignore=tuple(f"*.{ext}" for ext in constants.Reflex.STYLESHEETS_SUPPORTED),
|
|
239
238
|
)
|
|
240
239
|
|
|
241
240
|
# Set the environment variables in client (env.json).
|
|
@@ -248,7 +247,7 @@ def setup_frontend(
|
|
|
248
247
|
if disable_telemetry:
|
|
249
248
|
processes.new_process(
|
|
250
249
|
[
|
|
251
|
-
prerequisites.
|
|
250
|
+
*prerequisites.get_js_package_executor(raise_on_none=True)[0],
|
|
252
251
|
"run",
|
|
253
252
|
"next",
|
|
254
253
|
"telemetry",
|
reflex/utils/exec.py
CHANGED
|
@@ -154,7 +154,11 @@ def run_frontend(root: Path, port: str, backend_present: bool = True):
|
|
|
154
154
|
console.rule("[bold green]App Running")
|
|
155
155
|
os.environ["PORT"] = str(get_config().frontend_port if port is None else port)
|
|
156
156
|
run_process_and_launch_url(
|
|
157
|
-
[
|
|
157
|
+
[
|
|
158
|
+
*prerequisites.get_js_package_executor(raise_on_none=True)[0],
|
|
159
|
+
"run",
|
|
160
|
+
"dev",
|
|
161
|
+
],
|
|
158
162
|
backend_present,
|
|
159
163
|
)
|
|
160
164
|
|
|
@@ -176,7 +180,7 @@ def run_frontend_prod(root: Path, port: str, backend_present: bool = True):
|
|
|
176
180
|
# Run the frontend in production mode.
|
|
177
181
|
console.rule("[bold green]App Running")
|
|
178
182
|
run_process_and_launch_url(
|
|
179
|
-
[prerequisites.
|
|
183
|
+
[*prerequisites.get_js_package_executor(raise_on_none=True)[0], "run", "prod"],
|
|
180
184
|
backend_present,
|
|
181
185
|
)
|
|
182
186
|
|
|
@@ -518,13 +522,8 @@ def output_system_info():
|
|
|
518
522
|
|
|
519
523
|
system = platform.system()
|
|
520
524
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
dependencies.extend(
|
|
524
|
-
[
|
|
525
|
-
fnm_info,
|
|
526
|
-
f"[Bun {prerequisites.get_bun_version()} (Expected: {constants.Bun.VERSION}) (PATH: {path_ops.get_bun_path()})]",
|
|
527
|
-
],
|
|
525
|
+
dependencies.append(
|
|
526
|
+
f"[Bun {prerequisites.get_bun_version()} (Expected: {constants.Bun.VERSION}) (PATH: {path_ops.get_bun_path()})]"
|
|
528
527
|
)
|
|
529
528
|
|
|
530
529
|
if system == "Linux":
|
|
@@ -540,10 +539,10 @@ def output_system_info():
|
|
|
540
539
|
console.debug(f"{dep}")
|
|
541
540
|
|
|
542
541
|
console.debug(
|
|
543
|
-
f"Using package installer at: {prerequisites.
|
|
542
|
+
f"Using package installer at: {prerequisites.get_nodejs_compatible_package_managers(raise_on_none=False)}"
|
|
544
543
|
)
|
|
545
544
|
console.debug(
|
|
546
|
-
f"Using package executer at: {prerequisites.
|
|
545
|
+
f"Using package executer at: {prerequisites.get_js_package_executor(raise_on_none=False)}"
|
|
547
546
|
)
|
|
548
547
|
if system != "Windows":
|
|
549
548
|
console.debug(f"Unzip path: {path_ops.which('unzip')}")
|
reflex/utils/path_ops.py
CHANGED
|
@@ -9,7 +9,6 @@ import shutil
|
|
|
9
9
|
import stat
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
|
|
12
|
-
from reflex import constants
|
|
13
12
|
from reflex.config import environment, get_config
|
|
14
13
|
|
|
15
14
|
# Shorthand for join.
|
|
@@ -43,13 +42,19 @@ def rm(path: str | Path):
|
|
|
43
42
|
path.unlink()
|
|
44
43
|
|
|
45
44
|
|
|
46
|
-
def cp(
|
|
45
|
+
def cp(
|
|
46
|
+
src: str | Path,
|
|
47
|
+
dest: str | Path,
|
|
48
|
+
overwrite: bool = True,
|
|
49
|
+
ignore: tuple[str, ...] | None = None,
|
|
50
|
+
) -> bool:
|
|
47
51
|
"""Copy a file or directory.
|
|
48
52
|
|
|
49
53
|
Args:
|
|
50
54
|
src: The path to the file or directory.
|
|
51
55
|
dest: The path to the destination.
|
|
52
56
|
overwrite: Whether to overwrite the destination.
|
|
57
|
+
ignore: Ignoring files and directories that match one of the glob-style patterns provided
|
|
53
58
|
|
|
54
59
|
Returns:
|
|
55
60
|
Whether the copy was successful.
|
|
@@ -61,7 +66,11 @@ def cp(src: str | Path, dest: str | Path, overwrite: bool = True) -> bool:
|
|
|
61
66
|
return False
|
|
62
67
|
if src.is_dir():
|
|
63
68
|
rm(dest)
|
|
64
|
-
shutil.copytree(
|
|
69
|
+
shutil.copytree(
|
|
70
|
+
src,
|
|
71
|
+
dest,
|
|
72
|
+
ignore=shutil.ignore_patterns(*ignore) if ignore is not None else ignore,
|
|
73
|
+
)
|
|
65
74
|
else:
|
|
66
75
|
shutil.copyfile(src, dest)
|
|
67
76
|
return True
|
|
@@ -146,15 +155,6 @@ def which(program: str | Path) -> Path | None:
|
|
|
146
155
|
return Path(which_result) if which_result else None
|
|
147
156
|
|
|
148
157
|
|
|
149
|
-
def use_system_node() -> bool:
|
|
150
|
-
"""Check if the system node should be used.
|
|
151
|
-
|
|
152
|
-
Returns:
|
|
153
|
-
Whether the system node should be used.
|
|
154
|
-
"""
|
|
155
|
-
return environment.REFLEX_USE_SYSTEM_NODE.get()
|
|
156
|
-
|
|
157
|
-
|
|
158
158
|
def use_system_bun() -> bool:
|
|
159
159
|
"""Check if the system bun should be used.
|
|
160
160
|
|
|
@@ -170,11 +170,7 @@ def get_node_bin_path() -> Path | None:
|
|
|
170
170
|
Returns:
|
|
171
171
|
The path to the node bin folder.
|
|
172
172
|
"""
|
|
173
|
-
bin_path
|
|
174
|
-
if not bin_path.exists():
|
|
175
|
-
path = which("node")
|
|
176
|
-
return path.parent.absolute() if path else None
|
|
177
|
-
return bin_path.absolute()
|
|
173
|
+
return bin_path.parent.absolute() if (bin_path := get_node_path()) else None
|
|
178
174
|
|
|
179
175
|
|
|
180
176
|
def get_node_path() -> Path | None:
|
|
@@ -183,10 +179,7 @@ def get_node_path() -> Path | None:
|
|
|
183
179
|
Returns:
|
|
184
180
|
The path to the node binary file.
|
|
185
181
|
"""
|
|
186
|
-
|
|
187
|
-
if use_system_node() or not node_path.exists():
|
|
188
|
-
node_path = which("node")
|
|
189
|
-
return node_path
|
|
182
|
+
return which("node")
|
|
190
183
|
|
|
191
184
|
|
|
192
185
|
def get_npm_path() -> Path | None:
|
|
@@ -195,10 +188,7 @@ def get_npm_path() -> Path | None:
|
|
|
195
188
|
Returns:
|
|
196
189
|
The path to the npm binary file.
|
|
197
190
|
"""
|
|
198
|
-
npm_path
|
|
199
|
-
if use_system_node() or not npm_path.exists():
|
|
200
|
-
npm_path = which("npm")
|
|
201
|
-
return npm_path.absolute() if npm_path else None
|
|
191
|
+
return npm_path.absolute() if (npm_path := which("npm")) else None
|
|
202
192
|
|
|
203
193
|
|
|
204
194
|
def get_bun_path() -> Path | None:
|