Skip to content

Commit

Permalink
feat: update pyproject-metadata to support latest version of PEP 639 (#…
Browse files Browse the repository at this point in the history
…259)

* fix: update pyproject-metadata to 0.9.0

Signed-off-by: Frost Ming <me@frostming.com>

* feat: update pyproject-metadata to support latest version of PEP 639

Signed-off-by: Frost Ming <me@frostming.com>

* fix tests

Signed-off-by: Frost Ming <me@frostming.com>
  • Loading branch information
frostming authored Sep 20, 2024
1 parent 708aa3f commit 6c48d72
Show file tree
Hide file tree
Showing 52 changed files with 941 additions and 744 deletions.
3 changes: 1 addition & 2 deletions docs/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ pdm-build-mypyc
version = "0.1.0"
description = "A pdm build hook to compile Python code with mypyc"
authors = [{name = "...", email = "..."}]
license = {text = "MIT"}
license = "MIT"
readme = "README.md"

[project.entry-points."pdm.build.hook"]
Expand All @@ -156,7 +156,6 @@ pdm-build-mypyc
mypyc_build(context.build_dir)
```


The plugin must be distributed with an entry point under `pdm.build.hook` group. The entry point value can be any of the following:

- A module containing hook functions
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ authors = [{name = "John Doe", email="me@johndoe.org"}]
dependencies = ["requests"]
requires-python = ">=3.8"
readme = "README.md"
license = {text = "MIT"}
license = "MIT"
```

Then run the build command to build the project as wheel and sdist:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description = "The build backend used by PDM that supports latest packaging stan
authors = [
{ name = "Frost Ming", email = "me@frostming.com" }
]
license = {text = "MIT"}
license = "MIT"
requires-python = ">=3.8"
readme = "README.md"
keywords = ["packaging", "PEP 517", "build"]
Expand Down
94 changes: 52 additions & 42 deletions scripts/patches/pyproject_metadata.patch
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
diff --git a/src/pdm/backend/_vendor/pyproject_metadata/__init__.py b/src/pdm/backend/_vendor/pyproject_metadata/__init__.py
index df826f8..7f69f3a 100644
index 52289dc..7ef9fc9 100644
--- a/src/pdm/backend/_vendor/pyproject_metadata/__init__.py
+++ b/src/pdm/backend/_vendor/pyproject_metadata/__init__.py
@@ -24,11 +24,11 @@ if typing.TYPE_CHECKING:
@@ -20,18 +20,18 @@ if typing.TYPE_CHECKING:
from collections.abc import Generator, Iterable, Mapping
from typing import Any

- from packaging.requirements import Requirement
+ from pdm.backend._vendor.packaging.requirements import Requirement

if sys.version_info < (3, 11):
from typing_extensions import Self
else:
from typing import Self

Expand All @@ -18,22 +26,46 @@ index df826f8..7f69f3a 100644
+import pdm.backend._vendor.packaging.version as pkg_version


__version__ = '0.8.0'
@@ -175,11 +175,11 @@ class Readme(typing.NamedTuple):
__version__ = '0.9.0b3'
@@ -351,8 +351,8 @@ class ProjectFetcher(DataFetcher):
requirements: list[Requirement] = []
for req in requirement_strings:
try:
- requirements.append(packaging.requirements.Requirement(req))
- except packaging.requirements.InvalidRequirement as e:
+ requirements.append(pkg_requirements.Requirement(req))
+ except pkg_requirements.InvalidRequirement as e:
msg = (
'Field "project.dependencies" contains an invalid PEP 508 '
f'requirement string "{req}" ("{e}")'
@@ -393,9 +393,9 @@ class ProjectFetcher(DataFetcher):
raise ConfigurationError(msg)
try:
requirements_dict[extra].append(
- packaging.requirements.Requirement(req)
+ pkg_requirements.Requirement(req)
)
- except packaging.requirements.InvalidRequirement as e:
+ except pkg_requirements.InvalidRequirement as e:
msg = (
f'Field "project.optional-dependencies.{extra}" contains '
f'an invalid PEP 508 requirement string "{req}" ("{e}")'
@@ -453,12 +453,12 @@ class Readme(typing.NamedTuple):
@dataclasses.dataclass
class StandardMetadata:
name: str
- version: packaging.version.Version | None = None
+ version: pkg_version.Version | None = None
description: str | None = None
license: License | None = None
license: License | str | None = None
license_files: list[pathlib.Path] | None = None
readme: Readme | None = None
- requires_python: packaging.specifiers.SpecifierSet | None = None
+ requires_python: pkg_specifiers.SpecifierSet | None = None
dependencies: list[Requirement] = dataclasses.field(default_factory=list)
optional_dependencies: dict[str, list[Requirement]] = dataclasses.field(default_factory=dict)
entrypoints: dict[str, dict[str, str]] = dataclasses.field(default_factory=dict)
@@ -202,7 +202,7 @@ class StandardMetadata:
optional_dependencies: dict[str, list[Requirement]] = dataclasses.field(
default_factory=dict
@@ -547,7 +547,7 @@ class StandardMetadata:

@property
def canonical_name(self) -> str:
Expand All @@ -42,7 +74,7 @@ index df826f8..7f69f3a 100644

@classmethod
def from_pyproject(
@@ -235,7 +235,7 @@ class StandardMetadata:
@@ -590,7 +590,7 @@ class StandardMetadata:

version_string = fetcher.get_str('project.version')
requires_python_string = fetcher.get_str('project.requires-python')
Expand All @@ -51,16 +83,16 @@ index df826f8..7f69f3a 100644

if version is None and 'version' not in dynamic:
msg = 'Field "project.version" missing and "version" not specified in "project.dynamic"'
@@ -256,7 +256,7 @@ class StandardMetadata:
description,
cls._get_license(fetcher, project_dir),
cls._get_readme(fetcher, project_dir),
- packaging.specifiers.SpecifierSet(requires_python_string) if requires_python_string else None,
+ pkg_specifiers.SpecifierSet(requires_python_string) if requires_python_string else None,
cls._get_dependencies(fetcher),
cls._get_optional_dependencies(fetcher),
cls._get_entrypoints(fetcher),
@@ -358,15 +358,15 @@ class StandardMetadata:
@@ -608,7 +608,7 @@ class StandardMetadata:
fetcher.get_license(project_dir),
fetcher.get_license_files(project_dir),
fetcher.get_readme(project_dir),
- packaging.specifiers.SpecifierSet(requires_python_string)
+ pkg_specifiers.SpecifierSet(requires_python_string)
if requires_python_string
else None,
fetcher.get_dependencies(),
@@ -720,15 +720,15 @@ class StandardMetadata:
requirement = copy.copy(requirement)
if requirement.marker:
if 'or' in requirement.marker._markers:
Expand All @@ -78,26 +110,4 @@ index df826f8..7f69f3a 100644
+ requirement.marker = pkg_markers.Marker(f'extra == "{extra}"')
return requirement

@staticmethod
@@ -462,8 +462,8 @@ class StandardMetadata:
requirements: list[Requirement] = []
for req in requirement_strings:
try:
- requirements.append(packaging.requirements.Requirement(req))
- except packaging.requirements.InvalidRequirement as e:
+ requirements.append(pkg_requirements.Requirement(req))
+ except pkg_requirements.InvalidRequirement as e:
msg = (
'Field "project.dependencies" contains an invalid PEP 508 '
f'requirement string "{req}" ("{e}")'
@@ -502,8 +502,8 @@ class StandardMetadata:
)
raise ConfigurationError(msg)
try:
- requirements_dict[extra].append(packaging.requirements.Requirement(req))
- except packaging.requirements.InvalidRequirement as e:
+ requirements_dict[extra].append(pkg_requirements.Requirement(req))
+ except pkg_requirements.InvalidRequirement as e:
msg = (
f'Field "project.optional-dependencies.{extra}" contains '
f'an invalid PEP 508 requirement string "{req}" ("{e}")'

2 changes: 1 addition & 1 deletion src/pdm/backend/_vendor/packaging/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
__summary__ = "Core utilities for Python packages"
__uri__ = "https://github.com/pypa/packaging"

__version__ = "24.0"
__version__ = "24.1"

__author__ = "Donald Stufft and individual contributors"
__email__ = "donald@stufft.io"
Expand Down
8 changes: 5 additions & 3 deletions src/pdm/backend/_vendor/packaging/_elffile.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
ELF header: https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html
"""

from __future__ import annotations

import enum
import os
import struct
from typing import IO, Optional, Tuple
from typing import IO


class ELFInvalid(ValueError):
Expand Down Expand Up @@ -87,11 +89,11 @@ def __init__(self, f: IO[bytes]) -> None:
except struct.error as e:
raise ELFInvalid("unable to parse machine and section information") from e

def _read(self, fmt: str) -> Tuple[int, ...]:
def _read(self, fmt: str) -> tuple[int, ...]:
return struct.unpack(fmt, self._f.read(struct.calcsize(fmt)))

@property
def interpreter(self) -> Optional[str]:
def interpreter(self) -> str | None:
"""
The path recorded in the ``PT_INTERP`` section header.
"""
Expand Down
22 changes: 12 additions & 10 deletions src/pdm/backend/_vendor/packaging/_manylinux.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from __future__ import annotations

import collections
import contextlib
import functools
import os
import re
import sys
import warnings
from typing import Dict, Generator, Iterator, NamedTuple, Optional, Sequence, Tuple
from typing import Generator, Iterator, NamedTuple, Sequence

from ._elffile import EIClass, EIData, ELFFile, EMachine

Expand All @@ -17,7 +19,7 @@
# `os.PathLike` not a generic type until Python 3.9, so sticking with `str`
# as the type for `path` until then.
@contextlib.contextmanager
def _parse_elf(path: str) -> Generator[Optional[ELFFile], None, None]:
def _parse_elf(path: str) -> Generator[ELFFile | None, None, None]:
try:
with open(path, "rb") as f:
yield ELFFile(f)
Expand Down Expand Up @@ -72,15 +74,15 @@ def _have_compatible_abi(executable: str, archs: Sequence[str]) -> bool:
# For now, guess what the highest minor version might be, assume it will
# be 50 for testing. Once this actually happens, update the dictionary
# with the actual value.
_LAST_GLIBC_MINOR: Dict[int, int] = collections.defaultdict(lambda: 50)
_LAST_GLIBC_MINOR: dict[int, int] = collections.defaultdict(lambda: 50)


class _GLibCVersion(NamedTuple):
major: int
minor: int


def _glibc_version_string_confstr() -> Optional[str]:
def _glibc_version_string_confstr() -> str | None:
"""
Primary implementation of glibc_version_string using os.confstr.
"""
Expand All @@ -90,7 +92,7 @@ def _glibc_version_string_confstr() -> Optional[str]:
# https://github.com/python/cpython/blob/fcf1d003bf4f0100c/Lib/platform.py#L175-L183
try:
# Should be a string like "glibc 2.17".
version_string: Optional[str] = os.confstr("CS_GNU_LIBC_VERSION")
version_string: str | None = os.confstr("CS_GNU_LIBC_VERSION")
assert version_string is not None
_, version = version_string.rsplit()
except (AssertionError, AttributeError, OSError, ValueError):
Expand All @@ -99,7 +101,7 @@ def _glibc_version_string_confstr() -> Optional[str]:
return version


def _glibc_version_string_ctypes() -> Optional[str]:
def _glibc_version_string_ctypes() -> str | None:
"""
Fallback implementation of glibc_version_string using ctypes.
"""
Expand Down Expand Up @@ -143,12 +145,12 @@ def _glibc_version_string_ctypes() -> Optional[str]:
return version_str


def _glibc_version_string() -> Optional[str]:
def _glibc_version_string() -> str | None:
"""Returns glibc version string, or None if not using glibc."""
return _glibc_version_string_confstr() or _glibc_version_string_ctypes()


def _parse_glibc_version(version_str: str) -> Tuple[int, int]:
def _parse_glibc_version(version_str: str) -> tuple[int, int]:
"""Parse glibc version.
We use a regexp instead of str.split because we want to discard any
Expand All @@ -167,8 +169,8 @@ def _parse_glibc_version(version_str: str) -> Tuple[int, int]:
return int(m.group("major")), int(m.group("minor"))


@functools.lru_cache()
def _get_glibc_version() -> Tuple[int, int]:
@functools.lru_cache
def _get_glibc_version() -> tuple[int, int]:
version_str = _glibc_version_string()
if version_str is None:
return (-1, -1)
Expand Down
10 changes: 6 additions & 4 deletions src/pdm/backend/_vendor/packaging/_musllinux.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
linked against musl, and what musl version is used.
"""

from __future__ import annotations

import functools
import re
import subprocess
import sys
from typing import Iterator, NamedTuple, Optional, Sequence
from typing import Iterator, NamedTuple, Sequence

from ._elffile import ELFFile

Expand All @@ -18,7 +20,7 @@ class _MuslVersion(NamedTuple):
minor: int


def _parse_musl_version(output: str) -> Optional[_MuslVersion]:
def _parse_musl_version(output: str) -> _MuslVersion | None:
lines = [n for n in (n.strip() for n in output.splitlines()) if n]
if len(lines) < 2 or lines[0][:4] != "musl":
return None
Expand All @@ -28,8 +30,8 @@ def _parse_musl_version(output: str) -> Optional[_MuslVersion]:
return _MuslVersion(major=int(m.group(1)), minor=int(m.group(2)))


@functools.lru_cache()
def _get_musl_version(executable: str) -> Optional[_MuslVersion]:
@functools.lru_cache
def _get_musl_version(executable: str) -> _MuslVersion | None:
"""Detect currently-running musl runtime version.
This is done by checking the specified executable's dynamic linking
Expand Down
Loading

0 comments on commit 6c48d72

Please sign in to comment.