Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-pdm-pep517 for openSUSE:Factory checked in at 2022-10-06 07:42:11 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pdm-pep517 (Old) and /work/SRC/openSUSE:Factory/.python-pdm-pep517.new.2275 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pdm-pep517" Thu Oct 6 07:42:11 2022 rev:5 rq:1008164 version:1.0.4 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pdm-pep517/python-pdm-pep517.changes 2022-08-03 21:17:19.735541420 +0200 +++ /work/SRC/openSUSE:Factory/.python-pdm-pep517.new.2275/python-pdm-pep517.changes 2022-10-06 07:42:21.268707392 +0200 @@ -1,0 +2,9 @@ +Tue Oct 4 22:57:46 UTC 2022 - Yogalakshmi Arunachalam <yarunacha...@suse.com> + +- Update to 1.0.4 + Bug Fixes + Fix a bug of editable install not reading run-setuptools = false config. #107 + Put the long description in the body as specified by Metadata Version 2.1 #109 + Overwrite the existing files in the custom build stage of WheelBuilder. #114 + +------------------------------------------------------------------- Old: ---- pdm-pep517-1.0.3.tar.gz New: ---- pdm-pep517-1.0.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pdm-pep517.spec ++++++ --- /var/tmp/diff_new_pack.OhhB35/_old 2022-10-06 07:42:21.972708960 +0200 +++ /var/tmp/diff_new_pack.OhhB35/_new 2022-10-06 07:42:21.976708969 +0200 @@ -26,7 +26,7 @@ %endif Name: python-pdm-pep517%{psuffix} -Version: 1.0.3 +Version: 1.0.4 Release: 0 Summary: Python Development Master License: MIT ++++++ pdm-pep517-1.0.3.tar.gz -> pdm-pep517-1.0.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm-pep517-1.0.3/PKG-INFO new/pdm-pep517-1.0.4/PKG-INFO --- old/pdm-pep517-1.0.3/PKG-INFO 2022-07-27 11:27:55.516363600 +0200 +++ new/pdm-pep517-1.0.4/PKG-INFO 2022-08-06 17:29:42.799394800 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pdm-pep517 -Version: 1.0.3 +Version: 1.0.4 Summary: A PEP 517 backend for PDM that supports PEP 621 metadata License: MIT Keywords: packaging,PEP 517,build diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm-pep517-1.0.3/pdm/pep517/__init__.py new/pdm-pep517-1.0.4/pdm/pep517/__init__.py --- old/pdm-pep517-1.0.3/pdm/pep517/__init__.py 2022-07-27 11:27:54.648356700 +0200 +++ new/pdm-pep517-1.0.4/pdm/pep517/__init__.py 2022-08-06 17:29:41.923385100 +0200 @@ -1 +1 @@ -__version__ = "1.0.3" +__version__ = "1.0.4" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm-pep517-1.0.3/pdm/pep517/api.py new/pdm-pep517-1.0.4/pdm/pep517/api.py --- old/pdm-pep517-1.0.3/pdm/pep517/api.py 2022-07-27 11:27:54.656356800 +0200 +++ new/pdm-pep517-1.0.4/pdm/pep517/api.py 2022-08-06 17:29:41.927385300 +0200 @@ -1,8 +1,10 @@ """ PEP-517 compliant buildsystem API """ +from __future__ import annotations + from pathlib import Path -from typing import Any, List, Mapping, Optional +from typing import Any, Mapping from pdm.pep517.editable import EditableBuilder from pdm.pep517.sdist import SdistBuilder @@ -10,8 +12,8 @@ def get_requires_for_build_wheel( - config_settings: Optional[Mapping[str, Any]] = None -) -> List[str]: + config_settings: Mapping[str, Any] | None = None +) -> list[str]: """ Returns an additional list of requirements for building, as PEP508 strings, above and beyond those specified in the pyproject.toml file. @@ -26,8 +28,8 @@ def get_requires_for_build_sdist( - config_settings: Optional[Mapping[str, Any]] = None -) -> List[str]: + config_settings: Mapping[str, Any] | None = None +) -> list[str]: """There isn't any requirement for building a sdist at this point.""" return [] @@ -55,7 +57,7 @@ def prepare_metadata_for_build_wheel( - metadata_directory: str, config_settings: Optional[Mapping[str, Any]] = None + metadata_directory: str, config_settings: Mapping[str, Any] | None = None ) -> str: """Prepare the metadata, places it in metadata_directory""" with WheelBuilder(Path.cwd(), config_settings) as builder: @@ -64,8 +66,8 @@ def build_wheel( wheel_directory: str, - config_settings: Optional[Mapping[str, Any]] = None, - metadata_directory: Optional[str] = None, + config_settings: Mapping[str, Any] | None = None, + metadata_directory: str | None = None, ) -> str: """Builds a wheel, places it in wheel_directory""" with WheelBuilder(Path.cwd(), config_settings) as builder: @@ -73,7 +75,7 @@ def build_sdist( - sdist_directory: str, config_settings: Optional[Mapping[str, Any]] = None + sdist_directory: str, config_settings: Mapping[str, Any] | None = None ) -> str: """Builds an sdist, places it in sdist_directory""" with SdistBuilder(Path.cwd(), config_settings) as builder: @@ -84,7 +86,7 @@ def prepare_metadata_for_build_editable( - metadata_directory: str, config_settings: Optional[Mapping[str, Any]] = None + metadata_directory: str, config_settings: Mapping[str, Any] | None = None ) -> str: """Prepare the metadata, places it in metadata_directory""" with EditableBuilder(Path.cwd(), config_settings) as builder: @@ -94,8 +96,8 @@ def build_editable( wheel_directory: str, - config_settings: Optional[Mapping[str, Any]] = None, - metadata_directory: Optional[str] = None, + config_settings: Mapping[str, Any] | None = None, + metadata_directory: str | None = None, ) -> str: with EditableBuilder(Path.cwd(), config_settings) as builder: return Path(builder.build(wheel_directory)).name diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm-pep517-1.0.3/pdm/pep517/base.py new/pdm-pep517-1.0.4/pdm/pep517/base.py --- old/pdm-pep517-1.0.3/pdm/pep517/base.py 2022-07-27 11:27:54.656356800 +0200 +++ new/pdm-pep517-1.0.4/pdm/pep517/base.py 2022-08-06 17:29:41.927385300 +0200 @@ -1,20 +1,11 @@ +from __future__ import annotations + import atexit import glob import os import warnings from pathlib import Path -from typing import ( - Any, - Dict, - Iterator, - List, - Mapping, - Optional, - Tuple, - TypeVar, - Union, - cast, -) +from typing import Any, Iterator, Mapping, TypeVar, cast from pdm.pep517._vendor import tomli from pdm.pep517.exceptions import MetadataError, PDMWarning, ProjectError @@ -69,8 +60,8 @@ def _merge_globs( - include_globs: Dict[str, str], excludes_globs: Dict[str, str] -) -> Tuple[List[str], List[str]]: + include_globs: dict[str, str], excludes_globs: dict[str, str] +) -> tuple[list[str], list[str]]: """Correctly merge includes and excludes. When a pattern exists in both includes and excludes, determine the priority in the following ways: @@ -80,7 +71,7 @@ 3. If both have the same part number and concrete level, *excludes* wins """ - def path_weight(pathname: str) -> Tuple[int, int]: + def path_weight(pathname: str) -> tuple[int, int]: """Return a two-element tuple [part_num, concrete_level]""" pathname_parts = Path(pathname).parts wildcard_count = 0 @@ -104,7 +95,7 @@ return includes, list(excludes_globs) -def _find_top_packages(root: str) -> List[str]: +def _find_top_packages(root: str) -> list[str]: result = [] for path in os.listdir(root): path = os.path.join(root, path) @@ -113,7 +104,7 @@ return result -def _format_list(data: List[str], indent: int = 4) -> str: +def _format_list(data: list[str], indent: int = 4) -> str: result = ["["] for row in data: result.append(" " * indent + repr(row) + ",") @@ -121,7 +112,7 @@ return "\n".join(result) -def _format_dict_list(data: Dict[str, List[str]], indent: int = 4) -> str: +def _format_dict_list(data: dict[str, list[str]], indent: int = 4) -> str: result = ["{"] for key, value in data.items(): result.append( @@ -138,15 +129,15 @@ def __init__( self, - location: Union[str, Path], - config_settings: Optional[Mapping[str, Any]] = None, + location: str | Path, + config_settings: Mapping[str, Any] | None = None, ) -> None: - self._old_cwd: Optional[str] = None + self._old_cwd: str | None = None self.location = Path(location).absolute() self.config_settings = config_settings - self._meta: Optional[Metadata] = None + self._meta: Metadata | None = None - def _read_pyproject_toml(self) -> Dict[str, Any]: + def _read_pyproject_toml(self) -> dict[str, Any]: pyproject_toml = self.location / "pyproject.toml" if not pyproject_toml.exists(): raise ProjectError("No pyproject.toml found") @@ -184,7 +175,7 @@ def _get_include_and_exclude_paths( self, for_sdist: bool = False - ) -> Tuple[List[str], List[str]]: + ) -> tuple[list[str], list[str]]: includes = set() excludes = set(self.DEFAULT_EXCLUDES) @@ -221,7 +212,7 @@ include_paths, exclude_paths = _merge_globs(include_globs, excludes_globs) return sorted(include_paths), sorted(exclude_paths) - def _is_excluded(self, path: str, exclude_paths: List[str]) -> bool: + def _is_excluded(self, path: str, exclude_paths: list[str]) -> bool: return any( is_same_or_descendant_path(path, exclude_path) for exclude_path in exclude_paths @@ -259,7 +250,7 @@ if os.path.isfile("pyproject.toml"): yield "pyproject.toml" - def find_files_to_add(self, for_sdist: bool = False) -> List[Path]: + def find_files_to_add(self, for_sdist: bool = False) -> list[Path]: """Traverse the project path and return a list of file names that should be included in a sdist distribution. If for_sdist is True, will include files like LICENSE, README and pyproject @@ -267,7 +258,7 @@ """ return sorted({Path(p) for p in self._find_files_iter(for_sdist)}) - def find_license_files(self) -> List[str]: + def find_license_files(self) -> list[str]: """Return a list of license files from the PEP 639 metadata.""" license_files = self.meta.license_files if "paths" in license_files: @@ -325,7 +316,7 @@ if package_paths["packages"]: extra.append( " 'packages': {},\n".format( - _format_list(cast(List[str], package_paths["packages"]), 8) + _format_list(cast("list[str]", package_paths["packages"]), 8) ) ) if package_paths["package_dir"]: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm-pep517-1.0.3/pdm/pep517/editable.py new/pdm-pep517-1.0.4/pdm/pep517/editable.py --- old/pdm-pep517-1.0.3/pdm/pep517/editable.py 2022-07-27 11:27:54.656356800 +0200 +++ new/pdm-pep517-1.0.4/pdm/pep517/editable.py 2022-08-06 17:29:41.927385300 +0200 @@ -1,13 +1,12 @@ -import hashlib +from __future__ import annotations + import os import subprocess import sys import tokenize import warnings -import zipfile -from base64 import urlsafe_b64encode from pathlib import Path -from typing import Any, Dict, Iterable, List, Mapping, Optional, TextIO, Tuple, Union +from typing import Any, Iterable, Mapping, TextIO from pdm.pep517.exceptions import BuildError, PDMWarning from pdm.pep517.utils import is_relative_path, show_warning, to_filename @@ -20,8 +19,8 @@ def __init__(self, project_name: str, project_dir: str) -> None: self.project_name = project_name self.project_dir = Path(project_dir) - self.redirections: Dict[str, str] = {} - self.path_entries: List[Path] = [] + self.redirections: dict[str, str] = {} + self.path_entries: list[Path] = [] def make_absolute(self, path: str) -> Path: return (self.project_dir / path).resolve() @@ -40,7 +39,7 @@ def add_to_path(self, dirname: str) -> None: self.path_entries.append(self.make_absolute(dirname)) - def files(self) -> Iterable[Tuple[str, str]]: + def files(self) -> Iterable[tuple[str, str]]: yield f"{self.project_name}.pth", self.pth_file() if self.redirections: yield f"__editables_{self.project_name}.py", self.bootstrap_file() @@ -50,7 +49,7 @@ yield "editables" def pth_file(self) -> str: - lines: List[str] = [] + lines: list[str] = [] if self.redirections: lines.append(f"import __editables_{self.project_name}") for entry in self.path_entries: @@ -69,7 +68,7 @@ class EditableBuilder(WheelBuilder): def __init__( - self, location: Union[str, Path], config_settings: Optional[Mapping[str, Any]] + self, location: str | Path, config_settings: Mapping[str, Any] | None ) -> None: super().__init__(location, config_settings=config_settings) assert self.meta.project_name, "Project name is not specified" @@ -77,7 +76,7 @@ to_filename(self.meta.project_name), self.location.as_posix() ) - def _build(self, wheel: zipfile.ZipFile) -> None: + def _build(self) -> None: if self.meta.config.setup_script: if self.meta.config.run_setuptools: setup_py = self.ensure_setup_py() @@ -95,7 +94,7 @@ build_dir = self.location / self.meta.config.package_dir with tokenize.open(self.meta.config.setup_script) as f: code = compile(f.read(), self.meta.config.setup_script, "exec") - global_dict: Dict[str, Any] = {} + global_dict: dict[str, Any] = {} exec(code, global_dict) if "build" not in global_dict: show_warning( @@ -107,7 +106,8 @@ self._prepare_editable() for name, content in self.editables.files(): - self._add_file_content(wheel, name, content) + with self._open_for_write(name) as fp: + fp.write(content) def _prepare_editable(self) -> None: package_paths = self.meta.convert_package_paths() @@ -122,7 +122,7 @@ if "." in module: continue - patterns: Tuple[str, ...] = (f"{module}.py",) + patterns: tuple[str, ...] = (f"{module}.py",) if os.name == "nt": patterns += (f"{module}.*.pyd",) else: @@ -144,7 +144,7 @@ ) self.editables.add_to_path(package_dir) - def find_files_to_add(self, for_sdist: bool = False) -> List[Path]: + def find_files_to_add(self, for_sdist: bool = False) -> list[Path]: package_paths = self.meta.convert_package_paths() package_dir = self.meta.config.package_dir redirections = [ @@ -157,22 +157,6 @@ and not any(is_relative_path(p, package) for package in redirections) ] - def _add_file_content( - self, wheel: zipfile.ZipFile, rel_path: str, content: str - ) -> None: - print(f" - Adding {rel_path}") - zinfo = zipfile.ZipInfo(rel_path) - - hashsum = hashlib.sha256() - buf = content.encode("utf-8") - hashsum.update(buf) - - wheel.writestr(zinfo, buf, compress_type=zipfile.ZIP_DEFLATED) - size = len(buf) - hash_digest = urlsafe_b64encode(hashsum.digest()).decode("ascii").rstrip("=") - - self._records.append((rel_path, hash_digest, str(size))) - def _write_metadata_file(self, fp: TextIO) -> None: self.meta.data.setdefault("dependencies", []).extend( self.editables.dependencies() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm-pep517-1.0.3/pdm/pep517/exceptions.py new/pdm-pep517-1.0.4/pdm/pep517/exceptions.py --- old/pdm-pep517-1.0.3/pdm/pep517/exceptions.py 2022-07-27 11:27:54.656356800 +0200 +++ new/pdm-pep517-1.0.4/pdm/pep517/exceptions.py 2022-08-06 17:29:41.927385300 +0200 @@ -1,4 +1,6 @@ -from typing import Any, List +from __future__ import annotations + +from typing import Any class BuildError(RuntimeError): @@ -20,6 +22,6 @@ class PEP621ValidationError(ProjectError): - def __init__(self, errors: List[str]) -> None: + def __init__(self, errors: list[str]) -> None: super().__init__(errors) self.errors = errors diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm-pep517-1.0.3/pdm/pep517/macosx_platform.py new/pdm-pep517-1.0.4/pdm/pep517/macosx_platform.py --- old/pdm-pep517-1.0.3/pdm/pep517/macosx_platform.py 2022-07-27 11:27:54.656356800 +0200 +++ new/pdm-pep517-1.0.4/pdm/pep517/macosx_platform.py 2022-08-06 17:29:41.927385300 +0200 @@ -7,12 +7,13 @@ Adapted from https://github.com/pypa/wheel/blob/6e86e6b886/src/wheel/macosx_libfile.py """ +from __future__ import annotations import ctypes import os import sys from pathlib import Path -from typing import BinaryIO, List, Optional, Tuple, Type, TypeVar, Union, no_type_check +from typing import TYPE_CHECKING, BinaryIO, TypeVar, no_type_check """here the needed const and struct from mach-o header files""" @@ -206,8 +207,8 @@ uint32_t ntools; /* number of tool entries following this */ }; """ - -Version = Tuple[int, int, int] +if TYPE_CHECKING: + Version = tuple[int, int, int] def swap32(x: int) -> int: @@ -220,8 +221,8 @@ def get_base_class_and_magic_number( - lib_file: BinaryIO, seek: Optional[int] = None -) -> Tuple[Type[ctypes.Structure], int]: + lib_file: BinaryIO, seek: int | None = None +) -> tuple[type[ctypes.Structure], int]: if seek is None: seek = lib_file.tell() else: @@ -233,7 +234,7 @@ # Handle wrong byte order if magic_number in [FAT_CIGAM, FAT_CIGAM_64, MH_CIGAM, MH_CIGAM_64]: if sys.byteorder == "little": - BaseClass: Type[ctypes.Structure] = ctypes.BigEndianStructure + BaseClass: type[ctypes.Structure] = ctypes.BigEndianStructure else: BaseClass = ctypes.LittleEndianStructure @@ -248,12 +249,12 @@ S = TypeVar("S", bound=ctypes.Structure) -def read_data(struct_class: Type[S], lib_file: BinaryIO) -> S: +def read_data(struct_class: type[S], lib_file: BinaryIO) -> S: return struct_class.from_buffer_copy(lib_file.read(ctypes.sizeof(struct_class))) @no_type_check -def extract_macosx_min_system_version(path_to_lib: str) -> Optional[Version]: +def extract_macosx_min_system_version(path_to_lib: str) -> Version | None: with open(path_to_lib, "rb") as lib_file: BaseClass, magic_number = get_base_class_and_magic_number(lib_file, 0) if magic_number not in [FAT_MAGIC, FAT_MAGIC_64, MH_MAGIC, MH_MAGIC_64]: @@ -279,7 +280,7 @@ read_data(FatArch, lib_file) for _ in range(fat_header.nfat_arch) ] - versions_list: List[Version] = [] + versions_list: list[Version] = [] for el in fat_arch_list: try: version = read_mach_header(lib_file, el.offset) @@ -312,9 +313,7 @@ @no_type_check -def read_mach_header( - lib_file: BinaryIO, seek: Optional[int] = None -) -> Optional[Version]: +def read_mach_header(lib_file: BinaryIO, seek: int | None = None) -> Version | None: """ This funcition parse mach-O header and extract information about minimal system version @@ -370,9 +369,7 @@ return x, y, z -def calculate_macosx_platform_tag( - archive_root: Union[str, Path], platform_tag: str -) -> str: +def calculate_macosx_platform_tag(archive_root: str | Path, platform_tag: str) -> str: """ Calculate proper macosx platform tag basing on files which are included to wheel diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm-pep517-1.0.3/pdm/pep517/metadata.py new/pdm-pep517-1.0.4/pdm/pep517/metadata.py --- old/pdm-pep517-1.0.3/pdm/pep517/metadata.py 2022-07-27 11:27:54.656356800 +0200 +++ new/pdm-pep517-1.0.4/pdm/pep517/metadata.py 2022-08-06 17:29:41.927385300 +0200 @@ -1,20 +1,9 @@ +from __future__ import annotations + import glob import os from pathlib import Path -from typing import ( - Any, - Callable, - Dict, - Generic, - Iterable, - List, - Mapping, - Optional, - Type, - TypeVar, - Union, - cast, -) +from typing import Any, Callable, Generic, Iterable, Mapping, TypeVar, cast from pdm.pep517._vendor.packaging.requirements import Requirement from pdm.pep517.exceptions import MetadataError, PDMWarning, ProjectError @@ -36,12 +25,12 @@ class MetaField(Generic[T]): def __init__( - self, name: str, fget: Optional[Callable[["Metadata", Any], T]] = None + self, name: str, fget: Callable[[Metadata, Any], T] | None = None ) -> None: self.name = name self.fget = fget - def __get__(self, instance: "Metadata", owner: Type["Metadata"]) -> Optional[T]: + def __get__(self, instance: Metadata, owner: type[Metadata]) -> T | None: if instance is None: return self try: @@ -59,7 +48,7 @@ DEFAULT_ENCODING = "utf-8" SUPPORTED_CONTENT_TYPES = ("text/markdown", "text/x-rst", "text/plain") - def __init__(self, root: Union[str, Path], pyproject: Dict[str, Any]) -> None: + def __init__(self, root: str | Path, pyproject: dict[str, Any]) -> None: self.root = Path(root).absolute() if "project" not in pyproject: raise ProjectError("No [project] config in pyproject.toml") @@ -76,7 +65,7 @@ return self.data["name"] @property - def version(self) -> Optional[str]: + def version(self) -> str | None: static_version = self.data.get("version") if isinstance(static_version, str): return static_version @@ -91,12 +80,12 @@ description: MetaField[str] = MetaField("description") - def _get_readme_file(self, value: Union[Mapping[str, str], str]) -> str: + def _get_readme_file(self, value: Mapping[str, str] | str) -> str: if isinstance(value, str): return value return value.get("file", "") - def _get_readme_content(self, value: Union[Mapping[str, str], str]) -> str: + def _get_readme_content(self, value: Mapping[str, str] | str) -> str: if isinstance(value, str): return Path(value).read_text(encoding=self.DEFAULT_ENCODING) if "file" in value and "text" in value: @@ -111,7 +100,7 @@ encoding = value.get("charset", self.DEFAULT_ENCODING) return Path(file_path).read_text(encoding=encoding) - def _get_content_type(self, value: Union[Mapping[str, str], str]) -> str: + def _get_content_type(self, value: Mapping[str, str] | str) -> str: if isinstance(value, str): if value.lower().endswith(".md"): return "text/markdown" @@ -161,7 +150,7 @@ maintainer_email: MetaField[str] = MetaField("maintainers", _get_email) @property - def classifiers(self) -> List[str]: + def classifiers(self) -> list[str]: classifers = set(self.data.get("classifiers", [])) if self.dynamic and "classifiers" in self.dynamic: @@ -183,10 +172,10 @@ return sorted(classifers) keywords: MetaField[str] = MetaField("keywords") - project_urls: MetaField[Dict[str, str]] = MetaField("urls") + project_urls: MetaField[dict[str, str]] = MetaField("urls") @property - def license_expression(self) -> Optional[str]: + def license_expression(self) -> str | None: if "license-expression" in self.data: if "license" in self.data: raise MetadataError( @@ -208,7 +197,7 @@ return None @property - def license_files(self) -> Dict[str, List[str]]: + def license_files(self) -> dict[str, list[str]]: if "license-files" not in self.data: if self.data.get("license", {}).get("file"): # show_warning( @@ -242,28 +231,28 @@ return rv def _convert_dependencies( - self, deps: List[str], field: str = "dependencies" - ) -> List[str]: + self, deps: list[str], field: str = "dependencies" + ) -> list[str]: return list(filter(None, (ensure_pep440_req(dep, field) for dep in deps))) def _convert_optional_dependencies( - self, deps: Mapping[str, List[str]] - ) -> Dict[str, List[str]]: + self, deps: Mapping[str, list[str]] + ) -> dict[str, list[str]]: return { k: self._convert_dependencies(deps[k], "optional-dependencies") for k in deps } - dependencies: MetaField[List[str]] = MetaField( + dependencies: MetaField[list[str]] = MetaField( "dependencies", _convert_dependencies ) - optional_dependencies: MetaField[Dict[str, List[str]]] = MetaField( + optional_dependencies: MetaField[dict[str, list[str]]] = MetaField( "optional-dependencies", _convert_optional_dependencies ) - dynamic: MetaField[List[str]] = MetaField("dynamic") + dynamic: MetaField[list[str]] = MetaField("dynamic") @property - def project_name(self) -> Optional[str]: + def project_name(self) -> str | None: if self.name is None: return None return safe_name(self.name) @@ -275,11 +264,11 @@ return to_filename(self.project_name) @property - def requires_extra(self) -> Dict[str, List[str]]: + def requires_extra(self) -> dict[str, list[str]]: """For PKG-INFO metadata""" if not self.optional_dependencies: return {} - result: Dict[str, List[str]] = {} + result: dict[str, list[str]] = {} for name, reqs in self.optional_dependencies.items(): current = result[name] = [] for r in reqs: @@ -294,7 +283,7 @@ return "" if result == "*" else result @property - def entry_points(self) -> Dict[str, List[str]]: + def entry_points(self) -> dict[str, list[str]]: result = {} settings = self.data if "scripts" in settings: @@ -319,12 +308,12 @@ result[plugin] = [f"{k} = {v}" for k, v in value.items()] return result - def convert_package_paths(self) -> Dict[str, Union[List, Dict]]: + def convert_package_paths(self) -> dict[str, list | dict]: """Return a {package_dir, packages, package_data, exclude_package_data} dict.""" packages = [] py_modules = [] package_data = {"": ["*"]} - exclude_package_data: Dict[str, List[str]] = {} + exclude_package_data: dict[str, list[str]] = {} package_dir = self.config.package_dir includes = self.config.includes excludes = self.config.excludes @@ -389,12 +378,12 @@ class Config: """The [tool.pdm] table""" - def __init__(self, root: Path, data: Dict[str, Any]) -> None: + def __init__(self, root: Path, data: dict[str, Any]) -> None: self.root = root self.data = data def _compatible_get( - self, name: str, default: Any = None, old_name: Optional[str] = None + self, name: str, default: Any = None, old_name: str | None = None ) -> Any: if name in self.data.get("build", {}): return self.data["build"][name] @@ -410,19 +399,19 @@ return default @property - def includes(self) -> List[str]: + def includes(self) -> list[str]: return self._compatible_get("includes", []) @property - def source_includes(self) -> List[str]: + def source_includes(self) -> list[str]: return self._compatible_get("source-includes", []) @property - def excludes(self) -> List[str]: + def excludes(self) -> list[str]: return self._compatible_get("excludes", []) @property - def setup_script(self) -> Optional[str]: + def setup_script(self) -> str | None: build_table = self.data.get("build", {}) if "setup-script" in build_table: return build_table["setup-script"] @@ -463,7 +452,7 @@ return self._compatible_get("editable-backend", "path") @property - def dynamic_version(self) -> Optional[DynamicVersion]: + def dynamic_version(self) -> DynamicVersion | None: dynamic_version = self.data.get("version") if not dynamic_version: return None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm-pep517-1.0.3/pdm/pep517/scm.py new/pdm-pep517-1.0.4/pdm/pep517/scm.py --- old/pdm-pep517-1.0.3/pdm/pep517/scm.py 2022-07-27 11:27:54.656356800 +0200 +++ new/pdm-pep517-1.0.4/pdm/pep517/scm.py 2022-08-06 17:29:41.931385300 +0200 @@ -2,6 +2,8 @@ module to get version from tag of SCM repository. Adapted from setuptools-scm. Currently only support git and hg. """ +from __future__ import annotations + import os import re import shlex @@ -10,7 +12,7 @@ import warnings from datetime import datetime from pathlib import Path -from typing import Any, Dict, Iterable, List, NamedTuple, Optional, Tuple, Union +from typing import Any, Iterable, NamedTuple from pdm.pep517._vendor.packaging.version import LegacyVersion, Version from pdm.pep517._vendor.packaging.version import parse as parse_version @@ -21,10 +23,10 @@ def _subprocess_call( - cmd: Union[str, List[str]], - cwd: Optional[os.PathLike] = None, - extra_env: Optional[Dict[str, str]] = None, -) -> Tuple[int, str, str]: + cmd: str | list[str], + cwd: os.PathLike | None = None, + extra_env: dict[str, str] | None = None, +) -> tuple[int, str, str]: # adapted from pre-commit # Too many bugs dealing with environment variables and GIT: # https://github.com/pre-commit/pre-commit/issues/300 @@ -51,50 +53,50 @@ class VersionInfo(NamedTuple): - version: Union[Version, LegacyVersion] - distance: Optional[int] + version: Version | LegacyVersion + distance: int | None dirty: bool - node: Optional[str] - branch: Optional[str] + node: str | None + branch: str | None def meta( - tag: Union[str, Version, LegacyVersion], - distance: Optional[int] = None, + tag: str | Version | LegacyVersion, + distance: int | None = None, dirty: bool = False, - node: Optional[str] = None, - branch: Optional[str] = None, + node: str | None = None, + branch: str | None = None, ) -> VersionInfo: if isinstance(tag, str): tag = tag_to_version(tag) return VersionInfo(tag, distance, dirty, node, branch) -def _git_get_branch(root: "os.PathLike[Any]") -> Optional[str]: +def _git_get_branch(root: os.PathLike[Any]) -> str | None: ret, out, _ = _subprocess_call("git rev-parse --abbrev-ref HEAD", root) if not ret: return out return None -def _git_is_dirty(root: "os.PathLike[Any]") -> bool: +def _git_is_dirty(root: os.PathLike[Any]) -> bool: _, out, _ = _subprocess_call("git status --porcelain --untracked-files=no", root) return bool(out) -def _git_get_node(root: "os.PathLike[Any]") -> Optional[str]: +def _git_get_node(root: os.PathLike[Any]) -> str | None: ret, out, _ = _subprocess_call("git rev-parse --verify --quiet HEAD", root) if not ret: return out[:7] return None -def _git_count_all_nodes(root: "os.PathLike[Any]") -> int: +def _git_count_all_nodes(root: os.PathLike[Any]) -> int: _, out, _ = _subprocess_call("git rev-list HEAD", root) return out.count("\n") + 1 -def _git_parse_describe(describe_output: str) -> Tuple[str, int, str, bool]: +def _git_parse_describe(describe_output: str) -> tuple[str, int, str, bool]: # 'describe_output' looks e.g. like 'v1.5.0-0-g4060507' or # 'v1.15.1rc1-37-g9bd1298-dirty'. @@ -114,14 +116,14 @@ suffix: str -def _parse_version_tag(tag: str) -> Optional[_ParseResult]: +def _parse_version_tag(tag: str) -> _ParseResult | None: tagstring = tag if not isinstance(tag, str) else str(tag) match = DEFAULT_TAG_REGEX.match(tagstring) result = None if match: if len(match.groups()) == 1: - key: Union[int, str] = 1 + key: int | str = 1 else: key = "version" @@ -134,7 +136,7 @@ return result -def tag_to_version(tag: str) -> Union[Version, LegacyVersion]: +def tag_to_version(tag: str) -> Version | LegacyVersion: """ take a tag that might be prefixed with a keyword and return only the version part :param config: optional configuration object @@ -152,7 +154,7 @@ return parse_version(version) -def tags_to_versions(tags: Iterable[str]) -> List[Union[Version, LegacyVersion]]: +def tags_to_versions(tags: Iterable[str]) -> list[Version | LegacyVersion]: """ take tags that might be prefixed with a keyword and return only the version part :param tags: an iterable of tags @@ -161,7 +163,7 @@ return [tag_to_version(tag) for tag in tags if tag] -def git_parse_version(root: "os.PathLike[Any]") -> Optional[VersionInfo]: +def git_parse_version(root: os.PathLike[Any]) -> VersionInfo | None: GIT = shutil.which("git") if not GIT: return None @@ -187,7 +189,7 @@ return meta(tag, number or None, dirty, node, branch) -def get_latest_normalizable_tag(root: "os.PathLike[Any]") -> str: +def get_latest_normalizable_tag(root: os.PathLike[Any]) -> str: # Gets all tags containing a '.' from oldest to newest cmd = [ "hg", @@ -205,14 +207,14 @@ return tag -def hg_get_graph_distance(root: "os.PathLike[Any]", rev1: str, rev2: str = ".") -> int: +def hg_get_graph_distance(root: os.PathLike[Any], rev1: str, rev2: str = ".") -> int: cmd = ["hg", "log", "-q", "-r", f"{rev1}::{rev2}"] _, out, _ = _subprocess_call(cmd, root) return len(out.strip().splitlines()) - 1 def _hg_tagdist_normalize_tagcommit( - root: "os.PathLike[Any]", tag: str, dist: int, node: str, branch: str + root: os.PathLike[Any], tag: str, dist: int, node: str, branch: str ) -> VersionInfo: dirty = node.endswith("+") node = "h" + node.strip("+") @@ -239,7 +241,7 @@ return meta(tag) -def guess_next_version(tag_version: Union[Version, LegacyVersion]) -> str: +def guess_next_version(tag_version: Version | LegacyVersion) -> str: version = _strip_local(str(tag_version)) return _bump_dev(version) or _bump_regex(version) @@ -265,7 +267,7 @@ return "%s%d" % (prefix, int(tail) + 1) -def hg_parse_version(root: "os.PathLike[Any]") -> Optional[VersionInfo]: +def hg_parse_version(root: os.PathLike[Any]) -> VersionInfo | None: if not shutil.which("hg"): return None _, output, _ = _subprocess_call("hg id -i -b -t", root) @@ -314,7 +316,7 @@ return main_version + local_version -def get_version_from_scm(root: Union[str, Path]) -> str: +def get_version_from_scm(root: str | Path) -> str: if "PDM_PEP517_SCM_VERSION" in os.environ: version = meta(os.getenv("PDM_PEP517_SCM_VERSION", "")) else: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm-pep517-1.0.3/pdm/pep517/utils.py new/pdm-pep517-1.0.4/pdm/pep517/utils.py --- old/pdm-pep517-1.0.3/pdm/pep517/utils.py 2022-07-27 11:27:54.656356800 +0200 +++ new/pdm-pep517-1.0.4/pdm/pep517/utils.py 2022-08-06 17:29:41.931385300 +0200 @@ -1,3 +1,5 @@ +from __future__ import annotations + import functools import os import re @@ -7,7 +9,7 @@ from contextlib import contextmanager from fnmatch import fnmatchcase from pathlib import Path -from typing import Callable, Generator, Iterable, Optional, Type, Union +from typing import Callable, Generator, Iterable from pdm.pep517._vendor.packaging import tags from pdm.pep517._vendor.packaging.markers import Marker @@ -121,13 +123,13 @@ os.chdir(_old_cwd) -def normalize_path(filename: Union[str, Path]) -> str: +def normalize_path(filename: str | Path) -> str: """Normalize a file/dir name for comparison purposes""" filename = os.path.abspath(filename) if sys.platform == "cygwin" else filename return os.path.normcase(os.path.realpath(os.path.normpath(filename))) -def get_platform(build_dir: Union[str, Path]) -> str: +def get_platform(build_dir: str | Path) -> str: """Return our platform name 'win32', 'linux_x86_64'""" result = sysconfig.get_platform() if result.startswith("macosx") and os.path.exists(build_dir): @@ -156,7 +158,7 @@ return val == expected -def get_abi_tag() -> Optional[str]: +def get_abi_tag() -> str | None: """Return the ABI tag based on SOABI (if available) or emulate SOABI (CPython 2, PyPy).""" soabi = sysconfig.get_config_var("SOABI") @@ -185,7 +187,7 @@ return None -def ensure_pep440_req(req: str, field: str) -> Optional[str]: +def ensure_pep440_req(req: str, field: str) -> str | None: """Discard all non-PEP 440 requirements, e.g. editable VCS requirements.""" if req.strip().startswith("-e"): @@ -207,6 +209,6 @@ @functools.lru_cache(maxsize=None) -def show_warning(message: str, category: Type[Warning], stacklevel: int = 1) -> None: +def show_warning(message: str, category: type[Warning], stacklevel: int = 1) -> None: """A cached version of warnings.warn to avoid repeated warnings.""" warnings.warn(message, category, stacklevel + 1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm-pep517-1.0.3/pdm/pep517/version.py new/pdm-pep517-1.0.4/pdm/pep517/version.py --- old/pdm-pep517-1.0.3/pdm/pep517/version.py 2022-07-27 11:27:54.656356800 +0200 +++ new/pdm-pep517-1.0.4/pdm/pep517/version.py 2022-08-06 17:29:41.931385300 +0200 @@ -1,8 +1,10 @@ +from __future__ import annotations + import os import re import warnings from pathlib import Path -from typing import Any, Dict, Union +from typing import Any from pdm.pep517.exceptions import MetadataError from pdm.pep517.scm import get_version_from_scm @@ -21,7 +23,7 @@ self.options = options @classmethod - def from_toml(cls, toml: Dict[str, Any]) -> "DynamicVersion": + def from_toml(cls, toml: dict[str, Any]) -> DynamicVersion: """Create a DynamicVersion from a TOML dictionary.""" options = toml.copy() if "from" in options: @@ -63,7 +65,7 @@ ) return cls(source, **options) - def evaluate_in_project(self, root: Union[str, Path]) -> str: + def evaluate_in_project(self, root: str | Path) -> str: """Evaluate the dynamic version.""" if self.source == "file": version_source = os.path.join(root, self.options["path"]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm-pep517-1.0.3/pdm/pep517/wheel.py new/pdm-pep517-1.0.4/pdm/pep517/wheel.py --- old/pdm-pep517-1.0.3/pdm/pep517/wheel.py 2022-07-27 11:27:54.656356800 +0200 +++ new/pdm-pep517-1.0.4/pdm/pep517/wheel.py 2022-08-06 17:29:41.931385300 +0200 @@ -1,6 +1,10 @@ +from __future__ import annotations + +import abc import contextlib import csv import hashlib +import io import os import re import shutil @@ -11,9 +15,8 @@ import tokenize import zipfile from base64 import urlsafe_b64encode -from io import StringIO from pathlib import Path -from typing import Any, Dict, Generator, List, Mapping, Optional, TextIO, Tuple, Union +from typing import Any, BinaryIO, Generator, Mapping, NamedTuple, TextIO from pdm.pep517 import __version__ from pdm.pep517._vendor.packaging import tags @@ -35,14 +38,87 @@ PY_LIMITED_API_PATTERN = r"cp3\d" +class RecordEntry(NamedTuple): + relpath: str + hash_digest: str + size: str + + +class WheelEntry(metaclass=abc.ABCMeta): + # Fix the date time for reproducible builds + date_time = (2016, 1, 1, 0, 0, 0) + + def __init__(self, rel_path: str) -> None: + self.rel_path = rel_path + + @abc.abstractmethod + def open(self) -> BinaryIO: + pass + + def build_zipinfo(self) -> zipfile.ZipInfo: + return zipfile.ZipInfo(self.rel_path, self.date_time) + + def write_to_zip(self, zf: zipfile.ZipFile) -> RecordEntry: + zi = self.build_zipinfo() + + hashsum = hashlib.sha256() + with self.open() as src: + while True: + buf = src.read(1024 * 8) + if not buf: + break + hashsum.update(buf) + + src.seek(0) + zf.writestr(zi, src.read(), compress_type=zipfile.ZIP_DEFLATED) + + size = zi.file_size + hash_digest = urlsafe_b64encode(hashsum.digest()).decode("ascii").rstrip("=") + return RecordEntry(self.rel_path, f"sha256={hash_digest}", str(size)) + + +class WheelFileEntry(WheelEntry): + def __init__(self, rel_path: str, full_path: Path) -> None: + super().__init__(rel_path) + self.full_path = full_path + + def open(self) -> BinaryIO: + return self.full_path.open("rb") + + def build_zipinfo(self) -> zipfile.ZipInfo: + zi = super().build_zipinfo() + st_mode = os.stat(self.full_path).st_mode + zi.external_attr = (st_mode & 0xFFFF) << 16 # Unix attributes + + if stat.S_ISDIR(st_mode): + zi.external_attr |= 0x10 # MS-DOS directory flag + return zi + + +class WheelStringEntry(WheelEntry): + def __init__(self, rel_path: str) -> None: + super().__init__(rel_path) + self.buffer = io.BytesIO() + + def open(self) -> BinaryIO: + self.buffer.seek(0) + return self.buffer + + @contextlib.contextmanager + def text_open(self) -> Generator[TextIO, None, None]: + text_buffer = io.TextIOWrapper(self.open(), encoding="utf-8", newline="") + yield text_buffer + text_buffer.detach() + + class WheelBuilder(Builder): def __init__( self, - location: Union[str, Path], - config_settings: Optional[Mapping[str, Any]] = None, + location: str | Path, + config_settings: Mapping[str, Any] | None = None, ) -> None: super().__init__(location, config_settings) - self._records = [] # type: List[Tuple[str, str, str]] + self._entries: dict[str, WheelEntry] = {} self._parse_config_settings() def _parse_config_settings(self) -> None: @@ -66,16 +142,17 @@ if not os.path.exists(build_dir): os.makedirs(build_dir, exist_ok=True) - self._records.clear() + self._entries.clear() fd, temp_path = tempfile.mkstemp(suffix=".whl") os.close(fd) + self._copy_module() + self._build() + self._write_metadata() with zipfile.ZipFile( temp_path, mode="w", compression=zipfile.ZIP_DEFLATED ) as zip_file: - self._copy_module(zip_file) - self._build(zip_file) - self._write_metadata(zip_file) + self._write_to_zip(zip_file) target = os.path.join(build_dir, self.wheel_filename) if os.path.exists(target): @@ -131,60 +208,45 @@ version = self.meta_version return f"{name}-{version}.dist-info" - def _write_record(self, fp: TextIO) -> None: - writer = csv.writer(fp, lineterminator="\n") - writer.writerows( - [(path, f"sha256={hash}", size) for path, hash, size in self._records] - ) - writer.writerow([self.dist_info_name + "/RECORD", "", ""]) + def _write_record(self, records: list[RecordEntry]) -> WheelEntry: + entry = WheelStringEntry(self.dist_info_name + "/RECORD") + with entry.text_open() as fp: + writer = csv.writer(fp, lineterminator="\n") + writer.writerows(records) + writer.writerow(RecordEntry(entry.rel_path, "", "")) + return entry - def _write_metadata(self, wheel: zipfile.ZipFile) -> None: + def _write_metadata(self) -> None: dist_info = self.dist_info_name if self.meta.entry_points: - with self._write_to_zip(wheel, dist_info + "/entry_points.txt") as f: + with self._open_for_write(dist_info + "/entry_points.txt") as f: self._write_entry_points(f) - with self._write_to_zip(wheel, dist_info + "/WHEEL") as f: + with self._open_for_write(dist_info + "/WHEEL") as f: self._write_wheel_file(f) - with self._write_to_zip(wheel, dist_info + "/METADATA") as f: + with self._open_for_write(dist_info + "/METADATA") as f: self._write_metadata_file(f) for license_file in self.find_license_files(): self._add_file( - wheel, - os.path.join(self.location, license_file), f"{dist_info}/license_files/{license_file}", + self.location / license_file, ) - with self._write_to_zip(wheel, dist_info + "/RECORD") as f: - self._write_record(f) - @contextlib.contextmanager - def _write_to_zip( - self, wheel: zipfile.ZipFile, rel_path: str - ) -> Generator[StringIO, None, None]: - sio = StringIO() - yield sio - - # The default is a fixed timestamp rather than the current time, so - # that building a wheel twice on the same computer can automatically - # give you the exact same result. - date_time = (2016, 1, 1, 0, 0, 0) - zi = zipfile.ZipInfo(rel_path, date_time) - b = sio.getvalue().encode("utf-8") - hashsum = hashlib.sha256(b) - hash_digest = urlsafe_b64encode(hashsum.digest()).decode("ascii").rstrip("=") - - wheel.writestr(zi, b, compress_type=zipfile.ZIP_DEFLATED) + def _open_for_write(self, rel_path: str) -> Generator[TextIO, None, None]: + entry = WheelStringEntry(rel_path) + with entry.text_open() as fp: + yield fp print(f" - Adding {rel_path}") - self._records.append((rel_path, hash_digest, str(len(b)))) + self._entries[rel_path] = entry - def _build(self, wheel: zipfile.ZipFile) -> None: + def _build(self) -> None: build_dir = self.location / "build" if build_dir.exists(): shutil.rmtree(str(build_dir)) - lib_dir: Optional[Path] = None + lib_dir: Path | None = None if self.meta.config.setup_script: if self.meta.config.run_setuptools: setup_py = self.ensure_setup_py() @@ -204,7 +266,7 @@ build_dir.mkdir(exist_ok=True) with tokenize.open(self.meta.config.setup_script) as f: code = compile(f.read(), self.meta.config.setup_script, "exec") - global_dict: Dict[str, Any] = {} + global_dict: dict[str, Any] = {} exec(code, global_dict) if "build" not in global_dict: show_warning( @@ -233,16 +295,13 @@ if self._is_excluded(rel_path, excludes): continue - if whl_path in wheel.namelist(): - continue - - self._add_file(wheel, pkg.as_posix(), whl_path) + self._add_file(whl_path, pkg) def _write_version(self, destination: Path) -> None: dynamic_version = self.meta.config.dynamic_version if ( not dynamic_version - or dynamic_version.source != "scm" + or dynamic_version.source == "file" or "write_to" not in dynamic_version.options ): return @@ -253,48 +312,21 @@ with write_path.open("w") as f: f.write(write_template.format(self.meta_version)) - def _copy_module(self, wheel: zipfile.ZipFile) -> None: + def _copy_module(self) -> None: + root = self.meta.config.package_dir or self.location for path in self.find_files_to_add(): - rel_path = None - if self.meta.config.package_dir: - try: - rel_path = path.relative_to(self.meta.config.package_dir).as_posix() - except ValueError: - pass - self._add_file(wheel, str(path), rel_path) + try: + rel_path = path.relative_to(root).as_posix() + except ValueError: + rel_path = path.as_posix() + self._add_file(rel_path, path) - def _add_file( - self, wheel: zipfile.ZipFile, full_path: str, rel_path: Optional[str] = None - ) -> None: - if not rel_path: - rel_path = full_path + def _add_file(self, rel_path: str, full_path: Path) -> None: if os.sep != "/": # We always want to have /-separated paths in the zip file and in RECORD rel_path = rel_path.replace(os.sep, "/") print(f" - Adding {rel_path}") - zinfo = zipfile.ZipInfo.from_file(full_path, rel_path) - - # Normalize permission bits to either 755 (executable) or 644 - st_mode = os.stat(full_path).st_mode - - if stat.S_ISDIR(st_mode): - zinfo.external_attr |= 0x10 # MS-DOS directory flag - - hashsum = hashlib.sha256() - with open(full_path, "rb") as src: - while True: - buf = src.read(1024 * 8) - if not buf: - break - hashsum.update(buf) - - src.seek(0) - wheel.writestr(zinfo, src.read(), compress_type=zipfile.ZIP_DEFLATED) - - size = os.stat(full_path).st_size - hash_digest = urlsafe_b64encode(hashsum.digest()).decode("ascii").rstrip("=") - - self._records.append((rel_path, hash_digest, str(size))) + self._entries[rel_path] = WheelFileEntry(rel_path, full_path) def _write_metadata_file(self, fp: TextIO) -> None: fp.write(self.format_pkginfo()) @@ -314,3 +346,11 @@ fp.write(ep.replace(" ", "") + "\n") fp.write("\n") + + def _write_to_zip(self, zf: zipfile.ZipFile) -> None: + records: list[RecordEntry] = [] + for entry in self._entries.values(): + records.append(entry.write_to_zip(zf)) + + record_entry = self._write_record(records) + record_entry.write_to_zip(zf) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm-pep517-1.0.3/pyproject.toml new/pdm-pep517-1.0.4/pyproject.toml --- old/pdm-pep517-1.0.3/pyproject.toml 2022-07-27 11:27:54.656356800 +0200 +++ new/pdm-pep517-1.0.4/pyproject.toml 2022-08-06 17:29:41.931385300 +0200 @@ -22,7 +22,7 @@ "Programming Language :: Python :: 3.10", ] dependencies = [] -version = "1.0.3" +version = "1.0.4" [project.license] text = "MIT"