reflex 0.5.0a3__py3-none-any.whl → 0.5.1__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/web/utils/state.js +7 -2
- reflex/app.py +68 -50
- reflex/app_module_for_backend.py +3 -0
- reflex/base.py +5 -2
- reflex/components/component.py +49 -13
- reflex/components/core/__init__.py +7 -1
- reflex/components/core/banner.py +79 -6
- reflex/components/core/banner.pyi +130 -0
- reflex/components/core/cond.py +10 -4
- reflex/components/core/debounce.py +2 -4
- reflex/components/core/foreach.py +11 -0
- reflex/components/core/upload.py +9 -10
- reflex/components/el/elements/forms.py +12 -6
- reflex/components/el/elements/media.py +19 -0
- reflex/components/el/elements/media.pyi +3 -1
- reflex/components/gridjs/datatable.py +4 -2
- reflex/components/props.py +30 -0
- reflex/components/radix/themes/components/tabs.py +1 -1
- reflex/components/sonner/toast.py +102 -35
- reflex/components/sonner/toast.pyi +27 -14
- reflex/config.py +5 -3
- reflex/constants/compiler.py +3 -3
- reflex/constants/installer.py +1 -1
- reflex/event.py +38 -24
- reflex/experimental/__init__.py +4 -0
- reflex/experimental/client_state.py +198 -0
- reflex/state.py +59 -21
- reflex/style.py +3 -3
- reflex/testing.py +28 -9
- reflex/utils/exceptions.py +64 -8
- reflex/utils/format.py +73 -2
- reflex/utils/prerequisites.py +68 -23
- reflex/utils/processes.py +34 -4
- reflex/utils/telemetry.py +42 -16
- reflex/utils/types.py +16 -0
- reflex/vars.py +104 -61
- reflex/vars.pyi +7 -6
- {reflex-0.5.0a3.dist-info → reflex-0.5.1.dist-info}/METADATA +1 -1
- {reflex-0.5.0a3.dist-info → reflex-0.5.1.dist-info}/RECORD +42 -40
- {reflex-0.5.0a3.dist-info → reflex-0.5.1.dist-info}/LICENSE +0 -0
- {reflex-0.5.0a3.dist-info → reflex-0.5.1.dist-info}/WHEEL +0 -0
- {reflex-0.5.0a3.dist-info → reflex-0.5.1.dist-info}/entry_points.txt +0 -0
reflex/utils/processes.py
CHANGED
|
@@ -211,6 +211,7 @@ def stream_logs(
|
|
|
211
211
|
process: subprocess.Popen,
|
|
212
212
|
progress=None,
|
|
213
213
|
suppress_errors: bool = False,
|
|
214
|
+
analytics_enabled: bool = False,
|
|
214
215
|
):
|
|
215
216
|
"""Stream the logs for a process.
|
|
216
217
|
|
|
@@ -219,6 +220,7 @@ def stream_logs(
|
|
|
219
220
|
process: The process.
|
|
220
221
|
progress: The ongoing progress bar if one is being used.
|
|
221
222
|
suppress_errors: If True, do not exit if errors are encountered (for fallback).
|
|
223
|
+
analytics_enabled: Whether analytics are enabled for this command.
|
|
222
224
|
|
|
223
225
|
Yields:
|
|
224
226
|
The lines of the process output.
|
|
@@ -226,6 +228,8 @@ def stream_logs(
|
|
|
226
228
|
Raises:
|
|
227
229
|
Exit: If the process failed.
|
|
228
230
|
"""
|
|
231
|
+
from reflex.utils import telemetry
|
|
232
|
+
|
|
229
233
|
# Store the tail of the logs.
|
|
230
234
|
logs = collections.deque(maxlen=512)
|
|
231
235
|
with process:
|
|
@@ -246,6 +250,8 @@ def stream_logs(
|
|
|
246
250
|
console.error(f"{message} failed with exit code {process.returncode}")
|
|
247
251
|
for line in logs:
|
|
248
252
|
console.error(line, end="")
|
|
253
|
+
if analytics_enabled:
|
|
254
|
+
telemetry.send("error", context=message)
|
|
249
255
|
console.error("Run with [bold]--loglevel debug [/bold] for the full log.")
|
|
250
256
|
raise typer.Exit(1)
|
|
251
257
|
|
|
@@ -261,16 +267,27 @@ def show_logs(message: str, process: subprocess.Popen):
|
|
|
261
267
|
pass
|
|
262
268
|
|
|
263
269
|
|
|
264
|
-
def show_status(
|
|
270
|
+
def show_status(
|
|
271
|
+
message: str,
|
|
272
|
+
process: subprocess.Popen,
|
|
273
|
+
suppress_errors: bool = False,
|
|
274
|
+
analytics_enabled: bool = False,
|
|
275
|
+
):
|
|
265
276
|
"""Show the status of a process.
|
|
266
277
|
|
|
267
278
|
Args:
|
|
268
279
|
message: The initial message to display.
|
|
269
280
|
process: The process.
|
|
270
281
|
suppress_errors: If True, do not exit if errors are encountered (for fallback).
|
|
282
|
+
analytics_enabled: Whether analytics are enabled for this command.
|
|
271
283
|
"""
|
|
272
284
|
with console.status(message) as status:
|
|
273
|
-
for line in stream_logs(
|
|
285
|
+
for line in stream_logs(
|
|
286
|
+
message,
|
|
287
|
+
process,
|
|
288
|
+
suppress_errors=suppress_errors,
|
|
289
|
+
analytics_enabled=analytics_enabled,
|
|
290
|
+
):
|
|
274
291
|
status.update(f"{message} {line}")
|
|
275
292
|
|
|
276
293
|
|
|
@@ -319,19 +336,31 @@ def get_command_with_loglevel(command: list[str]) -> list[str]:
|
|
|
319
336
|
return command
|
|
320
337
|
|
|
321
338
|
|
|
322
|
-
def run_process_with_fallback(
|
|
339
|
+
def run_process_with_fallback(
|
|
340
|
+
args,
|
|
341
|
+
*,
|
|
342
|
+
show_status_message,
|
|
343
|
+
fallback=None,
|
|
344
|
+
analytics_enabled: bool = False,
|
|
345
|
+
**kwargs,
|
|
346
|
+
):
|
|
323
347
|
"""Run subprocess and retry using fallback command if initial command fails.
|
|
324
348
|
|
|
325
349
|
Args:
|
|
326
350
|
args: A string, or a sequence of program arguments.
|
|
327
351
|
show_status_message: The status message to be displayed in the console.
|
|
328
352
|
fallback: The fallback command to run.
|
|
353
|
+
analytics_enabled: Whether analytics are enabled for this command.
|
|
329
354
|
kwargs: Kwargs to pass to new_process function.
|
|
330
355
|
"""
|
|
331
356
|
process = new_process(get_command_with_loglevel(args), **kwargs)
|
|
332
357
|
if fallback is None:
|
|
333
358
|
# No fallback given, or this _is_ the fallback command.
|
|
334
|
-
show_status(
|
|
359
|
+
show_status(
|
|
360
|
+
show_status_message,
|
|
361
|
+
process,
|
|
362
|
+
analytics_enabled=analytics_enabled,
|
|
363
|
+
)
|
|
335
364
|
else:
|
|
336
365
|
# Suppress errors for initial command, because we will try to fallback
|
|
337
366
|
show_status(show_status_message, process, suppress_errors=True)
|
|
@@ -345,6 +374,7 @@ def run_process_with_fallback(args, *, show_status_message, fallback=None, **kwa
|
|
|
345
374
|
fallback_args,
|
|
346
375
|
show_status_message=show_status_message,
|
|
347
376
|
fallback=None,
|
|
377
|
+
analytics_enabled=analytics_enabled,
|
|
348
378
|
**kwargs,
|
|
349
379
|
)
|
|
350
380
|
|
reflex/utils/telemetry.py
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import asyncio
|
|
5
6
|
import multiprocessing
|
|
6
7
|
import platform
|
|
8
|
+
import warnings
|
|
7
9
|
|
|
8
10
|
try:
|
|
9
11
|
from datetime import UTC, datetime
|
|
@@ -126,6 +128,10 @@ def _prepare_event(event: str, **kwargs) -> dict:
|
|
|
126
128
|
|
|
127
129
|
cpuinfo = get_cpu_info()
|
|
128
130
|
|
|
131
|
+
additional_keys = ["template", "context", "detail"]
|
|
132
|
+
additional_fields = {
|
|
133
|
+
key: value for key in additional_keys if (value := kwargs.get(key)) is not None
|
|
134
|
+
}
|
|
129
135
|
return {
|
|
130
136
|
"api_key": "phc_JoMo0fOyi0GQAooY3UyO9k0hebGkMyFJrrCw1Gt5SGb",
|
|
131
137
|
"event": event,
|
|
@@ -139,11 +145,7 @@ def _prepare_event(event: str, **kwargs) -> dict:
|
|
|
139
145
|
"cpu_count": get_cpu_count(),
|
|
140
146
|
"memory": get_memory(),
|
|
141
147
|
"cpu_info": dict(cpuinfo) if cpuinfo else {},
|
|
142
|
-
**
|
|
143
|
-
{"template": template}
|
|
144
|
-
if (template := kwargs.get("template")) is not None
|
|
145
|
-
else {}
|
|
146
|
-
),
|
|
148
|
+
**additional_fields,
|
|
147
149
|
},
|
|
148
150
|
"timestamp": stamp,
|
|
149
151
|
}
|
|
@@ -157,17 +159,7 @@ def _send_event(event_data: dict) -> bool:
|
|
|
157
159
|
return False
|
|
158
160
|
|
|
159
161
|
|
|
160
|
-
def
|
|
161
|
-
"""Send anonymous telemetry for Reflex.
|
|
162
|
-
|
|
163
|
-
Args:
|
|
164
|
-
event: The event name.
|
|
165
|
-
telemetry_enabled: Whether to send the telemetry (If None, get from config).
|
|
166
|
-
kwargs: Additional data to send with the event.
|
|
167
|
-
|
|
168
|
-
Returns:
|
|
169
|
-
Whether the telemetry was sent successfully.
|
|
170
|
-
"""
|
|
162
|
+
def _send(event, telemetry_enabled, **kwargs):
|
|
171
163
|
from reflex.config import get_config
|
|
172
164
|
|
|
173
165
|
# Get the telemetry_enabled from the config if it is not specified.
|
|
@@ -182,3 +174,37 @@ def send(event: str, telemetry_enabled: bool | None = None, **kwargs) -> bool:
|
|
|
182
174
|
if not event_data:
|
|
183
175
|
return False
|
|
184
176
|
return _send_event(event_data)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def send(event: str, telemetry_enabled: bool | None = None, **kwargs):
|
|
180
|
+
"""Send anonymous telemetry for Reflex.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
event: The event name.
|
|
184
|
+
telemetry_enabled: Whether to send the telemetry (If None, get from config).
|
|
185
|
+
kwargs: Additional data to send with the event.
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
async def async_send(event, telemetry_enabled, **kwargs):
|
|
189
|
+
return _send(event, telemetry_enabled, **kwargs)
|
|
190
|
+
|
|
191
|
+
try:
|
|
192
|
+
# Within an event loop context, send the event asynchronously.
|
|
193
|
+
asyncio.create_task(async_send(event, telemetry_enabled, **kwargs))
|
|
194
|
+
except RuntimeError:
|
|
195
|
+
# If there is no event loop, send the event synchronously.
|
|
196
|
+
warnings.filterwarnings("ignore", category=RuntimeWarning)
|
|
197
|
+
_send(event, telemetry_enabled, **kwargs)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def send_error(error: Exception, context: str):
|
|
201
|
+
"""Send an error event.
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
error: The error to send.
|
|
205
|
+
context: The context of the error (e.g. "frontend" or "backend")
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
Whether the telemetry was sent successfully.
|
|
209
|
+
"""
|
|
210
|
+
return send("error", detail=type(error).__name__, context=context)
|
reflex/utils/types.py
CHANGED
|
@@ -44,6 +44,22 @@ from reflex import constants
|
|
|
44
44
|
from reflex.base import Base
|
|
45
45
|
from reflex.utils import console, serializers
|
|
46
46
|
|
|
47
|
+
if sys.version_info >= (3, 12):
|
|
48
|
+
from typing import override
|
|
49
|
+
else:
|
|
50
|
+
|
|
51
|
+
def override(func: Callable) -> Callable:
|
|
52
|
+
"""Fallback for @override decorator.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
func: The function to decorate.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
The unmodified function.
|
|
59
|
+
"""
|
|
60
|
+
return func
|
|
61
|
+
|
|
62
|
+
|
|
47
63
|
# Potential GenericAlias types for isinstance checks.
|
|
48
64
|
GenericAliasTypes = [_GenericAlias]
|
|
49
65
|
|