Skip to content

Commit 1b44007

Browse files
authored
Merge pull request #166 from sarugaku/fix/py-launcher-full-version-matching
fix: resolve full patch version from py-launcher executable
2 parents a17af70 + 2151996 commit 1b44007

2 files changed

Lines changed: 36 additions & 2 deletions

File tree

news/158.bugfix.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Fix full-version matching for Python installations discovered via the Windows
2+
py launcher.
3+
4+
``py --list-paths`` only reports ``major.minor`` (e.g. ``3.11``), so
5+
``PyLauncherFinder`` was storing ``patch=None`` for every entry. Callers that
6+
searched for a specific full version such as ``3.11.9`` (e.g. from
7+
``python_full_version`` in a Pipfile) received no match because
8+
``matches(patch=9)`` evaluated ``None == 9 → False``.
9+
10+
The finder now queries each discovered executable for its real version string
11+
(e.g. ``3.11.9``) via ``get_python_version()`` after the py-launcher lookup,
12+
so that full-version searches succeed. If the executable cannot be queried the
13+
code falls back gracefully to the ``major.minor`` string reported by the py
14+
launcher.
15+

src/pythonfinder/finders/py_launcher_finder.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,10 @@ def _create_python_info_from_py_launcher(
9292
Create a PythonInfo object from py launcher information.
9393
9494
Args:
95-
version: The Python version (e.g. "3.11").
95+
version: The Python version reported by the py launcher (e.g. "3.11").
96+
This is typically only major.minor; the full patch version is
97+
resolved by querying the executable so that searches for a
98+
specific full version (e.g. "3.11.9") succeed.
9699
path: The path to the Python executable.
97100
is_default: "*" if this is the default version, "" otherwise.
98101
@@ -102,14 +105,30 @@ def _create_python_info_from_py_launcher(
102105
if not path or not os.path.exists(path):
103106
return None
104107

105-
# Parse the version
108+
# Parse the version reported by the py launcher (usually major.minor only).
106109
try:
107110
version_data = parse_python_version(version)
108111
except InvalidPythonVersion:
109112
if not self.ignore_unsupported:
110113
raise
111114
return None
112115

116+
# `py --list-paths` only reports major.minor (e.g. "3.11"). Resolve the
117+
# real patch version by querying the executable so that callers searching
118+
# for a full version string like "3.11.9" can match correctly.
119+
if version_data.get("patch") is None:
120+
try:
121+
from ..utils.version_utils import get_python_version
122+
123+
full_version = get_python_version(path)
124+
full_version_data = parse_python_version(full_version)
125+
version_data = full_version_data
126+
version = full_version
127+
except Exception:
128+
# If we can't run the executable, fall back to the major.minor
129+
# version string provided by the py launcher.
130+
pass
131+
113132
# Create the PythonInfo object
114133
return PythonInfo(
115134
path=Path(path),

0 commit comments

Comments
 (0)