From cc772652cdf89ac65af465a04d729e893ba82472 Mon Sep 17 00:00:00 2001 From: Michael McNeil Forbes Date: Sun, 4 Sep 2022 12:32:36 -0700 Subject: [PATCH] Update noxutil.py Add `python` parameter to `get_version()` allowing one to limit versions based on the python version. --- noxutil.py | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/noxutil.py b/noxutil.py index 8a17bcbf5..8475a0e3d 100644 --- a/noxutil.py +++ b/noxutil.py @@ -2,7 +2,7 @@ from collections.abc import Iterable from pathlib import Path -from typing import Optional +from typing import Union from urllib.request import urlopen, Request from poetry.core.factory import Factory @@ -15,16 +15,20 @@ VERSION_PARTS = ('major', 'minor', 'patch') -def get_versions(dependency: str, granularity: str = 'minor', - # ascending: bool = False, limit: Optional[int] = None, - # allow_prerelease: bool = False, - ) -> Iterable[str]: +def get_versions( + dependency: str, + granularity: str = "minor", + python: Union[str, None] = None, + # ascending: bool = False, limit: Optional[int] = None, + # allow_prerelease: bool = False, +) -> Iterable[str]: """Yield all versions of `dependency` considering version constraints Args: dependency: the name of the dependency granularity: yield only the newest patch version of each major/minor release + python: version of python or None ascending: count backwards from latest version, by default (not much use without the 'limit' arg) limit: maximum number of entries to return @@ -36,16 +40,33 @@ def get_versions(dependency: str, granularity: str = 'minor', """ package = Factory().create_poetry(Path(__file__).parent).package - for requirement in package.requires: - if requirement.name == dependency: - break - else: + requirements = [ + requirement + for requirement in package.requires + if requirement.name == dependency + ] + if not requirements: raise ValueError(f"{package.name} has no dependency '{dependency}'") - filtered_versions = [version for version in all_versions(dependency) - if requirement.constraint.allows(version)] - parts = VERSION_PARTS[:VERSION_PARTS.index(granularity) + 1] + + def allowed(version): + """Return True if the version is allowed.""" + if python is None: + return any( + requirement.constraint.allows(version) for requirement in requirements + ) + + python_version = parse_single_constraint(python) + for requirement in requirements: + python_versions = parse_single_constraint(requirement.python_versions) + if python_versions.allows(python_version) and requirement.constraint.allows( + version + ): + return True + return False + + parts = VERSION_PARTS[: VERSION_PARTS.index(granularity) + 1] result = {} - for version in filtered_versions: + for version in filter(allowed, all_versions(dependency)): key = tuple(getattr(version, part) for part in parts) result[key] = (max((result[key], version)) if key in result else version)