diff --git a/docs/changelog/+skip-path-dir-probe.bugfix.rst b/docs/changelog/+skip-path-dir-probe.bugfix.rst new file mode 100644 index 0000000..839b584 --- /dev/null +++ b/docs/changelog/+skip-path-dir-probe.bugfix.rst @@ -0,0 +1,3 @@ +:func:`~python_discovery.iter_interpreters` with no key no longer probes each ``PATH`` directory as if it were an +interpreter. The empty spec made the literal name check point at the directory itself, so every entry cost a failed +subprocess and a retry. diff --git a/src/python_discovery/_discovery.py b/src/python_discovery/_discovery.py index 07d8684..33e2326 100644 --- a/src/python_discovery/_discovery.py +++ b/src/python_discovery/_discovery.py @@ -496,8 +496,9 @@ def path_exe_finder( direct = f"{direct}.exe" def path_exes(path: Path) -> Generator[tuple[Path, bool], None, None]: + # an empty spec (enumerating everything) would make the direct path the PATH directory itself direct_path = path / direct - if direct_path.exists(): + if direct_path.is_file(): yield direct_path, impl_must_match for exe in path.iterdir(): diff --git a/tests/test_iter_interpreters.py b/tests/test_iter_interpreters.py index f81b2ec..e7b6e7d 100644 --- a/tests/test_iter_interpreters.py +++ b/tests/test_iter_interpreters.py @@ -144,6 +144,21 @@ def test_iter_interpreters_no_key_probes_variant_builds_on_path( assert str(exe) in [call.args[0] for call in from_exe.call_args_list] +@pytest.mark.usefixtures("uv_dir") +def test_iter_interpreters_no_key_does_not_probe_path_directories( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch, mocker: MockerFixture +) -> None: + exe = tmp_path / "bin" / f"python3.99{'.exe' if IS_WIN else ''}" + exe.parent.mkdir() + exe.touch() + monkeypatch.setenv("PATH", str(exe.parent)) + from_exe = mocker.patch("python_discovery._discovery.PathPythonInfo.from_exe", return_value=None) + + list(iter_interpreters()) + + assert [call.args[0] for call in from_exe.call_args_list] == [str(exe)] + + @pytest.mark.usefixtures("uv_dir") def test_iter_interpreters_dedups_symlinks( tmp_path: Path,