diff --git a/docs/changelog/2782.bugfix.rst b/docs/changelog/2782.bugfix.rst new file mode 100644 index 000000000..38b04cc36 --- /dev/null +++ b/docs/changelog/2782.bugfix.rst @@ -0,0 +1 @@ +When a ``$PATH`` entry cannot be checked for existence, skip it instead of terminating - by :user:`hroncok`. diff --git a/src/virtualenv/discovery/builtin.py b/src/virtualenv/discovery/builtin.py index ae0612b36..d2f1cf433 100644 --- a/src/virtualenv/discovery/builtin.py +++ b/src/virtualenv/discovery/builtin.py @@ -3,6 +3,7 @@ import logging import os import sys +from contextlib import suppress from pathlib import Path from typing import TYPE_CHECKING, Callable @@ -166,8 +167,9 @@ def get_paths(env: Mapping[str, str]) -> Generator[Path, None, None]: path = os.defpath if path: for p in map(Path, path.split(os.pathsep)): - if p.exists(): - yield p + with suppress(OSError): + if p.exists(): + yield p class LazyPathDump: diff --git a/tests/unit/discovery/test_discovery.py b/tests/unit/discovery/test_discovery.py index 0e11c2d90..680131e7d 100644 --- a/tests/unit/discovery/test_discovery.py +++ b/tests/unit/discovery/test_discovery.py @@ -59,6 +59,14 @@ def test_discovery_via_path_not_found(tmp_path, monkeypatch): assert interpreter is None +def test_discovery_via_path_in_nonbrowseable_directory(tmp_path, monkeypatch): + bad_perm = tmp_path / "bad_perm" + bad_perm.mkdir(mode=0o000) + monkeypatch.setenv("PATH", str(bad_perm / "bin")) + interpreter = get_interpreter(uuid4().hex, []) + assert interpreter is None + + def test_relative_path(session_app_data, monkeypatch): sys_executable = Path(PythonInfo.current_system(app_data=session_app_data).system_executable) cwd = sys_executable.parents[1]