From 3a02d03cb1b9d78ff8ad221e95aa38fbe1e867f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Brand=C3=A9ho?= Date: Mon, 10 Feb 2025 20:44:44 +0100 Subject: [PATCH] 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 --- reflex/reflex.py | 21 ++++++++++++++------- reflex/utils/path_ops.py | 16 ++++++++++++++++ reflex/utils/prerequisites.py | 22 ++++++++++++++++++++-- tests/units/utils/test_utils.py | 19 ++++++++++++++++--- 4 files changed, 66 insertions(+), 12 deletions(-) diff --git a/reflex/reflex.py b/reflex/reflex.py index 70aa16a05..e4be0c89a 100644 --- a/reflex/reflex.py +++ b/reflex/reflex.py @@ -145,10 +145,7 @@ def _run( exec.output_system_info() # 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: _skip_compile() @@ -306,10 +303,18 @@ def export( True, "--no-zip", help="Disable zip for backend and frontend exports." ), 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( - 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( str(Path.cwd()), @@ -332,7 +337,9 @@ def export( from reflex.utils import export as export_utils 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) if frontend and not config.show_built_with_reflex: diff --git a/reflex/utils/path_ops.py b/reflex/utils/path_ops.py index 92557d801..dae938316 100644 --- a/reflex/utils/path_ops.py +++ b/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") +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): """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. diff --git a/reflex/utils/prerequisites.py b/reflex/utils/prerequisites.py index 6c6d34923..8047e1256 100644 --- a/reflex/utils/prerequisites.py +++ b/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: """Check if an app needs to be reinitialized. @@ -1293,10 +1308,13 @@ def validate_bun(): """ 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}") bun_version = get_bun_version() - if not bun_version: + if bun_version is None: console.error( "Failed to obtain bun version. Make sure the specified bun path in your config is correct." ) diff --git a/tests/units/utils/test_utils.py b/tests/units/utils/test_utils.py index 7cd53f14a..74dcf79b0 100644 --- a/tests/units/utils/test_utils.py +++ b/tests/units/utils/test_utils.py @@ -115,7 +115,20 @@ def test_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 or does not exist. @@ -123,13 +136,12 @@ def test_validate_invalid_bun_path(mocker): mocker: Pytest mocker object. """ 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.samefile", return_value=False) mocker.patch("reflex.utils.prerequisites.get_bun_version", return_value=None) with pytest.raises(typer.Exit): prerequisites.validate_bun() - mock_path.samefile.assert_called_once() 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.samefile.return_value = False 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=version.parse("0.6.5"),