reflex 0.7.2a2__py3-none-any.whl → 0.7.3a1__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.
- benchmarks/__init__.py +3 -0
- benchmarks/benchmark_compile_times.py +147 -0
- benchmarks/benchmark_imports.py +128 -0
- benchmarks/benchmark_lighthouse.py +75 -0
- benchmarks/benchmark_package_size.py +135 -0
- benchmarks/benchmark_web_size.py +106 -0
- benchmarks/conftest.py +20 -0
- benchmarks/lighthouse.sh +77 -0
- benchmarks/utils.py +74 -0
- reflex/.templates/jinja/web/pages/custom_component.js.jinja2 +6 -3
- reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +1 -1
- reflex/.templates/web/components/shiki/code.js +26 -21
- reflex/.templates/web/postcss.config.js +1 -1
- reflex/.templates/web/utils/client_side_routing.js +18 -16
- reflex/.templates/web/utils/helpers/dataeditor.js +1 -1
- reflex/.templates/web/utils/helpers/range.js +30 -30
- reflex/.templates/web/utils/state.js +44 -22
- reflex/app_mixins/middleware.py +7 -7
- reflex/compiler/compiler.py +7 -0
- reflex/components/core/banner.py +1 -1
- reflex/components/core/foreach.py +3 -2
- reflex/components/datadisplay/logo.py +1 -1
- reflex/components/el/__init__.pyi +22 -0
- reflex/components/el/elements/__init__.py +20 -1
- reflex/components/el/elements/__init__.pyi +42 -1
- reflex/components/el/elements/media.py +11 -0
- reflex/components/el/elements/media.pyi +11 -0
- reflex/components/lucide/icon.py +8 -6
- reflex/components/lucide/icon.pyi +0 -1
- reflex/components/radix/themes/components/slider.py +2 -1
- reflex/config.py +13 -7
- reflex/custom_components/custom_components.py +23 -25
- reflex/event.py +7 -2
- reflex/istate/data.py +59 -7
- reflex/reflex.py +75 -32
- reflex/state.py +3 -3
- reflex/style.py +3 -3
- reflex/testing.py +4 -10
- reflex/utils/exceptions.py +31 -1
- reflex/utils/exec.py +4 -8
- reflex/utils/export.py +2 -2
- reflex/utils/prerequisites.py +3 -45
- reflex/utils/pyi_generator.py +2 -2
- reflex/utils/redir.py +3 -12
- reflex/vars/base.py +26 -3
- reflex/vars/number.py +22 -21
- reflex/vars/object.py +29 -0
- reflex/vars/sequence.py +37 -0
- {reflex-0.7.2a2.dist-info → reflex-0.7.3a1.dist-info}/METADATA +52 -66
- {reflex-0.7.2a2.dist-info → reflex-0.7.3a1.dist-info}/RECORD +53 -44
- {reflex-0.7.2a2.dist-info → reflex-0.7.3a1.dist-info}/WHEEL +1 -1
- reflex-0.7.3a1.dist-info/entry_points.txt +5 -0
- reflex-0.7.2a2.dist-info/entry_points.txt +0 -3
- {reflex-0.7.2a2.dist-info → reflex-0.7.3a1.dist-info/licenses}/LICENSE +0 -0
reflex/reflex.py
CHANGED
|
@@ -13,7 +13,7 @@ from reflex import constants
|
|
|
13
13
|
from reflex.config import environment, get_config
|
|
14
14
|
from reflex.custom_components.custom_components import custom_components_cli
|
|
15
15
|
from reflex.state import reset_disk_state_manager
|
|
16
|
-
from reflex.utils import console, telemetry
|
|
16
|
+
from reflex.utils import console, redir, telemetry
|
|
17
17
|
|
|
18
18
|
# Disable typer+rich integration for help panels
|
|
19
19
|
typer.core.rich = None # pyright: ignore [reportPrivateImportUsage]
|
|
@@ -22,10 +22,6 @@ typer.core.rich = None # pyright: ignore [reportPrivateImportUsage]
|
|
|
22
22
|
cli = typer.Typer(add_completion=False, pretty_exceptions_enable=False)
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
# Get the config.
|
|
26
|
-
config = get_config()
|
|
27
|
-
|
|
28
|
-
|
|
29
25
|
def version(value: bool):
|
|
30
26
|
"""Get the Reflex version.
|
|
31
27
|
|
|
@@ -58,18 +54,28 @@ def main(
|
|
|
58
54
|
def _init(
|
|
59
55
|
name: str,
|
|
60
56
|
template: str | None = None,
|
|
61
|
-
loglevel: constants.LogLevel =
|
|
57
|
+
loglevel: constants.LogLevel | None = None,
|
|
62
58
|
ai: bool = False,
|
|
63
59
|
):
|
|
64
60
|
"""Initialize a new Reflex app in the given directory."""
|
|
65
61
|
from reflex.utils import exec, prerequisites
|
|
66
62
|
|
|
63
|
+
if loglevel is not None:
|
|
64
|
+
console.set_log_level(loglevel)
|
|
65
|
+
|
|
66
|
+
config = get_config()
|
|
67
|
+
|
|
67
68
|
# Set the log level.
|
|
69
|
+
loglevel = loglevel or config.loglevel
|
|
68
70
|
console.set_log_level(loglevel)
|
|
69
71
|
|
|
70
72
|
# Show system info
|
|
71
73
|
exec.output_system_info()
|
|
72
74
|
|
|
75
|
+
if ai:
|
|
76
|
+
redir.reflex_build_redirect()
|
|
77
|
+
return
|
|
78
|
+
|
|
73
79
|
# Validate the app name.
|
|
74
80
|
app_name = prerequisites.validate_app_name(name)
|
|
75
81
|
console.rule(f"[bold]Initializing {app_name}")
|
|
@@ -83,7 +89,7 @@ def _init(
|
|
|
83
89
|
prerequisites.initialize_frontend_dependencies()
|
|
84
90
|
|
|
85
91
|
# Initialize the app.
|
|
86
|
-
template = prerequisites.initialize_app(app_name, template
|
|
92
|
+
template = prerequisites.initialize_app(app_name, template)
|
|
87
93
|
|
|
88
94
|
# Initialize the .gitignore.
|
|
89
95
|
prerequisites.initialize_gitignore()
|
|
@@ -105,8 +111,8 @@ def init(
|
|
|
105
111
|
None,
|
|
106
112
|
help="The template to initialize the app with.",
|
|
107
113
|
),
|
|
108
|
-
loglevel: constants.LogLevel = typer.Option(
|
|
109
|
-
|
|
114
|
+
loglevel: constants.LogLevel | None = typer.Option(
|
|
115
|
+
None, help="The log level to use."
|
|
110
116
|
),
|
|
111
117
|
ai: bool = typer.Option(
|
|
112
118
|
False,
|
|
@@ -123,12 +129,20 @@ def _run(
|
|
|
123
129
|
backend: bool = True,
|
|
124
130
|
frontend_port: int | None = None,
|
|
125
131
|
backend_port: int | None = None,
|
|
126
|
-
backend_host: str =
|
|
127
|
-
loglevel: constants.LogLevel =
|
|
132
|
+
backend_host: str | None = None,
|
|
133
|
+
loglevel: constants.LogLevel | None = None,
|
|
128
134
|
):
|
|
129
135
|
"""Run the app in the given directory."""
|
|
130
136
|
from reflex.utils import build, exec, prerequisites, processes
|
|
131
137
|
|
|
138
|
+
if loglevel is not None:
|
|
139
|
+
console.set_log_level(loglevel)
|
|
140
|
+
|
|
141
|
+
config = get_config()
|
|
142
|
+
|
|
143
|
+
loglevel = loglevel or config.loglevel
|
|
144
|
+
backend_host = backend_host or config.backend_host
|
|
145
|
+
|
|
132
146
|
# Set the log level.
|
|
133
147
|
console.set_log_level(loglevel)
|
|
134
148
|
|
|
@@ -270,21 +284,19 @@ def run(
|
|
|
270
284
|
help="Execute only backend.",
|
|
271
285
|
envvar=environment.REFLEX_BACKEND_ONLY.name,
|
|
272
286
|
),
|
|
273
|
-
frontend_port: int = typer.Option(
|
|
274
|
-
|
|
287
|
+
frontend_port: int | None = typer.Option(
|
|
288
|
+
None,
|
|
275
289
|
help="Specify a different frontend port.",
|
|
276
290
|
envvar=environment.REFLEX_FRONTEND_PORT.name,
|
|
277
291
|
),
|
|
278
|
-
backend_port: int = typer.Option(
|
|
279
|
-
|
|
292
|
+
backend_port: int | None = typer.Option(
|
|
293
|
+
None,
|
|
280
294
|
help="Specify a different backend port.",
|
|
281
295
|
envvar=environment.REFLEX_BACKEND_PORT.name,
|
|
282
296
|
),
|
|
283
|
-
backend_host: str = typer.Option(
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
loglevel: constants.LogLevel = typer.Option(
|
|
287
|
-
config.loglevel, help="The log level to use."
|
|
297
|
+
backend_host: str | None = typer.Option(None, help="Specify the backend host."),
|
|
298
|
+
loglevel: constants.LogLevel | None = typer.Option(
|
|
299
|
+
None, help="The log level to use."
|
|
288
300
|
),
|
|
289
301
|
):
|
|
290
302
|
"""Run the app in the current directory."""
|
|
@@ -292,6 +304,16 @@ def run(
|
|
|
292
304
|
console.error("Cannot use both --frontend-only and --backend-only options.")
|
|
293
305
|
raise typer.Exit(1)
|
|
294
306
|
|
|
307
|
+
if loglevel is not None:
|
|
308
|
+
console.set_log_level(loglevel)
|
|
309
|
+
|
|
310
|
+
config = get_config()
|
|
311
|
+
|
|
312
|
+
frontend_port = frontend_port or config.frontend_port
|
|
313
|
+
backend_port = backend_port or config.backend_port
|
|
314
|
+
backend_host = backend_host or config.backend_host
|
|
315
|
+
loglevel = loglevel or config.loglevel
|
|
316
|
+
|
|
295
317
|
environment.REFLEX_COMPILE_CONTEXT.set(constants.CompileContext.RUN)
|
|
296
318
|
environment.REFLEX_BACKEND_ONLY.set(backend)
|
|
297
319
|
environment.REFLEX_FRONTEND_ONLY.set(frontend)
|
|
@@ -331,8 +353,8 @@ def export(
|
|
|
331
353
|
env: constants.Env = typer.Option(
|
|
332
354
|
constants.Env.PROD, help="The environment to export the app in."
|
|
333
355
|
),
|
|
334
|
-
loglevel: constants.LogLevel = typer.Option(
|
|
335
|
-
|
|
356
|
+
loglevel: constants.LogLevel | None = typer.Option(
|
|
357
|
+
None, help="The log level to use."
|
|
336
358
|
),
|
|
337
359
|
):
|
|
338
360
|
"""Export the app to a zip file."""
|
|
@@ -343,8 +365,11 @@ def export(
|
|
|
343
365
|
|
|
344
366
|
frontend, backend = prerequisites.check_running_mode(frontend, backend)
|
|
345
367
|
|
|
368
|
+
loglevel = loglevel or get_config().loglevel
|
|
369
|
+
console.set_log_level(loglevel)
|
|
370
|
+
|
|
346
371
|
if prerequisites.needs_reinit(frontend=frontend or not backend):
|
|
347
|
-
_init(name=
|
|
372
|
+
_init(name=get_config().app_name, loglevel=loglevel)
|
|
348
373
|
|
|
349
374
|
export_utils.export(
|
|
350
375
|
zipping=zipping,
|
|
@@ -358,10 +383,14 @@ def export(
|
|
|
358
383
|
|
|
359
384
|
|
|
360
385
|
@cli.command()
|
|
361
|
-
def login(loglevel: constants.LogLevel = typer.Option(
|
|
386
|
+
def login(loglevel: constants.LogLevel | None = typer.Option(None)):
|
|
362
387
|
"""Authenticate with experimental Reflex hosting service."""
|
|
363
388
|
from reflex_cli.v2 import cli as hosting_cli
|
|
364
389
|
|
|
390
|
+
loglevel = loglevel or get_config().loglevel
|
|
391
|
+
|
|
392
|
+
console.set_log_level(loglevel)
|
|
393
|
+
|
|
365
394
|
check_version()
|
|
366
395
|
|
|
367
396
|
validated_info = hosting_cli.login()
|
|
@@ -372,8 +401,8 @@ def login(loglevel: constants.LogLevel = typer.Option(config.loglevel)):
|
|
|
372
401
|
|
|
373
402
|
@cli.command()
|
|
374
403
|
def logout(
|
|
375
|
-
loglevel: constants.LogLevel = typer.Option(
|
|
376
|
-
|
|
404
|
+
loglevel: constants.LogLevel | None = typer.Option(
|
|
405
|
+
None, help="The log level to use."
|
|
377
406
|
),
|
|
378
407
|
):
|
|
379
408
|
"""Log out of access to Reflex hosting service."""
|
|
@@ -381,6 +410,8 @@ def logout(
|
|
|
381
410
|
|
|
382
411
|
check_version()
|
|
383
412
|
|
|
413
|
+
loglevel = loglevel or get_config().loglevel
|
|
414
|
+
|
|
384
415
|
logout(loglevel) # pyright: ignore [reportArgumentType]
|
|
385
416
|
|
|
386
417
|
|
|
@@ -399,6 +430,8 @@ def db_init():
|
|
|
399
430
|
from reflex import model
|
|
400
431
|
from reflex.utils import prerequisites
|
|
401
432
|
|
|
433
|
+
config = get_config()
|
|
434
|
+
|
|
402
435
|
# Check the database url.
|
|
403
436
|
if config.db_url is None:
|
|
404
437
|
console.error("db_url is not configured, cannot initialize.")
|
|
@@ -466,8 +499,8 @@ def makemigrations(
|
|
|
466
499
|
|
|
467
500
|
@cli.command()
|
|
468
501
|
def deploy(
|
|
469
|
-
app_name: str = typer.Option(
|
|
470
|
-
|
|
502
|
+
app_name: str | None = typer.Option(
|
|
503
|
+
None,
|
|
471
504
|
"--app-name",
|
|
472
505
|
help="The name of the App to deploy under.",
|
|
473
506
|
),
|
|
@@ -506,8 +539,8 @@ def deploy(
|
|
|
506
539
|
"--envfile",
|
|
507
540
|
help="The path to an env file to use. Will override any envs set manually.",
|
|
508
541
|
),
|
|
509
|
-
loglevel: constants.LogLevel = typer.Option(
|
|
510
|
-
|
|
542
|
+
loglevel: constants.LogLevel | None = typer.Option(
|
|
543
|
+
None, help="The log level to use."
|
|
511
544
|
),
|
|
512
545
|
project: str | None = typer.Option(
|
|
513
546
|
None,
|
|
@@ -538,6 +571,14 @@ def deploy(
|
|
|
538
571
|
from reflex.utils import export as export_utils
|
|
539
572
|
from reflex.utils import prerequisites
|
|
540
573
|
|
|
574
|
+
if loglevel is not None:
|
|
575
|
+
console.set_log_level(loglevel)
|
|
576
|
+
|
|
577
|
+
config = get_config()
|
|
578
|
+
|
|
579
|
+
loglevel = loglevel or config.loglevel
|
|
580
|
+
app_name = app_name or config.app_name
|
|
581
|
+
|
|
541
582
|
check_version()
|
|
542
583
|
|
|
543
584
|
environment.REFLEX_COMPILE_CONTEXT.set(constants.CompileContext.DEPLOY)
|
|
@@ -604,13 +645,15 @@ def deploy(
|
|
|
604
645
|
@cli.command()
|
|
605
646
|
def rename(
|
|
606
647
|
new_name: str = typer.Argument(..., help="The new name for the app."),
|
|
607
|
-
loglevel: constants.LogLevel = typer.Option(
|
|
608
|
-
|
|
648
|
+
loglevel: constants.LogLevel | None = typer.Option(
|
|
649
|
+
None, help="The log level to use."
|
|
609
650
|
),
|
|
610
651
|
):
|
|
611
652
|
"""Rename the app in the current directory."""
|
|
612
653
|
from reflex.utils import prerequisites
|
|
613
654
|
|
|
655
|
+
loglevel = loglevel or get_config().loglevel
|
|
656
|
+
|
|
614
657
|
prerequisites.validate_app_name(new_name)
|
|
615
658
|
prerequisites.rename_app(new_name, loglevel)
|
|
616
659
|
|
reflex/state.py
CHANGED
|
@@ -1013,9 +1013,9 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|
|
1013
1013
|
|
|
1014
1014
|
if not types.is_valid_var_type(prop._var_type):
|
|
1015
1015
|
raise VarTypeError(
|
|
1016
|
-
"State vars must be
|
|
1017
|
-
"
|
|
1018
|
-
"
|
|
1016
|
+
"State vars must be of a serializable type. "
|
|
1017
|
+
"Valid types include strings, numbers, booleans, lists, "
|
|
1018
|
+
"dictionaries, dataclasses, datetime objects, and pydantic models. "
|
|
1019
1019
|
f'Found var "{prop._js_expr}" with type {prop._var_type}.'
|
|
1020
1020
|
)
|
|
1021
1021
|
cls._set_var(prop)
|
reflex/style.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from typing import Any, Literal, Type
|
|
5
|
+
from typing import Any, Literal, Mapping, Type
|
|
6
6
|
|
|
7
7
|
from reflex import constants
|
|
8
8
|
from reflex.components.core.breakpoints import Breakpoints, breakpoints_values
|
|
@@ -10,7 +10,7 @@ from reflex.event import EventChain, EventHandler, EventSpec, run_script
|
|
|
10
10
|
from reflex.utils import format
|
|
11
11
|
from reflex.utils.exceptions import ReflexError
|
|
12
12
|
from reflex.utils.imports import ImportVar
|
|
13
|
-
from reflex.utils.types import
|
|
13
|
+
from reflex.utils.types import typehint_issubclass
|
|
14
14
|
from reflex.vars import VarData
|
|
15
15
|
from reflex.vars.base import LiteralVar, Var
|
|
16
16
|
from reflex.vars.function import FunctionVar
|
|
@@ -189,7 +189,7 @@ def convert(
|
|
|
189
189
|
or (isinstance(value, list) and all(not isinstance(v, dict) for v in value))
|
|
190
190
|
or (
|
|
191
191
|
isinstance(value, ObjectVar)
|
|
192
|
-
and not
|
|
192
|
+
and not typehint_issubclass(value._var_type, Mapping)
|
|
193
193
|
)
|
|
194
194
|
else (key,)
|
|
195
195
|
)
|
reflex/testing.py
CHANGED
|
@@ -54,18 +54,12 @@ from reflex.state import (
|
|
|
54
54
|
from reflex.utils import console
|
|
55
55
|
|
|
56
56
|
try:
|
|
57
|
-
from selenium import webdriver
|
|
58
|
-
from selenium.webdriver.remote.webdriver import
|
|
59
|
-
WebDriver,
|
|
60
|
-
)
|
|
57
|
+
from selenium import webdriver
|
|
58
|
+
from selenium.webdriver.remote.webdriver import WebDriver
|
|
61
59
|
|
|
62
60
|
if TYPE_CHECKING:
|
|
63
|
-
from selenium.webdriver.common.options import
|
|
64
|
-
|
|
65
|
-
)
|
|
66
|
-
from selenium.webdriver.remote.webelement import ( # pyright: ignore [reportMissingImports]
|
|
67
|
-
WebElement,
|
|
68
|
-
)
|
|
61
|
+
from selenium.webdriver.common.options import ArgOptions
|
|
62
|
+
from selenium.webdriver.remote.webelement import WebElement
|
|
69
63
|
|
|
70
64
|
has_selenium = True
|
|
71
65
|
except ImportError:
|
reflex/utils/exceptions.py
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
"""Custom Exceptions."""
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from reflex.vars import Var
|
|
4
9
|
|
|
5
10
|
|
|
6
11
|
class ReflexError(Exception):
|
|
@@ -78,6 +83,31 @@ class VarAttributeError(ReflexError, AttributeError):
|
|
|
78
83
|
class UntypedVarError(ReflexError, TypeError):
|
|
79
84
|
"""Custom TypeError for untyped var errors."""
|
|
80
85
|
|
|
86
|
+
def __init__(self, var: Var, action: str, doc_link: str = ""):
|
|
87
|
+
"""Create an UntypedVarError from a var.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
var: The var.
|
|
91
|
+
action: The action that caused the error.
|
|
92
|
+
doc_link: The link to the documentation.
|
|
93
|
+
"""
|
|
94
|
+
var_data = var._get_all_var_data()
|
|
95
|
+
is_state_var = (
|
|
96
|
+
var_data
|
|
97
|
+
and var_data.state
|
|
98
|
+
and var_data.field_name
|
|
99
|
+
and var_data.state + "." + var_data.field_name == str(var)
|
|
100
|
+
)
|
|
101
|
+
super().__init__(
|
|
102
|
+
f"Cannot {action} on untyped var '{var!s}' of type '{var._var_type!s}'."
|
|
103
|
+
+ (
|
|
104
|
+
" Please add a type annotation to the var in the state class."
|
|
105
|
+
if is_state_var
|
|
106
|
+
else " You can call the var's .to(desired_type) method to convert it to the desired type."
|
|
107
|
+
)
|
|
108
|
+
+ (f" See {doc_link}" if doc_link else "")
|
|
109
|
+
)
|
|
110
|
+
|
|
81
111
|
|
|
82
112
|
class UntypedComputedVarError(ReflexError, TypeError):
|
|
83
113
|
"""Custom TypeError for untyped computed var errors."""
|
reflex/utils/exec.py
CHANGED
|
@@ -332,11 +332,9 @@ def run_granian_backend(host: str, port: int, loglevel: LogLevel):
|
|
|
332
332
|
"""
|
|
333
333
|
console.debug("Using Granian for backend")
|
|
334
334
|
try:
|
|
335
|
-
from granian import
|
|
336
|
-
from granian.
|
|
337
|
-
|
|
338
|
-
)
|
|
339
|
-
from granian.log import LogLevels # pyright: ignore [reportMissingImports]
|
|
335
|
+
from granian.constants import Interfaces
|
|
336
|
+
from granian.log import LogLevels
|
|
337
|
+
from granian.server import Server as Granian
|
|
340
338
|
|
|
341
339
|
Granian(
|
|
342
340
|
target=get_granian_target(),
|
|
@@ -466,9 +464,7 @@ def run_granian_backend_prod(host: str, port: int, loglevel: LogLevel):
|
|
|
466
464
|
from reflex.utils import processes
|
|
467
465
|
|
|
468
466
|
try:
|
|
469
|
-
from granian.constants import
|
|
470
|
-
Interfaces,
|
|
471
|
-
)
|
|
467
|
+
from granian.constants import Interfaces
|
|
472
468
|
|
|
473
469
|
command = [
|
|
474
470
|
"granian",
|
reflex/utils/export.py
CHANGED
|
@@ -6,8 +6,6 @@ from reflex import constants
|
|
|
6
6
|
from reflex.config import environment, get_config
|
|
7
7
|
from reflex.utils import build, console, exec, prerequisites, telemetry
|
|
8
8
|
|
|
9
|
-
config = get_config()
|
|
10
|
-
|
|
11
9
|
|
|
12
10
|
def export(
|
|
13
11
|
zipping: bool = True,
|
|
@@ -33,6 +31,8 @@ def export(
|
|
|
33
31
|
env: The environment to use. Defaults to constants.Env.PROD.
|
|
34
32
|
loglevel: The log level to use. Defaults to console._LOG_LEVEL.
|
|
35
33
|
"""
|
|
34
|
+
config = get_config()
|
|
35
|
+
|
|
36
36
|
# Set the log level.
|
|
37
37
|
console.set_log_level(loglevel)
|
|
38
38
|
|
reflex/utils/prerequisites.py
CHANGED
|
@@ -37,7 +37,7 @@ from redis.exceptions import RedisError
|
|
|
37
37
|
from reflex import constants, model
|
|
38
38
|
from reflex.compiler import templates
|
|
39
39
|
from reflex.config import Config, environment, get_config
|
|
40
|
-
from reflex.utils import console, net, path_ops, processes
|
|
40
|
+
from reflex.utils import console, net, path_ops, processes
|
|
41
41
|
from reflex.utils.exceptions import (
|
|
42
42
|
GeneratedCodeHasNoFunctionDefsError,
|
|
43
43
|
SystemPackageMissingError,
|
|
@@ -1695,31 +1695,6 @@ def validate_and_create_app_using_remote_template(
|
|
|
1695
1695
|
)
|
|
1696
1696
|
|
|
1697
1697
|
|
|
1698
|
-
def generate_template_using_ai(template: str | None = None) -> str:
|
|
1699
|
-
"""Generate a template using AI(Flexgen).
|
|
1700
|
-
|
|
1701
|
-
Args:
|
|
1702
|
-
template: The name of the template.
|
|
1703
|
-
|
|
1704
|
-
Returns:
|
|
1705
|
-
The generation hash.
|
|
1706
|
-
|
|
1707
|
-
Raises:
|
|
1708
|
-
Exit: If the template and ai flags are used.
|
|
1709
|
-
"""
|
|
1710
|
-
if template is None:
|
|
1711
|
-
# If AI is requested and no template specified, redirect the user to reflex.build.
|
|
1712
|
-
return redir.reflex_build_redirect()
|
|
1713
|
-
elif is_generation_hash(template):
|
|
1714
|
-
# Otherwise treat the template as a generation hash.
|
|
1715
|
-
return template
|
|
1716
|
-
else:
|
|
1717
|
-
console.error(
|
|
1718
|
-
"Cannot use `--template` option with `--ai` option. Please remove `--template` option."
|
|
1719
|
-
)
|
|
1720
|
-
raise typer.Exit(2)
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
1698
|
def fetch_remote_templates(
|
|
1724
1699
|
template: str,
|
|
1725
1700
|
) -> tuple[str, dict[str, Template]]:
|
|
@@ -1744,15 +1719,12 @@ def fetch_remote_templates(
|
|
|
1744
1719
|
return template, available_templates
|
|
1745
1720
|
|
|
1746
1721
|
|
|
1747
|
-
def initialize_app(
|
|
1748
|
-
app_name: str, template: str | None = None, ai: bool = False
|
|
1749
|
-
) -> str | None:
|
|
1722
|
+
def initialize_app(app_name: str, template: str | None = None) -> str | None:
|
|
1750
1723
|
"""Initialize the app either from a remote template or a blank app. If the config file exists, it is considered as reinit.
|
|
1751
1724
|
|
|
1752
1725
|
Args:
|
|
1753
1726
|
app_name: The name of the app.
|
|
1754
1727
|
template: The name of the template to use.
|
|
1755
|
-
ai: Whether to use AI to generate the template.
|
|
1756
1728
|
|
|
1757
1729
|
Returns:
|
|
1758
1730
|
The name of the template.
|
|
@@ -1768,11 +1740,6 @@ def initialize_app(
|
|
|
1768
1740
|
telemetry.send("reinit")
|
|
1769
1741
|
return
|
|
1770
1742
|
|
|
1771
|
-
generation_hash = None
|
|
1772
|
-
if ai:
|
|
1773
|
-
generation_hash = generate_template_using_ai(template)
|
|
1774
|
-
template = constants.Templates.DEFAULT
|
|
1775
|
-
|
|
1776
1743
|
templates: dict[str, Template] = {}
|
|
1777
1744
|
|
|
1778
1745
|
# Don't fetch app templates if the user directly asked for DEFAULT.
|
|
@@ -1781,11 +1748,7 @@ def initialize_app(
|
|
|
1781
1748
|
|
|
1782
1749
|
if template is None:
|
|
1783
1750
|
template = prompt_for_template_options(get_init_cli_prompt_options())
|
|
1784
|
-
if template == constants.Templates.
|
|
1785
|
-
generation_hash = generate_template_using_ai()
|
|
1786
|
-
# change to the default to allow creation of default app
|
|
1787
|
-
template = constants.Templates.DEFAULT
|
|
1788
|
-
elif template == constants.Templates.CHOOSE_TEMPLATES:
|
|
1751
|
+
if template == constants.Templates.CHOOSE_TEMPLATES:
|
|
1789
1752
|
console.print(
|
|
1790
1753
|
f"Go to the templates page ({constants.Templates.REFLEX_TEMPLATES_URL}) and copy the command to init with a template."
|
|
1791
1754
|
)
|
|
@@ -1800,11 +1763,6 @@ def initialize_app(
|
|
|
1800
1763
|
app_name=app_name, template=template, templates=templates
|
|
1801
1764
|
)
|
|
1802
1765
|
|
|
1803
|
-
# If a reflex.build generation hash is available, download the code and apply it to the main module.
|
|
1804
|
-
if generation_hash:
|
|
1805
|
-
initialize_main_module_index_from_generation(
|
|
1806
|
-
app_name, generation_hash=generation_hash
|
|
1807
|
-
)
|
|
1808
1766
|
telemetry.send("init", template=template)
|
|
1809
1767
|
|
|
1810
1768
|
return template
|
reflex/utils/pyi_generator.py
CHANGED
|
@@ -348,7 +348,7 @@ def _extract_class_props_as_ast_nodes(
|
|
|
348
348
|
all_props = []
|
|
349
349
|
kwargs = []
|
|
350
350
|
for target_class in clzs:
|
|
351
|
-
event_triggers = target_class().get_event_triggers()
|
|
351
|
+
event_triggers = target_class._create([]).get_event_triggers()
|
|
352
352
|
# Import from the target class to ensure type hints are resolvable.
|
|
353
353
|
exec(f"from {target_class.__module__} import *", type_hint_globals)
|
|
354
354
|
for name, value in target_class.__annotations__.items():
|
|
@@ -575,7 +575,7 @@ def _generate_component_create_functiondef(
|
|
|
575
575
|
return ast.Name(id=f"{' | '.join(map(ast.unparse, all_count_args_type))}")
|
|
576
576
|
return ast.Name(id="EventType[Any]")
|
|
577
577
|
|
|
578
|
-
event_triggers = clz().get_event_triggers()
|
|
578
|
+
event_triggers = clz._create([]).get_event_triggers()
|
|
579
579
|
|
|
580
580
|
# event handler kwargs
|
|
581
581
|
kwargs.extend(
|
reflex/utils/redir.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""Utilities to handle redirection to browser UI."""
|
|
2
2
|
|
|
3
3
|
import time
|
|
4
|
-
import uuid
|
|
5
4
|
import webbrowser
|
|
6
5
|
|
|
7
6
|
import httpx
|
|
@@ -48,14 +47,6 @@ def open_browser_and_wait(
|
|
|
48
47
|
return response
|
|
49
48
|
|
|
50
49
|
|
|
51
|
-
def reflex_build_redirect() ->
|
|
52
|
-
"""Open the browser window to reflex.build
|
|
53
|
-
|
|
54
|
-
Returns:
|
|
55
|
-
The selected generation hash.
|
|
56
|
-
"""
|
|
57
|
-
token = str(uuid.uuid4())
|
|
58
|
-
target_url = constants.Templates.REFLEX_BUILD_URL.format(reflex_init_token=token)
|
|
59
|
-
poll_url = constants.Templates.REFLEX_BUILD_POLL_URL.format(reflex_init_token=token)
|
|
60
|
-
response = open_browser_and_wait(target_url, poll_url)
|
|
61
|
-
return response.json()["generation_hash"]
|
|
50
|
+
def reflex_build_redirect() -> None:
|
|
51
|
+
"""Open the browser window to reflex.build."""
|
|
52
|
+
open_browser(constants.Templates.REFLEX_BUILD_FRONTEND)
|
reflex/vars/base.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import contextlib
|
|
6
|
+
import copy
|
|
6
7
|
import dataclasses
|
|
7
8
|
import datetime
|
|
8
9
|
import functools
|
|
@@ -1255,6 +1256,27 @@ class Var(Generic[VAR_TYPE]):
|
|
|
1255
1256
|
|
|
1256
1257
|
if not TYPE_CHECKING:
|
|
1257
1258
|
|
|
1259
|
+
def __getitem__(self, key: Any) -> Var:
|
|
1260
|
+
"""Get the item from the var.
|
|
1261
|
+
|
|
1262
|
+
Args:
|
|
1263
|
+
key: The key to get.
|
|
1264
|
+
|
|
1265
|
+
Raises:
|
|
1266
|
+
UntypedVarError: If the var type is Any.
|
|
1267
|
+
TypeError: If the var type is Any.
|
|
1268
|
+
|
|
1269
|
+
# noqa: DAR101 self
|
|
1270
|
+
"""
|
|
1271
|
+
if self._var_type is Any:
|
|
1272
|
+
raise exceptions.UntypedVarError(
|
|
1273
|
+
self,
|
|
1274
|
+
f"access the item '{key}'",
|
|
1275
|
+
)
|
|
1276
|
+
raise TypeError(
|
|
1277
|
+
f"Var of type {self._var_type} does not support item access."
|
|
1278
|
+
)
|
|
1279
|
+
|
|
1258
1280
|
def __getattr__(self, name: str):
|
|
1259
1281
|
"""Get an attribute of the var.
|
|
1260
1282
|
|
|
@@ -1280,7 +1302,8 @@ class Var(Generic[VAR_TYPE]):
|
|
|
1280
1302
|
|
|
1281
1303
|
if self._var_type is Any:
|
|
1282
1304
|
raise exceptions.UntypedVarError(
|
|
1283
|
-
|
|
1305
|
+
self,
|
|
1306
|
+
f"access the attribute '{name}'",
|
|
1284
1307
|
)
|
|
1285
1308
|
|
|
1286
1309
|
raise VarAttributeError(
|
|
@@ -2146,7 +2169,7 @@ class ComputedVar(Var[RETURN_TYPE]):
|
|
|
2146
2169
|
"fget": kwargs.pop("fget", self._fget),
|
|
2147
2170
|
"initial_value": kwargs.pop("initial_value", self._initial_value),
|
|
2148
2171
|
"cache": kwargs.pop("cache", self._cache),
|
|
2149
|
-
"deps": kwargs.pop("deps", self._static_deps),
|
|
2172
|
+
"deps": kwargs.pop("deps", copy.copy(self._static_deps)),
|
|
2150
2173
|
"auto_deps": kwargs.pop("auto_deps", self._auto_deps),
|
|
2151
2174
|
"interval": kwargs.pop("interval", self._update_interval),
|
|
2152
2175
|
"backend": kwargs.pop("backend", self._backend),
|
|
@@ -2318,7 +2341,7 @@ class ComputedVar(Var[RETURN_TYPE]):
|
|
|
2318
2341
|
if not _isinstance(value, self._var_type, nested=1, treat_var_as_type=False):
|
|
2319
2342
|
console.error(
|
|
2320
2343
|
f"Computed var '{type(instance).__name__}.{self._js_expr}' must return"
|
|
2321
|
-
f" type '{self._var_type}', got '{type(value)}
|
|
2344
|
+
f" a value of type '{self._var_type}', got '{value}' of type {type(value)}."
|
|
2322
2345
|
)
|
|
2323
2346
|
|
|
2324
2347
|
def _deps(
|