diff --git a/pipenv/utils/shell.py b/pipenv/utils/shell.py index 50d2b9cfc5..1ae15c38f4 100644 --- a/pipenv/utils/shell.py +++ b/pipenv/utils/shell.py @@ -13,7 +13,7 @@ from pipenv.utils.fileutils import normalize_drive, normalize_path from pipenv.vendor import click -from pipenv.vendor.pythonfinder.utils import ensure_path +from pipenv.vendor.pythonfinder.utils import ensure_path, parse_python_version from .constants import FALSE_VALUES, SCHEME_LIST, TRUE_VALUES from .processes import subprocess_run @@ -237,7 +237,7 @@ def find_python(finder, line=None): :return: A path to python :rtype: str """ - + print(line) if line and not isinstance(line, str): raise TypeError(f"Invalid python search type: expected string, received {line!r}") if line: @@ -258,9 +258,20 @@ def find_python(finder, line=None): if not line: result = next(iter(finder.find_all_python_versions()), None) elif line and line[0].isdigit() or re.match(r"^\d+(\.\d+)*$", line): - result = finder.find_python_version(line) + version_info = parse_python_version(line) + print(version_info) + result = finder.find_python_version( + major=version_info.get("major"), + minor=version_info.get("minor"), + patch=version_info.get("patch"), + pre=version_info.get("is_prerelease"), + dev=version_info.get("is_devrelease"), + ) + print(f"result: {result}") else: + print(line) result = finder.find_python_version(name=line) + print(result) if not result: result = finder.which(line) if not result and not line.startswith("python"): diff --git a/pipenv/vendor/pythonfinder/models/mixins.py b/pipenv/vendor/pythonfinder/models/mixins.py index 4394fccf44..3bfce6d5c8 100644 --- a/pipenv/vendor/pythonfinder/models/mixins.py +++ b/pipenv/vendor/pythonfinder/models/mixins.py @@ -292,17 +292,10 @@ def version_matcher(py_version): if self.is_python and self.as_python and version_matcher(self.py_version): return self - matching_pythons = [ - [entry, entry.as_python.version_sort] - for entry in self._iter_pythons() - if ( - entry is not None - and entry.as_python is not None - and version_matcher(entry.py_version) - ) - ] - results = sorted(matching_pythons, key=lambda r: (r[1], r[0]), reverse=True) - return next(iter(r[0] for r in results if r is not None), None) + for entry in self._iter_pythons(): + if entry is not None and entry.as_python is not None: + if version_matcher(entry.as_python): + return entry def _filter_children(self) -> Iterator[Path]: if not os.access(str(self.path), os.R_OK): diff --git a/pipenv/vendor/pythonfinder/models/path.py b/pipenv/vendor/pythonfinder/models/path.py index 3ee960b4c4..77f5beae5b 100644 --- a/pipenv/vendor/pythonfinder/models/path.py +++ b/pipenv/vendor/pythonfinder/models/path.py @@ -31,6 +31,7 @@ parse_asdf_version_order, parse_pyenv_version_order, split_version_and_name, + looks_like_python, ) from .mixins import PathEntry from .python import PythonFinder @@ -363,17 +364,15 @@ def which(self, executable) -> PathEntry | None: def _filter_paths(self, finder) -> Iterator: for path in self._get_paths(): - if path is None: + if not path: continue - python_versions = finder(path) - if python_versions is not None: - for python in python_versions: - if python is not None: - yield python + python_version = finder(path) + if python_version: + yield python_version def _get_all_pythons(self, finder) -> Iterator: for python in self._filter_paths(finder): - if python is not None and python.is_python: + if python: yield python def get_pythons(self, finder) -> Iterator: diff --git a/pipenv/vendor/pythonfinder/models/python.py b/pipenv/vendor/pythonfinder/models/python.py index e984d96b30..9fa9d4e8e7 100644 --- a/pipenv/vendor/pythonfinder/models/python.py +++ b/pipenv/vendor/pythonfinder/models/python.py @@ -282,11 +282,13 @@ def version_sort(path_entry): return path_entry.as_python.version_sort unnested = [sub_finder(self.roots[path]) for path in self.roots] + print(f"unnested: {unnested}") unnested = [ p for p in unnested if p is not None and p.is_python and p.as_python is not None ] + print(unnested) paths = sorted(list(unnested), key=version_sort, reverse=True) return next(iter(p for p in paths if p is not None), None) @@ -388,37 +390,29 @@ def version_tuple(self) -> tuple[int, int, int, bool, bool, bool]: self.is_debug, ) - def matches( - self, - major: int | None = None, - minor: int | None = None, - patch: int | None = None, - pre: bool = False, - dev: bool = False, - arch: str | None = None, - debug: bool = False, - python_name: str | None = None, - ) -> bool: + def matches(self, major=None, minor=None, patch=None, pre=False, dev=False, arch=None, debug=False, + python_name=None): result = False if arch: own_arch = self.get_architecture() if arch.isdigit(): arch = f"{arch}bit" + if ( (major is None or self.major == major) and (minor is None or self.minor == minor) + # Check if patch is None OR self.patch equals patch and (patch is None or self.patch == patch) and (pre is None or self.is_prerelease == pre) and (dev is None or self.is_devrelease == dev) and (arch is None or own_arch == arch) and (debug is None or self.is_debug == debug) - and ( - python_name is None - or (python_name and self.name) - and (self.name == python_name or self.name.startswith(python_name)) - ) + and (python_name is None or + (python_name and self.name) and + (self.name == python_name or self.name.startswith(python_name))) ): result = True + return result def as_major(self) -> PythonVersion: