Skip to content

Commit 387b371

Browse files
authored
Merge pull request #165 from sarugaku/permission-error-handling
Windows Permission error handling
2 parents 6123a1b + ca74715 commit 387b371

3 files changed

Lines changed: 26 additions & 5 deletions

File tree

src/pythonfinder/finders/system_finder.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,12 @@ def __init__(
5757
venv = os.environ.get("VIRTUAL_ENV")
5858
if venv:
5959
bin_dir = "Scripts" if os.name == "nt" else "bin"
60-
venv_path = Path(venv).resolve() / bin_dir
60+
try:
61+
venv_path = Path(venv).resolve() / bin_dir
62+
except (PermissionError, OSError):
63+
# resolve() can raise PermissionError on Windows for restricted
64+
# system directories; fall back to a non-resolving join.
65+
venv_path = Path(venv) / bin_dir
6166

6267
# For Windows tests with Unix-style paths
6368
if os.name == "nt" and str(venv).startswith("/"):

src/pythonfinder/utils/path_utils.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,11 +238,14 @@ def exists_and_is_accessible(path: Path) -> bool:
238238
"""
239239
try:
240240
return path.exists()
241-
except PermissionError as pe:
242-
if pe.errno == errno.EACCES: # Permission denied
241+
except PermissionError as error:
242+
if error.errno == errno.EACCES or getattr(error, "winerror", None) == 5:
243243
return False
244-
else:
245-
raise
244+
raise
245+
except OSError as error:
246+
if error.errno == errno.EACCES or getattr(error, "winerror", None) == 5:
247+
return False
248+
raise
246249

247250

248251
def is_in_path(path: str | Path, parent_path: str | Path) -> bool:

tests/test_path_utils.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,19 @@ def test_exists_and_is_accessible():
241241
):
242242
exists_and_is_accessible(Path("/usr/bin/python"))
243243

244+
class WindowsAccessDenied(OSError):
245+
def __init__(self):
246+
super().__init__("Access is denied")
247+
self.winerror = 5
248+
self.errno = None
249+
250+
with mock.patch("pathlib.Path.exists", side_effect=WindowsAccessDenied()):
251+
assert not exists_and_is_accessible(Path("/usr/bin/python"))
252+
253+
with pytest.raises(OSError):
254+
with mock.patch("pathlib.Path.exists", side_effect=OSError(1, "Other error")):
255+
exists_and_is_accessible(Path("/usr/bin/python"))
256+
244257

245258
def test_is_in_path():
246259
"""Test that is_in_path correctly checks if a path is inside another path."""

0 commit comments

Comments
 (0)