From 2103c47b4637116f8ca452a560d0bb5b305a9636 Mon Sep 17 00:00:00 2001 From: Jean-Christophe Morin Date: Sat, 16 Dec 2023 14:04:55 -0500 Subject: [PATCH] Only return the latest version for major+minor python versions instead of returning all versions. Returning all versions is useless in the vast majority of cases. Signed-off-by: Jean-Christophe Morin --- README.md | 2 +- src/rez_pip/rez.py | 18 ++++++++++++++++-- tests/test_rez.py | 17 +++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 83a4aea..a082995 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Modern rez-pip implementation. Very WIP. * [x] Create rez package * [x] Copy distribution files to rez package. * [ ] Make it available as a rez plugin/sub-command - * [ ] Discover Python package using rez and use that when available. I think it's still fine to support non-rezified Python interpreters though. + * [x] Discover Python package using rez and use that when available. I think it's still fine to support non-rezified Python interpreters though. * [ ] Only download+convert package if it's not already in the rez repositories. * etc * [x] Accept multiple package names as input diff --git a/src/rez_pip/rez.py b/src/rez_pip/rez.py index 05f3447..1cefc0a 100644 --- a/src/rez_pip/rez.py +++ b/src/rez_pip/rez.py @@ -5,6 +5,7 @@ import typing import logging import pathlib +import itertools if sys.version_info >= (3, 10): import importlib.metadata as importlib_metadata @@ -233,15 +234,28 @@ def getPythonExecutables( :param packageFamily: Name of the rez package family for the python package. This allows ot support PyPy, etc. :returns: Dict where the keys are the python versions and values are abolute paths to executables. """ - packages = sorted( + all_packages = sorted( rez.packages.iter_packages( packageFamily, range_=range_ if range_ != "latest" else None ), key=lambda x: x.version, ) + packages: typing.List[rez.packages.Package] if range_ == "latest": - packages = [packages[-1]] + packages = [list(all_packages)[-1]] + else: + # Get the latest x.x (major+minor) and ignore anything else. + # We don't want to return 3.7.8 AND 3.7.9 for example. It doesn't + # make sense. We only need 3.7.x. + groups = [ + list(group) + for _, group in itertools.groupby( + all_packages, key=lambda x: x.version.as_tuple()[:2] + ) + ] + # Note that "pkgs" is already in the right order since all_packages is sorted. + packages = [pkgs[-1] for pkgs in groups] pythons: typing.Dict[str, pathlib.Path] = {} for package in packages: diff --git a/tests/test_rez.py b/tests/test_rez.py index 2301748..6cd4719 100644 --- a/tests/test_rez.py +++ b/tests/test_rez.py @@ -316,6 +316,23 @@ def test_convertMetadata( {"1.0.0": pathlib.Path("/path/python1.0")}, id="with-range-less-than-2", ), + pytest.param( + ["3.9.0", "3.7.1", "3.7.6", "3.7.5", "2.7.4", "2.7.9"], + None, + [ + # Due to how the test is structured, these have to be in the same + # order as the output. + "python2.7", + "python3.7", + "python3.9", + ], + { + "2.7.9": pathlib.Path("/path/python2.7"), + "3.7.6": pathlib.Path("/path/python3.7"), + "3.9.0": pathlib.Path("/path/python3.9"), + }, + id="select-latest-major+minor", + ), ], ) def test_getPythonExecutables(