Skip to content

Commit 50c87bf

Browse files
committed
Update validate-pyproject to 0.23.0
1 parent bf2ced2 commit 50c87bf

File tree

6 files changed

+286
-135
lines changed

6 files changed

+286
-135
lines changed

newsfragments/4734.misc.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Updated ``pyproject.toml`` validation via ``validate-pyproject`` v0.23.0.

setuptools/config/_validate_pyproject/NOTICE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
The code contained in this directory was automatically generated using the
22
following command:
33

4-
python -m validate_pyproject.pre_compile --output-dir=setuptools/config/_validate_pyproject --enable-plugins setuptools distutils --very-verbose -t distutils=setuptools/config/distutils.schema.json -t setuptools=setuptools/config/setuptools.schema.json
4+
python -m validate_pyproject.pre_compile --output-dir=setuptools/config/_validate_pyproject --enable-plugins setuptools distutils --very-verbose -t setuptools=setuptools/config/setuptools.schema.json -t distutils=setuptools/config/distutils.schema.json
55

66
Please avoid changing it manually.
77

setuptools/config/_validate_pyproject/extra_validations.py

+31-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ class RedefiningStaticFieldAsDynamic(ValidationError):
2424
)
2525

2626

27+
class IncludedDependencyGroupMustExist(ValidationError):
28+
_DESC = """An included dependency group must exist and must not be cyclic.
29+
"""
30+
__doc__ = _DESC
31+
_URL = "https://peps.python.org/pep-0735/"
32+
33+
2734
def validate_project_dynamic(pyproject: T) -> T:
2835
project_table = pyproject.get("project", {})
2936
dynamic = project_table.get("dynamic", [])
@@ -49,4 +56,27 @@ def validate_project_dynamic(pyproject: T) -> T:
4956
return pyproject
5057

5158

52-
EXTRA_VALIDATIONS = (validate_project_dynamic,)
59+
def validate_include_depenency(pyproject: T) -> T:
60+
dependency_groups = pyproject.get("dependency-groups", {})
61+
for key, value in dependency_groups.items():
62+
for each in value:
63+
if (
64+
isinstance(each, dict)
65+
and (include_group := each.get("include-group"))
66+
and include_group not in dependency_groups
67+
):
68+
raise IncludedDependencyGroupMustExist(
69+
message=f"The included dependency group {include_group} doesn't exist",
70+
value=each,
71+
name=f"data.dependency_groups.{key}",
72+
definition={
73+
"description": cleandoc(IncludedDependencyGroupMustExist._DESC),
74+
"see": IncludedDependencyGroupMustExist._URL,
75+
},
76+
rule="PEP 735",
77+
)
78+
# TODO: check for `include-group` cycles (can be conditional to graphlib)
79+
return pyproject
80+
81+
82+
EXTRA_VALIDATIONS = (validate_project_dynamic, validate_include_depenency)

setuptools/config/_validate_pyproject/fastjsonschema_validations.py

+222-129
Large diffs are not rendered by default.

setuptools/config/_validate_pyproject/formats.py

+30-3
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,15 @@ class _TroveClassifier:
164164
"""
165165

166166
downloaded: typing.Union[None, "Literal[False]", typing.Set[str]]
167+
"""
168+
None => not cached yet
169+
False => unavailable
170+
set => cached values
171+
"""
167172

168173
def __init__(self) -> None:
169174
self.downloaded = None
170175
self._skip_download = False
171-
# None => not cached yet
172-
# False => cache not available
173176
self.__name__ = "trove_classifier" # Emulate a public function
174177

175178
def _disable_download(self) -> None:
@@ -351,7 +354,7 @@ def python_entrypoint_reference(value: str) -> bool:
351354
obj = rest
352355

353356
module_parts = module.split(".")
354-
identifiers = _chain(module_parts, obj.split(".")) if rest else module_parts
357+
identifiers = _chain(module_parts, obj.split(".")) if rest else iter(module_parts)
355358
return all(python_identifier(i.strip()) for i in identifiers)
356359

357360

@@ -373,3 +376,27 @@ def uint(value: builtins.int) -> bool:
373376
def int(value: builtins.int) -> bool:
374377
r"""Signed 64-bit integer (:math:`-2^{63} \leq x < 2^{63}`)"""
375378
return -(2**63) <= value < 2**63
379+
380+
381+
try:
382+
from packaging import licenses as _licenses
383+
384+
def SPDX(value: str) -> bool:
385+
"""See :ref:`PyPA's License-Expression specification
386+
<pypa:core-metadata-license-expression>` (added in :pep:`639`).
387+
"""
388+
try:
389+
_licenses.canonicalize_license_expression(value)
390+
return True
391+
except _licenses.InvalidLicenseExpression:
392+
return False
393+
394+
except ImportError: # pragma: no cover
395+
_logger.warning(
396+
"Could not find an up-to-date installation of `packaging`. "
397+
"License expressions might not be validated. "
398+
"To enforce validation, please install `packaging>=24.2`."
399+
)
400+
401+
def SPDX(value: str) -> bool:
402+
return True

tox.ini

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ commands =
8383
[testenv:generate-validation-code]
8484
skip_install = True
8585
deps =
86-
validate-pyproject[all]==0.19
86+
validate-pyproject[all]==0.23
8787
commands =
8888
python -m tools.generate_validation_code
8989

0 commit comments

Comments
 (0)