reflex 0.7.8a1__py3-none-any.whl → 0.7.9__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.

Files changed (44) hide show
  1. reflex/.templates/jinja/web/tailwind.config.js.jinja2 +65 -31
  2. reflex/.templates/web/utils/state.js +11 -1
  3. reflex/app.py +191 -87
  4. reflex/app_mixins/lifespan.py +2 -2
  5. reflex/compiler/compiler.py +31 -4
  6. reflex/components/base/body.pyi +3 -197
  7. reflex/components/base/link.pyi +4 -392
  8. reflex/components/base/meta.pyi +28 -608
  9. reflex/components/component.py +39 -57
  10. reflex/components/core/upload.py +8 -0
  11. reflex/components/dynamic.py +9 -1
  12. reflex/components/el/elements/metadata.pyi +0 -1
  13. reflex/components/markdown/markdown.py +0 -21
  14. reflex/components/markdown/markdown.pyi +2 -2
  15. reflex/components/radix/primitives/accordion.py +1 -1
  16. reflex/components/radix/primitives/form.py +1 -1
  17. reflex/components/radix/primitives/progress.py +1 -1
  18. reflex/components/radix/primitives/slider.py +1 -1
  19. reflex/components/radix/themes/color_mode.py +1 -1
  20. reflex/components/radix/themes/color_mode.pyi +1 -1
  21. reflex/components/radix/themes/layout/list.pyi +2 -391
  22. reflex/components/recharts/recharts.py +2 -2
  23. reflex/components/sonner/toast.py +1 -1
  24. reflex/config.py +4 -7
  25. reflex/constants/base.py +21 -0
  26. reflex/constants/installer.py +6 -6
  27. reflex/custom_components/custom_components.py +67 -64
  28. reflex/event.py +2 -0
  29. reflex/page.py +8 -0
  30. reflex/reflex.py +277 -265
  31. reflex/testing.py +30 -24
  32. reflex/utils/codespaces.py +6 -2
  33. reflex/utils/console.py +4 -3
  34. reflex/utils/exec.py +60 -24
  35. reflex/utils/format.py +17 -2
  36. reflex/utils/prerequisites.py +43 -30
  37. reflex/utils/processes.py +6 -6
  38. reflex/utils/types.py +11 -6
  39. reflex/vars/base.py +19 -1
  40. {reflex-0.7.8a1.dist-info → reflex-0.7.9.dist-info}/METADATA +6 -9
  41. {reflex-0.7.8a1.dist-info → reflex-0.7.9.dist-info}/RECORD +44 -44
  42. {reflex-0.7.8a1.dist-info → reflex-0.7.9.dist-info}/WHEEL +0 -0
  43. {reflex-0.7.8a1.dist-info → reflex-0.7.9.dist-info}/entry_points.txt +0 -0
  44. {reflex-0.7.8a1.dist-info → reflex-0.7.9.dist-info}/licenses/LICENSE +0 -0
@@ -9,17 +9,46 @@ import sys
9
9
  from collections import namedtuple
10
10
  from contextlib import contextmanager
11
11
  from pathlib import Path
12
+ from typing import Any
12
13
 
14
+ import click
13
15
  import httpx
14
- import typer
15
16
 
16
17
  from reflex import constants
17
- from reflex.config import get_config
18
18
  from reflex.constants import CustomComponents
19
19
  from reflex.utils import console
20
20
 
21
- custom_components_cli = typer.Typer()
22
21
 
22
+ def set_loglevel(ctx: Any, self: Any, value: str | None):
23
+ """Set the log level.
24
+
25
+ Args:
26
+ ctx: The click context.
27
+ self: The click command.
28
+ value: The log level to set.
29
+ """
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
+ def custom_components_cli():
37
+ """CLI for creating custom components."""
38
+ pass
39
+
40
+
41
+ loglevel_option = click.option(
42
+ "--loglevel",
43
+ type=click.Choice(
44
+ [loglevel.value for loglevel in constants.LogLevel],
45
+ case_sensitive=False,
46
+ ),
47
+ callback=set_loglevel,
48
+ is_eager=True,
49
+ expose_value=False,
50
+ help="The log level to use.",
51
+ )
23
52
 
24
53
  POST_CUSTOM_COMPONENTS_GALLERY_TIMEOUT = 15
25
54
 
@@ -163,13 +192,13 @@ def _get_default_library_name_parts() -> list[str]:
163
192
  console.error(
164
193
  f"Based on current directory name {current_dir_name}, the library name is {constants.Reflex.MODULE_NAME}. This package already exists. Please use --library-name to specify a different name."
165
194
  )
166
- raise typer.Exit(code=1)
195
+ raise click.exceptions.Exit(code=1)
167
196
  if not parts:
168
197
  # The folder likely has a name not suitable for python paths.
169
198
  console.error(
170
199
  f"Could not find a valid library name based on the current directory: got {current_dir_name}."
171
200
  )
172
- raise typer.Exit(code=1)
201
+ raise click.exceptions.Exit(code=1)
173
202
  return parts
174
203
 
175
204
 
@@ -205,7 +234,7 @@ def _validate_library_name(library_name: str | None) -> NameVariants:
205
234
  console.error(
206
235
  f"Please use only alphanumeric characters or dashes: got {library_name}"
207
236
  )
208
- raise typer.Exit(code=1)
237
+ raise click.exceptions.Exit(code=1)
209
238
 
210
239
  # If not specified, use the current directory name to form the module name.
211
240
  name_parts = (
@@ -277,36 +306,35 @@ def _populate_custom_component_project(name_variants: NameVariants):
277
306
 
278
307
 
279
308
  @custom_components_cli.command(name="init")
309
+ @click.option(
310
+ "--library-name",
311
+ default=None,
312
+ help="The name of your library. On PyPI, package will be published as `reflex-{library-name}`.",
313
+ )
314
+ @click.option(
315
+ "--install/--no-install",
316
+ default=True,
317
+ help="Whether to install package from this local custom component in editable mode.",
318
+ )
319
+ @loglevel_option
280
320
  def init(
281
- library_name: str | None = typer.Option(
282
- None,
283
- help="The name of your library. On PyPI, package will be published as `reflex-{library-name}`.",
284
- ),
285
- install: bool = typer.Option(
286
- True,
287
- help="Whether to install package from this local custom component in editable mode.",
288
- ),
289
- loglevel: constants.LogLevel | None = typer.Option(
290
- None, help="The log level to use."
291
- ),
321
+ library_name: str | None,
322
+ install: bool,
292
323
  ):
293
324
  """Initialize a custom component.
294
325
 
295
326
  Args:
296
327
  library_name: The name of the library.
297
328
  install: Whether to install package from this local custom component in editable mode.
298
- loglevel: The log level to use.
299
329
 
300
330
  Raises:
301
331
  Exit: If the pyproject.toml already exists.
302
332
  """
303
333
  from reflex.utils import exec, prerequisites
304
334
 
305
- console.set_log_level(loglevel or get_config().loglevel)
306
-
307
335
  if CustomComponents.PYPROJECT_TOML.exists():
308
336
  console.error(f"A {CustomComponents.PYPROJECT_TOML} already exists. Aborting.")
309
- typer.Exit(code=1)
337
+ click.exceptions.Exit(code=1)
310
338
 
311
339
  # Show system info.
312
340
  exec.output_system_info()
@@ -331,7 +359,7 @@ def init(
331
359
  if _pip_install_on_demand(package_name=".", install_args=["-e"]):
332
360
  console.info(f"Package {package_name} installed!")
333
361
  else:
334
- raise typer.Exit(code=1)
362
+ raise click.exceptions.Exit(code=1)
335
363
 
336
364
  console.print("[bold]Custom component initialized successfully!")
337
365
  console.rule("[bold]Project Summary")
@@ -424,21 +452,13 @@ def _run_build():
424
452
  if _run_commands_in_subprocess(cmds):
425
453
  console.info("Custom component built successfully!")
426
454
  else:
427
- raise typer.Exit(code=1)
455
+ raise click.exceptions.Exit(code=1)
428
456
 
429
457
 
430
458
  @custom_components_cli.command(name="build")
431
- def build(
432
- loglevel: constants.LogLevel | None = typer.Option(
433
- None, help="The log level to use."
434
- ),
435
- ):
436
- """Build a custom component. Must be run from the project root directory where the pyproject.toml is.
437
-
438
- Args:
439
- loglevel: The log level to use.
440
- """
441
- console.set_log_level(loglevel or get_config().loglevel)
459
+ @loglevel_option
460
+ def build():
461
+ """Build a custom component. Must be run from the project root directory where the pyproject.toml is."""
442
462
  _run_build()
443
463
 
444
464
 
@@ -453,7 +473,7 @@ def publish():
453
473
  "The publish command is deprecated. You can use `reflex component build` followed by `twine upload` or a similar publishing command to publish your custom component."
454
474
  "\nIf you want to share your custom component with the Reflex community, please use `reflex component share`."
455
475
  )
456
- raise typer.Exit(code=1)
476
+ raise click.exceptions.Exit(code=1)
457
477
 
458
478
 
459
479
  def _collect_details_for_gallery():
@@ -472,7 +492,7 @@ def _collect_details_for_gallery():
472
492
  console.error(
473
493
  "Unable to authenticate with Reflex backend services. Make sure you are logged in."
474
494
  )
475
- raise typer.Exit(code=1)
495
+ raise click.exceptions.Exit(code=1)
476
496
 
477
497
  console.rule("[bold]Custom Component Information")
478
498
  params = {}
@@ -502,11 +522,11 @@ def _collect_details_for_gallery():
502
522
  console.error(
503
523
  f"{package_name} is owned by another user. Unable to update the information for it."
504
524
  )
505
- raise typer.Exit(code=1)
525
+ raise click.exceptions.Exit(code=1)
506
526
  response.raise_for_status()
507
527
  except httpx.HTTPError as he:
508
528
  console.error(f"Unable to complete request due to {he}.")
509
- raise typer.Exit(code=1) from he
529
+ raise click.exceptions.Exit(code=1) from he
510
530
 
511
531
  files = []
512
532
  if (image_file_and_extension := _get_file_from_prompt_in_loop()) is not None:
@@ -541,7 +561,7 @@ def _collect_details_for_gallery():
541
561
 
542
562
  except httpx.HTTPError as he:
543
563
  console.error(f"Unable to complete request due to {he}.")
544
- raise typer.Exit(code=1) from he
564
+ raise click.exceptions.Exit(code=1) from he
545
565
 
546
566
  console.info("Custom component information successfully shared!")
547
567
 
@@ -577,7 +597,7 @@ def _get_file_from_prompt_in_loop() -> tuple[bytes, str] | None:
577
597
  image_file = image_file_path.read_bytes()
578
598
  except OSError as ose:
579
599
  console.error(f"Unable to read the {file_extension} file due to {ose}")
580
- raise typer.Exit(code=1) from ose
600
+ raise click.exceptions.Exit(code=1) from ose
581
601
  else:
582
602
  return image_file, file_extension
583
603
 
@@ -586,38 +606,21 @@ def _get_file_from_prompt_in_loop() -> tuple[bytes, str] | None:
586
606
 
587
607
 
588
608
  @custom_components_cli.command(name="share")
589
- def share_more_detail(
590
- loglevel: constants.LogLevel | None = typer.Option(
591
- None, help="The log level to use."
592
- ),
593
- ):
594
- """Collect more details on the published package for gallery.
595
-
596
- Args:
597
- loglevel: The log level to use.
598
- """
599
- console.set_log_level(loglevel or get_config().loglevel)
600
-
609
+ @loglevel_option
610
+ def share_more_detail():
611
+ """Collect more details on the published package for gallery."""
601
612
  _collect_details_for_gallery()
602
613
 
603
614
 
604
- @custom_components_cli.command()
605
- def install(
606
- loglevel: constants.LogLevel | None = typer.Option(
607
- None, help="The log level to use."
608
- ),
609
- ):
615
+ @custom_components_cli.command(name="install")
616
+ @loglevel_option
617
+ def install():
610
618
  """Install package from this local custom component in editable mode.
611
619
 
612
- Args:
613
- loglevel: The log level to use.
614
-
615
620
  Raises:
616
621
  Exit: If unable to install the current directory in editable mode.
617
622
  """
618
- console.set_log_level(loglevel or get_config().loglevel)
619
-
620
623
  if _pip_install_on_demand(package_name=".", install_args=["-e"]):
621
624
  console.info("Package installed successfully!")
622
625
  else:
623
- raise typer.Exit(code=1)
626
+ raise click.exceptions.Exit(code=1)
reflex/event.py CHANGED
@@ -2064,6 +2064,8 @@ class EventNamespace:
2064
2064
  "Background task must be async function or generator."
2065
2065
  )
2066
2066
  setattr(func, BACKGROUND_TASK_MARKER, True)
2067
+ if getattr(func, "__name__", "").startswith("_"):
2068
+ raise ValueError("Event handlers cannot be private.")
2067
2069
  return func # pyright: ignore [reportReturnType]
2068
2070
 
2069
2071
  if func is not None:
reflex/page.py CHANGED
@@ -8,6 +8,7 @@ from typing import Any
8
8
 
9
9
  from reflex.config import get_config
10
10
  from reflex.event import EventType
11
+ from reflex.utils import console
11
12
 
12
13
  DECORATED_PAGES: dict[str, list] = defaultdict(list)
13
14
 
@@ -76,6 +77,13 @@ def get_decorated_pages(omit_implicit_routes: bool = True) -> list[dict[str, Any
76
77
  Returns:
77
78
  The decorated pages.
78
79
  """
80
+ console.deprecate(
81
+ "get_decorated_pages",
82
+ reason="This function is deprecated and will be removed in a future version.",
83
+ deprecation_version="0.7.9",
84
+ removal_version="0.8.0",
85
+ dedupe=True,
86
+ )
79
87
  return sorted(
80
88
  [
81
89
  page_data