reflex 0.7.8__py3-none-any.whl → 0.7.9a1__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/tailwind.config.js.jinja2 +65 -31
- reflex/.templates/web/utils/state.js +11 -1
- reflex/app.py +185 -79
- reflex/app_mixins/lifespan.py +2 -2
- reflex/compiler/compiler.py +31 -4
- reflex/components/component.py +39 -57
- reflex/components/core/upload.py +8 -0
- reflex/components/dynamic.py +9 -1
- reflex/components/markdown/markdown.py +0 -21
- reflex/components/radix/primitives/accordion.py +1 -1
- reflex/components/radix/primitives/form.py +1 -1
- reflex/components/radix/primitives/progress.py +1 -1
- reflex/components/radix/primitives/slider.py +1 -1
- reflex/components/radix/themes/color_mode.py +1 -1
- reflex/components/radix/themes/color_mode.pyi +1 -1
- reflex/components/recharts/recharts.py +2 -2
- reflex/components/sonner/toast.py +1 -1
- reflex/config.py +4 -7
- reflex/constants/base.py +21 -0
- reflex/constants/installer.py +6 -6
- reflex/custom_components/custom_components.py +67 -64
- reflex/event.py +2 -0
- reflex/reflex.py +276 -265
- reflex/testing.py +30 -24
- reflex/utils/codespaces.py +6 -2
- reflex/utils/console.py +4 -3
- reflex/utils/exec.py +60 -24
- reflex/utils/format.py +17 -2
- reflex/utils/prerequisites.py +43 -30
- reflex/utils/processes.py +6 -6
- reflex/utils/types.py +11 -6
- reflex/vars/base.py +19 -1
- {reflex-0.7.8.dist-info → reflex-0.7.9a1.dist-info}/METADATA +6 -9
- {reflex-0.7.8.dist-info → reflex-0.7.9a1.dist-info}/RECORD +37 -37
- {reflex-0.7.8.dist-info → reflex-0.7.9a1.dist-info}/WHEEL +0 -0
- {reflex-0.7.8.dist-info → reflex-0.7.9a1.dist-info}/entry_points.txt +0 -0
- {reflex-0.7.8.dist-info → reflex-0.7.9a1.dist-info}/licenses/LICENSE +0 -0
reflex/reflex.py
CHANGED
|
@@ -3,74 +3,63 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import atexit
|
|
6
|
+
from importlib.util import find_spec
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
from typing import TYPE_CHECKING
|
|
8
9
|
|
|
9
|
-
import
|
|
10
|
-
import typer.core
|
|
10
|
+
import click
|
|
11
11
|
from reflex_cli.v2.deployments import hosting_cli
|
|
12
12
|
|
|
13
13
|
from reflex import constants
|
|
14
14
|
from reflex.config import environment, get_config
|
|
15
|
+
from reflex.constants.base import LITERAL_ENV
|
|
15
16
|
from reflex.custom_components.custom_components import custom_components_cli
|
|
16
17
|
from reflex.state import reset_disk_state_manager
|
|
17
18
|
from reflex.utils import console, redir, telemetry
|
|
18
19
|
from reflex.utils.exec import should_use_granian
|
|
19
20
|
|
|
20
|
-
# Disable typer+rich integration for help panels
|
|
21
|
-
typer.core.rich = None # pyright: ignore [reportPrivateImportUsage]
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def version(value: bool):
|
|
28
|
-
"""Get the Reflex version.
|
|
22
|
+
def set_loglevel(ctx: click.Context, self: click.Parameter, value: str | None):
|
|
23
|
+
"""Set the log level.
|
|
29
24
|
|
|
30
25
|
Args:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
typer.Exit: If the version flag was passed.
|
|
26
|
+
ctx: The click context.
|
|
27
|
+
self: The click command.
|
|
28
|
+
value: The log level to set.
|
|
35
29
|
"""
|
|
36
|
-
if value:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
@
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
None,
|
|
45
|
-
"-v",
|
|
46
|
-
"--version",
|
|
47
|
-
callback=version,
|
|
48
|
-
help="Get the Reflex version.",
|
|
49
|
-
is_eager=True,
|
|
50
|
-
),
|
|
51
|
-
):
|
|
30
|
+
if value is not None:
|
|
31
|
+
loglevel = constants.LogLevel.from_string(value)
|
|
32
|
+
console.set_log_level(loglevel)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@click.group
|
|
36
|
+
@click.version_option(constants.Reflex.VERSION, message="%(version)s")
|
|
37
|
+
def cli():
|
|
52
38
|
"""Reflex CLI to create, run, and deploy apps."""
|
|
53
39
|
pass
|
|
54
40
|
|
|
55
41
|
|
|
42
|
+
loglevel_option = click.option(
|
|
43
|
+
"--loglevel",
|
|
44
|
+
type=click.Choice(
|
|
45
|
+
[loglevel.value for loglevel in constants.LogLevel],
|
|
46
|
+
case_sensitive=False,
|
|
47
|
+
),
|
|
48
|
+
is_eager=True,
|
|
49
|
+
callback=set_loglevel,
|
|
50
|
+
expose_value=False,
|
|
51
|
+
help="The log level to use.",
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
56
55
|
def _init(
|
|
57
56
|
name: str,
|
|
58
57
|
template: str | None = None,
|
|
59
|
-
loglevel: constants.LogLevel | None = None,
|
|
60
58
|
ai: bool = False,
|
|
61
59
|
):
|
|
62
60
|
"""Initialize a new Reflex app in the given directory."""
|
|
63
61
|
from reflex.utils import exec, prerequisites
|
|
64
62
|
|
|
65
|
-
if loglevel is not None:
|
|
66
|
-
console.set_log_level(loglevel)
|
|
67
|
-
|
|
68
|
-
config = get_config()
|
|
69
|
-
|
|
70
|
-
# Set the log level.
|
|
71
|
-
loglevel = loglevel or config.loglevel
|
|
72
|
-
console.set_log_level(loglevel)
|
|
73
|
-
|
|
74
63
|
# Show system info
|
|
75
64
|
exec.output_system_info()
|
|
76
65
|
|
|
@@ -112,24 +101,28 @@ def _init(
|
|
|
112
101
|
|
|
113
102
|
|
|
114
103
|
@cli.command()
|
|
104
|
+
@loglevel_option
|
|
105
|
+
@click.option(
|
|
106
|
+
"--name",
|
|
107
|
+
metavar="APP_NAME",
|
|
108
|
+
help="The name of the app to initialize.",
|
|
109
|
+
)
|
|
110
|
+
@click.option(
|
|
111
|
+
"--template",
|
|
112
|
+
help="The template to initialize the app with.",
|
|
113
|
+
)
|
|
114
|
+
@click.option(
|
|
115
|
+
"--ai",
|
|
116
|
+
is_flag=True,
|
|
117
|
+
help="Use AI to create the initial template. Cannot be used with existing app or `--template` option.",
|
|
118
|
+
)
|
|
115
119
|
def init(
|
|
116
|
-
name: str
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
template: str = typer.Option(
|
|
120
|
-
None,
|
|
121
|
-
help="The template to initialize the app with.",
|
|
122
|
-
),
|
|
123
|
-
loglevel: constants.LogLevel | None = typer.Option(
|
|
124
|
-
None, help="The log level to use."
|
|
125
|
-
),
|
|
126
|
-
ai: bool = typer.Option(
|
|
127
|
-
False,
|
|
128
|
-
help="Use AI to create the initial template. Cannot be used with existing app or `--template` option.",
|
|
129
|
-
),
|
|
120
|
+
name: str,
|
|
121
|
+
template: str | None,
|
|
122
|
+
ai: bool,
|
|
130
123
|
):
|
|
131
124
|
"""Initialize a new Reflex app in the current directory."""
|
|
132
|
-
_init(name, template,
|
|
125
|
+
_init(name, template, ai)
|
|
133
126
|
|
|
134
127
|
|
|
135
128
|
def _run(
|
|
@@ -139,22 +132,14 @@ def _run(
|
|
|
139
132
|
frontend_port: int | None = None,
|
|
140
133
|
backend_port: int | None = None,
|
|
141
134
|
backend_host: str | None = None,
|
|
142
|
-
loglevel: constants.LogLevel | None = None,
|
|
143
135
|
):
|
|
144
136
|
"""Run the app in the given directory."""
|
|
145
137
|
from reflex.utils import build, exec, prerequisites, processes
|
|
146
138
|
|
|
147
|
-
if loglevel is not None:
|
|
148
|
-
console.set_log_level(loglevel)
|
|
149
|
-
|
|
150
139
|
config = get_config()
|
|
151
140
|
|
|
152
|
-
loglevel = loglevel or config.loglevel
|
|
153
141
|
backend_host = backend_host or config.backend_host
|
|
154
142
|
|
|
155
|
-
# Set the log level.
|
|
156
|
-
console.set_log_level(loglevel)
|
|
157
|
-
|
|
158
143
|
# Set env mode in the environment
|
|
159
144
|
environment.REFLEX_ENV_MODE.set(env)
|
|
160
145
|
|
|
@@ -168,7 +153,7 @@ def _run(
|
|
|
168
153
|
|
|
169
154
|
# Check that the app is initialized.
|
|
170
155
|
if prerequisites.needs_reinit(frontend=frontend):
|
|
171
|
-
_init(name=config.app_name
|
|
156
|
+
_init(name=config.app_name)
|
|
172
157
|
|
|
173
158
|
# Delete the states folder if it exists.
|
|
174
159
|
reset_disk_state_manager()
|
|
@@ -228,7 +213,7 @@ def _run(
|
|
|
228
213
|
else:
|
|
229
214
|
validation_result = app_task(*args)
|
|
230
215
|
if not validation_result:
|
|
231
|
-
raise
|
|
216
|
+
raise click.exceptions.Exit(1)
|
|
232
217
|
|
|
233
218
|
# Warn if schema is not up to date.
|
|
234
219
|
prerequisites.check_schema_up_to_date()
|
|
@@ -248,7 +233,7 @@ def _run(
|
|
|
248
233
|
exec.run_backend_prod,
|
|
249
234
|
)
|
|
250
235
|
if not setup_frontend or not frontend_cmd or not backend_cmd:
|
|
251
|
-
raise ValueError("Invalid env")
|
|
236
|
+
raise ValueError(f"Invalid env: {env}. Must be DEV or PROD.")
|
|
252
237
|
|
|
253
238
|
# Post a telemetry event.
|
|
254
239
|
telemetry.send(f"run-{env.value}")
|
|
@@ -271,7 +256,7 @@ def _run(
|
|
|
271
256
|
backend_cmd,
|
|
272
257
|
backend_host,
|
|
273
258
|
backend_port,
|
|
274
|
-
loglevel.subprocess_level(),
|
|
259
|
+
config.loglevel.subprocess_level(),
|
|
275
260
|
frontend,
|
|
276
261
|
)
|
|
277
262
|
)
|
|
@@ -281,7 +266,10 @@ def _run(
|
|
|
281
266
|
# In dev mode, run the backend on the main thread.
|
|
282
267
|
if backend and backend_port and env == constants.Env.DEV:
|
|
283
268
|
backend_cmd(
|
|
284
|
-
backend_host,
|
|
269
|
+
backend_host,
|
|
270
|
+
int(backend_port),
|
|
271
|
+
config.loglevel.subprocess_level(),
|
|
272
|
+
frontend,
|
|
285
273
|
)
|
|
286
274
|
# The windows uvicorn bug workaround
|
|
287
275
|
# https://github.com/reflex-dev/reflex/issues/2335
|
|
@@ -291,94 +279,122 @@ def _run(
|
|
|
291
279
|
|
|
292
280
|
|
|
293
281
|
@cli.command()
|
|
282
|
+
@loglevel_option
|
|
283
|
+
@click.option(
|
|
284
|
+
"--env",
|
|
285
|
+
type=click.Choice([e.value for e in constants.Env], case_sensitive=False),
|
|
286
|
+
default=constants.Env.DEV.value,
|
|
287
|
+
help="The environment to run the app in.",
|
|
288
|
+
)
|
|
289
|
+
@click.option(
|
|
290
|
+
"--frontend-only",
|
|
291
|
+
is_flag=True,
|
|
292
|
+
show_default=False,
|
|
293
|
+
help="Execute only frontend.",
|
|
294
|
+
envvar=environment.REFLEX_FRONTEND_ONLY.name,
|
|
295
|
+
)
|
|
296
|
+
@click.option(
|
|
297
|
+
"--backend-only",
|
|
298
|
+
is_flag=True,
|
|
299
|
+
show_default=False,
|
|
300
|
+
help="Execute only backend.",
|
|
301
|
+
envvar=environment.REFLEX_BACKEND_ONLY.name,
|
|
302
|
+
)
|
|
303
|
+
@click.option(
|
|
304
|
+
"--frontend-port",
|
|
305
|
+
type=int,
|
|
306
|
+
help="Specify a different frontend port.",
|
|
307
|
+
envvar=environment.REFLEX_FRONTEND_PORT.name,
|
|
308
|
+
)
|
|
309
|
+
@click.option(
|
|
310
|
+
"--backend-port",
|
|
311
|
+
type=int,
|
|
312
|
+
help="Specify a different backend port.",
|
|
313
|
+
envvar=environment.REFLEX_BACKEND_PORT.name,
|
|
314
|
+
)
|
|
315
|
+
@click.option(
|
|
316
|
+
"--backend-host",
|
|
317
|
+
help="Specify the backend host.",
|
|
318
|
+
)
|
|
294
319
|
def run(
|
|
295
|
-
env:
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
help="Execute only frontend.",
|
|
302
|
-
envvar=environment.REFLEX_FRONTEND_ONLY.name,
|
|
303
|
-
),
|
|
304
|
-
backend: bool = typer.Option(
|
|
305
|
-
False,
|
|
306
|
-
"--backend-only",
|
|
307
|
-
help="Execute only backend.",
|
|
308
|
-
envvar=environment.REFLEX_BACKEND_ONLY.name,
|
|
309
|
-
),
|
|
310
|
-
frontend_port: int | None = typer.Option(
|
|
311
|
-
None,
|
|
312
|
-
help="Specify a different frontend port.",
|
|
313
|
-
envvar=environment.REFLEX_FRONTEND_PORT.name,
|
|
314
|
-
),
|
|
315
|
-
backend_port: int | None = typer.Option(
|
|
316
|
-
None,
|
|
317
|
-
help="Specify a different backend port.",
|
|
318
|
-
envvar=environment.REFLEX_BACKEND_PORT.name,
|
|
319
|
-
),
|
|
320
|
-
backend_host: str | None = typer.Option(None, help="Specify the backend host."),
|
|
321
|
-
loglevel: constants.LogLevel | None = typer.Option(
|
|
322
|
-
None, help="The log level to use."
|
|
323
|
-
),
|
|
320
|
+
env: LITERAL_ENV,
|
|
321
|
+
frontend_only: bool,
|
|
322
|
+
backend_only: bool,
|
|
323
|
+
frontend_port: int | None,
|
|
324
|
+
backend_port: int | None,
|
|
325
|
+
backend_host: str | None,
|
|
324
326
|
):
|
|
325
327
|
"""Run the app in the current directory."""
|
|
326
|
-
if
|
|
328
|
+
if frontend_only and backend_only:
|
|
327
329
|
console.error("Cannot use both --frontend-only and --backend-only options.")
|
|
328
|
-
raise
|
|
329
|
-
|
|
330
|
-
if loglevel is not None:
|
|
331
|
-
console.set_log_level(loglevel)
|
|
330
|
+
raise click.exceptions.Exit(1)
|
|
332
331
|
|
|
333
332
|
config = get_config()
|
|
334
333
|
|
|
335
334
|
frontend_port = frontend_port or config.frontend_port
|
|
336
335
|
backend_port = backend_port or config.backend_port
|
|
337
336
|
backend_host = backend_host or config.backend_host
|
|
338
|
-
loglevel = loglevel or config.loglevel
|
|
339
337
|
|
|
340
338
|
environment.REFLEX_COMPILE_CONTEXT.set(constants.CompileContext.RUN)
|
|
341
|
-
environment.REFLEX_BACKEND_ONLY.set(
|
|
342
|
-
environment.REFLEX_FRONTEND_ONLY.set(
|
|
343
|
-
|
|
344
|
-
_run(
|
|
339
|
+
environment.REFLEX_BACKEND_ONLY.set(backend_only)
|
|
340
|
+
environment.REFLEX_FRONTEND_ONLY.set(frontend_only)
|
|
341
|
+
|
|
342
|
+
_run(
|
|
343
|
+
constants.Env.DEV if env == constants.Env.DEV else constants.Env.PROD,
|
|
344
|
+
frontend_only,
|
|
345
|
+
backend_only,
|
|
346
|
+
frontend_port,
|
|
347
|
+
backend_port,
|
|
348
|
+
backend_host,
|
|
349
|
+
)
|
|
345
350
|
|
|
346
351
|
|
|
347
352
|
@cli.command()
|
|
353
|
+
@loglevel_option
|
|
354
|
+
@click.option(
|
|
355
|
+
"--zip/--no-zip",
|
|
356
|
+
default=True,
|
|
357
|
+
help="Whether to zip the backend and frontend exports.",
|
|
358
|
+
)
|
|
359
|
+
@click.option(
|
|
360
|
+
"--frontend-only",
|
|
361
|
+
is_flag=True,
|
|
362
|
+
show_default=False,
|
|
363
|
+
envvar=environment.REFLEX_FRONTEND_ONLY.name,
|
|
364
|
+
help="Export only frontend.",
|
|
365
|
+
)
|
|
366
|
+
@click.option(
|
|
367
|
+
"--backend-only",
|
|
368
|
+
is_flag=True,
|
|
369
|
+
show_default=False,
|
|
370
|
+
envvar=environment.REFLEX_BACKEND_ONLY.name,
|
|
371
|
+
help="Export only backend.",
|
|
372
|
+
)
|
|
373
|
+
@click.option(
|
|
374
|
+
"--zip-dest-dir",
|
|
375
|
+
default=str(Path.cwd()),
|
|
376
|
+
help="The directory to export the zip files to.",
|
|
377
|
+
show_default=False,
|
|
378
|
+
)
|
|
379
|
+
@click.option(
|
|
380
|
+
"--upload-db-file",
|
|
381
|
+
is_flag=True,
|
|
382
|
+
help="Whether to exclude sqlite db files when exporting backend.",
|
|
383
|
+
hidden=True,
|
|
384
|
+
)
|
|
385
|
+
@click.option(
|
|
386
|
+
"--env",
|
|
387
|
+
type=click.Choice([e.value for e in constants.Env], case_sensitive=False),
|
|
388
|
+
default=constants.Env.PROD.value,
|
|
389
|
+
help="The environment to export the app in.",
|
|
390
|
+
)
|
|
348
391
|
def export(
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
help="Export only frontend.",
|
|
356
|
-
show_default=False,
|
|
357
|
-
envvar=environment.REFLEX_FRONTEND_ONLY.name,
|
|
358
|
-
),
|
|
359
|
-
backend: bool = typer.Option(
|
|
360
|
-
False,
|
|
361
|
-
"--backend-only",
|
|
362
|
-
help="Export only backend.",
|
|
363
|
-
show_default=False,
|
|
364
|
-
envvar=environment.REFLEX_BACKEND_ONLY.name,
|
|
365
|
-
),
|
|
366
|
-
zip_dest_dir: str = typer.Option(
|
|
367
|
-
str(Path.cwd()),
|
|
368
|
-
help="The directory to export the zip files to.",
|
|
369
|
-
show_default=False,
|
|
370
|
-
),
|
|
371
|
-
upload_db_file: bool = typer.Option(
|
|
372
|
-
False,
|
|
373
|
-
help="Whether to exclude sqlite db files when exporting backend.",
|
|
374
|
-
hidden=True,
|
|
375
|
-
),
|
|
376
|
-
env: constants.Env = typer.Option(
|
|
377
|
-
constants.Env.PROD, help="The environment to export the app in."
|
|
378
|
-
),
|
|
379
|
-
loglevel: constants.LogLevel | None = typer.Option(
|
|
380
|
-
None, help="The log level to use."
|
|
381
|
-
),
|
|
392
|
+
zip: bool,
|
|
393
|
+
frontend_only: bool,
|
|
394
|
+
backend_only: bool,
|
|
395
|
+
zip_dest_dir: str,
|
|
396
|
+
upload_db_file: bool,
|
|
397
|
+
env: LITERAL_ENV,
|
|
382
398
|
):
|
|
383
399
|
"""Export the app to a zip file."""
|
|
384
400
|
from reflex.utils import export as export_utils
|
|
@@ -386,35 +402,33 @@ def export(
|
|
|
386
402
|
|
|
387
403
|
environment.REFLEX_COMPILE_CONTEXT.set(constants.CompileContext.EXPORT)
|
|
388
404
|
|
|
389
|
-
|
|
405
|
+
frontend_only, backend_only = prerequisites.check_running_mode(
|
|
406
|
+
frontend_only, backend_only
|
|
407
|
+
)
|
|
390
408
|
|
|
391
|
-
|
|
392
|
-
console.set_log_level(loglevel)
|
|
409
|
+
config = get_config()
|
|
393
410
|
|
|
394
|
-
if prerequisites.needs_reinit(frontend=
|
|
395
|
-
_init(name=
|
|
411
|
+
if prerequisites.needs_reinit(frontend=frontend_only or not backend_only):
|
|
412
|
+
_init(name=config.app_name)
|
|
396
413
|
|
|
397
414
|
export_utils.export(
|
|
398
|
-
zipping=
|
|
399
|
-
frontend=
|
|
400
|
-
backend=
|
|
415
|
+
zipping=zip,
|
|
416
|
+
frontend=frontend_only,
|
|
417
|
+
backend=backend_only,
|
|
401
418
|
zip_dest_dir=zip_dest_dir,
|
|
402
419
|
upload_db_file=upload_db_file,
|
|
403
|
-
env=env,
|
|
404
|
-
loglevel=loglevel.subprocess_level(),
|
|
420
|
+
env=constants.Env.DEV if env == constants.Env.DEV else constants.Env.PROD,
|
|
421
|
+
loglevel=config.loglevel.subprocess_level(),
|
|
405
422
|
)
|
|
406
423
|
|
|
407
424
|
|
|
408
425
|
@cli.command()
|
|
409
|
-
|
|
426
|
+
@loglevel_option
|
|
427
|
+
def login():
|
|
410
428
|
"""Authenticate with experimental Reflex hosting service."""
|
|
411
429
|
from reflex_cli.v2 import cli as hosting_cli
|
|
412
430
|
from reflex_cli.v2.deployments import check_version
|
|
413
431
|
|
|
414
|
-
loglevel = loglevel or get_config().loglevel
|
|
415
|
-
|
|
416
|
-
console.set_log_level(loglevel)
|
|
417
|
-
|
|
418
432
|
check_version()
|
|
419
433
|
|
|
420
434
|
validated_info = hosting_cli.login()
|
|
@@ -424,24 +438,27 @@ def login(loglevel: constants.LogLevel | None = typer.Option(None)):
|
|
|
424
438
|
|
|
425
439
|
|
|
426
440
|
@cli.command()
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
None, help="The log level to use."
|
|
430
|
-
),
|
|
431
|
-
):
|
|
441
|
+
@loglevel_option
|
|
442
|
+
def logout():
|
|
432
443
|
"""Log out of access to Reflex hosting service."""
|
|
433
444
|
from reflex_cli.v2.cli import logout
|
|
434
445
|
from reflex_cli.v2.deployments import check_version
|
|
435
446
|
|
|
436
447
|
check_version()
|
|
437
448
|
|
|
438
|
-
|
|
449
|
+
logout(_convert_reflex_loglevel_to_reflex_cli_loglevel(get_config().loglevel))
|
|
439
450
|
|
|
440
|
-
logout(_convert_reflex_loglevel_to_reflex_cli_loglevel(loglevel))
|
|
441
451
|
|
|
452
|
+
@click.group
|
|
453
|
+
def db_cli():
|
|
454
|
+
"""Subcommands for managing the database schema."""
|
|
455
|
+
pass
|
|
442
456
|
|
|
443
|
-
|
|
444
|
-
|
|
457
|
+
|
|
458
|
+
@click.group
|
|
459
|
+
def script_cli():
|
|
460
|
+
"""Subcommands for running helper scripts."""
|
|
461
|
+
pass
|
|
445
462
|
|
|
446
463
|
|
|
447
464
|
def _skip_compile():
|
|
@@ -495,11 +512,11 @@ def migrate():
|
|
|
495
512
|
|
|
496
513
|
|
|
497
514
|
@db_cli.command()
|
|
498
|
-
|
|
499
|
-
message
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
):
|
|
515
|
+
@click.option(
|
|
516
|
+
"--message",
|
|
517
|
+
help="Human readable identifier for the generated revision.",
|
|
518
|
+
)
|
|
519
|
+
def makemigrations(message: str | None):
|
|
503
520
|
"""Create autogenerated alembic migration scripts."""
|
|
504
521
|
from alembic.util.exc import CommandError
|
|
505
522
|
|
|
@@ -523,70 +540,74 @@ def makemigrations(
|
|
|
523
540
|
|
|
524
541
|
|
|
525
542
|
@cli.command()
|
|
543
|
+
@loglevel_option
|
|
544
|
+
@click.option(
|
|
545
|
+
"--app-name",
|
|
546
|
+
help="The name of the app to deploy.",
|
|
547
|
+
)
|
|
548
|
+
@click.option(
|
|
549
|
+
"--app-id",
|
|
550
|
+
help="The ID of the app to deploy.",
|
|
551
|
+
)
|
|
552
|
+
@click.option(
|
|
553
|
+
"-r",
|
|
554
|
+
"--region",
|
|
555
|
+
multiple=True,
|
|
556
|
+
help="The regions to deploy to. `reflex cloud regions` For multiple envs, repeat this option, e.g. --region sjc --region iad",
|
|
557
|
+
)
|
|
558
|
+
@click.option(
|
|
559
|
+
"--env",
|
|
560
|
+
multiple=True,
|
|
561
|
+
help="The environment variables to set: <key>=<value>. For multiple envs, repeat this option, e.g. --env k1=v2 --env k2=v2.",
|
|
562
|
+
)
|
|
563
|
+
@click.option(
|
|
564
|
+
"--vmtype",
|
|
565
|
+
help="Vm type id. Run `reflex cloud vmtypes` to get options.",
|
|
566
|
+
)
|
|
567
|
+
@click.option(
|
|
568
|
+
"--hostname",
|
|
569
|
+
help="The hostname of the frontend.",
|
|
570
|
+
)
|
|
571
|
+
@click.option(
|
|
572
|
+
"--interactive",
|
|
573
|
+
is_flag=True,
|
|
574
|
+
default=True,
|
|
575
|
+
help="Whether to list configuration options and ask for confirmation.",
|
|
576
|
+
)
|
|
577
|
+
@click.option(
|
|
578
|
+
"--envfile",
|
|
579
|
+
help="The path to an env file to use. Will override any envs set manually.",
|
|
580
|
+
)
|
|
581
|
+
@click.option(
|
|
582
|
+
"--project",
|
|
583
|
+
help="project id to deploy to",
|
|
584
|
+
)
|
|
585
|
+
@click.option(
|
|
586
|
+
"--project-name",
|
|
587
|
+
help="The name of the project to deploy to.",
|
|
588
|
+
)
|
|
589
|
+
@click.option(
|
|
590
|
+
"--token",
|
|
591
|
+
help="token to use for auth",
|
|
592
|
+
)
|
|
593
|
+
@click.option(
|
|
594
|
+
"--config-path",
|
|
595
|
+
"--config",
|
|
596
|
+
help="path to the config file",
|
|
597
|
+
)
|
|
526
598
|
def deploy(
|
|
527
|
-
app_name: str | None
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
"-r",
|
|
540
|
-
"--region",
|
|
541
|
-
help="The regions to deploy to. `reflex cloud regions` For multiple envs, repeat this option, e.g. --region sjc --region iad",
|
|
542
|
-
),
|
|
543
|
-
envs: list[str] = typer.Option(
|
|
544
|
-
[],
|
|
545
|
-
"--env",
|
|
546
|
-
help="The environment variables to set: <key>=<value>. For multiple envs, repeat this option, e.g. --env k1=v2 --env k2=v2.",
|
|
547
|
-
),
|
|
548
|
-
vmtype: str | None = typer.Option(
|
|
549
|
-
None,
|
|
550
|
-
"--vmtype",
|
|
551
|
-
help="Vm type id. Run `reflex cloud vmtypes` to get options.",
|
|
552
|
-
),
|
|
553
|
-
hostname: str | None = typer.Option(
|
|
554
|
-
None,
|
|
555
|
-
"--hostname",
|
|
556
|
-
help="The hostname of the frontend.",
|
|
557
|
-
),
|
|
558
|
-
interactive: bool = typer.Option(
|
|
559
|
-
True,
|
|
560
|
-
help="Whether to list configuration options and ask for confirmation.",
|
|
561
|
-
),
|
|
562
|
-
envfile: str | None = typer.Option(
|
|
563
|
-
None,
|
|
564
|
-
"--envfile",
|
|
565
|
-
help="The path to an env file to use. Will override any envs set manually.",
|
|
566
|
-
),
|
|
567
|
-
loglevel: constants.LogLevel | None = typer.Option(
|
|
568
|
-
None, help="The log level to use."
|
|
569
|
-
),
|
|
570
|
-
project: str | None = typer.Option(
|
|
571
|
-
None,
|
|
572
|
-
"--project",
|
|
573
|
-
help="project id to deploy to",
|
|
574
|
-
),
|
|
575
|
-
project_name: str | None = typer.Option(
|
|
576
|
-
None,
|
|
577
|
-
"--project-name",
|
|
578
|
-
help="The name of the project to deploy to.",
|
|
579
|
-
),
|
|
580
|
-
token: str | None = typer.Option(
|
|
581
|
-
None,
|
|
582
|
-
"--token",
|
|
583
|
-
help="token to use for auth",
|
|
584
|
-
),
|
|
585
|
-
config_path: str | None = typer.Option(
|
|
586
|
-
None,
|
|
587
|
-
"--config",
|
|
588
|
-
help="path to the config file",
|
|
589
|
-
),
|
|
599
|
+
app_name: str | None,
|
|
600
|
+
app_id: str | None,
|
|
601
|
+
region: tuple[str, ...],
|
|
602
|
+
env: tuple[str],
|
|
603
|
+
vmtype: str | None,
|
|
604
|
+
hostname: str | None,
|
|
605
|
+
interactive: bool,
|
|
606
|
+
envfile: str | None,
|
|
607
|
+
project: str | None,
|
|
608
|
+
project_name: str | None,
|
|
609
|
+
token: str | None,
|
|
610
|
+
config_path: str | None,
|
|
590
611
|
):
|
|
591
612
|
"""Deploy the app to the Reflex hosting service."""
|
|
592
613
|
from reflex_cli.utils import dependency
|
|
@@ -596,21 +617,14 @@ def deploy(
|
|
|
596
617
|
from reflex.utils import export as export_utils
|
|
597
618
|
from reflex.utils import prerequisites
|
|
598
619
|
|
|
599
|
-
if loglevel is not None:
|
|
600
|
-
console.set_log_level(loglevel)
|
|
601
|
-
|
|
602
620
|
config = get_config()
|
|
603
621
|
|
|
604
|
-
loglevel = loglevel or config.loglevel
|
|
605
622
|
app_name = app_name or config.app_name
|
|
606
623
|
|
|
607
624
|
check_version()
|
|
608
625
|
|
|
609
626
|
environment.REFLEX_COMPILE_CONTEXT.set(constants.CompileContext.DEPLOY)
|
|
610
627
|
|
|
611
|
-
# Set the log level.
|
|
612
|
-
console.set_log_level(loglevel)
|
|
613
|
-
|
|
614
628
|
# Only check requirements if interactive.
|
|
615
629
|
# There is user interaction for requirements update.
|
|
616
630
|
if interactive:
|
|
@@ -618,7 +632,7 @@ def deploy(
|
|
|
618
632
|
|
|
619
633
|
# Check if we are set up.
|
|
620
634
|
if prerequisites.needs_reinit(frontend=True):
|
|
621
|
-
_init(name=config.app_name
|
|
635
|
+
_init(name=config.app_name)
|
|
622
636
|
prerequisites.check_latest_package_version(constants.ReflexHostingCLI.MODULE_NAME)
|
|
623
637
|
|
|
624
638
|
hosting_cli.deploy(
|
|
@@ -638,17 +652,17 @@ def deploy(
|
|
|
638
652
|
frontend=frontend,
|
|
639
653
|
backend=backend,
|
|
640
654
|
zipping=zipping,
|
|
641
|
-
loglevel=loglevel.subprocess_level(),
|
|
655
|
+
loglevel=config.loglevel.subprocess_level(),
|
|
642
656
|
upload_db_file=upload_db,
|
|
643
657
|
)
|
|
644
658
|
),
|
|
645
|
-
regions=
|
|
646
|
-
envs=
|
|
659
|
+
regions=list(region),
|
|
660
|
+
envs=list(env),
|
|
647
661
|
vmtype=vmtype,
|
|
648
662
|
envfile=envfile,
|
|
649
663
|
hostname=hostname,
|
|
650
664
|
interactive=interactive,
|
|
651
|
-
loglevel=_convert_reflex_loglevel_to_reflex_cli_loglevel(loglevel),
|
|
665
|
+
loglevel=_convert_reflex_loglevel_to_reflex_cli_loglevel(config.loglevel),
|
|
652
666
|
token=token,
|
|
653
667
|
project=project,
|
|
654
668
|
project_name=project_name,
|
|
@@ -657,19 +671,14 @@ def deploy(
|
|
|
657
671
|
|
|
658
672
|
|
|
659
673
|
@cli.command()
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
None, help="The log level to use."
|
|
664
|
-
),
|
|
665
|
-
):
|
|
674
|
+
@loglevel_option
|
|
675
|
+
@click.argument("new_name")
|
|
676
|
+
def rename(new_name: str):
|
|
666
677
|
"""Rename the app in the current directory."""
|
|
667
678
|
from reflex.utils import prerequisites
|
|
668
679
|
|
|
669
|
-
loglevel = loglevel or get_config().loglevel
|
|
670
|
-
|
|
671
680
|
prerequisites.validate_app_name(new_name)
|
|
672
|
-
prerequisites.rename_app(new_name, loglevel)
|
|
681
|
+
prerequisites.rename_app(new_name, get_config().loglevel)
|
|
673
682
|
|
|
674
683
|
|
|
675
684
|
if TYPE_CHECKING:
|
|
@@ -702,18 +711,20 @@ def _convert_reflex_loglevel_to_reflex_cli_loglevel(
|
|
|
702
711
|
return HostingLogLevel.INFO
|
|
703
712
|
|
|
704
713
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
hosting_cli,
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
)
|
|
714
|
+
if find_spec("typer"):
|
|
715
|
+
import typer # pyright: ignore[reportMissingImports]
|
|
716
|
+
|
|
717
|
+
if isinstance(hosting_cli, typer.Typer):
|
|
718
|
+
hosting_cli_command = typer.main.get_command(hosting_cli)
|
|
719
|
+
else:
|
|
720
|
+
hosting_cli_command = hosting_cli
|
|
721
|
+
else:
|
|
722
|
+
hosting_cli_command = hosting_cli
|
|
723
|
+
|
|
724
|
+
cli.add_command(hosting_cli_command, name="cloud")
|
|
725
|
+
cli.add_command(db_cli, name="db")
|
|
726
|
+
cli.add_command(script_cli, name="script")
|
|
727
|
+
cli.add_command(custom_components_cli, name="component")
|
|
717
728
|
|
|
718
729
|
if __name__ == "__main__":
|
|
719
730
|
cli()
|