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 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..8657bc4 100644 --- a/devpi_builder/wheeler.py +++ b/devpi_builder/wheeler.py @@ -11,9 +11,20 @@ import tempfile from packaging import tags -from pkg_resources import Distribution, Requirement +from packaging.requirements import Requirement +from packaging.utils import canonicalize_name + +# 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_filename import InvalidFilenameError, parse_wheel_filename from wheel_inspect import inspect_wheel from wheel_inspect.classes import WheelFile @@ -52,13 +63,14 @@ 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) + req_name = canonicalize_name(req.name) 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 +132,12 @@ def is_compatible(package): Compatibility is based on https://www.python.org/dev/peps/pep-0425/ """ try: - w = parse_wheel_filename(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 InvalidFilenameError: + except _WheelParseError: return False