Skip to content

Require setuptools>=77 to build (PEP 639 license expression) - #210

Open
AtharvaTilewale wants to merge 1 commit into
pharmai:masterfrom
AtharvaTilewale:fix/199-pin-setuptools-pep639
Open

AtharvaTilewale wants to merge 1 commit into
pharmai:masterfrom
AtharvaTilewale:fix/199-pin-setuptools-pep639

Conversation

@AtharvaTilewale

@AtharvaTilewale AtharvaTilewale commented Oct 24, 2026 •

Copy link
Copy Markdown

Problem

Building PLIP in an environment whose setuptools is older than 77 fails with a confusing
schema error rather than a message about setuptools (#199):

configuration error: `project.license` must be valid exactly by one definition (2 matches found):
    - keys:
        'file': {type: string}
      required: ['file']
    - keys:
        'text': {type: string}
      required: ['text']
GIVEN VALUE:
    "GPL-2.0-only"

Nothing in that message says which build requirement is too old, so it reads as a defect
in pyproject.toml.

Root cause

pyproject.toml declares the license as the PEP 639 SPDX expression
license = "GPL-2.0-only" (line 7). setuptools only accepts the string form from 77.0
onwards; before that, project.license had to be a table ({text = ...} or
{file = ...}), hence the "exactly by one definition" validation error. The build
requirement on line 3 was just requires = ["setuptools"], so nothing recorded that the
project now needs setuptools >= 77 to build.

What this change does

One line: requires = ["setuptools>=77"].

That makes the real build requirement explicit, so any front-end that resolves build
requirements reports an unmet setuptools>=77 instead of the schema error above. Nothing
else is changed — in particular requires-python is left at >=3.6 and no version is
bumped, and CHANGES.txt is left to the maintainers' release prep since v3.0.1 is
already tagged at the current master.

Validation

All builds below are of this branch, in throwaway venvs, with build 1.3.0:

1. Reproducing the report — pre-patch (requires = ["setuptools"]), setuptools
75.8.0, no build isolation:

$ python -m build --no-isolation --sdist --wheel .
ValueError: invalid pyproject.toml config: `project.license`.
configuration error: `project.license` must be valid exactly by one definition (2 matches found)
ERROR Backend subprocess exited when trying to invoke get_requires_for_build_sdist
--> exit=1  dist: (empty)

2. The check that changes — an isolated build whose build environment is constrained
to the old setuptools (PIP_CONSTRAINT=setuptools==75.8.0):

# pre-patch
$ PIP_CONSTRAINT=constraint.txt python -m build --sdist .
configuration error: `project.license` must be valid exactly by one definition (2 matches found)
ERROR Backend subprocess exited when trying to invoke get_requires_for_build_sdist
--> dist: (empty)

# post-patch
$ PIP_CONSTRAINT=constraint.txt python -m build --sdist .
ERROR: Cannot install setuptools>=77 because these package versions have conflicting dependencies.
ERROR: ResolutionImpossible

i.e. the failure now names the actual unmet build requirement.

3. Builds succeed with a setuptools that supports PEP 639 — post-patch, setuptools
80.9.0, no build isolation:

$ python -m build --no-isolation --sdist --wheel .
Successfully built plip-3.0.1.tar.gz and plip-3.0.1-py3-none-any.whl
--> exit=0

and the same with the default isolated build (pip resolves setuptools >= 77), plus
uv build --no-build-isolation in a venv with setuptools 80.9.0. The resulting wheel
metadata carries the SPDX expression:

Metadata-Version: 2.4
Name: plip
Version: 3.0.1
License-Expression: GPL-2.0-only
Requires-Python: >=3.6
License-File: LICENSE.txt

Honest limitation: this pin cannot rescue a non-isolated build that already has an
old setuptools installed (pip install --no-build-isolation . or
uv build --no-build-isolation with setuptools 75.8.0 still show the schema error, both
pre- and post-patch). No pyproject.toml change can, because the front-end invokes the
backend before any build requirement is checked; such environments have to upgrade
setuptools. What the pin fixes is the declaration itself and every resolver-driven build.
The python setup.py install path from the original report no longer exists on master
(setup.py/setup.cfg were removed in fc804af).

Fixes #199

Disclosure: this change was prepared with AI assistance and validated locally as described above.

pyproject.toml declares the license as the PEP 639 SPDX expression
`license = "GPL-2.0-only"`, which setuptools only accepts from version
77.0 onwards, but the build requirement was left unpinned. Build
environments that resolve an older setuptools therefore fail with
"configuration error: `project.license` must be valid exactly by one
definition" instead of reporting the unmet build requirement.

Fixes pharmai#199
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

python setup.py install alias plip='python plip/plip/plipcmd.py'

1 participant