Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: bump validate-pyproject to 0.9.0 #265

Merged
merged 2 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 15 additions & 19 deletions src/pdm/backend/_vendor/pyproject_metadata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
import pdm.backend._vendor.packaging.utils
import pdm.backend._vendor.packaging.version

__version__ = "0.9.0b7"
__version__ = "0.9.0"

__all__ = [
"ConfigurationError",
Expand Down Expand Up @@ -127,7 +127,6 @@ class _SmartMessageSetter:
reduce boilerplate.

If a value is None, do nothing.
If a value contains a newline, indent it (may produce a warning in the future).
"""

message: email.message.Message
Expand Down Expand Up @@ -253,23 +252,10 @@ class StandardMetadata:
"""
If True, all errors will be collected and raised in an ExceptionGroup.
"""
_locked_metadata: bool = False
"""
Internal flag to prevent setting non-dynamic fields after initialization.
"""

def __post_init__(self) -> None:
self.validate()

def __setattr__(self, name: str, value: Any) -> None:
if self._locked_metadata:
metadata_name = name.replace("_", "-")
locked_fields = constants.KNOWN_METADATA_FIELDS - set(self.dynamic)
if metadata_name in locked_fields:
msg = f"Field {name!r} is not dynamic"
raise AttributeError(msg)
super().__setattr__(name, value)

@property
def auto_metadata_version(self) -> str:
"""
Expand Down Expand Up @@ -443,7 +429,6 @@ def from_pyproject( # noqa: C901
metadata_version=metadata_version,
all_errors=all_errors,
)
self._locked_metadata = True

pyproject.finalize("Failed to parse pyproject.toml")
assert self is not None
Expand Down Expand Up @@ -482,6 +467,7 @@ def validate(self, *, warn: bool = True) -> None: # noqa: C901
- License classifiers deprecated for metadata_version >= 2.4 (warning)
- ``license`` is an SPDX license expression if metadata_version >= 2.4
- ``license_files`` is supported only for metadata_version >= 2.4
- ``project_url`` can't contain keys over 32 characters
"""
errors = ErrorCollector(collect_errors=self.all_errors)

Expand Down Expand Up @@ -545,6 +531,11 @@ def validate(self, *, warn: bool = True) -> None: # noqa: C901
msg = "{key} is supported only when emitting metadata version >= 2.4"
errors.config_error(msg, key="project.license-files")

for name in self.urls:
if len(name) > 32:
msg = "{key} names cannot be more than 32 characters long"
errors.config_error(msg, key="project.urls", got=name)

errors.finalize("Metadata validation failed")

def _write_metadata( # noqa: C901
Expand All @@ -566,8 +557,7 @@ def _write_metadata( # noqa: C901
if self.description:
smart_message["Summary"] = self.description
smart_message["Keywords"] = ",".join(self.keywords) or None
if "homepage" in self.urls:
smart_message["Home-page"] = self.urls["homepage"]
# skip 'Home-page'
# skip 'Download-URL'
smart_message["Author"] = _name_list(self.authors)
smart_message["Author-Email"] = _email_list(self.authors)
Expand All @@ -582,14 +572,20 @@ def _write_metadata( # noqa: C901
if self.license_files is not None:
for license_file in sorted(set(self.license_files)):
smart_message["License-File"] = os.fspath(license_file.as_posix())
elif (
self.auto_metadata_version not in constants.PRE_SPDX_METADATA_VERSIONS
and isinstance(self.license, License)
and self.license.file
):
smart_message["License-File"] = os.fspath(self.license.file.as_posix())

for classifier in self.classifiers:
smart_message["Classifier"] = classifier
# skip 'Provides-Dist'
# skip 'Obsoletes-Dist'
# skip 'Requires-External'
for name, url in self.urls.items():
smart_message["Project-URL"] = f"{name.capitalize()}, {url}"
smart_message["Project-URL"] = f"{name}, {url}"
if self.requires_python:
smart_message["Requires-Python"] = str(self.requires_python)
for dep in self.dependencies:
Expand Down
6 changes: 3 additions & 3 deletions src/pdm/backend/_vendor/pyproject_metadata/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def __dir__() -> list[str]:
"version": frozenset(["Version"]),
}

KNOWN_TOPLEVEL_FIELDS = {"build-system", "project", "tool"}
KNOWN_TOPLEVEL_FIELDS = {"build-system", "project", "tool", "dependency-groups"}
KNOWN_BUILD_SYSTEM_FIELDS = {"backend-path", "build-backend", "requires"}
KNOWN_PROJECT_FIELDS = set(PROJECT_TO_METADATA)

Expand All @@ -58,9 +58,9 @@ def __dir__() -> list[str]:
"classifier",
"description",
"description-content-type",
"download-url", # Not specified via pyproject standards
"download-url", # Not specified via pyproject standards, deprecated by PEP 753
"dynamic", # Can't be in dynamic
"home-page", # Not specified via pyproject standards
"home-page", # Not specified via pyproject standards, deprecated by PEP 753
"keywords",
"license",
"license-expression",
Expand Down
34 changes: 34 additions & 0 deletions src/pdm/backend/_vendor/pyproject_metadata/project_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from __future__ import annotations

import sys
import typing
from typing import Any, Dict, List, Union

if sys.version_info < (3, 11):
Expand All @@ -28,6 +29,7 @@
"BuildSystemTable",
"ContactTable",
"Dynamic",
"IncludeGroupTable",
"LicenseTable",
"ProjectTable",
"PyProjectTable",
Expand Down Expand Up @@ -107,12 +109,44 @@ class LicenseTable(TypedDict, total=False):
total=False,
)

# total=False here because this could be
# extended in the future
IncludeGroupTable = TypedDict(
"IncludeGroupTable",
{"include-group": str},
total=False,
)

PyProjectTable = TypedDict(
"PyProjectTable",
{
"build-system": BuildSystemTable,
"project": ProjectTable,
"tool": Dict[str, Any],
"dependency-groups": Dict[str, List[Union[str, IncludeGroupTable]]],
},
total=False,
)

# Tests for type checking
if typing.TYPE_CHECKING:
PyProjectTable(
{
"build-system": BuildSystemTable(
{"build-backend": "one", "requires": ["two"]}
),
"project": ProjectTable(
{
"name": "one",
"version": "0.1.0",
}
),
"tool": {"thing": object()},
"dependency-groups": {
"one": [
"one",
IncludeGroupTable({"include-group": "two"}),
]
},
}
)
2 changes: 1 addition & 1 deletion src/pdm/backend/_vendor/vendor.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
packaging==24.1
tomli==2.0.1
tomli_w==1.0.0
pyproject-metadata==0.9.0b7
pyproject-metadata==0.9.0
editables==0.5