reflex 0.8.0a5__py3-none-any.whl → 0.8.0a7__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/.templates/web/utils/state.js +78 -31
- reflex/__init__.pyi +327 -188
- reflex/app.py +17 -7
- reflex/compiler/compiler.py +3 -1
- reflex/compiler/utils.py +28 -12
- reflex/components/__init__.pyi +34 -15
- reflex/components/base/__init__.pyi +30 -19
- reflex/components/base/app_wrap.pyi +2 -3
- reflex/components/base/body.pyi +2 -3
- reflex/components/base/document.pyi +7 -13
- reflex/components/base/error_boundary.pyi +2 -3
- reflex/components/base/fragment.pyi +2 -3
- reflex/components/base/link.pyi +3 -5
- reflex/components/base/meta.pyi +14 -18
- reflex/components/base/script.pyi +2 -3
- reflex/components/base/strict_mode.pyi +2 -3
- reflex/components/core/__init__.pyi +77 -38
- reflex/components/core/auto_scroll.pyi +2 -3
- reflex/components/core/banner.pyi +8 -14
- reflex/components/core/client_side_routing.pyi +2 -3
- reflex/components/core/clipboard.pyi +2 -3
- reflex/components/core/debounce.pyi +2 -3
- reflex/components/core/helmet.pyi +2 -3
- reflex/components/core/html.pyi +2 -3
- reflex/components/core/sticky.pyi +4 -7
- reflex/components/core/upload.pyi +5 -9
- reflex/components/datadisplay/__init__.pyi +13 -7
- reflex/components/datadisplay/code.pyi +2 -3
- reflex/components/datadisplay/dataeditor.pyi +33 -11
- reflex/components/datadisplay/shiki_code_block.pyi +3 -5
- reflex/components/el/__init__.pyi +506 -246
- reflex/components/el/element.pyi +2 -3
- reflex/components/el/elements/__init__.pyi +504 -245
- reflex/components/el/elements/base.pyi +2 -3
- reflex/components/el/elements/forms.pyi +77 -49
- reflex/components/el/elements/inline.pyi +29 -57
- reflex/components/el/elements/media.pyi +26 -51
- reflex/components/el/elements/metadata.pyi +7 -13
- reflex/components/el/elements/other.pyi +8 -15
- reflex/components/el/elements/scripts.pyi +4 -7
- reflex/components/el/elements/sectioning.pyi +16 -31
- reflex/components/el/elements/tables.pyi +11 -21
- reflex/components/el/elements/typography.pyi +16 -31
- reflex/components/gridjs/datatable.pyi +3 -5
- reflex/components/lucide/icon.pyi +4 -7
- reflex/components/markdown/markdown.pyi +2 -3
- reflex/components/moment/moment.py +1 -1
- reflex/components/moment/moment.pyi +2 -3
- reflex/components/plotly/plotly.pyi +31 -39
- reflex/components/radix/__init__.pyi +123 -65
- reflex/components/radix/primitives/__init__.pyi +6 -4
- reflex/components/radix/primitives/accordion.pyi +8 -15
- reflex/components/radix/primitives/base.pyi +3 -5
- reflex/components/radix/primitives/drawer.pyi +11 -21
- reflex/components/radix/primitives/form.pyi +22 -22
- reflex/components/radix/primitives/progress.pyi +5 -9
- reflex/components/radix/primitives/slider.pyi +6 -11
- reflex/components/radix/themes/__init__.pyi +5 -6
- reflex/components/radix/themes/base.pyi +9 -17
- reflex/components/radix/themes/color_mode.pyi +4 -7
- reflex/components/radix/themes/components/__init__.pyi +75 -38
- reflex/components/radix/themes/components/alert_dialog.pyi +8 -15
- reflex/components/radix/themes/components/aspect_ratio.pyi +2 -3
- reflex/components/radix/themes/components/avatar.pyi +2 -3
- reflex/components/radix/themes/components/badge.pyi +2 -3
- reflex/components/radix/themes/components/button.pyi +2 -3
- reflex/components/radix/themes/components/callout.pyi +5 -9
- reflex/components/radix/themes/components/card.pyi +2 -3
- reflex/components/radix/themes/components/checkbox.pyi +3 -5
- reflex/components/radix/themes/components/checkbox_cards.pyi +3 -5
- reflex/components/radix/themes/components/checkbox_group.pyi +3 -5
- reflex/components/radix/themes/components/context_menu.pyi +14 -27
- reflex/components/radix/themes/components/data_list.pyi +5 -9
- reflex/components/radix/themes/components/dialog.pyi +7 -13
- reflex/components/radix/themes/components/dropdown_menu.pyi +9 -17
- reflex/components/radix/themes/components/hover_card.pyi +4 -7
- reflex/components/radix/themes/components/icon_button.pyi +2 -3
- reflex/components/radix/themes/components/inset.pyi +2 -3
- reflex/components/radix/themes/components/popover.pyi +5 -9
- reflex/components/radix/themes/components/progress.pyi +2 -3
- reflex/components/radix/themes/components/radio.pyi +2 -3
- reflex/components/radix/themes/components/radio_cards.pyi +3 -5
- reflex/components/radix/themes/components/radio_group.pyi +4 -7
- reflex/components/radix/themes/components/scroll_area.pyi +2 -3
- reflex/components/radix/themes/components/segmented_control.pyi +3 -5
- reflex/components/radix/themes/components/select.pyi +9 -17
- reflex/components/radix/themes/components/separator.pyi +2 -3
- reflex/components/radix/themes/components/skeleton.pyi +2 -3
- reflex/components/radix/themes/components/slider.pyi +12 -5
- reflex/components/radix/themes/components/spinner.pyi +2 -3
- reflex/components/radix/themes/components/switch.pyi +2 -3
- reflex/components/radix/themes/components/table.pyi +8 -15
- reflex/components/radix/themes/components/tabs.pyi +5 -9
- reflex/components/radix/themes/components/text_area.pyi +10 -5
- reflex/components/radix/themes/components/text_field.pyi +19 -9
- reflex/components/radix/themes/components/tooltip.pyi +2 -3
- reflex/components/radix/themes/layout/__init__.pyi +27 -14
- reflex/components/radix/themes/layout/base.pyi +2 -3
- reflex/components/radix/themes/layout/box.pyi +2 -3
- reflex/components/radix/themes/layout/center.pyi +2 -3
- reflex/components/radix/themes/layout/container.pyi +2 -3
- reflex/components/radix/themes/layout/flex.pyi +2 -3
- reflex/components/radix/themes/layout/grid.pyi +2 -3
- reflex/components/radix/themes/layout/list.pyi +5 -9
- reflex/components/radix/themes/layout/section.pyi +2 -3
- reflex/components/radix/themes/layout/spacer.pyi +2 -3
- reflex/components/radix/themes/layout/stack.pyi +4 -7
- reflex/components/radix/themes/typography/__init__.pyi +7 -5
- reflex/components/radix/themes/typography/blockquote.pyi +2 -3
- reflex/components/radix/themes/typography/code.pyi +2 -3
- reflex/components/radix/themes/typography/heading.pyi +2 -3
- reflex/components/radix/themes/typography/link.pyi +3 -5
- reflex/components/radix/themes/typography/text.pyi +7 -13
- reflex/components/react_player/audio.pyi +5 -4
- reflex/components/react_player/react_player.pyi +2 -3
- reflex/components/react_player/video.pyi +5 -4
- reflex/components/recharts/__init__.pyi +208 -100
- reflex/components/recharts/cartesian.py +0 -6
- reflex/components/recharts/cartesian.pyi +25 -48
- reflex/components/recharts/charts.pyi +13 -25
- reflex/components/recharts/general.pyi +7 -13
- reflex/components/recharts/polar.pyi +7 -13
- reflex/components/recharts/recharts.py +2 -2
- reflex/components/recharts/recharts.pyi +3 -5
- reflex/components/sonner/toast.py +1 -1
- reflex/components/sonner/toast.pyi +2 -3
- reflex/config.py +7 -36
- reflex/constants/installer.py +7 -8
- reflex/environment.py +70 -0
- reflex/istate/__init__.py +69 -0
- reflex/istate/manager.py +1 -0
- reflex/plugins/shared_tailwind.py +58 -1
- reflex/plugins/tailwind_v3.py +4 -4
- reflex/plugins/tailwind_v4.py +6 -5
- reflex/state.py +17 -12
- reflex/testing.py +2 -1
- reflex/utils/exec.py +16 -6
- reflex/utils/imports.py +5 -12
- reflex/utils/misc.py +1 -2
- reflex/utils/prerequisites.py +1 -1
- reflex/utils/processes.py +14 -39
- reflex/utils/telemetry.py +0 -15
- {reflex-0.8.0a5.dist-info → reflex-0.8.0a7.dist-info}/METADATA +3 -3
- {reflex-0.8.0a5.dist-info → reflex-0.8.0a7.dist-info}/RECORD +148 -148
- {reflex-0.8.0a5.dist-info → reflex-0.8.0a7.dist-info}/WHEEL +0 -0
- {reflex-0.8.0a5.dist-info → reflex-0.8.0a7.dist-info}/entry_points.txt +0 -0
- {reflex-0.8.0a5.dist-info → reflex-0.8.0a7.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Tailwind CSS configuration types for Reflex plugins."""
|
|
2
2
|
|
|
3
3
|
import dataclasses
|
|
4
|
+
from copy import deepcopy
|
|
4
5
|
from typing import Any, Literal, TypedDict
|
|
5
6
|
|
|
6
7
|
from typing_extensions import NotRequired
|
|
@@ -40,6 +41,28 @@ TailwindPluginConfig = (
|
|
|
40
41
|
)
|
|
41
42
|
|
|
42
43
|
|
|
44
|
+
def remove_version_from_plugin(plugin: TailwindPluginConfig) -> TailwindPluginConfig:
|
|
45
|
+
"""Remove the version from a plugin name.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
plugin: The plugin to remove the version from.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
The plugin without the version.
|
|
52
|
+
"""
|
|
53
|
+
from reflex.utils.format import format_library_name
|
|
54
|
+
|
|
55
|
+
if isinstance(plugin, str):
|
|
56
|
+
return format_library_name(plugin)
|
|
57
|
+
|
|
58
|
+
if plugin_import := plugin.get("import"):
|
|
59
|
+
plugin_import["from"] = format_library_name(plugin_import["from"])
|
|
60
|
+
|
|
61
|
+
plugin["name"] = format_library_name(plugin["name"])
|
|
62
|
+
|
|
63
|
+
return plugin
|
|
64
|
+
|
|
65
|
+
|
|
43
66
|
class TailwindConfig(TypedDict):
|
|
44
67
|
"""Tailwind CSS configuration options.
|
|
45
68
|
|
|
@@ -131,11 +154,27 @@ class TailwindPlugin(PluginBase):
|
|
|
131
154
|
config: TailwindConfig = dataclasses.field(
|
|
132
155
|
default_factory=lambda: TailwindConfig(
|
|
133
156
|
plugins=[
|
|
134
|
-
"@tailwindcss/typography",
|
|
157
|
+
"@tailwindcss/typography@0.5.16",
|
|
135
158
|
],
|
|
136
159
|
)
|
|
137
160
|
)
|
|
138
161
|
|
|
162
|
+
def get_frontend_development_dependencies(self, **context) -> list[str]:
|
|
163
|
+
"""Get the packages required by the plugin.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
**context: The context for the plugin.
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
A list of packages required by the plugin.
|
|
170
|
+
"""
|
|
171
|
+
config = self.get_config()
|
|
172
|
+
|
|
173
|
+
return [
|
|
174
|
+
plugin if isinstance(plugin, str) else plugin.get("name")
|
|
175
|
+
for plugin in config.get("plugins", [])
|
|
176
|
+
] + config.get("presets", [])
|
|
177
|
+
|
|
139
178
|
def get_config(self) -> TailwindConfig:
|
|
140
179
|
"""Get the Tailwind CSS configuration.
|
|
141
180
|
|
|
@@ -156,3 +195,21 @@ class TailwindPlugin(PluginBase):
|
|
|
156
195
|
return rxconfig_config
|
|
157
196
|
|
|
158
197
|
return self.config
|
|
198
|
+
|
|
199
|
+
def get_unversioned_config(self) -> TailwindConfig:
|
|
200
|
+
"""Get the Tailwind CSS configuration without version-specific adjustments.
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
The Tailwind CSS configuration without version-specific adjustments.
|
|
204
|
+
"""
|
|
205
|
+
from reflex.utils.format import format_library_name
|
|
206
|
+
|
|
207
|
+
config = deepcopy(self.get_config())
|
|
208
|
+
if presets := config.get("presets"):
|
|
209
|
+
# Somehow, having an empty list of presets breaks Tailwind.
|
|
210
|
+
# So we only set the presets if there are any.
|
|
211
|
+
config["presets"] = [format_library_name(preset) for preset in presets]
|
|
212
|
+
config["plugins"] = [
|
|
213
|
+
remove_version_from_plugin(plugin) for plugin in config.get("plugins", [])
|
|
214
|
+
]
|
|
215
|
+
return config
|
reflex/plugins/tailwind_v3.py
CHANGED
|
@@ -151,9 +151,9 @@ class TailwindV3Plugin(TailwindPlugin):
|
|
|
151
151
|
A list of packages required by the plugin.
|
|
152
152
|
"""
|
|
153
153
|
return [
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
]
|
|
154
|
+
*super().get_frontend_development_dependencies(**context),
|
|
155
|
+
Constants.VERSION,
|
|
156
|
+
]
|
|
157
157
|
|
|
158
158
|
def pre_compile(self, **context):
|
|
159
159
|
"""Pre-compile the plugin.
|
|
@@ -161,7 +161,7 @@ class TailwindV3Plugin(TailwindPlugin):
|
|
|
161
161
|
Args:
|
|
162
162
|
context: The context for the plugin.
|
|
163
163
|
"""
|
|
164
|
-
context["add_save_task"](compile_config, self.
|
|
164
|
+
context["add_save_task"](compile_config, self.get_unversioned_config())
|
|
165
165
|
context["add_save_task"](compile_root_style)
|
|
166
166
|
context["add_modify_task"](Dirs.POSTCSS_JS, add_tailwind_to_postcss_config)
|
|
167
167
|
context["add_modify_task"](
|
reflex/plugins/tailwind_v4.py
CHANGED
|
@@ -17,7 +17,7 @@ class Constants(SimpleNamespace):
|
|
|
17
17
|
"""Tailwind constants."""
|
|
18
18
|
|
|
19
19
|
# The Tailwindcss version
|
|
20
|
-
VERSION = "tailwindcss@4.1.
|
|
20
|
+
VERSION = "tailwindcss@4.1.10"
|
|
21
21
|
# The Tailwind config.
|
|
22
22
|
CONFIG = "tailwind.config.js"
|
|
23
23
|
# Default Tailwind content paths
|
|
@@ -154,9 +154,10 @@ class TailwindV4Plugin(TailwindPlugin):
|
|
|
154
154
|
A list of packages required by the plugin.
|
|
155
155
|
"""
|
|
156
156
|
return [
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
*super().get_frontend_development_dependencies(**context),
|
|
158
|
+
Constants.VERSION,
|
|
159
|
+
"@tailwindcss/postcss@4.1.10",
|
|
160
|
+
]
|
|
160
161
|
|
|
161
162
|
def pre_compile(self, **context):
|
|
162
163
|
"""Pre-compile the plugin.
|
|
@@ -164,7 +165,7 @@ class TailwindV4Plugin(TailwindPlugin):
|
|
|
164
165
|
Args:
|
|
165
166
|
context: The context for the plugin.
|
|
166
167
|
"""
|
|
167
|
-
context["add_save_task"](compile_config, self.
|
|
168
|
+
context["add_save_task"](compile_config, self.get_unversioned_config())
|
|
168
169
|
context["add_save_task"](compile_root_style)
|
|
169
170
|
context["add_modify_task"](Dirs.POSTCSS_JS, add_tailwind_to_postcss_config)
|
|
170
171
|
context["add_modify_task"](
|
reflex/state.py
CHANGED
|
@@ -37,6 +37,7 @@ from reflex.event import (
|
|
|
37
37
|
EventSpec,
|
|
38
38
|
fix_events,
|
|
39
39
|
)
|
|
40
|
+
from reflex.istate import HANDLED_PICKLE_ERRORS, debug_failed_pickles
|
|
40
41
|
from reflex.istate.data import RouterData
|
|
41
42
|
from reflex.istate.proxy import ImmutableMutableProxy as ImmutableMutableProxy
|
|
42
43
|
from reflex.istate.proxy import MutableProxy, StateProxy
|
|
@@ -85,14 +86,6 @@ if environment.REFLEX_PERF_MODE.get() != PerformanceMode.OFF:
|
|
|
85
86
|
# Only warn about each state class size once.
|
|
86
87
|
_WARNED_ABOUT_STATE_SIZE: set[str] = set()
|
|
87
88
|
|
|
88
|
-
# Errors caught during pickling of state
|
|
89
|
-
HANDLED_PICKLE_ERRORS = (
|
|
90
|
-
pickle.PicklingError,
|
|
91
|
-
AttributeError,
|
|
92
|
-
IndexError,
|
|
93
|
-
TypeError,
|
|
94
|
-
ValueError,
|
|
95
|
-
)
|
|
96
89
|
|
|
97
90
|
# For BaseState.get_var_value
|
|
98
91
|
VAR_TYPE = TypeVar("VAR_TYPE")
|
|
@@ -2251,11 +2244,16 @@ class BaseState(EvenMoreBasicBaseState):
|
|
|
2251
2244
|
|
|
2252
2245
|
Raises:
|
|
2253
2246
|
StateSerializationError: If the state cannot be serialized.
|
|
2247
|
+
|
|
2248
|
+
# noqa: DAR401: e
|
|
2249
|
+
# noqa: DAR402: StateSerializationError
|
|
2254
2250
|
"""
|
|
2255
2251
|
payload = b""
|
|
2256
2252
|
error = ""
|
|
2253
|
+
self_schema = self._to_schema()
|
|
2254
|
+
pickle_function = pickle.dumps
|
|
2257
2255
|
try:
|
|
2258
|
-
payload = pickle.dumps((
|
|
2256
|
+
payload = pickle.dumps((self_schema, self))
|
|
2259
2257
|
except HANDLED_PICKLE_ERRORS as og_pickle_error:
|
|
2260
2258
|
error = (
|
|
2261
2259
|
f"Failed to serialize state {self.get_full_name()} due to unpicklable object. "
|
|
@@ -2264,7 +2262,8 @@ class BaseState(EvenMoreBasicBaseState):
|
|
|
2264
2262
|
try:
|
|
2265
2263
|
import dill
|
|
2266
2264
|
|
|
2267
|
-
|
|
2265
|
+
pickle_function = dill.dumps
|
|
2266
|
+
payload = dill.dumps((self_schema, self))
|
|
2268
2267
|
except ImportError:
|
|
2269
2268
|
error += (
|
|
2270
2269
|
f"Pickle error: {og_pickle_error}. "
|
|
@@ -2272,13 +2271,19 @@ class BaseState(EvenMoreBasicBaseState):
|
|
|
2272
2271
|
)
|
|
2273
2272
|
except HANDLED_PICKLE_ERRORS as ex:
|
|
2274
2273
|
error += f"Dill was also unable to pickle the state: {ex}"
|
|
2275
|
-
console.warn(error)
|
|
2276
2274
|
|
|
2277
2275
|
if environment.REFLEX_PERF_MODE.get() != PerformanceMode.OFF:
|
|
2278
2276
|
self._check_state_size(len(payload))
|
|
2279
2277
|
|
|
2280
2278
|
if not payload:
|
|
2281
|
-
|
|
2279
|
+
e = StateSerializationError(error)
|
|
2280
|
+
if sys.version_info >= (3, 11):
|
|
2281
|
+
try:
|
|
2282
|
+
debug_failed_pickles(self, pickle_function)
|
|
2283
|
+
except HANDLED_PICKLE_ERRORS as ex:
|
|
2284
|
+
for note in ex.__notes__:
|
|
2285
|
+
e.add_note(note)
|
|
2286
|
+
raise e
|
|
2282
2287
|
|
|
2283
2288
|
return payload
|
|
2284
2289
|
|
reflex/testing.py
CHANGED
|
@@ -24,7 +24,6 @@ from http.server import SimpleHTTPRequestHandler
|
|
|
24
24
|
from pathlib import Path
|
|
25
25
|
from typing import TYPE_CHECKING, Any, Literal, TypeVar
|
|
26
26
|
|
|
27
|
-
import psutil
|
|
28
27
|
import uvicorn
|
|
29
28
|
|
|
30
29
|
import reflex
|
|
@@ -478,6 +477,8 @@ class AppHarness:
|
|
|
478
477
|
|
|
479
478
|
def stop(self) -> None:
|
|
480
479
|
"""Stop the frontend and backend servers."""
|
|
480
|
+
import psutil
|
|
481
|
+
|
|
481
482
|
# Quit browsers first to avoid any lingering events being sent during shutdown.
|
|
482
483
|
for driver in self._frontends:
|
|
483
484
|
driver.quit()
|
reflex/utils/exec.py
CHANGED
|
@@ -15,8 +15,6 @@ from pathlib import Path
|
|
|
15
15
|
from typing import Any, NamedTuple, TypedDict
|
|
16
16
|
from urllib.parse import urljoin
|
|
17
17
|
|
|
18
|
-
import psutil
|
|
19
|
-
|
|
20
18
|
from reflex import constants
|
|
21
19
|
from reflex.config import get_config
|
|
22
20
|
from reflex.constants.base import LogLevel
|
|
@@ -131,12 +129,16 @@ def get_different_packages(
|
|
|
131
129
|
def kill(proc_pid: int):
|
|
132
130
|
"""Kills a process and all its child processes.
|
|
133
131
|
|
|
132
|
+
Requires the `psutil` library to be installed.
|
|
133
|
+
|
|
134
134
|
Args:
|
|
135
|
-
proc_pid
|
|
135
|
+
proc_pid: The process ID of the process to be killed.
|
|
136
136
|
|
|
137
137
|
Example:
|
|
138
138
|
>>> kill(1234)
|
|
139
139
|
"""
|
|
140
|
+
import psutil
|
|
141
|
+
|
|
140
142
|
process = psutil.Process(proc_pid)
|
|
141
143
|
for proc in process.children(recursive=True):
|
|
142
144
|
proc.kill()
|
|
@@ -365,6 +367,9 @@ def run_backend(
|
|
|
365
367
|
|
|
366
368
|
# Run the backend in development mode.
|
|
367
369
|
if should_use_granian():
|
|
370
|
+
# We import reflex app because this lets granian cache the module
|
|
371
|
+
import reflex.app # noqa: F401
|
|
372
|
+
|
|
368
373
|
run_granian_backend(host, port, loglevel)
|
|
369
374
|
else:
|
|
370
375
|
run_uvicorn_backend(host, port, loglevel)
|
|
@@ -514,9 +519,11 @@ def run_granian_backend(host: str, port: int, loglevel: LogLevel):
|
|
|
514
519
|
|
|
515
520
|
from granian.constants import Interfaces
|
|
516
521
|
from granian.log import LogLevels
|
|
517
|
-
from granian.server import
|
|
522
|
+
from granian.server import Server as Granian
|
|
518
523
|
|
|
519
|
-
|
|
524
|
+
from reflex.environment import _paths_from_environment
|
|
525
|
+
|
|
526
|
+
granian_app = Granian(
|
|
520
527
|
target=get_app_instance_from_file(),
|
|
521
528
|
factory=True,
|
|
522
529
|
address=host,
|
|
@@ -528,8 +535,11 @@ def run_granian_backend(host: str, port: int, loglevel: LogLevel):
|
|
|
528
535
|
reload_ignore_worker_failure=True,
|
|
529
536
|
reload_ignore_patterns=HOTRELOAD_IGNORE_PATTERNS,
|
|
530
537
|
reload_tick=100,
|
|
538
|
+
env_files=_paths_from_environment() or None,
|
|
531
539
|
workers_kill_timeout=2,
|
|
532
|
-
)
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
granian_app.serve()
|
|
533
543
|
|
|
534
544
|
|
|
535
545
|
def run_backend_prod(
|
reflex/utils/imports.py
CHANGED
|
@@ -52,19 +52,12 @@ def parse_imports(
|
|
|
52
52
|
Returns:
|
|
53
53
|
The parsed import dict.
|
|
54
54
|
"""
|
|
55
|
-
|
|
56
|
-
def _make_list(
|
|
57
|
-
value: ImmutableImportTypes,
|
|
58
|
-
) -> list[str | ImportVar] | list[ImportVar]:
|
|
59
|
-
if isinstance(value, (str, ImportVar)):
|
|
60
|
-
return [value]
|
|
61
|
-
return list(value)
|
|
62
|
-
|
|
63
55
|
return {
|
|
64
|
-
package: [
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
56
|
+
package: [maybe_tags]
|
|
57
|
+
if isinstance(maybe_tags, ImportVar)
|
|
58
|
+
else [ImportVar(tag=maybe_tags)]
|
|
59
|
+
if isinstance(maybe_tags, str)
|
|
60
|
+
else [ImportVar(tag=tag) if isinstance(tag, str) else tag for tag in maybe_tags]
|
|
68
61
|
for package, maybe_tags in imports.items()
|
|
69
62
|
}
|
|
70
63
|
|
reflex/utils/misc.py
CHANGED
|
@@ -31,14 +31,13 @@ def get_module_path(module_name: str) -> Path | None:
|
|
|
31
31
|
for i, part in enumerate(parts):
|
|
32
32
|
potential_file = current_path / (part + ".py")
|
|
33
33
|
potential_dir = current_path / part
|
|
34
|
-
potential_init = current_path / part / "__init__.py"
|
|
35
34
|
|
|
36
35
|
if potential_file.is_file():
|
|
37
36
|
# We encountered a file, but we can't continue deeper
|
|
38
37
|
if i == len(parts) - 1:
|
|
39
38
|
return potential_file
|
|
40
39
|
return None # Can't continue deeper
|
|
41
|
-
if potential_dir.is_dir()
|
|
40
|
+
if potential_dir.is_dir():
|
|
42
41
|
# It's a package, so we can continue deeper
|
|
43
42
|
current_path = potential_dir
|
|
44
43
|
else:
|
reflex/utils/prerequisites.py
CHANGED
|
@@ -116,7 +116,7 @@ def check_latest_package_version(package_name: str):
|
|
|
116
116
|
# Get the latest version from PyPI
|
|
117
117
|
current_version = importlib.metadata.version(package_name)
|
|
118
118
|
url = f"https://pypi.org/pypi/{package_name}/json"
|
|
119
|
-
response = net.get(url)
|
|
119
|
+
response = net.get(url, timeout=2)
|
|
120
120
|
latest_version = response.json()["info"]["version"]
|
|
121
121
|
console.debug(f"Latest version of {package_name}: {latest_version}")
|
|
122
122
|
if get_or_set_last_reflex_version_check_datetime():
|
reflex/utils/processes.py
CHANGED
|
@@ -4,17 +4,17 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import collections
|
|
6
6
|
import contextlib
|
|
7
|
-
import importlib.metadata
|
|
8
7
|
import os
|
|
9
8
|
import signal
|
|
9
|
+
import socket
|
|
10
10
|
import subprocess
|
|
11
11
|
from collections.abc import Callable, Generator, Sequence
|
|
12
12
|
from concurrent import futures
|
|
13
|
+
from contextlib import closing
|
|
13
14
|
from pathlib import Path
|
|
14
15
|
from typing import Any, Literal, overload
|
|
15
16
|
|
|
16
17
|
import click
|
|
17
|
-
import psutil
|
|
18
18
|
from redis.exceptions import RedisError
|
|
19
19
|
from rich.progress import Progress
|
|
20
20
|
|
|
@@ -52,29 +52,6 @@ def get_num_workers() -> int:
|
|
|
52
52
|
return (os.cpu_count() or 1) * 2 + 1
|
|
53
53
|
|
|
54
54
|
|
|
55
|
-
def get_process_on_port(port: int) -> psutil.Process | None:
|
|
56
|
-
"""Get the process on the given port.
|
|
57
|
-
|
|
58
|
-
Args:
|
|
59
|
-
port: The port.
|
|
60
|
-
|
|
61
|
-
Returns:
|
|
62
|
-
The process on the given port.
|
|
63
|
-
"""
|
|
64
|
-
for proc in psutil.process_iter(["pid", "name", "cmdline"]):
|
|
65
|
-
with contextlib.suppress(
|
|
66
|
-
psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess
|
|
67
|
-
):
|
|
68
|
-
if importlib.metadata.version("psutil") >= "6.0.0":
|
|
69
|
-
conns = proc.net_connections(kind="inet")
|
|
70
|
-
else:
|
|
71
|
-
conns = proc.connections(kind="inet")
|
|
72
|
-
for conn in conns:
|
|
73
|
-
if conn.laddr.port == int(port):
|
|
74
|
-
return proc
|
|
75
|
-
return None
|
|
76
|
-
|
|
77
|
-
|
|
78
55
|
def is_process_on_port(port: int) -> bool:
|
|
79
56
|
"""Check if a process is running on the given port.
|
|
80
57
|
|
|
@@ -84,18 +61,16 @@ def is_process_on_port(port: int) -> bool:
|
|
|
84
61
|
Returns:
|
|
85
62
|
Whether a process is running on the given port.
|
|
86
63
|
"""
|
|
87
|
-
|
|
64
|
+
# Test IPv4 localhost (127.0.0.1)
|
|
65
|
+
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
|
|
66
|
+
ipv4_result = sock.connect_ex(("127.0.0.1", port)) == 0
|
|
88
67
|
|
|
68
|
+
# Test IPv6 localhost (::1)
|
|
69
|
+
with closing(socket.socket(socket.AF_INET6, socket.SOCK_STREAM)) as sock:
|
|
70
|
+
ipv6_result = sock.connect_ex(("::1", port)) == 0
|
|
89
71
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
Args:
|
|
94
|
-
port: The port.
|
|
95
|
-
"""
|
|
96
|
-
if get_process_on_port(port) is not None:
|
|
97
|
-
with contextlib.suppress(psutil.AccessDenied):
|
|
98
|
-
get_process_on_port(port).kill() # pyright: ignore [reportOptionalMemberAccess]
|
|
72
|
+
# Port is in use if either IPv4 or IPv6 is listening
|
|
73
|
+
return ipv4_result or ipv6_result
|
|
99
74
|
|
|
100
75
|
|
|
101
76
|
def change_port(port: int, _type: str) -> int:
|
|
@@ -133,13 +108,13 @@ def handle_port(service_name: str, port: int, auto_increment: bool) -> int:
|
|
|
133
108
|
Raises:
|
|
134
109
|
Exit:when the port is in use.
|
|
135
110
|
"""
|
|
136
|
-
if (
|
|
111
|
+
console.debug(f"Checking if {service_name.capitalize()} port: {port} is in use.")
|
|
112
|
+
if not is_process_on_port(port):
|
|
113
|
+
console.debug(f"{service_name.capitalize()} port: {port} is not in use.")
|
|
137
114
|
return port
|
|
138
115
|
if auto_increment:
|
|
139
116
|
return change_port(port, service_name)
|
|
140
|
-
console.error(
|
|
141
|
-
f"{service_name.capitalize()} port: {port} is already in use by PID: {process.pid}."
|
|
142
|
-
)
|
|
117
|
+
console.error(f"{service_name.capitalize()} port: {port} is already in use.")
|
|
143
118
|
raise click.exceptions.Exit
|
|
144
119
|
|
|
145
120
|
|
reflex/utils/telemetry.py
CHANGED
|
@@ -13,7 +13,6 @@ from datetime import datetime, timezone
|
|
|
13
13
|
from typing import TypedDict
|
|
14
14
|
|
|
15
15
|
import httpx
|
|
16
|
-
import psutil
|
|
17
16
|
|
|
18
17
|
from reflex import constants
|
|
19
18
|
from reflex.environment import environment
|
|
@@ -89,18 +88,6 @@ def get_reflex_enterprise_version() -> str | None:
|
|
|
89
88
|
return None
|
|
90
89
|
|
|
91
90
|
|
|
92
|
-
def get_memory() -> int:
|
|
93
|
-
"""Get the total memory in MB.
|
|
94
|
-
|
|
95
|
-
Returns:
|
|
96
|
-
The total memory in MB.
|
|
97
|
-
"""
|
|
98
|
-
try:
|
|
99
|
-
return psutil.virtual_memory().total >> 20
|
|
100
|
-
except ValueError: # needed to pass ubuntu test
|
|
101
|
-
return 0
|
|
102
|
-
|
|
103
|
-
|
|
104
91
|
def _raise_on_missing_project_hash() -> bool:
|
|
105
92
|
"""Check if an error should be raised when project hash is missing.
|
|
106
93
|
|
|
@@ -128,7 +115,6 @@ class _Properties(TypedDict):
|
|
|
128
115
|
bun_version: str | None
|
|
129
116
|
reflex_enterprise_version: str | None
|
|
130
117
|
cpu_count: int
|
|
131
|
-
memory: int
|
|
132
118
|
cpu_info: dict
|
|
133
119
|
|
|
134
120
|
|
|
@@ -182,7 +168,6 @@ def _get_event_defaults() -> _DefaultEvent | None:
|
|
|
182
168
|
),
|
|
183
169
|
"reflex_enterprise_version": get_reflex_enterprise_version(),
|
|
184
170
|
"cpu_count": get_cpu_count(),
|
|
185
|
-
"memory": get_memory(),
|
|
186
171
|
"cpu_info": dataclasses.asdict(cpuinfo) if cpuinfo else {},
|
|
187
172
|
},
|
|
188
173
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: reflex
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.0a7
|
|
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
|
|
@@ -21,12 +21,12 @@ Requires-Python: <4.0,>=3.10
|
|
|
21
21
|
Requires-Dist: alembic<2.0,>=1.15.2
|
|
22
22
|
Requires-Dist: click>=8.2
|
|
23
23
|
Requires-Dist: fastapi>=0.115.0
|
|
24
|
-
Requires-Dist: granian[reload]>=2.
|
|
24
|
+
Requires-Dist: granian[reload]>=2.4.0
|
|
25
25
|
Requires-Dist: httpx<1.0,>=0.28.0
|
|
26
26
|
Requires-Dist: jinja2<4.0,>=3.1.2
|
|
27
27
|
Requires-Dist: packaging<26,>=24.2
|
|
28
28
|
Requires-Dist: platformdirs<5.0,>=4.3.7
|
|
29
|
-
Requires-Dist: psutil<8.0,>=7.0.0
|
|
29
|
+
Requires-Dist: psutil<8.0,>=7.0.0; sys_platform == 'win32'
|
|
30
30
|
Requires-Dist: pydantic<3.0,>=1.10.21
|
|
31
31
|
Requires-Dist: python-multipart<1.0,>=0.0.20
|
|
32
32
|
Requires-Dist: python-socketio<6.0,>=5.12.0
|