Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/changelog/215.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Prevent an earlier virtual-environment lookup from reporting an executable under the wrong Python version.
4 changes: 2 additions & 2 deletions src/python_discovery/_py_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ def resolve_to_system(cls, cache: PyInfoCache | None, target: PythonInfo) -> Pyt
target.executable = start_executable
return target

_cache_exe_discovery: ClassVar[dict[tuple[str, bool], PythonInfo]] = {}
_cache_exe_discovery: ClassVar[dict[tuple[str, bool, VersionInfo], PythonInfo]] = {}

def discover_exe(
self,
Expand All @@ -502,7 +502,7 @@ def discover_exe(
:param exact: when ``True``, require an exact version match.
:param env: environment mapping; defaults to :data:`os.environ`.
"""
key = prefix, exact
key = prefix, exact, self.version_info
if key in self._cache_exe_discovery and prefix:
_LOGGER.debug("discover exe from cache %s - exact %s: %r", prefix, exact, self._cache_exe_discovery[key])
return self._cache_exe_discovery[key]
Expand Down
20 changes: 18 additions & 2 deletions tests/test_py_info_extra.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,28 @@ def test_resolve_to_system_single_prefix_self_link(mocker: MockerFixture, caplog
def test_discover_exe_cache_hit() -> None:
info = copy.deepcopy(CURRENT)
cached = copy.deepcopy(CURRENT)
PythonInfo._cache_exe_discovery["/some/prefix", True] = cached
PythonInfo._cache_exe_discovery["/some/prefix", True, info.version_info] = cached
try:
result = info.discover_exe(MagicMock(), prefix="/some/prefix", exact=True)
assert result is cached
finally:
del PythonInfo._cache_exe_discovery["/some/prefix", True]
del PythonInfo._cache_exe_discovery["/some/prefix", True, info.version_info]


def test_discover_exe_cache_keeps_requested_version(tmp_path: Path) -> None:
prefix = CURRENT.prefix
assert prefix is not None
cache = DiskCache(tmp_path)
PythonInfo.clear_cache(cache)
try:
found = CURRENT.discover_exe(cache, prefix)
assert found.version_info == CURRENT.version_info
other = copy.deepcopy(CURRENT)
other.version_info = other.version_info._replace(major=0)
with pytest.raises(RuntimeError):
other.discover_exe(cache, prefix)
finally:
PythonInfo.clear_cache(cache)


def test_check_exe_none_path(tmp_path: Path) -> None:
Expand Down