-
Notifications
You must be signed in to change notification settings - Fork 52
Description
Problem description
While trying to package my project, I am running into an issue with the permitted SPDX expressions for the license string. I'm not sure if my problem is with the build backend, the format, the spec/PEP, or something else entirely, so I'm opening an issue here in the hopes that somebody can direct me to the correct place.
My project is licensed under the AGPL with custom additional terms. Within the project, I use the license identifier AGPL-3.0-only WITH AdditionRef-Pretalx-AGPL-3.0-Terms, which is to my understanding the correct way of expressing this situation in SPDX v3.0.
PEP 639 links to SPDX v2.2 in its definition of a license identifier. In that version of SPDX, only a select list of expressions is allowed to follow a WITH statements. I assume that this is why setuptools breaks when I use this in my pyproject.toml file:
Traceback
× Failed to build `pretalx @ file:///home/rixx/src/pretalx` ├─▶ The build backend returned an error ╰─▶ Call to `setuptools.build_meta.build_editable` failed (exit status: 1) [stdout]
configuration error: `project.license` must be valid exactly by one definition (0 matches found):
- {type: string, format: 'SPDX'}
- type: table
keys:
'file': {type: string}
required: ['file']
- type: table
keys:
'text': {type: string}
required: ['text']
DESCRIPTION:
`Project license <https://peps.python.org/pep-0621/#license>`_.
GIVEN VALUE:
"AGPL-3.0-only WITH AdditionRef-Pretalx-AGPL-3.0-Terms"
OFFENDING RULE: 'oneOf'
DEFINITION:
{
"oneOf": [
{
"type": "string",
"description": "An SPDX license identifier",
"format": "SPDX"
},
{
"type": "object",
"properties": {
"file": {
"type": "string",
"$$description": [
"Relative path to the file (UTF-8) which contains the license for the",
"project."
]
}
},
"required": [
"file"
]
},
{
"type": "object",
"properties": {
"text": {
"type": "string",
"$$description": [
"The license of the project whose meaning is that of the",
"`License field from the core metadata",
"<https://packaging.python.org/specifications/core-metadata/#license>`_."
]
}
},
"required": [
"text"
]
}
]
}
For more details about `format` see
https://validate-pyproject.readthedocs.io/en/latest/api/validate_pyproject.formats.html
[stderr]
Traceback (most recent call last):
File "<string>", line 14, in <module>
File "/home/rixx/.cache/uv/builds-v0/.tmp3KAqm4/lib/python3.12/site-packages/setuptools/build_meta.py", line 473, in get_requires_for_build_editable
return self.get_requires_for_build_wheel(config_settings)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/rixx/.cache/uv/builds-v0/.tmp3KAqm4/lib/python3.12/site-packages/setuptools/build_meta.py", line 331, in get_requires_for_build_wheel
return self._get_build_requires(config_settings, requirements=[])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/rixx/.cache/uv/builds-v0/.tmp3KAqm4/lib/python3.12/site-packages/setuptools/build_meta.py", line 301, in _get_build_requires
self.run_setup()
File "/home/rixx/.cache/uv/builds-v0/.tmp3KAqm4/lib/python3.12/site-packages/setuptools/build_meta.py", line 317, in run_setup
exec(code, locals())
File "<string>", line 1, in <module>
File "/home/rixx/.cache/uv/builds-v0/.tmp3KAqm4/lib/python3.12/site-packages/setuptools/__init__.py", line 115, in setup
return distutils.core.setup(**attrs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/rixx/.cache/uv/builds-v0/.tmp3KAqm4/lib/python3.12/site-packages/setuptools/_distutils/core.py", line 160, in setup
dist.parse_config_files()
File "/home/rixx/.cache/uv/builds-v0/.tmp3KAqm4/lib/python3.12/site-packages/_virtualenv.py", line 20, in parse_config_files
result = old_parse_config_files(self, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/rixx/.cache/uv/builds-v0/.tmp3KAqm4/lib/python3.12/site-packages/setuptools/dist.py", line 756, in parse_config_files
pyprojecttoml.apply_configuration(self, filename, ignore_option_errors)
File "/home/rixx/.cache/uv/builds-v0/.tmp3KAqm4/lib/python3.12/site-packages/setuptools/config/pyprojecttoml.py", line 72, in apply_configuration
config = read_configuration(filepath, True, ignore_option_errors, dist)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/rixx/.cache/uv/builds-v0/.tmp3KAqm4/lib/python3.12/site-packages/setuptools/config/pyprojecttoml.py", line 140, in read_configuration
validate(subset, filepath)
File "/home/rixx/.cache/uv/builds-v0/.tmp3KAqm4/lib/python3.12/site-packages/setuptools/config/pyprojecttoml.py", line 61, in validate
raise ValueError(f"{error}\n{summary}") from None
ValueError: invalid pyproject.toml config: `project.license`.
configuration error: `project.license` must be valid exactly by one definition (0 matches found):
- {type: string, format: 'SPDX'}
- type: table
keys:
'file': {type: string}
required: ['file']
- type: table
keys:
'text': {type: string}
required: ['text']
The PyPA documentation at no point (that I could find), e.g. at the License-Expression docs, mentions the version of SPDX that is used, so I was pretty confused by running into this.
The PEP mentions that “This includes all valid SPDX identifiers and the custom LicenseRef-[idstring] strings conforming to the SPDX specification, clause 10.1.”, which again links to SPDX v2.2 – but then, SPDX v3.0 was not out yet at that point.
As the PEP does not explicitly mention an SPDX version, and as SPDX v3 is backwards-compatible (in that it accepts all SPDX v2 license identifiers), I had expected that I could use this format, instead of having to choose between using the AGPL identifier (not quite correct, but more helpful to people) and a custom identifier. Is this something that I could take up with PyPA, or with setuptools, or with the Python project? Or is Python expected to stick with SPDX v2.2 indefinitely (in which case it would be good to clarify this at least in the packaging docs)?