reflex 0.6.8a1__py3-none-any.whl → 0.7.0__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/custom_components/pyproject.toml.jinja2 +1 -1
- reflex/.templates/jinja/web/pages/_app.js.jinja2 +7 -7
- reflex/.templates/jinja/web/pages/utils.js.jinja2 +3 -3
- reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +1 -4
- reflex/.templates/web/utils/state.js +65 -36
- reflex/__init__.py +4 -17
- reflex/__init__.pyi +1 -2
- reflex/app.py +286 -135
- reflex/app_mixins/lifespan.py +9 -9
- reflex/app_mixins/middleware.py +6 -6
- reflex/app_module_for_backend.py +3 -7
- reflex/base.py +7 -7
- reflex/compiler/compiler.py +8 -0
- reflex/compiler/utils.py +57 -18
- reflex/components/base/app_wrap.pyi +16 -16
- reflex/components/base/bare.py +1 -1
- reflex/components/base/body.pyi +16 -16
- reflex/components/base/document.pyi +76 -76
- reflex/components/base/error_boundary.py +2 -1
- reflex/components/base/error_boundary.pyi +19 -22
- reflex/components/base/fragment.pyi +16 -16
- reflex/components/base/head.pyi +31 -31
- reflex/components/base/link.pyi +31 -31
- reflex/components/base/meta.py +2 -2
- reflex/components/base/meta.pyi +61 -61
- reflex/components/base/script.pyi +19 -19
- reflex/components/base/strict_mode.py +10 -0
- reflex/components/base/strict_mode.pyi +57 -0
- reflex/components/component.py +38 -77
- reflex/components/core/banner.py +159 -4
- reflex/components/core/banner.pyi +162 -76
- reflex/components/core/breakpoints.py +3 -1
- reflex/components/core/client_side_routing.py +1 -1
- reflex/components/core/client_side_routing.pyi +32 -32
- reflex/components/core/clipboard.pyi +17 -20
- reflex/components/core/cond.py +9 -10
- reflex/components/core/debounce.py +1 -1
- reflex/components/core/debounce.pyi +17 -17
- reflex/components/core/foreach.py +28 -3
- reflex/components/core/html.py +1 -1
- reflex/components/core/html.pyi +16 -16
- reflex/components/core/match.py +5 -5
- reflex/components/core/sticky.py +134 -0
- reflex/components/core/sticky.pyi +449 -0
- reflex/components/core/upload.py +2 -2
- reflex/components/core/upload.pyi +80 -88
- reflex/components/datadisplay/code.py +5 -14
- reflex/components/datadisplay/code.pyi +31 -31
- reflex/components/datadisplay/dataeditor.py +7 -4
- reflex/components/datadisplay/dataeditor.pyi +40 -54
- reflex/components/datadisplay/logo.py +13 -8
- reflex/components/datadisplay/shiki_code_block.py +14 -9
- reflex/components/datadisplay/shiki_code_block.pyi +46 -46
- reflex/components/dynamic.py +22 -3
- reflex/components/el/constants/reflex.py +1 -1
- reflex/components/el/element.py +1 -1
- reflex/components/el/element.pyi +16 -16
- reflex/components/el/elements/base.pyi +16 -16
- reflex/components/el/elements/forms.py +4 -4
- reflex/components/el/elements/forms.pyi +224 -258
- reflex/components/el/elements/inline.pyi +421 -421
- reflex/components/el/elements/media.pyi +376 -376
- reflex/components/el/elements/metadata.pyi +91 -91
- reflex/components/el/elements/other.pyi +106 -106
- reflex/components/el/elements/scripts.pyi +46 -46
- reflex/components/el/elements/sectioning.pyi +226 -226
- reflex/components/el/elements/tables.pyi +151 -151
- reflex/components/el/elements/typography.pyi +226 -226
- reflex/components/gridjs/datatable.pyi +31 -31
- reflex/components/lucide/icon.py +46 -8
- reflex/components/lucide/icon.pyi +85 -31
- reflex/components/markdown/markdown.py +10 -8
- reflex/components/markdown/markdown.pyi +16 -16
- reflex/components/moment/moment.py +2 -2
- reflex/components/moment/moment.pyi +17 -19
- reflex/components/next/base.pyi +16 -16
- reflex/components/next/image.py +16 -4
- reflex/components/next/image.pyi +22 -20
- reflex/components/next/link.py +1 -1
- reflex/components/next/link.pyi +16 -16
- reflex/components/next/video.pyi +16 -16
- reflex/components/plotly/__init__.py +29 -2
- reflex/components/plotly/plotly.py +240 -5
- reflex/components/plotly/plotly.pyi +799 -44
- reflex/components/props.py +3 -3
- reflex/components/radix/__init__.pyi +1 -1
- reflex/components/radix/primitives/accordion.py +9 -5
- reflex/components/radix/primitives/accordion.pyi +110 -108
- reflex/components/radix/primitives/base.pyi +31 -31
- reflex/components/radix/primitives/drawer.py +5 -2
- reflex/components/radix/primitives/drawer.pyi +179 -187
- reflex/components/radix/primitives/form.pyi +160 -172
- reflex/components/radix/primitives/progress.py +1 -1
- reflex/components/radix/primitives/progress.pyi +76 -76
- reflex/components/radix/primitives/slider.py +1 -1
- reflex/components/radix/primitives/slider.pyi +78 -82
- reflex/components/radix/themes/base.pyi +121 -121
- reflex/components/radix/themes/color_mode.py +11 -9
- reflex/components/radix/themes/color_mode.pyi +47 -49
- reflex/components/radix/themes/components/alert_dialog.py +3 -0
- reflex/components/radix/themes/components/alert_dialog.pyi +110 -112
- reflex/components/radix/themes/components/aspect_ratio.pyi +16 -16
- reflex/components/radix/themes/components/avatar.pyi +16 -16
- reflex/components/radix/themes/components/badge.pyi +16 -16
- reflex/components/radix/themes/components/button.pyi +16 -16
- reflex/components/radix/themes/components/callout.pyi +76 -76
- reflex/components/radix/themes/components/card.py +1 -1
- reflex/components/radix/themes/components/card.pyi +17 -17
- reflex/components/radix/themes/components/checkbox.pyi +49 -55
- reflex/components/radix/themes/components/checkbox_cards.pyi +31 -31
- reflex/components/radix/themes/components/checkbox_group.pyi +31 -31
- reflex/components/radix/themes/components/context_menu.py +5 -0
- reflex/components/radix/themes/components/context_menu.pyi +149 -155
- reflex/components/radix/themes/components/data_list.pyi +61 -61
- reflex/components/radix/themes/components/dialog.py +3 -0
- reflex/components/radix/themes/components/dialog.pyi +113 -117
- reflex/components/radix/themes/components/dropdown_menu.py +5 -0
- reflex/components/radix/themes/components/dropdown_menu.pyi +133 -137
- reflex/components/radix/themes/components/hover_card.py +3 -0
- reflex/components/radix/themes/components/hover_card.pyi +63 -67
- reflex/components/radix/themes/components/icon_button.py +2 -2
- reflex/components/radix/themes/components/icon_button.pyi +17 -16
- reflex/components/radix/themes/components/inset.pyi +16 -16
- reflex/components/radix/themes/components/popover.py +3 -0
- reflex/components/radix/themes/components/popover.pyi +68 -70
- reflex/components/radix/themes/components/progress.pyi +16 -16
- reflex/components/radix/themes/components/radio.pyi +16 -16
- reflex/components/radix/themes/components/radio_cards.py +2 -0
- reflex/components/radix/themes/components/radio_cards.pyi +32 -34
- reflex/components/radix/themes/components/radio_group.py +1 -1
- reflex/components/radix/themes/components/radio_group.pyi +62 -64
- reflex/components/radix/themes/components/scroll_area.pyi +16 -16
- reflex/components/radix/themes/components/segmented_control.pyi +32 -35
- reflex/components/radix/themes/components/select.py +4 -0
- reflex/components/radix/themes/components/select.pyi +145 -157
- reflex/components/radix/themes/components/separator.pyi +16 -16
- reflex/components/radix/themes/components/skeleton.py +3 -0
- reflex/components/radix/themes/components/skeleton.pyi +16 -16
- reflex/components/radix/themes/components/slider.pyi +22 -28
- reflex/components/radix/themes/components/spinner.pyi +16 -16
- reflex/components/radix/themes/components/switch.pyi +17 -19
- reflex/components/radix/themes/components/table.pyi +106 -106
- reflex/components/radix/themes/components/tabs.py +3 -0
- reflex/components/radix/themes/components/tabs.pyi +78 -82
- reflex/components/radix/themes/components/text_area.py +12 -0
- reflex/components/radix/themes/components/text_area.pyi +21 -33
- reflex/components/radix/themes/components/text_field.py +1 -1
- reflex/components/radix/themes/components/text_field.pyi +52 -80
- reflex/components/radix/themes/components/tooltip.py +6 -1
- reflex/components/radix/themes/components/tooltip.pyi +20 -21
- reflex/components/radix/themes/layout/__init__.pyi +1 -1
- reflex/components/radix/themes/layout/base.pyi +16 -16
- reflex/components/radix/themes/layout/box.pyi +16 -16
- reflex/components/radix/themes/layout/center.pyi +16 -16
- reflex/components/radix/themes/layout/container.pyi +16 -16
- reflex/components/radix/themes/layout/flex.pyi +16 -16
- reflex/components/radix/themes/layout/grid.pyi +16 -16
- reflex/components/radix/themes/layout/list.py +2 -2
- reflex/components/radix/themes/layout/list.pyi +76 -76
- reflex/components/radix/themes/layout/section.pyi +16 -16
- reflex/components/radix/themes/layout/spacer.pyi +16 -16
- reflex/components/radix/themes/layout/stack.py +2 -2
- reflex/components/radix/themes/layout/stack.pyi +46 -46
- reflex/components/radix/themes/typography/blockquote.pyi +16 -16
- reflex/components/radix/themes/typography/code.pyi +16 -16
- reflex/components/radix/themes/typography/heading.pyi +16 -16
- reflex/components/radix/themes/typography/link.py +1 -1
- reflex/components/radix/themes/typography/link.pyi +16 -16
- reflex/components/radix/themes/typography/text.py +2 -2
- reflex/components/radix/themes/typography/text.pyi +106 -106
- reflex/components/react_player/audio.pyi +33 -39
- reflex/components/react_player/react_player.py +1 -1
- reflex/components/react_player/react_player.pyi +32 -38
- reflex/components/react_player/video.pyi +33 -39
- reflex/components/recharts/__init__.py +2 -0
- reflex/components/recharts/__init__.pyi +2 -0
- reflex/components/recharts/cartesian.pyi +282 -282
- reflex/components/recharts/charts.py +15 -15
- reflex/components/recharts/charts.pyi +164 -164
- reflex/components/recharts/general.py +19 -4
- reflex/components/recharts/general.pyi +132 -81
- reflex/components/recharts/polar.py +2 -2
- reflex/components/recharts/polar.pyi +55 -55
- reflex/components/recharts/recharts.py +4 -4
- reflex/components/recharts/recharts.pyi +31 -31
- reflex/components/sonner/toast.py +15 -13
- reflex/components/sonner/toast.pyi +22 -22
- reflex/components/suneditor/editor.py +6 -4
- reflex/components/suneditor/editor.pyi +26 -40
- reflex/components/tags/iter_tag.py +3 -3
- reflex/components/tags/tag.py +25 -3
- reflex/config.py +48 -20
- reflex/constants/__init__.py +1 -0
- reflex/constants/base.py +4 -1
- reflex/constants/compiler.py +5 -2
- reflex/constants/config.py +8 -1
- reflex/constants/installer.py +9 -9
- reflex/constants/style.py +1 -1
- reflex/custom_components/custom_components.py +18 -10
- reflex/event.py +228 -233
- reflex/experimental/__init__.py +19 -11
- reflex/experimental/client_state.py +53 -28
- reflex/experimental/hooks.py +5 -5
- reflex/experimental/layout.py +8 -5
- reflex/experimental/layout.pyi +79 -83
- reflex/experimental/misc.py +3 -3
- reflex/istate/wrappers.py +1 -1
- reflex/middleware/hydrate_middleware.py +2 -2
- reflex/model.py +11 -6
- reflex/page.py +5 -5
- reflex/reflex.py +104 -26
- reflex/route.py +1 -1
- reflex/state.py +358 -401
- reflex/style.py +27 -3
- reflex/testing.py +34 -39
- reflex/utils/build.py +6 -2
- reflex/utils/codespaces.py +1 -4
- reflex/utils/compat.py +6 -5
- reflex/utils/console.py +71 -21
- reflex/utils/exceptions.py +89 -26
- reflex/utils/exec.py +69 -74
- reflex/utils/export.py +6 -1
- reflex/utils/format.py +8 -40
- reflex/utils/imports.py +5 -2
- reflex/utils/lazy_loader.py +7 -1
- reflex/utils/path_ops.py +74 -14
- reflex/utils/prerequisites.py +345 -68
- reflex/utils/processes.py +45 -32
- reflex/utils/pyi_generator.py +39 -33
- reflex/utils/registry.py +4 -4
- reflex/utils/serializers.py +1 -1
- reflex/utils/telemetry.py +5 -4
- reflex/utils/types.py +42 -18
- reflex/vars/base.py +695 -330
- reflex/vars/datetime.py +6 -7
- reflex/vars/dep_tracking.py +344 -0
- reflex/vars/function.py +11 -5
- reflex/vars/number.py +31 -43
- reflex/vars/object.py +74 -64
- reflex/vars/sequence.py +79 -67
- {reflex-0.6.8a1.dist-info → reflex-0.7.0.dist-info}/METADATA +7 -10
- reflex-0.7.0.dist-info/RECORD +401 -0
- {reflex-0.6.8a1.dist-info → reflex-0.7.0.dist-info}/WHEEL +1 -1
- reflex/experimental/assets.py +0 -37
- reflex/proxy.py +0 -119
- reflex-0.6.8a1.dist-info/RECORD +0 -398
- {reflex-0.6.8a1.dist-info → reflex-0.7.0.dist-info}/LICENSE +0 -0
- {reflex-0.6.8a1.dist-info → reflex-0.7.0.dist-info}/entry_points.txt +0 -0
reflex/utils/processes.py
CHANGED
|
@@ -15,12 +15,14 @@ from typing import Callable, Generator, List, Optional, Tuple, Union
|
|
|
15
15
|
import psutil
|
|
16
16
|
import typer
|
|
17
17
|
from redis.exceptions import RedisError
|
|
18
|
+
from rich.progress import Progress
|
|
18
19
|
|
|
19
20
|
from reflex import constants
|
|
21
|
+
from reflex.config import environment
|
|
20
22
|
from reflex.utils import console, path_ops, prerequisites
|
|
21
23
|
|
|
22
24
|
|
|
23
|
-
def kill(pid):
|
|
25
|
+
def kill(pid: int):
|
|
24
26
|
"""Kill a process.
|
|
25
27
|
|
|
26
28
|
Args:
|
|
@@ -48,7 +50,7 @@ def get_num_workers() -> int:
|
|
|
48
50
|
return (os.cpu_count() or 1) * 2 + 1
|
|
49
51
|
|
|
50
52
|
|
|
51
|
-
def get_process_on_port(port) -> Optional[psutil.Process]:
|
|
53
|
+
def get_process_on_port(port: int) -> Optional[psutil.Process]:
|
|
52
54
|
"""Get the process on the given port.
|
|
53
55
|
|
|
54
56
|
Args:
|
|
@@ -62,7 +64,7 @@ def get_process_on_port(port) -> Optional[psutil.Process]:
|
|
|
62
64
|
psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess
|
|
63
65
|
):
|
|
64
66
|
if importlib.metadata.version("psutil") >= "6.0.0":
|
|
65
|
-
conns = proc.net_connections(kind="inet")
|
|
67
|
+
conns = proc.net_connections(kind="inet")
|
|
66
68
|
else:
|
|
67
69
|
conns = proc.connections(kind="inet")
|
|
68
70
|
for conn in conns:
|
|
@@ -71,7 +73,7 @@ def get_process_on_port(port) -> Optional[psutil.Process]:
|
|
|
71
73
|
return None
|
|
72
74
|
|
|
73
75
|
|
|
74
|
-
def is_process_on_port(port) -> bool:
|
|
76
|
+
def is_process_on_port(port: int) -> bool:
|
|
75
77
|
"""Check if a process is running on the given port.
|
|
76
78
|
|
|
77
79
|
Args:
|
|
@@ -83,7 +85,7 @@ def is_process_on_port(port) -> bool:
|
|
|
83
85
|
return get_process_on_port(port) is not None
|
|
84
86
|
|
|
85
87
|
|
|
86
|
-
def kill_process_on_port(port):
|
|
88
|
+
def kill_process_on_port(port: int):
|
|
87
89
|
"""Kill the process on the given port.
|
|
88
90
|
|
|
89
91
|
Args:
|
|
@@ -91,10 +93,10 @@ def kill_process_on_port(port):
|
|
|
91
93
|
"""
|
|
92
94
|
if get_process_on_port(port) is not None:
|
|
93
95
|
with contextlib.suppress(psutil.AccessDenied):
|
|
94
|
-
get_process_on_port(port).kill() #
|
|
96
|
+
get_process_on_port(port).kill() # pyright: ignore [reportOptionalMemberAccess]
|
|
95
97
|
|
|
96
98
|
|
|
97
|
-
def change_port(port:
|
|
99
|
+
def change_port(port: int, _type: str) -> int:
|
|
98
100
|
"""Change the port.
|
|
99
101
|
|
|
100
102
|
Args:
|
|
@@ -105,7 +107,7 @@ def change_port(port: str, _type: str) -> str:
|
|
|
105
107
|
The new port.
|
|
106
108
|
|
|
107
109
|
"""
|
|
108
|
-
new_port =
|
|
110
|
+
new_port = port + 1
|
|
109
111
|
if is_process_on_port(new_port):
|
|
110
112
|
return change_port(new_port, _type)
|
|
111
113
|
console.info(
|
|
@@ -114,7 +116,7 @@ def change_port(port: str, _type: str) -> str:
|
|
|
114
116
|
return new_port
|
|
115
117
|
|
|
116
118
|
|
|
117
|
-
def handle_port(service_name: str, port:
|
|
119
|
+
def handle_port(service_name: str, port: int, default_port: int) -> int:
|
|
118
120
|
"""Change port if the specified port is in use and is not explicitly specified as a CLI arg or config arg.
|
|
119
121
|
otherwise tell the user the port is in use and exit the app.
|
|
120
122
|
|
|
@@ -133,7 +135,7 @@ def handle_port(service_name: str, port: str, default_port: str) -> str:
|
|
|
133
135
|
Exit:when the port is in use.
|
|
134
136
|
"""
|
|
135
137
|
if is_process_on_port(port):
|
|
136
|
-
if
|
|
138
|
+
if port == int(default_port):
|
|
137
139
|
return change_port(port, service_name)
|
|
138
140
|
else:
|
|
139
141
|
console.error(f"{service_name.capitalize()} port: {port} is already in use")
|
|
@@ -141,7 +143,12 @@ def handle_port(service_name: str, port: str, default_port: str) -> str:
|
|
|
141
143
|
return port
|
|
142
144
|
|
|
143
145
|
|
|
144
|
-
def new_process(
|
|
146
|
+
def new_process(
|
|
147
|
+
args: str | list[str] | list[str | None] | list[str | Path | None],
|
|
148
|
+
run: bool = False,
|
|
149
|
+
show_logs: bool = False,
|
|
150
|
+
**kwargs,
|
|
151
|
+
):
|
|
145
152
|
"""Wrapper over subprocess.Popen to unify the launch of child processes.
|
|
146
153
|
|
|
147
154
|
Args:
|
|
@@ -156,24 +163,30 @@ def new_process(args, run: bool = False, show_logs: bool = False, **kwargs):
|
|
|
156
163
|
Raises:
|
|
157
164
|
Exit: When attempting to run a command with a None value.
|
|
158
165
|
"""
|
|
159
|
-
|
|
160
|
-
if
|
|
161
|
-
console.warn(
|
|
162
|
-
"The path to the Node binary could not be found. Please ensure that Node is properly "
|
|
163
|
-
"installed and added to your system's PATH environment variable or try running "
|
|
164
|
-
"`reflex init` again."
|
|
165
|
-
)
|
|
166
|
-
if None in args:
|
|
166
|
+
# Check for invalid command first.
|
|
167
|
+
if isinstance(args, list) and None in args:
|
|
167
168
|
console.error(f"Invalid command: {args}")
|
|
168
169
|
raise typer.Exit(1)
|
|
169
|
-
|
|
170
|
+
|
|
171
|
+
path_env: str = os.environ.get("PATH", "")
|
|
172
|
+
|
|
173
|
+
# Add node_bin_path to the PATH environment variable.
|
|
174
|
+
if not environment.REFLEX_BACKEND_ONLY.get():
|
|
175
|
+
node_bin_path = str(path_ops.get_node_bin_path())
|
|
176
|
+
if not node_bin_path and not prerequisites.CURRENTLY_INSTALLING_NODE:
|
|
177
|
+
console.warn(
|
|
178
|
+
"The path to the Node binary could not be found. Please ensure that Node is properly "
|
|
179
|
+
"installed and added to your system's PATH environment variable or try running "
|
|
180
|
+
"`reflex init` again."
|
|
181
|
+
)
|
|
182
|
+
path_env = os.pathsep.join([node_bin_path, path_env])
|
|
183
|
+
|
|
170
184
|
env: dict[str, str] = {
|
|
171
185
|
**os.environ,
|
|
172
|
-
"PATH":
|
|
173
|
-
[node_bin_path if node_bin_path else "", os.environ["PATH"]]
|
|
174
|
-
), # type: ignore
|
|
186
|
+
"PATH": path_env,
|
|
175
187
|
**kwargs.pop("env", {}),
|
|
176
188
|
}
|
|
189
|
+
|
|
177
190
|
kwargs = {
|
|
178
191
|
"env": env,
|
|
179
192
|
"stderr": None if show_logs else subprocess.STDOUT,
|
|
@@ -185,7 +198,7 @@ def new_process(args, run: bool = False, show_logs: bool = False, **kwargs):
|
|
|
185
198
|
}
|
|
186
199
|
console.debug(f"Running command: {args}")
|
|
187
200
|
fn = subprocess.run if run else subprocess.Popen
|
|
188
|
-
return fn(args, **kwargs)
|
|
201
|
+
return fn(args, **kwargs) # pyright: ignore [reportCallIssue, reportArgumentType]
|
|
189
202
|
|
|
190
203
|
|
|
191
204
|
@contextlib.contextmanager
|
|
@@ -206,14 +219,14 @@ def run_concurrently_context(
|
|
|
206
219
|
return
|
|
207
220
|
|
|
208
221
|
# Convert the functions to tuples.
|
|
209
|
-
fns = [fn if isinstance(fn, tuple) else (fn,) for fn in fns] #
|
|
222
|
+
fns = [fn if isinstance(fn, tuple) else (fn,) for fn in fns] # pyright: ignore [reportAssignmentType]
|
|
210
223
|
|
|
211
224
|
# Run the functions concurrently.
|
|
212
225
|
executor = None
|
|
213
226
|
try:
|
|
214
227
|
executor = futures.ThreadPoolExecutor(max_workers=len(fns))
|
|
215
228
|
# Submit the tasks.
|
|
216
|
-
tasks = [executor.submit(*fn) for fn in fns] #
|
|
229
|
+
tasks = [executor.submit(*fn) for fn in fns] # pyright: ignore [reportArgumentType]
|
|
217
230
|
|
|
218
231
|
# Yield control back to the main thread while tasks are running.
|
|
219
232
|
yield tasks
|
|
@@ -241,7 +254,7 @@ def run_concurrently(*fns: Union[Callable, Tuple]) -> None:
|
|
|
241
254
|
def stream_logs(
|
|
242
255
|
message: str,
|
|
243
256
|
process: subprocess.Popen,
|
|
244
|
-
progress=None,
|
|
257
|
+
progress: Progress | None = None,
|
|
245
258
|
suppress_errors: bool = False,
|
|
246
259
|
analytics_enabled: bool = False,
|
|
247
260
|
):
|
|
@@ -361,7 +374,7 @@ def get_command_with_loglevel(command: list[str]) -> list[str]:
|
|
|
361
374
|
The updated command list
|
|
362
375
|
"""
|
|
363
376
|
npm_path = path_ops.get_npm_path()
|
|
364
|
-
npm_path = str(
|
|
377
|
+
npm_path = str(npm_path) if npm_path else None
|
|
365
378
|
|
|
366
379
|
if command[0] == npm_path:
|
|
367
380
|
return [*command, "--loglevel", "silly"]
|
|
@@ -369,10 +382,10 @@ def get_command_with_loglevel(command: list[str]) -> list[str]:
|
|
|
369
382
|
|
|
370
383
|
|
|
371
384
|
def run_process_with_fallback(
|
|
372
|
-
args,
|
|
385
|
+
args: list[str],
|
|
373
386
|
*,
|
|
374
|
-
show_status_message,
|
|
375
|
-
fallback=None,
|
|
387
|
+
show_status_message: str,
|
|
388
|
+
fallback: str | list | None = None,
|
|
376
389
|
analytics_enabled: bool = False,
|
|
377
390
|
**kwargs,
|
|
378
391
|
):
|
|
@@ -411,7 +424,7 @@ def run_process_with_fallback(
|
|
|
411
424
|
)
|
|
412
425
|
|
|
413
426
|
|
|
414
|
-
def execute_command_and_return_output(command) -> str | None:
|
|
427
|
+
def execute_command_and_return_output(command: str) -> str | None:
|
|
415
428
|
"""Execute a command and return the output.
|
|
416
429
|
|
|
417
430
|
Args:
|
reflex/utils/pyi_generator.py
CHANGED
|
@@ -75,7 +75,6 @@ DEFAULT_IMPORTS = {
|
|
|
75
75
|
"EventHandler",
|
|
76
76
|
"EventSpec",
|
|
77
77
|
"EventType",
|
|
78
|
-
"BASE_STATE",
|
|
79
78
|
"KeyInputInfo",
|
|
80
79
|
],
|
|
81
80
|
"reflex.style": ["Style"],
|
|
@@ -83,7 +82,7 @@ DEFAULT_IMPORTS = {
|
|
|
83
82
|
}
|
|
84
83
|
|
|
85
84
|
|
|
86
|
-
def _walk_files(path):
|
|
85
|
+
def _walk_files(path: str | Path):
|
|
87
86
|
"""Walk all files in a path.
|
|
88
87
|
This can be replaced with Path.walk() in python3.12.
|
|
89
88
|
|
|
@@ -114,7 +113,9 @@ def _relative_to_pwd(path: Path) -> Path:
|
|
|
114
113
|
return path
|
|
115
114
|
|
|
116
115
|
|
|
117
|
-
def _get_type_hint(
|
|
116
|
+
def _get_type_hint(
|
|
117
|
+
value: Any, type_hint_globals: dict, is_optional: bool = True
|
|
118
|
+
) -> str:
|
|
118
119
|
"""Resolve the type hint for value.
|
|
119
120
|
|
|
120
121
|
Args:
|
|
@@ -229,7 +230,7 @@ def _generate_imports(
|
|
|
229
230
|
"""
|
|
230
231
|
return [
|
|
231
232
|
*[
|
|
232
|
-
ast.ImportFrom(module=name, names=[ast.alias(name=val) for val in values])
|
|
233
|
+
ast.ImportFrom(module=name, names=[ast.alias(name=val) for val in values]) # pyright: ignore [reportCallIssue]
|
|
233
234
|
for name, values in DEFAULT_IMPORTS.items()
|
|
234
235
|
],
|
|
235
236
|
ast.Import([ast.alias("reflex")]),
|
|
@@ -367,7 +368,7 @@ def _extract_class_props_as_ast_nodes(
|
|
|
367
368
|
# Try to get default from pydantic field definition.
|
|
368
369
|
default = target_class.__fields__[name].default
|
|
369
370
|
if isinstance(default, Var):
|
|
370
|
-
default = default._decode()
|
|
371
|
+
default = default._decode()
|
|
371
372
|
|
|
372
373
|
kwargs.append(
|
|
373
374
|
(
|
|
@@ -383,7 +384,7 @@ def _extract_class_props_as_ast_nodes(
|
|
|
383
384
|
return kwargs
|
|
384
385
|
|
|
385
386
|
|
|
386
|
-
def type_to_ast(typ, cls: type) -> ast.AST:
|
|
387
|
+
def type_to_ast(typ: Any, cls: type) -> ast.AST:
|
|
387
388
|
"""Converts any type annotation into its AST representation.
|
|
388
389
|
Handles nested generic types, unions, etc.
|
|
389
390
|
|
|
@@ -434,14 +435,16 @@ def type_to_ast(typ, cls: type) -> ast.AST:
|
|
|
434
435
|
if len(arg_nodes) == 1:
|
|
435
436
|
slice_value = arg_nodes[0]
|
|
436
437
|
else:
|
|
437
|
-
slice_value = ast.Tuple(elts=arg_nodes, ctx=ast.Load())
|
|
438
|
+
slice_value = ast.Tuple(elts=arg_nodes, ctx=ast.Load()) # pyright: ignore [reportArgumentType]
|
|
438
439
|
|
|
439
440
|
return ast.Subscript(
|
|
440
|
-
value=ast.Name(id=base_name),
|
|
441
|
+
value=ast.Name(id=base_name),
|
|
442
|
+
slice=ast.Index(value=slice_value), # pyright: ignore [reportArgumentType]
|
|
443
|
+
ctx=ast.Load(),
|
|
441
444
|
)
|
|
442
445
|
|
|
443
446
|
|
|
444
|
-
def _get_parent_imports(func):
|
|
447
|
+
def _get_parent_imports(func: Callable):
|
|
445
448
|
_imports = {"reflex.vars": ["Var"]}
|
|
446
449
|
for type_hint in inspect.get_annotations(func).values():
|
|
447
450
|
try:
|
|
@@ -498,7 +501,7 @@ def _generate_component_create_functiondef(
|
|
|
498
501
|
|
|
499
502
|
def figure_out_return_type(annotation: Any):
|
|
500
503
|
if inspect.isclass(annotation) and issubclass(annotation, inspect._empty):
|
|
501
|
-
return ast.Name(id="EventType[
|
|
504
|
+
return ast.Name(id="EventType[Any]")
|
|
502
505
|
|
|
503
506
|
if not isinstance(annotation, str) and get_origin(annotation) is tuple:
|
|
504
507
|
arguments = get_args(annotation)
|
|
@@ -514,8 +517,10 @@ def _generate_component_create_functiondef(
|
|
|
514
517
|
# Get all prefixes of the type arguments
|
|
515
518
|
all_count_args_type = [
|
|
516
519
|
ast.Name(
|
|
517
|
-
f"EventType[
|
|
520
|
+
f"EventType[{', '.join([ast.unparse(arg) for arg in type_args[:i]])}]"
|
|
518
521
|
)
|
|
522
|
+
if i > 0
|
|
523
|
+
else ast.Name("EventType[()]")
|
|
519
524
|
for i in range(len(type_args) + 1)
|
|
520
525
|
]
|
|
521
526
|
|
|
@@ -528,7 +533,7 @@ def _generate_component_create_functiondef(
|
|
|
528
533
|
inside_of_tuple = annotation.removeprefix("Tuple[").removesuffix("]")
|
|
529
534
|
|
|
530
535
|
if inside_of_tuple == "()":
|
|
531
|
-
return ast.Name(id="EventType[
|
|
536
|
+
return ast.Name(id="EventType[()]")
|
|
532
537
|
|
|
533
538
|
arguments = [""]
|
|
534
539
|
|
|
@@ -555,16 +560,16 @@ def _generate_component_create_functiondef(
|
|
|
555
560
|
]
|
|
556
561
|
|
|
557
562
|
all_count_args_type = [
|
|
558
|
-
ast.Name(
|
|
559
|
-
|
|
560
|
-
)
|
|
563
|
+
ast.Name(f"EventType[{', '.join(arguments_without_var[:i])}]")
|
|
564
|
+
if i > 0
|
|
565
|
+
else ast.Name("EventType[()]")
|
|
561
566
|
for i in range(len(arguments) + 1)
|
|
562
567
|
]
|
|
563
568
|
|
|
564
569
|
return ast.Name(
|
|
565
570
|
id=f"Union[{', '.join(map(ast.unparse, all_count_args_type))}]"
|
|
566
571
|
)
|
|
567
|
-
return ast.Name(id="EventType[
|
|
572
|
+
return ast.Name(id="EventType[Any]")
|
|
568
573
|
|
|
569
574
|
event_triggers = clz().get_event_triggers()
|
|
570
575
|
|
|
@@ -575,7 +580,7 @@ def _generate_component_create_functiondef(
|
|
|
575
580
|
arg=trigger,
|
|
576
581
|
annotation=ast.Subscript(
|
|
577
582
|
ast.Name("Optional"),
|
|
578
|
-
ast.Index( #
|
|
583
|
+
ast.Index( # pyright: ignore [reportArgumentType]
|
|
579
584
|
value=ast.Name(
|
|
580
585
|
id=ast.unparse(
|
|
581
586
|
figure_out_return_type(
|
|
@@ -618,10 +623,10 @@ def _generate_component_create_functiondef(
|
|
|
618
623
|
defaults=[],
|
|
619
624
|
)
|
|
620
625
|
|
|
621
|
-
definition = ast.FunctionDef(
|
|
626
|
+
definition = ast.FunctionDef( # pyright: ignore [reportCallIssue]
|
|
622
627
|
name="create",
|
|
623
628
|
args=create_args,
|
|
624
|
-
body=[
|
|
629
|
+
body=[ # pyright: ignore [reportArgumentType]
|
|
625
630
|
ast.Expr(
|
|
626
631
|
value=ast.Constant(
|
|
627
632
|
value=_generate_docstrings(
|
|
@@ -630,7 +635,7 @@ def _generate_component_create_functiondef(
|
|
|
630
635
|
),
|
|
631
636
|
),
|
|
632
637
|
ast.Expr(
|
|
633
|
-
value=ast.Ellipsis
|
|
638
|
+
value=ast.Constant(value=Ellipsis),
|
|
634
639
|
),
|
|
635
640
|
],
|
|
636
641
|
decorator_list=[
|
|
@@ -641,7 +646,7 @@ def _generate_component_create_functiondef(
|
|
|
641
646
|
else [ast.Name(id="classmethod")]
|
|
642
647
|
),
|
|
643
648
|
],
|
|
644
|
-
lineno=node.lineno if node is not None else None,
|
|
649
|
+
lineno=node.lineno if node is not None else None, # pyright: ignore [reportArgumentType]
|
|
645
650
|
returns=ast.Constant(value=clz.__name__),
|
|
646
651
|
)
|
|
647
652
|
return definition
|
|
@@ -680,7 +685,7 @@ def _generate_staticmethod_call_functiondef(
|
|
|
680
685
|
else []
|
|
681
686
|
),
|
|
682
687
|
)
|
|
683
|
-
definition = ast.FunctionDef(
|
|
688
|
+
definition = ast.FunctionDef( # pyright: ignore [reportCallIssue]
|
|
684
689
|
name="__call__",
|
|
685
690
|
args=call_args,
|
|
686
691
|
body=[
|
|
@@ -690,11 +695,12 @@ def _generate_staticmethod_call_functiondef(
|
|
|
690
695
|
),
|
|
691
696
|
],
|
|
692
697
|
decorator_list=[ast.Name(id="staticmethod")],
|
|
693
|
-
lineno=node.lineno if node is not None else None,
|
|
698
|
+
lineno=node.lineno if node is not None else None, # pyright: ignore [reportArgumentType]
|
|
694
699
|
returns=ast.Constant(
|
|
695
700
|
value=_get_type_hint(
|
|
696
701
|
typing.get_type_hints(clz.__call__).get("return", None),
|
|
697
702
|
type_hint_globals,
|
|
703
|
+
is_optional=False,
|
|
698
704
|
)
|
|
699
705
|
),
|
|
700
706
|
)
|
|
@@ -726,17 +732,17 @@ def _generate_namespace_call_functiondef(
|
|
|
726
732
|
clz = classes[clz_name]
|
|
727
733
|
|
|
728
734
|
if not hasattr(clz.__call__, "__self__"):
|
|
729
|
-
return _generate_staticmethod_call_functiondef(node, clz, type_hint_globals) #
|
|
735
|
+
return _generate_staticmethod_call_functiondef(node, clz, type_hint_globals) # pyright: ignore [reportArgumentType]
|
|
730
736
|
|
|
731
737
|
# Determine which class is wrapped by the namespace __call__ method
|
|
732
738
|
component_clz = clz.__call__.__self__
|
|
733
739
|
|
|
734
|
-
if clz.__call__.__func__.__name__ != "create":
|
|
740
|
+
if clz.__call__.__func__.__name__ != "create": # pyright: ignore [reportFunctionMemberAccess]
|
|
735
741
|
return None
|
|
736
742
|
|
|
737
743
|
definition = _generate_component_create_functiondef(
|
|
738
744
|
node=None,
|
|
739
|
-
clz=component_clz, #
|
|
745
|
+
clz=component_clz, # pyright: ignore [reportArgumentType]
|
|
740
746
|
type_hint_globals=type_hint_globals,
|
|
741
747
|
)
|
|
742
748
|
definition.name = "__call__"
|
|
@@ -816,7 +822,7 @@ class StubGenerator(ast.NodeTransformer):
|
|
|
816
822
|
The modified Module node.
|
|
817
823
|
"""
|
|
818
824
|
self.generic_visit(node)
|
|
819
|
-
return self._remove_docstring(node) #
|
|
825
|
+
return self._remove_docstring(node) # pyright: ignore [reportReturnType]
|
|
820
826
|
|
|
821
827
|
def visit_Import(
|
|
822
828
|
self, node: ast.Import | ast.ImportFrom
|
|
@@ -914,7 +920,7 @@ class StubGenerator(ast.NodeTransformer):
|
|
|
914
920
|
node.body.append(call_definition)
|
|
915
921
|
if not node.body:
|
|
916
922
|
# We should never return an empty body.
|
|
917
|
-
node.body.append(ast.Expr(value=ast.Ellipsis
|
|
923
|
+
node.body.append(ast.Expr(value=ast.Constant(value=Ellipsis)))
|
|
918
924
|
self.current_class = None
|
|
919
925
|
return node
|
|
920
926
|
|
|
@@ -941,9 +947,9 @@ class StubGenerator(ast.NodeTransformer):
|
|
|
941
947
|
if node.name.startswith("_") and node.name != "__call__":
|
|
942
948
|
return None # remove private methods
|
|
943
949
|
|
|
944
|
-
if node.body[-1] != ast.Expr(value=ast.Ellipsis
|
|
950
|
+
if node.body[-1] != ast.Expr(value=ast.Constant(value=Ellipsis)):
|
|
945
951
|
# Blank out the function body for public functions.
|
|
946
|
-
node.body = [ast.Expr(value=ast.Ellipsis
|
|
952
|
+
node.body = [ast.Expr(value=ast.Constant(value=Ellipsis))]
|
|
947
953
|
return node
|
|
948
954
|
|
|
949
955
|
def visit_Assign(self, node: ast.Assign) -> ast.Assign | None:
|
|
@@ -1050,7 +1056,7 @@ class PyiGenerator:
|
|
|
1050
1056
|
pyi_path.write_text(pyi_content)
|
|
1051
1057
|
logger.info(f"Wrote {relpath}")
|
|
1052
1058
|
|
|
1053
|
-
def _get_init_lazy_imports(self, mod, new_tree):
|
|
1059
|
+
def _get_init_lazy_imports(self, mod: tuple | ModuleType, new_tree: ast.AST):
|
|
1054
1060
|
# retrieve the _SUBMODULES and _SUBMOD_ATTRS from an init file if present.
|
|
1055
1061
|
sub_mods = getattr(mod, "_SUBMODULES", None)
|
|
1056
1062
|
sub_mod_attrs = getattr(mod, "_SUBMOD_ATTRS", None)
|
|
@@ -1077,7 +1083,7 @@ class PyiGenerator:
|
|
|
1077
1083
|
+ (
|
|
1078
1084
|
" # type: ignore"
|
|
1079
1085
|
if mod in pyright_ignore_imports
|
|
1080
|
-
else " # noqa" # ignore ruff formatting here for cases like rx.list.
|
|
1086
|
+
else " # noqa: F401" # ignore ruff formatting here for cases like rx.list.
|
|
1081
1087
|
if isinstance(mod, tuple)
|
|
1082
1088
|
else ""
|
|
1083
1089
|
)
|
|
@@ -1136,7 +1142,7 @@ class PyiGenerator:
|
|
|
1136
1142
|
if pyi_path:
|
|
1137
1143
|
self.written_files.append(pyi_path)
|
|
1138
1144
|
|
|
1139
|
-
def scan_all(self, targets, changed_files: list[Path] | None = None):
|
|
1145
|
+
def scan_all(self, targets: list, changed_files: list[Path] | None = None):
|
|
1140
1146
|
"""Scan all targets for class inheriting Component and generate the .pyi files.
|
|
1141
1147
|
|
|
1142
1148
|
Args:
|
reflex/utils/registry.py
CHANGED
|
@@ -22,15 +22,15 @@ def latency(registry: str) -> int:
|
|
|
22
22
|
return 10_000_000
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
def average_latency(registry, attempts: int = 3) -> int:
|
|
25
|
+
def average_latency(registry: str, attempts: int = 3) -> int:
|
|
26
26
|
"""Get the average latency of a registry.
|
|
27
27
|
|
|
28
28
|
Args:
|
|
29
|
-
registry
|
|
30
|
-
attempts
|
|
29
|
+
registry: The URL of the registry.
|
|
30
|
+
attempts: The number of attempts to make. Defaults to 10.
|
|
31
31
|
|
|
32
32
|
Returns:
|
|
33
|
-
|
|
33
|
+
The average latency of the registry in microseconds.
|
|
34
34
|
"""
|
|
35
35
|
return sum(latency(registry) for _ in range(attempts)) // attempts
|
|
36
36
|
|
reflex/utils/serializers.py
CHANGED
|
@@ -476,7 +476,7 @@ try:
|
|
|
476
476
|
base64_image = base64.b64encode(image_bytes).decode("utf-8")
|
|
477
477
|
try:
|
|
478
478
|
# Newer method to get the mime type, but does not always work.
|
|
479
|
-
mime_type = image.get_format_mimetype() #
|
|
479
|
+
mime_type = image.get_format_mimetype() # pyright: ignore [reportAttributeAccessIssue]
|
|
480
480
|
except AttributeError:
|
|
481
481
|
try:
|
|
482
482
|
# Fallback method
|
reflex/utils/telemetry.py
CHANGED
|
@@ -122,7 +122,7 @@ def _prepare_event(event: str, **kwargs) -> dict:
|
|
|
122
122
|
return {}
|
|
123
123
|
|
|
124
124
|
if UTC is None:
|
|
125
|
-
# for python 3.
|
|
125
|
+
# for python 3.10
|
|
126
126
|
stamp = datetime.utcnow().isoformat()
|
|
127
127
|
else:
|
|
128
128
|
# for python 3.11 & 3.12
|
|
@@ -156,12 +156,13 @@ def _prepare_event(event: str, **kwargs) -> dict:
|
|
|
156
156
|
def _send_event(event_data: dict) -> bool:
|
|
157
157
|
try:
|
|
158
158
|
httpx.post(POSTHOG_API_URL, json=event_data)
|
|
159
|
-
return True
|
|
160
159
|
except Exception:
|
|
161
160
|
return False
|
|
161
|
+
else:
|
|
162
|
+
return True
|
|
162
163
|
|
|
163
164
|
|
|
164
|
-
def _send(event, telemetry_enabled, **kwargs):
|
|
165
|
+
def _send(event: str, telemetry_enabled: bool | None, **kwargs):
|
|
165
166
|
from reflex.config import get_config
|
|
166
167
|
|
|
167
168
|
# Get the telemetry_enabled from the config if it is not specified.
|
|
@@ -188,7 +189,7 @@ def send(event: str, telemetry_enabled: bool | None = None, **kwargs):
|
|
|
188
189
|
kwargs: Additional data to send with the event.
|
|
189
190
|
"""
|
|
190
191
|
|
|
191
|
-
async def async_send(event, telemetry_enabled, **kwargs):
|
|
192
|
+
async def async_send(event: str, telemetry_enabled: bool | None, **kwargs):
|
|
192
193
|
return _send(event, telemetry_enabled, **kwargs)
|
|
193
194
|
|
|
194
195
|
try:
|