From bc6cb55227d2a4b5c6fa02b796f4de0a1cb1de9c Mon Sep 17 00:00:00 2001 From: Karolina Surma Date: Thu, 3 Oct 2024 12:22:35 +0200 Subject: [PATCH] Fix handling of self-referencing extras when reading pyproject.toml Keep the information about the requirement extras by storing the Requirement instances in the list of the ignored requirements, rather than the strings in the form they were initially read from metadata. The requirements strings read from pyproject.toml don't contain the extra information, we insert the extra marker only after converting them to Requirement instances. When stored as the text, the information about the extra went missing in the course of the script. --- pyproject-rpm-macros.spec | 5 +++- pyproject_buildrequires.py | 25 ++++++++++++-------- pyproject_buildrequires_testcases.yaml | 32 ++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 11 deletions(-) diff --git a/pyproject-rpm-macros.spec b/pyproject-rpm-macros.spec index 46da06b..3d3ac78 100644 --- a/pyproject-rpm-macros.spec +++ b/pyproject-rpm-macros.spec @@ -14,7 +14,7 @@ License: MIT # Increment Y and reset Z when new macros or features are added # Increment Z when this is a bugfix or a cosmetic change # Dropping support for EOL Fedoras is *not* considered a breaking change -Version: 1.15.0 +Version: 1.15.1 Release: 1%{?dist} # Macro files @@ -173,6 +173,9 @@ export HOSTNAME="rpmbuild" # to speedup tox in network-less mock, see rhbz#1856 %changelog +* Thu Oct 03 2024 Karolina Surma - 1.15.1-1 +- Fix handling of self-referencing extras when reading pyproject.toml + * Tue Sep 17 2024 Python Maint - 1.15.0-1 - Add a possibility to read runtime requirements from pyproject.toml [project] table - Fixes: rhbz#2261939 diff --git a/pyproject_buildrequires.py b/pyproject_buildrequires.py index 9913e98..bbe3651 100644 --- a/pyproject_buildrequires.py +++ b/pyproject_buildrequires.py @@ -101,18 +101,23 @@ class Requirements: return True return False - def add(self, requirement_str, *, package_name=None, source=None, extra=None): + def add(self, requirement, *, package_name=None, source=None, extra=None): """Output a Python-style requirement string as RPM dep""" + + requirement_str = str(requirement) print_err(f'Handling {requirement_str} from {source}') - try: - requirement = Requirement(requirement_str) - except InvalidRequirement: - hint = guess_reason_for_invalid_requirement(requirement_str) - message = f'Requirement {requirement_str!r} from {source} is invalid.' - if hint: - message += f' Hint: {hint}' - raise ValueError(message) + # requirements read initially from the metadata are strings + # further on we work with them as Requirement instances + if not isinstance(requirement, Requirement): + try: + requirement = Requirement(requirement) + except InvalidRequirement: + hint = guess_reason_for_invalid_requirement(requirement) + message = f'Requirement {requirement!r} from {source} is invalid.' + if hint: + message += f' Hint: {hint}' + raise ValueError(message) if requirement.url: print_err( @@ -130,7 +135,7 @@ class Requirements: if (requirement.marker is not None and not self.evaluate_all_environments(requirement)): print_err(f'Ignoring alien requirement:', requirement_str) - self.ignored_alien_requirements.append(requirement_str) + self.ignored_alien_requirements.append(requirement) return # Handle self-referencing requirements diff --git a/pyproject_buildrequires_testcases.yaml b/pyproject_buildrequires_testcases.yaml index 315e52e..63cf5cc 100644 --- a/pyproject_buildrequires_testcases.yaml +++ b/pyproject_buildrequires_testcases.yaml @@ -1246,3 +1246,35 @@ pyproject.toml with dynamic table and no deps: python3dist(setuptools) python3dist(wheel) result: 0 + +pyproject.toml with self-referencing extras: + skipif: not SETUPTOOLS_60 + read_pyproject_dependencies: true + installed: + setuptools: 50 + wheel: 1 + tomli: 1 + extras: + - test + pyproject.toml: | + [build-system] + requires = ["setuptools"] + build-backend = "setuptools.build_meta" + [project] + name = "contourpy" + version = "0.1" + dependencies = ["numpy >= 1.23"] + [project.optional-dependencies] + bokeh = ["bokeh", "selenium"] + test = ["contourpy[test-no-images]", "matplotlib", "Pillow"] + test-no-images = ["pytest", "pytest-rerunfailures", "wurlitzer"] + expected: | + python3dist(setuptools) + python3dist(wheel) + python3dist(numpy) >= 1.23 + python3dist(matplotlib) + python3dist(pillow) + python3dist(pytest) + python3dist(pytest-rerunfailures) + python3dist(wurlitzer) + result: 0