reflex 0.8.0a6__py3-none-any.whl → 0.8.0a7__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/config.py CHANGED
@@ -19,7 +19,12 @@ from reflex.base import Base
19
19
  from reflex.constants.base import LogLevel
20
20
  from reflex.environment import EnvironmentVariables as EnvironmentVariables
21
21
  from reflex.environment import EnvVar as EnvVar
22
- from reflex.environment import ExistingPath, interpret_env_var_value
22
+ from reflex.environment import (
23
+ ExistingPath,
24
+ _load_dotenv_from_files,
25
+ _paths_from_env_files,
26
+ interpret_env_var_value,
27
+ )
23
28
  from reflex.environment import env_var as env_var
24
29
  from reflex.environment import environment as environment
25
30
  from reflex.plugins import Plugin
@@ -27,40 +32,6 @@ from reflex.utils import console
27
32
  from reflex.utils.exceptions import ConfigError
28
33
  from reflex.utils.types import true_type_for_pydantic_field
29
34
 
30
- try:
31
- from dotenv import load_dotenv
32
- except ImportError:
33
- load_dotenv = None
34
-
35
-
36
- def _load_dotenv_from_str(env_files: str) -> None:
37
- if not env_files:
38
- return
39
-
40
- if load_dotenv is None:
41
- console.error(
42
- """The `python-dotenv` package is required to load environment variables from a file. Run `pip install "python-dotenv>=1.1.0"`."""
43
- )
44
- return
45
-
46
- # load env files in reverse order if they exist
47
- for env_file_path in [
48
- Path(p) for s in reversed(env_files.split(os.pathsep)) if (p := s.strip())
49
- ]:
50
- if env_file_path.exists():
51
- load_dotenv(env_file_path, override=True)
52
-
53
-
54
- def _load_dotenv_from_env():
55
- """Load environment variables from paths specified in REFLEX_ENV_FILE."""
56
- env_env_file = os.environ.get("REFLEX_ENV_FILE")
57
- if env_env_file:
58
- _load_dotenv_from_str(env_env_file)
59
-
60
-
61
- # Load the env files at import time if they are set in the ENV_FILE environment variable.
62
- _load_dotenv_from_env()
63
-
64
35
 
65
36
  class DBConfig(Base):
66
37
  """Database config."""
@@ -358,7 +329,7 @@ class Config(Base):
358
329
  The updated config values.
359
330
  """
360
331
  if self.env_file:
361
- _load_dotenv_from_str(self.env_file)
332
+ _load_dotenv_from_files(_paths_from_env_files(self.env_file))
362
333
 
363
334
  updated_values = {}
364
335
  # Iterate over the fields.
reflex/environment.py CHANGED
@@ -606,3 +606,73 @@ class EnvironmentVariables:
606
606
 
607
607
 
608
608
  environment = EnvironmentVariables()
609
+
610
+ try:
611
+ from dotenv import load_dotenv
612
+ except ImportError:
613
+ load_dotenv = None
614
+
615
+
616
+ def _paths_from_env_files(env_files: str) -> list[Path]:
617
+ """Convert a string of paths separated by os.pathsep into a list of Path objects.
618
+
619
+ Args:
620
+ env_files: The string of paths.
621
+
622
+ Returns:
623
+ A list of Path objects.
624
+ """
625
+ # load env files in reverse order
626
+ return list(
627
+ reversed(
628
+ [
629
+ Path(path)
630
+ for path_element in env_files.split(os.pathsep)
631
+ if (path := path_element.strip())
632
+ ]
633
+ )
634
+ )
635
+
636
+
637
+ def _load_dotenv_from_files(files: list[Path]):
638
+ """Load environment variables from a list of files.
639
+
640
+ Args:
641
+ files: A list of Path objects representing the environment variable files.
642
+ """
643
+ from reflex.utils import console
644
+
645
+ if not files:
646
+ return
647
+
648
+ if load_dotenv is None:
649
+ console.error(
650
+ """The `python-dotenv` package is required to load environment variables from a file. Run `pip install "python-dotenv>=1.1.0"`."""
651
+ )
652
+ return
653
+
654
+ for env_file in files:
655
+ if env_file.exists():
656
+ load_dotenv(env_file, override=True)
657
+
658
+
659
+ def _paths_from_environment() -> list[Path]:
660
+ """Get the paths from the REFLEX_ENV_FILE environment variable.
661
+
662
+ Returns:
663
+ A list of Path objects.
664
+ """
665
+ env_files = os.environ.get("REFLEX_ENV_FILE")
666
+ if not env_files:
667
+ return []
668
+
669
+ return _paths_from_env_files(env_files)
670
+
671
+
672
+ def _load_dotenv_from_env():
673
+ """Load environment variables from paths specified in REFLEX_ENV_FILE."""
674
+ _load_dotenv_from_files(_paths_from_environment())
675
+
676
+
677
+ # Load the env files at import time if they are set in the ENV_FILE environment variable.
678
+ _load_dotenv_from_env()
reflex/utils/exec.py CHANGED
@@ -519,9 +519,11 @@ def run_granian_backend(host: str, port: int, loglevel: LogLevel):
519
519
 
520
520
  from granian.constants import Interfaces
521
521
  from granian.log import LogLevels
522
- from granian.server import MPServer as Granian
522
+ from granian.server import Server as Granian
523
523
 
524
- Granian(
524
+ from reflex.environment import _paths_from_environment
525
+
526
+ granian_app = Granian(
525
527
  target=get_app_instance_from_file(),
526
528
  factory=True,
527
529
  address=host,
@@ -533,8 +535,11 @@ def run_granian_backend(host: str, port: int, loglevel: LogLevel):
533
535
  reload_ignore_worker_failure=True,
534
536
  reload_ignore_patterns=HOTRELOAD_IGNORE_PATTERNS,
535
537
  reload_tick=100,
538
+ env_files=_paths_from_environment() or None,
536
539
  workers_kill_timeout=2,
537
- ).serve()
540
+ )
541
+
542
+ granian_app.serve()
538
543
 
539
544
 
540
545
  def run_backend_prod(
reflex/utils/misc.py CHANGED
@@ -31,14 +31,13 @@ def get_module_path(module_name: str) -> Path | None:
31
31
  for i, part in enumerate(parts):
32
32
  potential_file = current_path / (part + ".py")
33
33
  potential_dir = current_path / part
34
- potential_init = current_path / part / "__init__.py"
35
34
 
36
35
  if potential_file.is_file():
37
36
  # We encountered a file, but we can't continue deeper
38
37
  if i == len(parts) - 1:
39
38
  return potential_file
40
39
  return None # Can't continue deeper
41
- if potential_dir.is_dir() and potential_init.is_file():
40
+ if potential_dir.is_dir():
42
41
  # It's a package, so we can continue deeper
43
42
  current_path = potential_dir
44
43
  else:
reflex/utils/processes.py CHANGED
@@ -61,8 +61,16 @@ def is_process_on_port(port: int) -> bool:
61
61
  Returns:
62
62
  Whether a process is running on the given port.
63
63
  """
64
+ # Test IPv4 localhost (127.0.0.1)
64
65
  with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
65
- return sock.connect_ex(("127.0.0.1", port)) == 0
66
+ ipv4_result = sock.connect_ex(("127.0.0.1", port)) == 0
67
+
68
+ # Test IPv6 localhost (::1)
69
+ with closing(socket.socket(socket.AF_INET6, socket.SOCK_STREAM)) as sock:
70
+ ipv6_result = sock.connect_ex(("::1", port)) == 0
71
+
72
+ # Port is in use if either IPv4 or IPv6 is listening
73
+ return ipv4_result or ipv6_result
66
74
 
67
75
 
68
76
  def change_port(port: int, _type: str) -> int:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reflex
3
- Version: 0.8.0a6
3
+ Version: 0.8.0a7
4
4
  Summary: Web apps in pure Python.
5
5
  Project-URL: homepage, https://reflex.dev
6
6
  Project-URL: repository, https://github.com/reflex-dev/reflex
@@ -21,7 +21,7 @@ Requires-Python: <4.0,>=3.10
21
21
  Requires-Dist: alembic<2.0,>=1.15.2
22
22
  Requires-Dist: click>=8.2
23
23
  Requires-Dist: fastapi>=0.115.0
24
- Requires-Dist: granian[reload]>=2.2.5
24
+ Requires-Dist: granian[reload]>=2.4.0
25
25
  Requires-Dist: httpx<1.0,>=0.28.0
26
26
  Requires-Dist: jinja2<4.0,>=3.1.2
27
27
  Requires-Dist: packaging<26,>=24.2
@@ -5,8 +5,8 @@ reflex/admin.py,sha256=Nbc38y-M8iaRBvh1W6DQu_D3kEhO8JFvxrog4q2cB_E,434
5
5
  reflex/app.py,sha256=qRyXDNd9ASIeyescIg71E08mUarppiITdh-btn1TREQ,75003
6
6
  reflex/assets.py,sha256=l5O_mlrTprC0lF7Rc_McOe3a0OtSLnRdNl_PqCpDCBA,3431
7
7
  reflex/base.py,sha256=Oh664QL3fZEHErhUasFqP7fE4olYf1y-9Oj6uZI2FCU,1173
8
- reflex/config.py,sha256=7-OHwPa9UGlz8fxQx6SumT4netp6NgWRHJ3UvUL-opg,16631
9
- reflex/environment.py,sha256=0Olf4Z0m6lZI0EnUBWXUPQtzd7ggKWkKKvwL5CcsnZo,19785
8
+ reflex/config.py,sha256=tEUaW4oJbkCDtQ1SgsT4APtLpQ9-VknVWdqwFoYorvg,15729
9
+ reflex/environment.py,sha256=f9-5-XGTcI2OF02SM7DXGQMjW9YdfK0gj6IGyqOglvQ,21567
10
10
  reflex/event.py,sha256=IDjHAbbzMo7mNUiFKvgiR7sGlQ883B00rvmncVy5I-Q,69724
11
11
  reflex/model.py,sha256=xED7blemoiKxPFaOkCMrSayjjon7AJp8t5g459p7dGs,17646
12
12
  reflex/page.py,sha256=Bn8FTlUtjjKwUtpQA5r5eaWE_ZUb8i4XgrQi8FWbzNA,1880
@@ -370,16 +370,16 @@ reflex/utils/compat.py,sha256=aSJH_M6iomgHPQ4onQ153xh1MWqPi3HSYDzE68N6gZM,2635
370
370
  reflex/utils/console.py,sha256=OFyXqnyhpAgXCDM7m5lokoUMjvXMohc2ftgrmcf62nc,11500
371
371
  reflex/utils/decorator.py,sha256=DVrlVGljV5OchMs-5_y1CbbqnCWlH6lv-dFko8yHxVY,1738
372
372
  reflex/utils/exceptions.py,sha256=Wwu7Ji2xgq521bJKtU2NgjwhmFfnG8erirEVN2h8S-g,8884
373
- reflex/utils/exec.py,sha256=EaJX92P2vfq29TlS7u7GR_eOrUpgqujv4p1W3F-fxyE,20884
373
+ reflex/utils/exec.py,sha256=zQ4WlH80QPjFF4RnGZPOxbCYR8ly9VO0CdJsPZZOQ40,21026
374
374
  reflex/utils/export.py,sha256=Z2AHuhkxGQzOi9I90BejQ4qEcD0URr2i-ZU5qTJt7eQ,2562
375
375
  reflex/utils/format.py,sha256=6lgPpYsArWDwGuC_BT-X9g4BnCG14vvH7-oNjrCA5Xc,21119
376
376
  reflex/utils/imports.py,sha256=Ov-lqv-PfsPl3kTEW13r5aDauIfn6TqzEMyv42RKLOA,3761
377
377
  reflex/utils/lazy_loader.py,sha256=UREKeql_aSusSFMn6qldyol4n8qD3Sm9Wg7LLICjJgQ,4136
378
- reflex/utils/misc.py,sha256=KQh1swi_FZ4a_YJOnRMWE5hikNKZXarwMY9t1MkoSoA,2973
378
+ reflex/utils/misc.py,sha256=zbYIl7mI08is9enr851sj7PnDaNeVVvq5jDmQ4wdlCE,2879
379
379
  reflex/utils/net.py,sha256=HEHA8L5g7L9s0fFG4dTiZzB9PFO_0WRrlbMgpZr_GAQ,4093
380
380
  reflex/utils/path_ops.py,sha256=_RS17IQDNr5vcoLLGZx2-z1E5WP-JgDHvaRAOgqrZiU,8154
381
381
  reflex/utils/prerequisites.py,sha256=L2tCFqqiYqygRbQ0JMMBduMdsMkKJLDvzGKZnvI1Enc,66001
382
- reflex/utils/processes.py,sha256=3h93VXTpJaXcZunrqRPrPyviVsRx5o5GOt2UZrpwT8I,15847
382
+ reflex/utils/processes.py,sha256=e5V6-eRSh-r7hR34wW5qvowurhDEW9qv-DTOFJl7kO8,16157
383
383
  reflex/utils/pyi_generator.py,sha256=Qm_og4yQcJ3-dwMfGJ2QhPxiFng3lftPJne-dMCC8C0,45532
384
384
  reflex/utils/redir.py,sha256=3JG0cRdfIZnFIBHHN32ynD5cfbUZa7gLRxzrxRGGl5I,1751
385
385
  reflex/utils/registry.py,sha256=DEF7csYQ5VnrZhy6ULVfMlceh7XVH0pks96lIyyThuc,1882
@@ -395,8 +395,8 @@ reflex/vars/number.py,sha256=tO7pnvFaBsedq1HWT4skytnSqHWMluGEhUbjAUMx8XQ,28190
395
395
  reflex/vars/object.py,sha256=BDmeiwG8v97s_BnR1Egq3NxOKVjv9TfnREB3cz0zZtk,17322
396
396
  reflex/vars/sequence.py,sha256=1kBrqihspyjyQ1XDqFPC8OpVGtZs_EVkOdIKBro5ilA,55249
397
397
  scripts/hatch_build.py,sha256=-4pxcLSFmirmujGpQX9UUxjhIC03tQ_fIQwVbHu9kc0,1861
398
- reflex-0.8.0a6.dist-info/METADATA,sha256=o234MDuUTRMP6ROap8i9MnfjD2cHQuAo6lBfOIKuknA,12371
399
- reflex-0.8.0a6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
400
- reflex-0.8.0a6.dist-info/entry_points.txt,sha256=Rxt4dXc7MLBNt5CSHTehVPuSe9Xqow4HLX55nD9tQQ0,45
401
- reflex-0.8.0a6.dist-info/licenses/LICENSE,sha256=dw3zLrp9f5ObD7kqS32vWfhcImfO52PMmRqvtxq_YEE,11358
402
- reflex-0.8.0a6.dist-info/RECORD,,
398
+ reflex-0.8.0a7.dist-info/METADATA,sha256=XK-wK7ZpvQvGbKnF_mSKw5ohRMG9FJ3HrXNrfslwGGI,12371
399
+ reflex-0.8.0a7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
400
+ reflex-0.8.0a7.dist-info/entry_points.txt,sha256=Rxt4dXc7MLBNt5CSHTehVPuSe9Xqow4HLX55nD9tQQ0,45
401
+ reflex-0.8.0a7.dist-info/licenses/LICENSE,sha256=dw3zLrp9f5ObD7kqS32vWfhcImfO52PMmRqvtxq_YEE,11358
402
+ reflex-0.8.0a7.dist-info/RECORD,,