Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-pdm-backend for openSUSE:Factory checked in at 2024-01-07 21:40:59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pdm-backend (Old) and /work/SRC/openSUSE:Factory/.python-pdm-backend.new.28375 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pdm-backend" Sun Jan 7 21:40:59 2024 rev:3 rq:1137425 version:2.1.8 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pdm-backend/python-pdm-backend.changes 2023-06-26 18:17:16.550785429 +0200 +++ /work/SRC/openSUSE:Factory/.python-pdm-backend.new.28375/python-pdm-backend.changes 2024-01-07 21:41:14.894083624 +0100 @@ -1,0 +2,24 @@ +Sun Jan 7 19:20:21 UTC 2024 - Dirk Müller <[email protected]> + +- update to 2.1.8: + * Can't include nested data files in built wheel + * Update domain name +- update to 2.1.7: + * Rename tag-pattern to tag_regex in the docs + * Copytree handle existing dirs + * Normalize the dist info name in the wheel +- update to 2.1.6: + * Path to uri expansion in dependency string +- update to 2.1.5: + * Don't quote project root in file:// urls Fix #190 + * Write version to file doesn't work for editable installs +- update to 2.1.4: + * Write version file for sdist build as well +- update to 2.1.3: + * Remove duplicate files when building wheel +- update to 2.1.2: + * Fix file permissions to 644 for wheel +- update to 2.1.1: + * Pdm-backend should not normalize names in project metadata + +------------------------------------------------------------------- Old: ---- pdm_backend-2.1.0.tar.gz New: ---- pdm_backend-2.1.8.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pdm-backend.spec ++++++ --- /var/tmp/diff_new_pack.hVVLIK/_old 2024-01-07 21:41:15.338099775 +0100 +++ /var/tmp/diff_new_pack.hVVLIK/_new 2024-01-07 21:41:15.338099775 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-pdm-backend # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,12 +18,12 @@ %{?sle15_python_module_pythons} Name: python-pdm-backend -Version: 2.1.0 +Version: 2.1.8 Release: 0 Summary: Backend used by PDM License: MIT URL: https://github.com/pdm-project/pdm-backend -Source: https://files.pythonhosted.org/packages/8f/aa/df3ad85bf4eeb7a7a3364610ca399f56812e4827cff6495c2a20e4bf1bb4/pdm_backend-2.1.0.tar.gz +Source: https://files.pythonhosted.org/packages/source/p/pdm-backend/pdm_backend-%{version}.tar.gz BuildRequires: %{python_module devel} BuildRequires: %{python_module editables} BuildRequires: %{python_module importlib-metadata >= 3.6.0 if %python-base < 3.10} ++++++ pdm_backend-2.1.0.tar.gz -> pdm_backend-2.1.8.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/PKG-INFO new/pdm_backend-2.1.8/PKG-INFO --- old/pdm_backend-2.1.0/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 +++ new/pdm_backend-2.1.8/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pdm-backend -Version: 2.1.0 +Version: 2.1.8 Summary: The build backend used by PDM that supports latest packaging standards Keywords: packaging PEP 517 build Author-Email: Frost Ming <[email protected]> @@ -15,7 +15,7 @@ Classifier: Programming Language :: Python :: 3.11 Project-URL: Homepage, https://github.com/pdm-project/pdm-backend Project-URL: Repository, https://github.com/pdm-project/pdm-backend -Project-URL: Documentation, https://pdm-backend.fming.dev +Project-URL: Documentation, https://backend.pdm-project.org Requires-Python: >=3.7 Requires-Dist: importlib-metadata>=3.6; python_version < "3.10" Description-Content-Type: text/markdown @@ -27,7 +27,7 @@ [](https://pypi.org/project/pdm-backend) [](https://github.com/pdm-project/pdm-backend/actions/workflows/ci.yml) [](https://results.pre-commit.ci/latest/github/pdm-project/pdm-backend/main) -[](https://pdm.fming.dev) +[][PDM] This is the backend for [PDM] projects that is fully-compatible with [PEP 517] spec, but you can also use it alone. It reads the metadata of [PEP 621] format and coverts it to [Core metadata]. @@ -35,11 +35,11 @@ [pep 517]: https://www.python.org/dev/peps/pep-0517/ [pep 621]: https://www.python.org/dev/peps/pep-0621/ [Core metadata]: https://packaging.python.org/specifications/core-metadata/ -[PDM]: https://pdm.fming.dev +[PDM]: https://pdm-project.org ## Links -- [Documentation](https://pdm-backend.fming.dev) +- [Documentation](https://backend.pdm-project.org) - [Changelog](https://github.com/pdm-project/pdm-backend/releases) - [PDM Documentation][PDM] - [PyPI](https://pypi.org/project/pdm-backend) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/README.md new/pdm_backend-2.1.8/README.md --- old/pdm_backend-2.1.0/README.md 2023-06-08 10:15:04.705250500 +0200 +++ new/pdm_backend-2.1.8/README.md 2023-12-27 08:00:03.135141100 +0100 @@ -5,7 +5,7 @@ [](https://pypi.org/project/pdm-backend) [](https://github.com/pdm-project/pdm-backend/actions/workflows/ci.yml) [](https://results.pre-commit.ci/latest/github/pdm-project/pdm-backend/main) -[](https://pdm.fming.dev) +[][PDM] This is the backend for [PDM] projects that is fully-compatible with [PEP 517] spec, but you can also use it alone. It reads the metadata of [PEP 621] format and coverts it to [Core metadata]. @@ -13,11 +13,11 @@ [pep 517]: https://www.python.org/dev/peps/pep-0517/ [pep 621]: https://www.python.org/dev/peps/pep-0621/ [Core metadata]: https://packaging.python.org/specifications/core-metadata/ -[PDM]: https://pdm.fming.dev +[PDM]: https://pdm-project.org ## Links -- [Documentation](https://pdm-backend.fming.dev) +- [Documentation](https://backend.pdm-project.org) - [Changelog](https://github.com/pdm-project/pdm-backend/releases) - [PDM Documentation][PDM] - [PyPI](https://pypi.org/project/pdm-backend) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/pyproject.toml new/pdm_backend-2.1.8/pyproject.toml --- old/pdm_backend-2.1.0/pyproject.toml 2023-06-08 10:15:25.005818400 +0200 +++ new/pdm_backend-2.1.8/pyproject.toml 2023-12-27 08:00:14.563159000 +0100 @@ -25,7 +25,7 @@ dependencies = [ "importlib-metadata>=3.6; python_version < \"3.10\"", ] -version = "2.1.0" +version = "2.1.8" [project.license] text = "MIT" @@ -33,7 +33,7 @@ [project.urls] Homepage = "https://github.com/pdm-project/pdm-backend" Repository = "https://github.com/pdm-project/pdm-backend" -Documentation = "https://pdm-backend.fming.dev" +Documentation = "https://backend.pdm-project.org" [tool.pdm.version] source = "scm" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/src/pdm/backend/base.py new/pdm_backend-2.1.8/src/pdm/backend/base.py --- old/pdm_backend-2.1.0/src/pdm/backend/base.py 2023-06-08 10:15:04.709250500 +0200 +++ new/pdm_backend-2.1.8/src/pdm/backend/base.py 2023-12-27 08:00:03.139141000 +0100 @@ -14,7 +14,7 @@ from pdm.backend.hooks import BuildHookInterface, Context from pdm.backend.hooks.version import DynamicVersionBuildHook from pdm.backend.structures import FileMap -from pdm.backend.utils import import_module_at_path, is_python_package +from pdm.backend.utils import expand_vars, import_module_at_path, is_python_package if TYPE_CHECKING: from typing import SupportsIndex @@ -160,8 +160,23 @@ if context.build_dir.exists(): shutil.rmtree(context.build_dir) + def _fix_dependencies(self) -> None: + """Fix the dependencies and remove dynamic variables from the metadata""" + metadata = self.config.metadata + root = self.location.as_posix() + if metadata.get("dependencies"): + metadata["dependencies"] = [ + expand_vars(dep, root) for dep in metadata["dependencies"] + ] + if metadata.get("optional-dependencies"): + for name, deps in metadata["optional-dependencies"].items(): + metadata["optional-dependencies"][name] = [ + expand_vars(dep, root) for dep in deps + ] + def initialize(self, context: Context) -> None: """Initialize the build context.""" + self._fix_dependencies() self.call_hook("pdm_build_initialize", context) def get_files(self, context: Context) -> Iterable[tuple[str, Path]]: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/src/pdm/backend/config.py new/pdm_backend-2.1.8/src/pdm/backend/config.py --- old/pdm_backend-2.1.0/src/pdm/backend/config.py 2023-06-08 10:15:04.709250500 +0200 +++ new/pdm_backend-2.1.8/src/pdm/backend/config.py 2023-12-27 08:00:03.139141000 +0100 @@ -52,6 +52,8 @@ def to_coremetadata(self) -> str: """Return the metadata as a Core Metadata string.""" metadata = StandardMetadata.from_pyproject(self.data, project_dir=self.root) + # Fix the name field to unnormalized form. + metadata.name = self.metadata["name"] return str(metadata.as_rfc822()) @classmethod diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/src/pdm/backend/editable.py new/pdm_backend-2.1.8/src/pdm/backend/editable.py --- old/pdm_backend-2.1.0/src/pdm/backend/editable.py 2023-06-08 10:15:04.709250500 +0200 +++ new/pdm_backend-2.1.8/src/pdm/backend/editable.py 2023-12-27 08:00:03.139141000 +0100 @@ -35,8 +35,7 @@ def pdm_build_update_files(self, context: Context, files: dict[str, Path]) -> None: packages: list[str] = context.config.convert_package_paths()["packages"] - package_dir = context.config.build_config.package_dir - proxied = {os.path.join(package_dir, p.replace(".", "/")) for p in packages} + proxied = {p.replace(".", "/") for p in packages} for relpath in list(files): if os.path.splitext(relpath)[1] in (".py", ".pyc", ".pyo"): # All .py[cod] files are proxied diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/src/pdm/backend/hooks/base.py new/pdm_backend-2.1.8/src/pdm/backend/hooks/base.py --- old/pdm_backend-2.1.0/src/pdm/backend/hooks/base.py 2023-06-08 10:15:04.709250500 +0200 +++ new/pdm_backend-2.1.8/src/pdm/backend/hooks/base.py 2023-12-27 08:00:03.139141000 +0100 @@ -61,11 +61,16 @@ return self.build_dir def expand_paths(self, path: str) -> Iterable[Path]: + def path_filter(p: Path) -> bool: + return p.is_file() or p.is_symlink() + plib_path = Path(path) if plib_path.parts and plib_path.parts[0] == "${BUILD_DIR}": - return self.build_dir.glob(Path(*plib_path.parts[1:]).as_posix()) + return filter( + path_filter, self.build_dir.glob(Path(*plib_path.parts[1:]).as_posix()) + ) - return self.root.glob(path) + return filter(path_filter, self.root.glob(path)) class BuildHookInterface(Protocol): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/src/pdm/backend/hooks/setuptools.py new/pdm_backend-2.1.8/src/pdm/backend/hooks/setuptools.py --- old/pdm_backend-2.1.0/src/pdm/backend/hooks/setuptools.py 2023-06-08 10:15:04.709250500 +0200 +++ new/pdm_backend-2.1.8/src/pdm/backend/hooks/setuptools.py 2023-12-27 08:00:03.139141000 +0100 @@ -59,6 +59,15 @@ return "\n".join(result) +def _recursive_copy_files(src: Path, dest: Path) -> None: + if src.is_file(): + shutil.copy2(src, dest) + else: + dest.mkdir(exist_ok=True) + for child in src.iterdir(): + _recursive_copy_files(child, dest / child.name) + + class SetuptoolsBuildHook: """A build hook to run setuptools build command.""" @@ -84,11 +93,7 @@ if not lib_dir: return # copy the files under temp_dir/lib.* to context.build_dir - for file in lib_dir.iterdir(): - if file.is_dir(): - shutil.copytree(file, build_dir / file.name) - else: - shutil.copy2(file, build_dir) + _recursive_copy_files(lib_dir, build_dir) def _build_inplace(self, context: Context) -> None: setup_py = self.ensure_setup_py(context) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/src/pdm/backend/hooks/version/__init__.py new/pdm_backend-2.1.8/src/pdm/backend/hooks/version/__init__.py --- old/pdm_backend-2.1.0/src/pdm/backend/hooks/version/__init__.py 2023-06-08 10:15:04.709250500 +0200 +++ new/pdm_backend-2.1.8/src/pdm/backend/hooks/version/__init__.py 2023-12-27 08:00:03.139141000 +0100 @@ -108,8 +108,15 @@ write_template: str = "{}\n", ) -> None: """Write the resolved version to the file.""" - if write_to is not None and context.target != "sdist": - target = context.build_dir / write_to + if write_to is not None: + if context.target == "sdist" and context.config.build_config.package_dir: + write_to = os.path.join( + context.config.build_config.package_dir, write_to + ) + if context.target == "editable": + target = Path(context.config.build_config.package_dir or ".") / write_to + else: + target = context.build_dir / write_to if not target.parent.exists(): target.parent.mkdir(0o700, parents=True) with open(target, "w", encoding="utf-8", newline="") as fp: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/src/pdm/backend/sdist.py new/pdm_backend-2.1.8/src/pdm/backend/sdist.py --- old/pdm_backend-2.1.0/src/pdm/backend/sdist.py 2023-06-08 10:15:04.709250500 +0200 +++ new/pdm_backend-2.1.8/src/pdm/backend/sdist.py 2023-12-27 08:00:03.139141000 +0100 @@ -11,23 +11,7 @@ from pdm.backend._vendor.packaging.utils import canonicalize_name from pdm.backend.base import Builder from pdm.backend.hooks import Context -from pdm.backend.utils import safe_version, to_filename - - -def normalize_file_permissions(st_mode: int) -> int: - """ - Normalizes the permission bits in the st_mode field from stat to 644/755 - - Popular VCSs only track whether a file is executable or not. The exact - permissions can vary on systems with different umasks. Normalising - to 644 (non executable) or 755 (executable) makes builds more reproducible. - """ - # Set 644 permissions, leaving higher bits of st_mode unchanged - new_mode = (st_mode | 0o644) & ~0o133 - if st_mode & 0o100: - new_mode |= 0o111 # Executable: 644 -> 755 - - return new_mode +from pdm.backend.utils import normalize_file_permissions, safe_version, to_filename def clean_tarinfo(tar_info: tarfile.TarInfo) -> tarfile.TarInfo: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/src/pdm/backend/utils.py new/pdm_backend-2.1.8/src/pdm/backend/utils.py --- old/pdm_backend-2.1.0/src/pdm/backend/utils.py 2023-06-08 10:15:04.709250500 +0200 +++ new/pdm_backend-2.1.8/src/pdm/backend/utils.py 2023-12-27 08:00:03.139141000 +0100 @@ -198,7 +198,7 @@ quote: Callable[[str], str] = urllib.parse.quote else: quote = str - line = line.replace("${PROJECT_ROOT}", quote(root).lstrip("/")) + line = line.replace("file:///${PROJECT_ROOT}", Path(root).as_uri()) def replace_func(match: Match[str]) -> str: rv = os.getenv(match.group(1)) @@ -219,3 +219,18 @@ module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) # type: ignore return module + + +def normalize_file_permissions(st_mode: int) -> int: + """ + Normalizes the permission bits in the st_mode field from stat to 644/755 + Popular VCSs only track whether a file is executable or not. The exact + permissions can vary on systems with different umasks. Normalising + to 644 (non executable) or 755 (executable) makes builds more reproducible. + """ + # Set 644 permissions, leaving higher bits of st_mode unchanged + new_mode = (st_mode | 0o644) & ~0o133 + if st_mode & 0o100: + new_mode |= 0o111 # Executable: 644 -> 755 + + return new_mode diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/src/pdm/backend/wheel.py new/pdm_backend-2.1.8/src/pdm/backend/wheel.py --- old/pdm_backend-2.1.0/src/pdm/backend/wheel.py 2023-06-08 10:15:04.709250500 +0200 +++ new/pdm_backend-2.1.8/src/pdm/backend/wheel.py 2023-12-27 08:00:03.139141000 +0100 @@ -4,6 +4,7 @@ import hashlib import io import os +import posixpath import shutil import stat import sys @@ -20,10 +21,11 @@ from pdm.backend.base import Builder from pdm.backend.hooks import Context from pdm.backend.hooks.setuptools import SetuptoolsBuildHook +from pdm.backend.structures import FileMap from pdm.backend.utils import ( - expand_vars, get_abi_tag, get_platform, + normalize_file_permissions, safe_version, to_filename, ) @@ -97,46 +99,39 @@ plat_name = self.config_settings["--plat-name"] return python_tag, py_limited_api, plat_name - def _fix_dependencies(self) -> None: - """Fix the dependencies and remove dynamic variables from the metadata""" - metadata = self.config.metadata - root = self.location.as_posix() - if metadata.get("dependencies"): - metadata["dependencies"] = [ - expand_vars(dep, root) for dep in metadata["dependencies"] - ] - if metadata.get("optional-dependencies"): - for name, deps in metadata["optional-dependencies"].items(): - metadata["optional-dependencies"][name] = [ - expand_vars(dep, root) for dep in deps - ] - - def initialize(self, context: Context) -> None: - self._fix_dependencies() - return super().initialize(context) - def prepare_metadata(self, metadata_directory: str) -> Path: """Write the dist-info files under the given directory""" context = self.build_context(Path(metadata_directory)) self.initialize(context) return self._write_dist_info(Path(metadata_directory)) - def get_files(self, context: Context) -> Iterable[tuple[str, Path]]: + def _collect_files(self, context: Context) -> FileMap: package_dir = self.config.build_config.package_dir - for relpath, path in super().get_files(context): + result = FileMap() + + def clean_prefix(relpath: str) -> str: # remove the package-dir part from the relative paths if package_dir and relpath.startswith(package_dir + "/"): relpath = relpath[len(package_dir) + 1 :] - yield relpath, path + return relpath + + result.update( + (clean_prefix(k), v) for k, v in super()._collect_files(context).items() + ) + return result + + def get_files(self, context: Context) -> Iterable[tuple[str, Path]]: + yield from super().get_files(context) yield from self._get_metadata_files(context) yield from self._get_wheel_data(context) def _get_wheel_data(self, context: Context) -> Iterable[tuple[str, Path]]: for name, paths in context.config.build_config.wheel_data.items(): for path in paths: - relative_to: str | None = None + relative_to: Path | None = None if not isinstance(path, str): - relative_to = path.get("relative-to") + if path.get("relative-to"): + relative_to = context.root / path["relative-to"] path = path["path"] for child in context.expand_paths(path): relpath = ( @@ -150,7 +145,12 @@ self, context: Context, files: Iterable[tuple[str, Path]] ) -> Path: records: list[RecordEntry] = [] - with tempfile.NamedTemporaryFile(suffix=".whl", delete=False) as fp: + fd, temp_name = tempfile.mkstemp(suffix=".whl") + st_mode = os.stat(temp_name).st_mode + new_mode = normalize_file_permissions(st_mode) + os.chmod(temp_name, new_mode) + + with os.fdopen(fd, "w+b") as fp: with zipfile.ZipFile(fp, "w", compression=zipfile.ZIP_DEFLATED) as zf: for rel_path, full_path in files: records.append(self._add_file_to_zip(zf, rel_path, full_path)) @@ -159,7 +159,7 @@ target = context.dist_dir / f"{self.name_version}-{self.tag}.whl" if target.exists(): target.unlink() - shutil.move(fp.name, target) + shutil.move(temp_name, target) return target @property @@ -235,8 +235,9 @@ ) -> RecordEntry: self._show_add_file(rel_path, full_path) zi = zipfile.ZipInfo(rel_path, ZIPINFO_DATE_TIME) - st_mode = os.stat(full_path).st_mode - zi.external_attr = (st_mode & 0xFFFF) << 16 # Unix attributes + st_mode = full_path.stat().st_mode + new_mode = normalize_file_permissions(st_mode) + zi.external_attr = (new_mode & 0xFFFF) << 16 # Unix attributes if stat.S_ISDIR(st_mode): zi.external_attr |= 0x10 # MS-DOS directory flag @@ -251,11 +252,9 @@ zf: zipfile.ZipFile, zi: zipfile.ZipInfo, src: IO[bytes] ) -> str: hashsum = hashlib.sha256() - for buf in iter(lambda: src.read(2**16), b""): - hashsum.update(buf) - - src.seek(0) - zf.writestr(zi, src.read(), compress_type=zipfile.ZIP_DEFLATED) + data = src.read() + hashsum.update(data) + zf.writestr(zi, data, compress_type=zipfile.ZIP_DEFLATED) return urlsafe_b64encode(hashsum.digest()).decode("ascii").rstrip("=") def _write_record(self, zf: zipfile.ZipFile, records: list[RecordEntry]) -> None: @@ -296,13 +295,19 @@ def _get_metadata_files(self, context: Context) -> Iterable[tuple[str, Path]]: """Generate the metadata files for the wheel.""" if context.kwargs.get("metadata_directory"): - return self._iter_files_in_directory(context.kwargs["metadata_directory"]) + return self._iter_metadata_files(context.kwargs["metadata_directory"]) else: dist_info = self._write_dist_info(context.ensure_build_dir()) - return self._iter_files_in_directory(str(dist_info)) + return self._iter_metadata_files(str(dist_info)) - def _iter_files_in_directory(self, path: str) -> Iterable[tuple[str, Path]]: + def _iter_metadata_files(self, path: str) -> Iterable[tuple[str, Path]]: + dist_info_name = self.dist_info_name for root, _, files in os.walk(path): - relroot = os.path.relpath(root, os.path.dirname(path)) for file in files: - yield (Path(relroot, file).as_posix(), Path(root) / file) + # the relative path is concated with the dist-info name + # so that the dist info name is always consistent with the current build + # e.g. <path>/METADATA -> <name>-<version>.dist-info/METADATA + relpath = posixpath.join( + dist_info_name, Path(root, file).relative_to(path).as_posix() + ) + yield relpath, Path(root, file) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/tests/conftest.py new/pdm_backend-2.1.8/tests/conftest.py --- old/pdm_backend-2.1.0/tests/conftest.py 2023-06-08 10:15:04.709250500 +0200 +++ new/pdm_backend-2.1.8/tests/conftest.py 2023-12-27 08:00:03.139141000 +0100 @@ -1,5 +1,7 @@ import shutil import subprocess +from pathlib import Path +from typing import Generator import pytest @@ -7,15 +9,24 @@ from tests import FIXTURES [email protected]() -def project_with_scm(tmp_path): - project = FIXTURES / "projects/demo-using-scm" - shutil.copytree(project, tmp_path / project.name) - with utils.cd(tmp_path / project.name): - subprocess.check_call(["git", "init"]) - subprocess.check_call(["git", "config", "user.email", "[email protected]"]) - subprocess.check_call(["git", "config", "user.name", "Name"]) - subprocess.check_call(["git", "add", "."]) - subprocess.check_call(["git", "commit", "-m", "initial commit"]) - subprocess.check_call(["git", "tag", "-a", "0.1.0", "-m", "version 0.1.0"]) - yield tmp_path / project.name [email protected] +def fixture_project(tmp_path: Path, name: str) -> Generator[Path, None, None]: + project = FIXTURES / "projects" / name + shutil.copytree(project, tmp_path / name) + with utils.cd(tmp_path / name): + yield tmp_path / name + + [email protected] +def dist(tmp_path: Path) -> Path: + return tmp_path / "dist" + + [email protected] +def scm(fixture_project: Path) -> None: + subprocess.check_call(["git", "init"]) + subprocess.check_call(["git", "config", "user.email", "[email protected]"]) + subprocess.check_call(["git", "config", "user.name", "Name"]) + subprocess.check_call(["git", "add", "."]) + subprocess.check_call(["git", "commit", "-m", "initial commit"]) + subprocess.check_call(["git", "tag", "-a", "0.1.0", "-m", "version 0.1.0"]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/tests/fixtures/projects/demo-package-include/pyproject.toml new/pdm_backend-2.1.8/tests/fixtures/projects/demo-package-include/pyproject.toml --- old/pdm_backend-2.1.0/tests/fixtures/projects/demo-package-include/pyproject.toml 2023-06-08 10:15:04.709250500 +0200 +++ new/pdm_backend-2.1.8/tests/fixtures/projects/demo-package-include/pyproject.toml 2023-12-27 08:00:03.139141000 +0100 @@ -31,4 +31,4 @@ source-includes = ["scripts/"] [tool.pdm.build.wheel-data] -scripts = ["scripts/*"] +scripts = ["scripts/**/*"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/tests/fixtures/projects/demo-package-include/scripts/data/my_script.sh new/pdm_backend-2.1.8/tests/fixtures/projects/demo-package-include/scripts/data/my_script.sh --- old/pdm_backend-2.1.0/tests/fixtures/projects/demo-package-include/scripts/data/my_script.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/pdm_backend-2.1.8/tests/fixtures/projects/demo-package-include/scripts/data/my_script.sh 2023-12-27 08:00:03.143141300 +0100 @@ -0,0 +1,3 @@ +#!/bin/bash + +echo "Hello world" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/tests/fixtures/projects/demo-package-include/scripts/my_script.sh new/pdm_backend-2.1.8/tests/fixtures/projects/demo-package-include/scripts/my_script.sh --- old/pdm_backend-2.1.0/tests/fixtures/projects/demo-package-include/scripts/my_script.sh 2023-06-08 10:15:04.709250500 +0200 +++ new/pdm_backend-2.1.8/tests/fixtures/projects/demo-package-include/scripts/my_script.sh 1970-01-01 01:00:00.000000000 +0100 @@ -1,3 +0,0 @@ -#!/bin/bash - -echo "Hello world" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/tests/test_api.py new/pdm_backend-2.1.8/tests/test_api.py --- old/pdm_backend-2.1.0/tests/test_api.py 2023-06-08 10:15:04.713250400 +0200 +++ new/pdm_backend-2.1.8/tests/test_api.py 2023-12-27 08:00:03.143141300 +0100 @@ -8,435 +8,470 @@ import pdm.backend as api from pdm.backend.wheel import WheelBuilder -from tests.testutils import build_fixture_project, get_tarball_names, get_wheel_names +from tests.testutils import get_tarball_names, get_wheel_names +pytestmark = pytest.mark.usefixtures("fixture_project") -def test_build_single_module(tmp_path: Path) -> None: - with build_fixture_project("demo-module"): - wheel_name = api.build_wheel(tmp_path.as_posix()) - sdist_name = api.build_sdist(tmp_path.as_posix()) - assert api.get_requires_for_build_sdist() == [] - assert api.get_requires_for_build_wheel() == [] - assert sdist_name == "demo_module-0.1.0.tar.gz" - assert wheel_name == "demo_module-0.1.0-py3-none-any.whl" - tar_names = get_tarball_names(tmp_path / sdist_name) - for name in [ - "foo_module.py", - "bar_module.py", - "LICENSE", - "pyproject.toml", - "PKG-INFO", - "README.md", - ]: - assert f"demo_module-0.1.0/{name}" in tar_names - - zip_names = get_wheel_names(tmp_path / wheel_name) - for name in ["foo_module.py", "bar_module.py"]: - assert name in zip_names - - for name in ("pyproject.toml", "LICENSE"): - assert name not in zip_names - - assert "demo_module-0.1.0.dist-info/licenses/LICENSE" in zip_names - - -def test_build_package(tmp_path: Path) -> None: - with build_fixture_project("demo-package"): - wheel_name = api.build_wheel(tmp_path.as_posix()) - sdist_name = api.build_sdist(tmp_path.as_posix()) - assert sdist_name == "demo_package-0.1.0.tar.gz" - assert wheel_name == "demo_package-0.1.0-py2.py3-none-any.whl" - - tar_names = get_tarball_names(tmp_path / sdist_name) - assert "demo_package-0.1.0/my_package/__init__.py" in tar_names - assert "demo_package-0.1.0/my_package/data.json" in tar_names - assert "demo_package-0.1.0/single_module.py" not in tar_names - assert "demo_package-0.1.0/data_out.json" in tar_names - zip_names = get_wheel_names(tmp_path / wheel_name) - assert "my_package/__init__.py" in zip_names - assert "my_package/data.json" in zip_names - assert "single_module.py" not in zip_names - assert "data_out.json" not in zip_names - - -def test_build_src_package(tmp_path: Path) -> None: - with build_fixture_project("demo-src-package"): - wheel_name = api.build_wheel(tmp_path.as_posix()) - sdist_name = api.build_sdist(tmp_path.as_posix()) - assert sdist_name == "demo_package-0.1.0.tar.gz" - assert wheel_name == "demo_package-0.1.0-py3-none-any.whl" - - tar_names = get_tarball_names(tmp_path / sdist_name) - zip_names = get_wheel_names(tmp_path / wheel_name) - assert "demo_package-0.1.0/src/my_package/__init__.py" in tar_names - assert "demo_package-0.1.0/src/my_package/data.json" in tar_names [email protected]("name", ["demo-module"]) +def test_build_single_module(dist: Path) -> None: + wheel_name = api.build_wheel(dist.as_posix()) + sdist_name = api.build_sdist(dist.as_posix()) + assert api.get_requires_for_build_sdist() == [] + assert api.get_requires_for_build_wheel() == [] + assert sdist_name == "demo_module-0.1.0.tar.gz" + assert wheel_name == "demo_module-0.1.0-py3-none-any.whl" + tar_names = get_tarball_names(dist / sdist_name) + for name in [ + "foo_module.py", + "bar_module.py", + "LICENSE", + "pyproject.toml", + "PKG-INFO", + "README.md", + ]: + assert f"demo_module-0.1.0/{name}" in tar_names + + zip_names = get_wheel_names(dist / wheel_name) + for name in ["foo_module.py", "bar_module.py"]: + assert name in zip_names + + for name in ("pyproject.toml", "LICENSE"): + assert name not in zip_names + + assert "demo_module-0.1.0.dist-info/licenses/LICENSE" in zip_names + + [email protected]("name", ["demo-package"]) +def test_build_package(dist: Path) -> None: + wheel_name = api.build_wheel(dist.as_posix()) + sdist_name = api.build_sdist(dist.as_posix()) + assert sdist_name == "demo_package-0.1.0.tar.gz" + assert wheel_name == "demo_package-0.1.0-py2.py3-none-any.whl" + + tar_names = get_tarball_names(dist / sdist_name) + assert "demo_package-0.1.0/my_package/__init__.py" in tar_names + assert "demo_package-0.1.0/my_package/data.json" in tar_names + assert "demo_package-0.1.0/single_module.py" not in tar_names + assert "demo_package-0.1.0/data_out.json" in tar_names + + zip_names = get_wheel_names(dist / wheel_name) + assert "my_package/__init__.py" in zip_names + assert "my_package/data.json" in zip_names + assert "single_module.py" not in zip_names + assert "data_out.json" not in zip_names + + [email protected]("name", ["demo-src-package"]) +def test_build_src_package(dist: Path) -> None: + wheel_name = api.build_wheel(dist.as_posix()) + sdist_name = api.build_sdist(dist.as_posix()) + assert sdist_name == "demo_package-0.1.0.tar.gz" + assert wheel_name == "demo_package-0.1.0-py3-none-any.whl" + + tar_names = get_tarball_names(dist / sdist_name) + zip_names = get_wheel_names(dist / wheel_name) + assert "demo_package-0.1.0/src/my_package/__init__.py" in tar_names + assert "demo_package-0.1.0/src/my_package/data.json" in tar_names + + assert "my_package/__init__.py" in zip_names + assert "my_package/data.json" in zip_names + + [email protected]("name", ["demo-package-include"]) +def test_build_package_include(dist: Path) -> None: + wheel_name = api.build_wheel(dist.as_posix()) + sdist_name = api.build_sdist(dist.as_posix()) + assert sdist_name == "demo_package-0.1.0.tar.gz" + assert wheel_name == "demo_package-0.1.0-py3-none-any.whl" + + tar_names = get_tarball_names(dist / sdist_name) + + assert "demo_package-0.1.0/my_package/__init__.py" in tar_names + assert "demo_package-0.1.0/my_package/data.json" not in tar_names + assert "demo_package-0.1.0/requirements.txt" in tar_names + assert "demo_package-0.1.0/data_out.json" in tar_names + with zipfile.ZipFile(dist / wheel_name) as zf: + zip_names = zf.namelist() assert "my_package/__init__.py" in zip_names - assert "my_package/data.json" in zip_names + assert "my_package/data.json" not in zip_names + assert "requirements.txt" in zip_names + assert "data_out.json" in zip_names + assert "demo_package-0.1.0.data/scripts/my_script.sh" in zip_names + if os.name != "nt": + info = zf.getinfo("demo_package-0.1.0.data/scripts/my_script.sh") + filemode = info.external_attr >> 16 + assert filemode & 0o111 -def test_build_package_include(tmp_path: Path) -> None: - with build_fixture_project("demo-package-include"): - wheel_name = api.build_wheel(tmp_path.as_posix()) - sdist_name = api.build_sdist(tmp_path.as_posix()) - assert sdist_name == "demo_package-0.1.0.tar.gz" - assert wheel_name == "demo_package-0.1.0-py3-none-any.whl" - - tar_names = get_tarball_names(tmp_path / sdist_name) - - assert "demo_package-0.1.0/my_package/__init__.py" in tar_names - assert "demo_package-0.1.0/my_package/data.json" not in tar_names - assert "demo_package-0.1.0/requirements.txt" in tar_names - assert "demo_package-0.1.0/data_out.json" in tar_names - - with zipfile.ZipFile(tmp_path / wheel_name) as zf: - zip_names = zf.namelist() - assert "my_package/__init__.py" in zip_names - assert "my_package/data.json" not in zip_names - assert "requirements.txt" in zip_names - assert "data_out.json" in zip_names - assert "demo_package-0.1.0.data/scripts/my_script.sh" in zip_names - if os.name != "nt": - info = zf.getinfo("demo_package-0.1.0.data/scripts/my_script.sh") - filemode = info.external_attr >> 16 - assert filemode & 0o111 - - -def test_namespace_package_by_include(tmp_path: Path) -> None: - with build_fixture_project("demo-pep420-package"): - wheel_name = api.build_wheel(tmp_path.as_posix()) - sdist_name = api.build_sdist(tmp_path.as_posix()) - assert sdist_name == "demo_package-0.1.0.tar.gz" - assert wheel_name == "demo_package-0.1.0-py3-none-any.whl" - - tar_names = get_tarball_names(tmp_path / sdist_name) - zip_names = get_wheel_names(tmp_path / wheel_name) - assert "demo_package-0.1.0/foo/my_package/__init__.py" in tar_names - assert "demo_package-0.1.0/foo/my_package/data.json" in tar_names - - assert "foo/my_package/__init__.py" in zip_names - assert "foo/my_package/data.json" in zip_names - - -def test_build_explicit_package_dir(tmp_path: Path) -> None: - with build_fixture_project("demo-explicit-package-dir"): - wheel_name = api.build_wheel(tmp_path.as_posix()) - sdist_name = api.build_sdist(tmp_path.as_posix()) - assert sdist_name == "demo_package-0.1.0.tar.gz" - assert wheel_name == "demo_package-0.1.0-py3-none-any.whl" - - tar_names = get_tarball_names(tmp_path / sdist_name) - zip_names = get_wheel_names(tmp_path / wheel_name) - assert "demo_package-0.1.0/foo/my_package/__init__.py" in tar_names - assert "demo_package-0.1.0/foo/my_package/data.json" in tar_names [email protected]("name", ["demo-package-include"]) +def test_build_package_data_relative(dist: Path, fixture_project: Path) -> None: + from pdm.backend.config import tomli_w, tomllib + + with open(fixture_project / "pyproject.toml", "rb") as fp: + pyproject = tomllib.load(fp) + pyproject["tool"]["pdm"]["build"]["wheel-data"]["scripts"] = [ + {"path": "scripts/**/*", "relative-to": "scripts/"} + ] + with open(fixture_project / "pyproject.toml", "wb") as fp: + tomli_w.dump(pyproject, fp) + wheel_name = api.build_wheel(dist.as_posix()) + with zipfile.ZipFile(dist / wheel_name) as zf: + zip_names = zf.namelist() assert "my_package/__init__.py" in zip_names - assert "my_package/data.json" in zip_names + assert "my_package/data.json" not in zip_names + assert "requirements.txt" in zip_names + assert "data_out.json" in zip_names + assert "demo_package-0.1.0.data/scripts/data/my_script.sh" in zip_names + if os.name != "nt": + info = zf.getinfo("demo_package-0.1.0.data/scripts/data/my_script.sh") + filemode = info.external_attr >> 16 + assert filemode & 0o111 -def test_prepare_metadata(tmp_path: Path) -> None: - with build_fixture_project("demo-package"): - dist_info = api.prepare_metadata_for_build_wheel(tmp_path.as_posix()) - assert dist_info == "demo_package-0.1.0.dist-info" - for filename in ("WHEEL", "METADATA"): - assert (tmp_path / dist_info / filename).is_file() [email protected]("name", ["demo-pep420-package"]) +def test_namespace_package_by_include(dist: Path) -> None: + wheel_name = api.build_wheel(dist.as_posix()) + sdist_name = api.build_sdist(dist.as_posix()) + assert sdist_name == "demo_package-0.1.0.tar.gz" + assert wheel_name == "demo_package-0.1.0-py3-none-any.whl" + + tar_names = get_tarball_names(dist / sdist_name) + zip_names = get_wheel_names(dist / wheel_name) + assert "demo_package-0.1.0/foo/my_package/__init__.py" in tar_names + assert "demo_package-0.1.0/foo/my_package/data.json" in tar_names + + assert "foo/my_package/__init__.py" in zip_names + assert "foo/my_package/data.json" in zip_names + + [email protected]("name", ["demo-explicit-package-dir"]) +def test_build_explicit_package_dir(dist: Path) -> None: + wheel_name = api.build_wheel(dist.as_posix()) + sdist_name = api.build_sdist(dist.as_posix()) + assert sdist_name == "demo_package-0.1.0.tar.gz" + assert wheel_name == "demo_package-0.1.0-py3-none-any.whl" + + tar_names = get_tarball_names(dist / sdist_name) + zip_names = get_wheel_names(dist / wheel_name) + assert "demo_package-0.1.0/foo/my_package/__init__.py" in tar_names + assert "demo_package-0.1.0/foo/my_package/data.json" in tar_names + + assert "my_package/__init__.py" in zip_names + assert "my_package/data.json" in zip_names + + [email protected]("name", ["demo-package"]) +def test_prepare_metadata(dist: Path) -> None: + dist_info = api.prepare_metadata_for_build_wheel(dist.as_posix()) + assert dist_info == "demo_package-0.1.0.dist-info" + for filename in ("WHEEL", "METADATA"): + assert (dist / dist_info / filename).is_file() + + [email protected]("name", ["demo-package"]) +def test_build_wheel_metadata_identical(dist: Path) -> None: + dist_info = api.prepare_metadata_for_build_wheel(dist.as_posix()) + (dist / dist_info / "other.txt").write_text("foo") + wheel_name = api.build_wheel( + dist.as_posix(), metadata_directory=str(dist / dist_info) + ) -def test_build_wheel_metadata_identical(tmp_path: Path) -> None: - with build_fixture_project("demo-package"): - dist_info = api.prepare_metadata_for_build_wheel(tmp_path.as_posix()) - (tmp_path / dist_info / "other.txt").write_text("foo") + with zipfile.ZipFile(dist / wheel_name) as wheel: + assert f"{dist_info}/other.txt" in wheel.namelist() + assert wheel.read(f"{dist_info}/other.txt") == b"foo" + + [email protected]("name", ["demo-src-pymodule"]) +def test_build_package_with_modules_in_src(dist: Path) -> None: + wheel_name = api.build_wheel(dist.as_posix()) + sdist_name = api.build_sdist(dist.as_posix()) + + tar_names = get_tarball_names(dist / sdist_name) + assert "demo_module-0.1.0/src/foo_module.py" in tar_names + + zip_names = get_wheel_names(dist / wheel_name) + assert "foo_module.py" in zip_names + + [email protected]("name", ["demo-cextension"]) +def test_build_with_cextension(dist: Path) -> None: + wheel_name = api.build_wheel(dist.as_posix()) + sdist_name = api.build_sdist(dist.as_posix()) + assert api.get_requires_for_build_sdist() == [] + assert api.get_requires_for_build_wheel() == ["setuptools>=40.8.0"] + + zip_names = get_wheel_names(dist / wheel_name) + assert "my_package/__init__.py" in zip_names + assert ( + "my_package/hellomodule.c" not in zip_names + ), "Not collect c files while building wheel" + extension_suffix = ".pyd" if sys.platform == "win32" else ".so" + assert any(name.endswith(extension_suffix) for name in zip_names) + + tar_names = get_tarball_names(dist / sdist_name) + assert "demo_package-0.1.0/my_package/__init__.py" in tar_names + assert ( + "demo_package-0.1.0/my_package/hellomodule.c" in tar_names + ), "Collect c files while building sdist" + assert not any( + path.startswith("build") for path in tar_names + ), 'Not collect c files in temporary directory "./build"' + + [email protected]("name", ["demo-cextension-in-src"]) +def test_build_with_cextension_in_src(dist: Path) -> None: + wheel_name = api.build_wheel(dist.as_posix()) + sdist_name = api.build_sdist(dist.as_posix()) + + zip_names = get_wheel_names(dist / wheel_name) + assert "my_package/__init__.py" in zip_names + assert ( + "my_package/hellomodule.c" not in zip_names + ), "Not collect c files while building wheel" + extension_suffix = ".pyd" if sys.platform == "win32" else ".so" + assert any(name.endswith(extension_suffix) for name in zip_names) + + tar_names = get_tarball_names(dist / sdist_name) + assert "demo_package-0.1.0/src/my_package/__init__.py" in tar_names + assert ( + "demo_package-0.1.0/src/my_package/hellomodule.c" in tar_names + ), "Collect c files while building sdist" + assert not any( + path.startswith("build") for path in tar_names + ), 'Not collect c files in temporary directory "./build"' + + [email protected]("name", ["demo-package"]) +def test_build_editable(dist: Path, fixture_project: Path) -> None: + wheel_name = api.build_editable(dist.as_posix()) + assert api.get_requires_for_build_editable() == ["editables"] + with zipfile.ZipFile(dist / wheel_name) as zf: + namelist = zf.namelist() + assert "demo_package.pth" in namelist + assert "_editable_impl_demo_package.py" in namelist + assert "demo_package-0.1.0+editable.dist-info/licenses/LICENSE" in namelist - wheel_name = api.build_wheel( - tmp_path.as_posix(), metadata_directory=str(tmp_path / dist_info) + metadata = email.message_from_bytes( + zf.read("demo_package-0.1.0+editable.dist-info/METADATA") ) + assert "editables" in metadata.get_all("Requires-Dist", []) - with zipfile.ZipFile(tmp_path / wheel_name) as wheel: - assert f"{dist_info}/other.txt" in wheel.namelist() - assert wheel.read(f"{dist_info}/other.txt") == b"foo" - - -def test_build_package_with_modules_in_src(tmp_path: Path) -> None: - with build_fixture_project("demo-src-pymodule"): - wheel_name = api.build_wheel(tmp_path.as_posix()) - sdist_name = api.build_sdist(tmp_path.as_posix()) - - tar_names = get_tarball_names(tmp_path / sdist_name) - assert "demo_module-0.1.0/src/foo_module.py" in tar_names - - zip_names = get_wheel_names(tmp_path / wheel_name) - assert "foo_module.py" in zip_names - - -def test_build_with_cextension(tmp_path: Path) -> None: - with build_fixture_project("demo-cextension"): - wheel_name = api.build_wheel(tmp_path.as_posix()) - sdist_name = api.build_sdist(tmp_path.as_posix()) - assert api.get_requires_for_build_sdist() == [] - assert api.get_requires_for_build_wheel() == ["setuptools>=40.8.0"] - - zip_names = get_wheel_names(tmp_path / wheel_name) - assert "my_package/__init__.py" in zip_names - assert ( - "my_package/hellomodule.c" not in zip_names - ), "Not collect c files while building wheel" - extension_suffix = ".pyd" if sys.platform == "win32" else ".so" - assert any(name.endswith(extension_suffix) for name in zip_names) - - tar_names = get_tarball_names(tmp_path / sdist_name) - assert "demo_package-0.1.0/my_package/__init__.py" in tar_names - assert ( - "demo_package-0.1.0/my_package/hellomodule.c" in tar_names - ), "Collect c files while building sdist" - assert not any( - path.startswith("build") for path in tar_names - ), 'Not collect c files in temporary directory "./build"' - - -def test_build_with_cextension_in_src(tmp_path: Path) -> None: - with build_fixture_project("demo-cextension-in-src"): - wheel_name = api.build_wheel(tmp_path.as_posix()) - sdist_name = api.build_sdist(tmp_path.as_posix()) - - zip_names = get_wheel_names(tmp_path / wheel_name) - assert "my_package/__init__.py" in zip_names - assert ( - "my_package/hellomodule.c" not in zip_names - ), "Not collect c files while building wheel" - extension_suffix = ".pyd" if sys.platform == "win32" else ".so" - assert any(name.endswith(extension_suffix) for name in zip_names) - - tar_names = get_tarball_names(tmp_path / sdist_name) - assert "demo_package-0.1.0/src/my_package/__init__.py" in tar_names - assert ( - "demo_package-0.1.0/src/my_package/hellomodule.c" in tar_names - ), "Collect c files while building sdist" - assert not any( - path.startswith("build") for path in tar_names - ), 'Not collect c files in temporary directory "./build"' - - -def test_build_editable(tmp_path: Path) -> None: - with build_fixture_project("demo-package") as project: - wheel_name = api.build_editable(tmp_path.as_posix()) - assert api.get_requires_for_build_editable() == ["editables"] - with zipfile.ZipFile(tmp_path / wheel_name) as zf: - namelist = zf.namelist() - assert "demo_package.pth" in namelist - assert "_editable_impl_demo_package.py" in namelist - assert "demo_package-0.1.0+editable.dist-info/licenses/LICENSE" in namelist + pth_content = zf.read("demo_package.pth").decode("utf-8").strip() + assert pth_content == "import _editable_impl_demo_package" - metadata = email.message_from_bytes( - zf.read("demo_package-0.1.0+editable.dist-info/METADATA") + proxy_module = zf.read("_editable_impl_demo_package.py").decode("utf-8").strip() + assert proxy_module == ( + "from editables.redirector import RedirectingFinder as F\n" + "F.install()\n" + "F.map_module('my_package', {!r})".format( + str((fixture_project / "my_package" / "__init__.py").resolve()) ) - assert "editables" in metadata.get_all("Requires-Dist", []) + ) - pth_content = zf.read("demo_package.pth").decode("utf-8").strip() - assert pth_content == "import _editable_impl_demo_package" - proxy_module = ( - zf.read("_editable_impl_demo_package.py").decode("utf-8").strip() - ) - assert proxy_module == ( - "from editables.redirector import RedirectingFinder as F\n" - "F.install()\n" - "F.map_module('my_package', {!r})".format( - str((project / "my_package" / "__init__.py").resolve()) - ) [email protected]("name", ["demo-src-package-include"]) +def test_build_editable_src(dist: Path, fixture_project: Path) -> None: + wheel_name = api.build_editable(dist.as_posix()) + + with zipfile.ZipFile(dist / wheel_name) as zf: + namelist = zf.namelist() + assert "demo_package.pth" in namelist + assert "_editable_impl_demo_package.py" in namelist + assert ( + "my_package/data.json" not in namelist + ), "data files in proxy modules are excluded" + assert "data_out.json" in namelist + + pth_content = zf.read("demo_package.pth").decode("utf-8").strip() + assert pth_content == "import _editable_impl_demo_package" + + proxy_module = zf.read("_editable_impl_demo_package.py").decode("utf-8").strip() + assert proxy_module == ( + "from editables.redirector import RedirectingFinder as F\n" + "F.install()\n" + "F.map_module('my_package', {!r})".format( + str((fixture_project / "sub" / "my_package" / "__init__.py").resolve()) ) + ) -def test_build_editable_src(tmp_path: Path) -> None: - with build_fixture_project("demo-src-package-include") as project: - wheel_name = api.build_editable(tmp_path.as_posix()) - - with zipfile.ZipFile(tmp_path / wheel_name) as zf: - namelist = zf.namelist() - assert "demo_package.pth" in namelist - assert "_editable_impl_demo_package.py" in namelist - assert ( - "my_package/data.json" not in namelist - ), "data files in proxy modules are excluded" - assert "data_out.json" in namelist - - pth_content = zf.read("demo_package.pth").decode("utf-8").strip() - assert pth_content == "import _editable_impl_demo_package" - - proxy_module = ( - zf.read("_editable_impl_demo_package.py").decode("utf-8").strip() - ) - assert proxy_module == ( - "from editables.redirector import RedirectingFinder as F\n" - "F.install()\n" - "F.map_module('my_package', {!r})".format( - str((project / "sub" / "my_package" / "__init__.py").resolve()) - ) - ) - [email protected]("name", ["demo-pep420-package"]) +def test_build_editable_pep420(dist: Path, fixture_project: Path) -> None: + with pytest.warns(UserWarning) as recorded: + wheel_name = api.build_editable(dist.as_posix()) + + assert len(recorded) == 1 + assert str(recorded.pop().message).startswith("editables backend is not available") + + with zipfile.ZipFile(dist / wheel_name) as zf: + namelist = zf.namelist() + assert "demo_package.pth" in namelist + assert "__editables_demo_package.py" not in namelist -def test_build_editable_pep420(tmp_path: Path) -> None: - with build_fixture_project("demo-pep420-package") as project: - with pytest.warns(UserWarning) as recorded: - wheel_name = api.build_editable(tmp_path.as_posix()) - - assert len(recorded) == 1 - assert str(recorded.pop().message).startswith( - "editables backend is not available" + metadata = email.message_from_bytes( + zf.read("demo_package-0.1.0+editable.dist-info/METADATA") ) + assert "editables" not in metadata.get_all("Requires-Dist", []) - with zipfile.ZipFile(tmp_path / wheel_name) as zf: - namelist = zf.namelist() - assert "demo_package.pth" in namelist - assert "__editables_demo_package.py" not in namelist - - metadata = email.message_from_bytes( - zf.read("demo_package-0.1.0+editable.dist-info/METADATA") - ) - assert "editables" not in metadata.get_all("Requires-Dist", []) - - pth_content = zf.read("demo_package.pth").decode("utf-8").strip() - assert pth_content == str(project.resolve()) + pth_content = zf.read("demo_package.pth").decode("utf-8").strip() + assert pth_content == str(fixture_project.resolve()) -def test_prepare_metadata_for_editable(tmp_path: Path) -> None: - with build_fixture_project("demo-package"): - dist_info = api.prepare_metadata_for_build_editable(tmp_path.as_posix()) - assert dist_info == "demo_package-0.1.0+editable.dist-info" - with (tmp_path / dist_info / "METADATA").open("rb") as metadata: - deps = email.message_from_binary_file(metadata).get_all("Requires-Dist") - assert "editables" in deps [email protected]("name", ["demo-package"]) +def test_prepare_metadata_for_editable(dist: Path) -> None: + dist_info = api.prepare_metadata_for_build_editable(dist.as_posix()) + assert dist_info == "demo_package-0.1.0+editable.dist-info" + with (dist / dist_info / "METADATA").open("rb") as metadata: + deps = email.message_from_binary_file(metadata).get_all("Requires-Dist") + assert "editables" in deps -def test_build_purelib_project_with_build(tmp_path: Path) -> None: - with build_fixture_project("demo-purelib-with-build"): - wheel_name = api.build_wheel(tmp_path.as_posix()) - assert wheel_name == "demo_package-0.1.0-py3-none-any.whl" [email protected]("name", ["demo-purelib-with-build"]) +def test_build_purelib_project_with_build(dist: Path) -> None: + wheel_name = api.build_wheel(dist.as_posix()) + assert wheel_name == "demo_package-0.1.0-py3-none-any.whl" - with zipfile.ZipFile(tmp_path / wheel_name) as zf: - wheel_metadata = email.message_from_bytes( - zf.read("demo_package-0.1.0.dist-info/WHEEL") - ) - version = zf.read("my_package/version.txt").decode("utf-8").strip() - assert version == "0.1.0" - assert wheel_metadata["Root-Is-Purelib"] == "true" + with zipfile.ZipFile(dist / wheel_name) as zf: + wheel_metadata = email.message_from_bytes( + zf.read("demo_package-0.1.0.dist-info/WHEEL") + ) + version = zf.read("my_package/version.txt").decode("utf-8").strip() + assert version == "0.1.0" + assert wheel_metadata["Root-Is-Purelib"] == "true" @pytest.mark.skipif( sys.platform.startswith("win"), reason="Check file mode on Unix only" ) -def test_build_wheel_preserve_permission(tmp_path: Path) -> None: - with build_fixture_project("demo-package"): - wheel_name = api.build_wheel(tmp_path.as_posix()) - with zipfile.ZipFile(tmp_path / wheel_name) as zf: - info = zf.getinfo("my_package/executable") - filemode = info.external_attr >> 16 - assert filemode & 0o111 [email protected]("name", ["demo-package"]) +def test_build_wheel_preserve_permission(dist: Path) -> None: + wheel_name = api.build_wheel(dist.as_posix()) + with zipfile.ZipFile(dist / wheel_name) as zf: + info = zf.getinfo("my_package/executable") + filemode = info.external_attr >> 16 + assert filemode & 0o111 -def test_build_wheel_write_version_to_file(project_with_scm: Path) -> None: - builder = WheelBuilder(project_with_scm) [email protected]("scm") [email protected]("name", ["demo-using-scm"]) +def test_build_wheel_write_version_to_file(fixture_project: Path, dist) -> None: + builder = WheelBuilder(fixture_project) builder.config.data.setdefault("tool", {}).setdefault("pdm", {})["version"] = { "source": "scm", "write_to": "foo/__version__.py", } with builder: - wheel_name = builder.build(project_with_scm / "dist") + wheel_name = builder.build(dist) with zipfile.ZipFile(wheel_name) as zf: version = zf.read("foo/__version__.py").decode("utf-8").strip() assert version == "0.1.0" -def test_build_wheel_write_version_to_file_template(project_with_scm: Path) -> None: - builder = WheelBuilder(project_with_scm) [email protected]("scm") [email protected]("name", ["demo-using-scm"]) +def test_build_wheel_write_version_to_file_template( + fixture_project: Path, dist: Path +) -> None: + builder = WheelBuilder(fixture_project) builder.config.data.setdefault("tool", {}).setdefault("pdm", {})["version"] = { "source": "scm", "write_to": "foo/__version__.py", "write_template": '__version__ = "{}"\n', } with builder: - wheel_name = builder.build(project_with_scm / "dist") + wheel_name = builder.build(dist) with zipfile.ZipFile(wheel_name) as zf: version = zf.read("foo/__version__.py").decode("utf-8").strip() assert version == '__version__ = "0.1.0"' -def test_override_scm_version_via_env_var(tmp_path: Path, monkeypatch) -> None: [email protected]("name", ["demo-using-scm"]) +def test_override_scm_version_via_env_var( + dist: Path, monkeypatch: pytest.MonkeyPatch +) -> None: monkeypatch.setenv("PDM_BUILD_SCM_VERSION", "1.0.0") - with build_fixture_project("demo-using-scm"): - wheel_name = api.build_wheel(tmp_path.as_posix()) - assert wheel_name == "foo-1.0.0-py3-none-any.whl" + wheel_name = api.build_wheel(dist.as_posix()) + assert wheel_name == "foo-1.0.0-py3-none-any.whl" [email protected]("scm") @pytest.mark.parametrize("getter", ["get_version:run", "get_version:run()"]) -def test_get_version_from_call(project_with_scm: Path, getter: str) -> None: - builder = WheelBuilder(project_with_scm) [email protected]("name", ["demo-using-scm"]) +def test_get_version_from_call(fixture_project: Path, getter: str, dist: Path) -> None: + builder = WheelBuilder(fixture_project) builder.config.data.setdefault("tool", {}).setdefault("pdm", {})["version"] = { "source": "call", "write_to": "foo/__version__.py", "getter": getter, } - project_with_scm.joinpath("get_version.py").write_text( - "def run(): return '1.1.1'\n" - ) + fixture_project.joinpath("get_version.py").write_text("def run(): return '1.1.1'\n") with builder: - wheel_name = builder.build(project_with_scm / "dist") + wheel_name = builder.build(dist) assert wheel_name.name == "foo-1.1.1-py3-none-any.whl" with zipfile.ZipFile(wheel_name) as zf: version = zf.read("foo/__version__.py").decode("utf-8").strip() assert version == "1.1.1" [email protected]("scm") @pytest.mark.parametrize( "settings, cleanup", [("true", False), ("false", True), ("0", True), ("1", False)] ) [email protected]("name", ["demo-using-scm"]) def test_clean_not_called_if_envset( - project_with_scm: Path, + fixture_project: Path, monkeypatch: pytest.MonkeyPatch, settings: str, cleanup: bool, + dist: Path, ) -> None: monkeypatch.setenv("PDM_BUILD_NO_CLEAN", settings) - builder = WheelBuilder(project_with_scm) + builder = WheelBuilder(fixture_project) builder.config.data.setdefault("tool", {}).setdefault("pdm", {})["version"] = { "source": "scm", "write_to": "foo/__version__.py", } - test_file = project_with_scm / ".pdm-build" / "testfile" - os.makedirs(project_with_scm / ".pdm-build", exist_ok=True) + test_file = fixture_project / ".pdm-build" / "testfile" + os.makedirs(fixture_project / ".pdm-build", exist_ok=True) test_file.touch() assert os.path.exists(test_file) with builder: - builder.build(project_with_scm / "dist") + builder.build(dist) if cleanup: assert not os.path.exists(test_file) else: assert os.path.exists(test_file) [email protected]("scm") @pytest.mark.parametrize( "settings, cleanup", [("", False), (True, False), (None, False)] ) [email protected]("name", ["demo-using-scm"]) def test_clean_not_called_if_config_settings_exist( - project_with_scm: Path, settings: bool, cleanup: bool + fixture_project: Path, settings: bool, cleanup: bool, dist: Path ) -> None: builder = WheelBuilder( - project_with_scm, config_settings={"no-clean-build": settings} + fixture_project, config_settings={"no-clean-build": settings} ) builder.config.data.setdefault("tool", {}).setdefault("pdm", {})["version"] = { "source": "scm", "write_to": "foo/__version__.py", } - test_file = project_with_scm / ".pdm-build" / "testfile" - os.makedirs(project_with_scm / ".pdm-build", exist_ok=True) + test_file = fixture_project / ".pdm-build" / "testfile" + os.makedirs(fixture_project / ".pdm-build", exist_ok=True) test_file.touch() assert os.path.exists(test_file) with builder: - builder.build(project_with_scm / "dist") + builder.build(dist) if cleanup: assert not os.path.exists(test_file) else: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/tests/test_utils.py new/pdm_backend-2.1.8/tests/test_utils.py --- old/pdm_backend-2.1.0/tests/test_utils.py 2023-06-08 10:15:04.713250400 +0200 +++ new/pdm_backend-2.1.8/tests/test_utils.py 2023-12-27 08:00:03.143141300 +0100 @@ -1,10 +1,27 @@ +import os + +import pytest + from pdm.backend.utils import expand_vars +is_nt = os.name == "nt" + -def test_expand_vars(monkeypatch): [email protected](is_nt, reason="Posix path") +def test_expand_vars_posix(monkeypatch): monkeypatch.setenv("FOO", "foo=a") monkeypatch.setenv("BAR", "bar") root = "/abc/def" line = "file:///${PROJECT_ROOT}/${FOO}:${BAR}:${BAZ}" assert expand_vars(line, root) == "file:///abc/def/foo%3Da:bar:${BAZ}" + + [email protected](not is_nt, reason="Windows path") +def test_expand_vars_win(monkeypatch): + monkeypatch.setenv("FOO", "foo=a") + monkeypatch.setenv("BAR", "bar") + root = "C:/abc/def" + + line = "file:///${PROJECT_ROOT}/${FOO}:${BAR}:${BAZ}" + assert expand_vars(line, root) == "file:///C:/abc/def/foo%3Da:bar:${BAZ}" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdm_backend-2.1.0/tests/testutils.py new/pdm_backend-2.1.8/tests/testutils.py --- old/pdm_backend-2.1.0/tests/testutils.py 2023-06-08 10:15:04.713250400 +0200 +++ new/pdm_backend-2.1.8/tests/testutils.py 2023-12-27 08:00:03.143141300 +0100 @@ -1,11 +1,7 @@ -import contextlib import tarfile import zipfile from pathlib import Path -from typing import Iterator, List - -from pdm.backend import utils -from tests import FIXTURES +from typing import List def get_tarball_names(path: Path) -> List[str]: @@ -16,10 +12,3 @@ def get_wheel_names(path: Path) -> List[str]: with zipfile.ZipFile(path) as zf: return zf.namelist() - - [email protected] -def build_fixture_project(project_name: str) -> Iterator[Path]: - project = FIXTURES / "projects" / project_name - with utils.cd(project): - yield project
