Explorar o código

fix bun path handling and add a test (#4785)

* fix bun path handling and add a test

* fix flags

* fix tests

* fix unit tests and mock object

* fix units test again

* revert some changes for now

* remove unused test
Thomas Brandého hai 3 meses
pai
achega
3a02d03cb1
Modificáronse 4 ficheiros con 66 adicións e 12 borrados
  1. 14 7
      reflex/reflex.py
  2. 16 0
      reflex/utils/path_ops.py
  3. 20 2
      reflex/utils/prerequisites.py
  4. 16 3
      tests/units/utils/test_utils.py

+ 14 - 7
reflex/reflex.py

@@ -145,10 +145,7 @@ def _run(
     exec.output_system_info()
     exec.output_system_info()
 
 
     # If no --frontend-only and no --backend-only, then turn on frontend and backend both
     # If no --frontend-only and no --backend-only, then turn on frontend and backend both
-    if not frontend and not backend:
-        frontend = True
-        backend = True
-
+    frontend, backend = prerequisites.check_running_mode(frontend, backend)
     if not frontend and backend:
     if not frontend and backend:
         _skip_compile()
         _skip_compile()
 
 
@@ -306,10 +303,18 @@ def export(
         True, "--no-zip", help="Disable zip for backend and frontend exports."
         True, "--no-zip", help="Disable zip for backend and frontend exports."
     ),
     ),
     frontend: bool = typer.Option(
     frontend: bool = typer.Option(
-        True, "--backend-only", help="Export only backend.", show_default=False
+        False,
+        "--frontend-only",
+        help="Export only frontend.",
+        show_default=False,
+        envvar=environment.REFLEX_FRONTEND_ONLY.name,
     ),
     ),
     backend: bool = typer.Option(
     backend: bool = typer.Option(
-        True, "--frontend-only", help="Export only frontend.", show_default=False
+        False,
+        "--backend-only",
+        help="Export only backend.",
+        show_default=False,
+        envvar=environment.REFLEX_BACKEND_ONLY.name,
     ),
     ),
     zip_dest_dir: str = typer.Option(
     zip_dest_dir: str = typer.Option(
         str(Path.cwd()),
         str(Path.cwd()),
@@ -332,7 +337,9 @@ def export(
     from reflex.utils import export as export_utils
     from reflex.utils import export as export_utils
     from reflex.utils import prerequisites
     from reflex.utils import prerequisites
 
 
-    if prerequisites.needs_reinit(frontend=True):
+    frontend, backend = prerequisites.check_running_mode(frontend, backend)
+
+    if prerequisites.needs_reinit(frontend=frontend or not backend):
         _init(name=config.app_name, loglevel=loglevel)
         _init(name=config.app_name, loglevel=loglevel)
 
 
     if frontend and not config.show_built_with_reflex:
     if frontend and not config.show_built_with_reflex:

+ 16 - 0
reflex/utils/path_ops.py

@@ -262,6 +262,22 @@ def find_replace(directory: str | Path, find: str, replace: str):
             filepath.write_text(text, encoding="utf-8")
             filepath.write_text(text, encoding="utf-8")
 
 
 
 
+def samefile(file1: Path, file2: Path) -> bool:
+    """Check if two files are the same.
+
+    Args:
+        file1: The first file.
+        file2: The second file.
+
+    Returns:
+        Whether the files are the same. If either file does not exist, returns False.
+    """
+    if file1.exists() and file2.exists():
+        return file1.samefile(file2)
+
+    return False
+
+
 def update_directory_tree(src: Path, dest: Path):
 def update_directory_tree(src: Path, dest: Path):
     """Recursively copies a directory tree from src to dest.
     """Recursively copies a directory tree from src to dest.
     Only copies files if the destination file is missing or modified earlier than the source file.
     Only copies files if the destination file is missing or modified earlier than the source file.

+ 20 - 2
reflex/utils/prerequisites.py

@@ -1225,6 +1225,21 @@ def install_frontend_packages(packages: set[str], config: Config):
         )
         )
 
 
 
 
+def check_running_mode(frontend: bool, backend: bool) -> tuple[bool, bool]:
+    """Check if the app is running in frontend or backend mode.
+
+    Args:
+        frontend: Whether to run the frontend of the app.
+        backend: Whether to run the backend of the app.
+
+    Returns:
+        The running modes.
+    """
+    if not frontend and not backend:
+        return True, True
+    return frontend, backend
+
+
 def needs_reinit(frontend: bool = True) -> bool:
 def needs_reinit(frontend: bool = True) -> bool:
     """Check if an app needs to be reinitialized.
     """Check if an app needs to be reinitialized.
 
 
@@ -1293,10 +1308,13 @@ def validate_bun():
     """
     """
     bun_path = path_ops.get_bun_path()
     bun_path = path_ops.get_bun_path()
 
 
-    if bun_path and not bun_path.samefile(constants.Bun.DEFAULT_PATH):
+    if bun_path is None:
+        return
+
+    if not path_ops.samefile(bun_path, constants.Bun.DEFAULT_PATH):
         console.info(f"Using custom Bun path: {bun_path}")
         console.info(f"Using custom Bun path: {bun_path}")
         bun_version = get_bun_version()
         bun_version = get_bun_version()
-        if not bun_version:
+        if bun_version is None:
             console.error(
             console.error(
                 "Failed to obtain bun version. Make sure the specified bun path in your config is correct."
                 "Failed to obtain bun version. Make sure the specified bun path in your config is correct."
             )
             )

+ 16 - 3
tests/units/utils/test_utils.py

@@ -115,7 +115,20 @@ def test_typehint_issubclass(subclass, superclass, expected):
     assert types.typehint_issubclass(subclass, superclass) == expected
     assert types.typehint_issubclass(subclass, superclass) == expected
 
 
 
 
-def test_validate_invalid_bun_path(mocker):
+def test_validate_none_bun_path(mocker):
+    """Test that an error is thrown when a bun path is not specified.
+
+    Args:
+        mocker: Pytest mocker object.
+    """
+    mocker.patch("reflex.utils.path_ops.get_bun_path", return_value=None)
+    # with pytest.raises(typer.Exit):
+    prerequisites.validate_bun()
+
+
+def test_validate_invalid_bun_path(
+    mocker,
+):
     """Test that an error is thrown when a custom specified bun path is not valid
     """Test that an error is thrown when a custom specified bun path is not valid
     or does not exist.
     or does not exist.
 
 
@@ -123,13 +136,12 @@ def test_validate_invalid_bun_path(mocker):
         mocker: Pytest mocker object.
         mocker: Pytest mocker object.
     """
     """
     mock_path = mocker.Mock()
     mock_path = mocker.Mock()
-    mock_path.samefile.return_value = False
     mocker.patch("reflex.utils.path_ops.get_bun_path", return_value=mock_path)
     mocker.patch("reflex.utils.path_ops.get_bun_path", return_value=mock_path)
+    mocker.patch("reflex.utils.path_ops.samefile", return_value=False)
     mocker.patch("reflex.utils.prerequisites.get_bun_version", return_value=None)
     mocker.patch("reflex.utils.prerequisites.get_bun_version", return_value=None)
 
 
     with pytest.raises(typer.Exit):
     with pytest.raises(typer.Exit):
         prerequisites.validate_bun()
         prerequisites.validate_bun()
-    mock_path.samefile.assert_called_once()
 
 
 
 
 def test_validate_bun_path_incompatible_version(mocker):
 def test_validate_bun_path_incompatible_version(mocker):
@@ -141,6 +153,7 @@ def test_validate_bun_path_incompatible_version(mocker):
     mock_path = mocker.Mock()
     mock_path = mocker.Mock()
     mock_path.samefile.return_value = False
     mock_path.samefile.return_value = False
     mocker.patch("reflex.utils.path_ops.get_bun_path", return_value=mock_path)
     mocker.patch("reflex.utils.path_ops.get_bun_path", return_value=mock_path)
+    mocker.patch("reflex.utils.path_ops.samefile", return_value=False)
     mocker.patch(
     mocker.patch(
         "reflex.utils.prerequisites.get_bun_version",
         "reflex.utils.prerequisites.get_bun_version",
         return_value=version.parse("0.6.5"),
         return_value=version.parse("0.6.5"),