diff --git a/src/pythonfinder/finders/system_finder.py b/src/pythonfinder/finders/system_finder.py index 0563b9f..d43fe22 100644 --- a/src/pythonfinder/finders/system_finder.py +++ b/src/pythonfinder/finders/system_finder.py @@ -57,7 +57,12 @@ def __init__( venv = os.environ.get("VIRTUAL_ENV") if venv: bin_dir = "Scripts" if os.name == "nt" else "bin" - venv_path = Path(venv).resolve() / bin_dir + try: + venv_path = Path(venv).resolve() / bin_dir + except (PermissionError, OSError): + # resolve() can raise PermissionError on Windows for restricted + # system directories; fall back to a non-resolving join. + venv_path = Path(venv) / bin_dir # For Windows tests with Unix-style paths if os.name == "nt" and str(venv).startswith("/"): diff --git a/src/pythonfinder/utils/path_utils.py b/src/pythonfinder/utils/path_utils.py index a97f556..8a633e6 100644 --- a/src/pythonfinder/utils/path_utils.py +++ b/src/pythonfinder/utils/path_utils.py @@ -238,11 +238,14 @@ def exists_and_is_accessible(path: Path) -> bool: """ try: return path.exists() - except PermissionError as pe: - if pe.errno == errno.EACCES: # Permission denied + except PermissionError as error: + if error.errno == errno.EACCES or getattr(error, "winerror", None) == 5: return False - else: - raise + raise + except OSError as error: + if error.errno == errno.EACCES or getattr(error, "winerror", None) == 5: + return False + raise def is_in_path(path: str | Path, parent_path: str | Path) -> bool: diff --git a/tests/test_path_utils.py b/tests/test_path_utils.py index 70adbe0..ac4d424 100644 --- a/tests/test_path_utils.py +++ b/tests/test_path_utils.py @@ -241,6 +241,19 @@ def test_exists_and_is_accessible(): ): exists_and_is_accessible(Path("/usr/bin/python")) + class WindowsAccessDenied(OSError): + def __init__(self): + super().__init__("Access is denied") + self.winerror = 5 + self.errno = None + + with mock.patch("pathlib.Path.exists", side_effect=WindowsAccessDenied()): + assert not exists_and_is_accessible(Path("/usr/bin/python")) + + with pytest.raises(OSError): + with mock.patch("pathlib.Path.exists", side_effect=OSError(1, "Other error")): + exists_and_is_accessible(Path("/usr/bin/python")) + def test_is_in_path(): """Test that is_in_path correctly checks if a path is inside another path."""