From 7a9d3dbb47258703859ccf5f2e035b328542139e Mon Sep 17 00:00:00 2001 From: Matt Ghantous Date: Mon, 9 Feb 2026 16:17:48 -0500 Subject: [PATCH 1/4] Work with latest setuptools and wheel packages --- core-requirements.txt | 2 +- devpi_builder/requirements.py | 8 ++++---- devpi_builder/wheeler.py | 15 ++++++++------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/core-requirements.txt b/core-requirements.txt index d8d84ee..226d83b 100644 --- a/core-requirements.txt +++ b/core-requirements.txt @@ -2,7 +2,7 @@ devpi-plumber>=0.2.14 setuptools wheel wheel-filename -wheel-inspect>=1.6.0 +wheel-inspect>=1.8.0 pip>=1.5.3 junit-xml>=1.9 # First version to support to_xml_report_file pip-requirements-parser>=32.0.1 diff --git a/devpi_builder/requirements.py b/devpi_builder/requirements.py index 179998a..84922c9 100644 --- a/devpi_builder/requirements.py +++ b/devpi_builder/requirements.py @@ -5,7 +5,7 @@ """ import pip_requirements_parser -import pkg_resources +from packaging.utils import canonicalize_name, canonicalize_version def _extract_project_version(requirement): @@ -61,10 +61,10 @@ def matched_by_list(package, version, requirements): :param requirements: A list of requirements as read by read_raw() :return: True if the package can be used to fulfil on of the requirements in the file, False otherwise """ - version = pkg_resources.safe_version('{}'.format(version)) - package = pkg_resources.safe_name(package) + version = canonicalize_version('{}'.format(version)) + package = canonicalize_name(package) matches = ( - package.lower() == pkg_resources.safe_name(requirement.name) and (requirement.specifier.contains(version) if requirement.specifier else 1) + package == canonicalize_name(requirement.name) and (requirement.specifier.contains(version) if requirement.specifier else True) for requirement in requirements ) return any(matches) diff --git a/devpi_builder/wheeler.py b/devpi_builder/wheeler.py index 66bc621..bb7cfe7 100644 --- a/devpi_builder/wheeler.py +++ b/devpi_builder/wheeler.py @@ -11,9 +11,10 @@ import tempfile from packaging import tags -from pkg_resources import Distribution, Requirement +from packaging.requirements import Requirement +from packaging.utils import canonicalize_name -from wheel_filename import InvalidFilenameError, parse_wheel_filename +from wheel_filename import ParseError, WheelFilename from wheel_inspect import inspect_wheel from wheel_inspect.classes import WheelFile @@ -52,13 +53,13 @@ def _matches_requirement(self, requirement, wheels): :param requirement:str : The requirement to satisfy :param wheels: List of wheels to search. """ - req = Requirement.parse(requirement) + req = Requirement(requirement) matching = [] for wheel in wheels: w = wheel.parsed_filename - dist = Distribution(project_name=self._standardize_package_name(w.project), version=w.version) - if dist in req: + name = canonicalize_name(self._standardize_package_name(w.project)) + if name == req.name and req.specifier.contains(str(w.version)): matching.append(wheel.path) return matching @@ -120,12 +121,12 @@ def is_compatible(package): Compatibility is based on https://www.python.org/dev/peps/pep-0425/ """ try: - w = parse_wheel_filename(package) + w = WheelFilename.parse(package) for systag in tags.sys_tags(): for tag in w.tag_triples(): if systag in tags.parse_tag(tag): return True - except InvalidFilenameError: + except ParseError: return False From 0e9e745aa9cd663ec700ea91e4c7af65620830e4 Mon Sep 17 00:00:00 2001 From: Matt Ghantous Date: Mon, 9 Feb 2026 17:13:05 -0500 Subject: [PATCH 2/4] backwards compat --- core-requirements.txt | 2 +- devpi_builder/wheeler.py | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/core-requirements.txt b/core-requirements.txt index 226d83b..d8d84ee 100644 --- a/core-requirements.txt +++ b/core-requirements.txt @@ -2,7 +2,7 @@ devpi-plumber>=0.2.14 setuptools wheel wheel-filename -wheel-inspect>=1.8.0 +wheel-inspect>=1.6.0 pip>=1.5.3 junit-xml>=1.9 # First version to support to_xml_report_file pip-requirements-parser>=32.0.1 diff --git a/devpi_builder/wheeler.py b/devpi_builder/wheeler.py index bb7cfe7..7f5b588 100644 --- a/devpi_builder/wheeler.py +++ b/devpi_builder/wheeler.py @@ -14,7 +14,17 @@ from packaging.requirements import Requirement from packaging.utils import canonicalize_name -from wheel_filename import ParseError, WheelFilename +# Support both wheel-filename 1.x (Python 3.9 + wheel-inspect 1.7) and 2.x (Python 3.10+ + wheel-inspect 1.8) +try: + from wheel_filename import ParseError as _WheelParseError + from wheel_filename import WheelFilename + + def _parse_wheel_filename(filename): + return WheelFilename.parse(filename) +except ImportError: + from wheel_filename import InvalidFilenameError as _WheelParseError + from wheel_filename import parse_wheel_filename as _parse_wheel_filename + from wheel_inspect import inspect_wheel from wheel_inspect.classes import WheelFile @@ -121,12 +131,12 @@ def is_compatible(package): Compatibility is based on https://www.python.org/dev/peps/pep-0425/ """ try: - w = WheelFilename.parse(package) + w = _parse_wheel_filename(package) for systag in tags.sys_tags(): for tag in w.tag_triples(): if systag in tags.parse_tag(tag): return True - except ParseError: + except _WheelParseError: return False From c88b04ba1b76b6664079e74bbce892057a0a27a5 Mon Sep 17 00:00:00 2001 From: Matt Ghantous Date: Mon, 9 Feb 2026 18:10:27 -0500 Subject: [PATCH 3/4] normalize req_name --- devpi_builder/wheeler.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/devpi_builder/wheeler.py b/devpi_builder/wheeler.py index 7f5b588..8657bc4 100644 --- a/devpi_builder/wheeler.py +++ b/devpi_builder/wheeler.py @@ -64,12 +64,13 @@ def _matches_requirement(self, requirement, wheels): :param wheels: List of wheels to search. """ req = Requirement(requirement) + req_name = canonicalize_name(req.name) matching = [] for wheel in wheels: w = wheel.parsed_filename name = canonicalize_name(self._standardize_package_name(w.project)) - if name == req.name and req.specifier.contains(str(w.version)): + if name == req_name and req.specifier.contains(str(w.version)): matching.append(wheel.path) return matching From e28b46d3c8d6010eecf5aa3dcb9b7050ca1147fb Mon Sep 17 00:00:00 2001 From: Matt Ghantous Date: Mon, 9 Feb 2026 19:22:01 -0500 Subject: [PATCH 4/4] Use setuptools<82 for tests --- .github/workflows/tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 83a1a98..5657c10 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -22,6 +22,9 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip + # devpi-plumber runs devpi-init, which still uses pkg_resources; use setuptools <82 in CI only + # so integration tests pass + python -m pip install 'setuptools<82' python -m pip install -r requirements.txt python -m pip install --no-deps -e . if [ "${{ matrix.python-version }}" != "3.13" ]; then # workaround for TheKevJames/coveralls-python#523