-
Notifications
You must be signed in to change notification settings - Fork 273
Description
To start: I am fully aware that reporting this might be seen as pedantry. However, given that pypa/packaging implements the PEP-level item PEP 639, I feel it's important for it to be fully compliant with that PEP, including edge cases.
PEP 639 states the following about the license
field of pyproject.toml
:
This PEP adopts the SPDX license expression syntax as documented in the SPDX specification, either Version 2.2 or a later compatible version.
SPDX specification v2.2.2 states that a license expression is (in part):
compound-expression = 1*1(simple-expression /
simple-expression "WITH" license-exception-id /
compound-expression "AND" compound-expression /
compound-expression "OR" compound-expression /
"(" compound-expression ")" )
Which means that MIT
is a valid compound expression (as it is a simple expression), as is (MIT)
(following the "(" compound-expression ")"
rule), as is ((MIT))
(following the "(" compound-expression ")"
rule twice), and so on.
However, canonicalize_license_expression
errors on more than one nested of parentheses:
>>> packaging.metadata.licenses.canonicalize_license_expression("((MIT))")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/homebrew/lib/python3.12/site-packages/packaging/licenses/__init__.py", line 94, in canonicalize_license_expression
raise InvalidLicenseExpression(message)
packaging.licenses.InvalidLicenseExpression: Invalid license expression: '((MIT))'
I'm not fully familiar with the relationship between eg setuptools
and pypa/packaging
, but I am guessing this or a related issue is the cause of an error when running pip install -e .
on the following pyproject.toml
:
[build-system]
requires = ["setuptools>=61"]
build-backend = "setuptools.build_meta"
[project]
name = "test-package-name"
version = "0.1.0"
license = "((MIT))"
stacktrace
~/Desktop/testing-can-delete λ pip install -e .
Obtaining file:///Users/tybug/Desktop/testing-can-delete
Installing build dependencies ... done
Checking if build backend supports build_editable ... done
Getting requirements to build editable ... error
error: subprocess-exited-with-error
× Getting requirements to build editable did not run successfully.
│ exit code: 1
╰─> [112 lines of output]
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:
"((MIT))"
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
Traceback (most recent call last):
File "/opt/homebrew/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 389, in <module>
main()
File "/opt/homebrew/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 373, in main
json_out["return_val"] = hook(**hook_input["kwargs"])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 157, in get_requires_for_build_editable
return hook(config_settings)
^^^^^^^^^^^^^^^^^^^^^
File "/private/var/folders/t1/415srbnx62b2h3f1kx00n66w0000gn/T/pip-build-env-raxmk0vi/overlay/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 "/private/var/folders/t1/415srbnx62b2h3f1kx00n66w0000gn/T/pip-build-env-raxmk0vi/overlay/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 "/private/var/folders/t1/415srbnx62b2h3f1kx00n66w0000gn/T/pip-build-env-raxmk0vi/overlay/lib/python3.12/site-packages/setuptools/build_meta.py", line 301, in _get_build_requires
self.run_setup()
File "/private/var/folders/t1/415srbnx62b2h3f1kx00n66w0000gn/T/pip-build-env-raxmk0vi/overlay/lib/python3.12/site-packages/setuptools/build_meta.py", line 317, in run_setup
exec(code, locals())
File "<string>", line 1, in <module>
File "/private/var/folders/t1/415srbnx62b2h3f1kx00n66w0000gn/T/pip-build-env-raxmk0vi/overlay/lib/python3.12/site-packages/setuptools/__init__.py", line 115, in setup
return distutils.core.setup(**attrs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/private/var/folders/t1/415srbnx62b2h3f1kx00n66w0000gn/T/pip-build-env-raxmk0vi/overlay/lib/python3.12/site-packages/setuptools/_distutils/core.py", line 160, in setup
dist.parse_config_files()
File "/private/var/folders/t1/415srbnx62b2h3f1kx00n66w0000gn/T/pip-build-env-raxmk0vi/overlay/lib/python3.12/site-packages/setuptools/dist.py", line 756, in parse_config_files
pyprojecttoml.apply_configuration(self, filename, ignore_option_errors)
File "/private/var/folders/t1/415srbnx62b2h3f1kx00n66w0000gn/T/pip-build-env-raxmk0vi/overlay/lib/python3.12/site-packages/setuptools/config/pyprojecttoml.py", line 72, in apply_configuration
config = read_configuration(filepath, True, ignore_option_errors, dist)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/private/var/folders/t1/415srbnx62b2h3f1kx00n66w0000gn/T/pip-build-env-raxmk0vi/overlay/lib/python3.12/site-packages/setuptools/config/pyprojecttoml.py", line 140, in read_configuration
validate(subset, filepath)
File "/private/var/folders/t1/415srbnx62b2h3f1kx00n66w0000gn/T/pip-build-env-raxmk0vi/overlay/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']
[end of output]
note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error
× Getting requirements to build editable did not run successfully.
│ exit code: 1
╰─> See above for output.
note: This error originates from a subprocess, and is likely not a problem with pip.
~/Desktop/testing-can-delete λ
I would likely be willing to submit a PR for this.