From ba90ece0dbbed8c458efab020aaa6f40c30b59bf Mon Sep 17 00:00:00 2001 From: John Sirois Date: Sat, 2 Aug 2025 14:03:07 -0700 Subject: [PATCH] Use `pex.build_backend.wrap` to embed dist lock. --- CHANGES.md | 5 + build-backend/dev_cmd_build/__init__.py | 2 - .../dev_cmd_build/setuptools/__init__.py | 2 - .../dev_cmd_build/setuptools/build.py | 118 ------------------ dev_cmd/__init__.py | 2 +- pyproject.toml | 29 ++++- 6 files changed, 32 insertions(+), 126 deletions(-) delete mode 100644 build-backend/dev_cmd_build/__init__.py delete mode 100644 build-backend/dev_cmd_build/setuptools/__init__.py delete mode 100644 build-backend/dev_cmd_build/setuptools/build.py diff --git a/CHANGES.md b/CHANGES.md index e5cccc5..ba1ec7e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,10 @@ # Release Notes +## 0.32.3 + +This release switches from a bespoke lock embedding in dev-cmd distributuons to use of the +`pex.build_backend.wrap` delegating backend to embed the dev-cmd lock. + ## 0.32.2 This release fixes the dev-cmd wheel `RECORD` metadata to be Windows compatible. diff --git a/build-backend/dev_cmd_build/__init__.py b/build-backend/dev_cmd_build/__init__.py deleted file mode 100644 index a939005..0000000 --- a/build-backend/dev_cmd_build/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# Copyright 2025 John Sirois. -# Licensed under the Apache License, Version 2.0 (see LICENSE). diff --git a/build-backend/dev_cmd_build/setuptools/__init__.py b/build-backend/dev_cmd_build/setuptools/__init__.py deleted file mode 100644 index a939005..0000000 --- a/build-backend/dev_cmd_build/setuptools/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# Copyright 2025 John Sirois. -# Licensed under the Apache License, Version 2.0 (see LICENSE). diff --git a/build-backend/dev_cmd_build/setuptools/build.py b/build-backend/dev_cmd_build/setuptools/build.py deleted file mode 100644 index 4be7597..0000000 --- a/build-backend/dev_cmd_build/setuptools/build.py +++ /dev/null @@ -1,118 +0,0 @@ -# Copyright 2025 John Sirois. -# Licensed under the Apache License, Version 2.0 (see LICENSE). - -from __future__ import annotations - -import base64 -import csv -import hashlib -import os.path -import shutil -import subprocess -import tarfile -import tempfile -import zipfile -from contextlib import contextmanager -from pathlib import Path -from typing import Any, Iterator - -import setuptools.build_meta - -# We re-export all the setuptools PEP-517 build backend hooks here for the build frontend to call. -from setuptools.build_meta import * # NOQA - -from dev_cmd import __version__ - - -def _add_lock(dest_dir: Path) -> Path: - dest_dir.mkdir(parents=True, exist_ok=True) - pylock_toml = dest_dir / "pylock.toml" - subprocess.run( - args=[ - "uv", - "export", - "--format", - "pylock.toml", - "--no-header", - "--no-emit-project", - "--all-extras", - "--no-dev", - "-q", - "-o", - pylock_toml, - ], - check=True, - ) - return pylock_toml - - -@contextmanager -def _build_dir(name: str) -> Iterator[Path]: - tmpdir = Path(tempfile.mkdtemp(prefix="dev-cmd.", suffix=f".{name}-build-dir")) - try: - yield tmpdir - finally: - shutil.rmtree(tmpdir, ignore_errors=True) - - -def build_sdist(sdist_directory: str, config_settings: dict[str, Any] | None = None) -> str: - sdist_name = setuptools.build_meta.build_sdist(sdist_directory, config_settings) - - sdist_path = Path(sdist_directory) / sdist_name - tarball_root_dir_name = f"dev_cmd-{__version__}" - - with _build_dir("sdist") as tmpdir: - tarball_root_dir = tmpdir / tarball_root_dir_name - with tarfile.open(sdist_path) as tf: - tf.extractall(tmpdir) - _add_lock(tarball_root_dir) - with tarfile.open(sdist_path, "w:gz") as tf: - tf.add(tarball_root_dir, tarball_root_dir_name) - return sdist_name - - -def build_wheel( - wheel_directory: str, - config_settings: dict[str, Any] | None = None, - metadata_directory: str | None = None, -) -> str: - wheel_name = setuptools.build_meta.build_wheel( - wheel_directory, config_settings, metadata_directory - ) - - wheel_path = Path(wheel_directory) / wheel_name - dist_info_dir_name = f"dev_cmd-{__version__}.dist-info" - - with _build_dir("wheel") as tmpdir: - with zipfile.ZipFile(wheel_path) as zf: - original_contents = zf.namelist() - zf.extractall(tmpdir) - - pylock_toml = _add_lock(tmpdir / dist_info_dir_name / "pylock") - pylock_toml_data = pylock_toml.read_bytes() - fingerprint = base64.urlsafe_b64encode(hashlib.sha256(pylock_toml_data).digest()).rstrip( - b"=" - ) - pylock_toml_dest: str | None = str(pylock_toml.relative_to(tmpdir).as_posix()) - record = tmpdir / dist_info_dir_name / "RECORD" - with record.open() as fp: - record_entries = list(csv.reader(fp)) - record_entries.append( - [pylock_toml_dest, f"sha256={fingerprint.decode('ascii')}", len(pylock_toml_data)] - ) - with (tmpdir / dist_info_dir_name / "RECORD").open(mode="w") as fp: - csv.writer(fp, delimiter=",", doublequote='"', lineterminator="\n").writerows( - sorted(record_entries) - ) - - with zipfile.ZipFile(wheel_path, "w") as zf: - for path in original_contents: - if ( - pylock_toml_dest - and dist_info_dir_name == os.path.commonpath((path, dist_info_dir_name)) - and pylock_toml_dest < path - ): - zf.write(pylock_toml, pylock_toml_dest) - pylock_toml_dest = None - zf.write(tmpdir / path, path) - return wheel_name diff --git a/dev_cmd/__init__.py b/dev_cmd/__init__.py index 005ff45..dfa2254 100644 --- a/dev_cmd/__init__.py +++ b/dev_cmd/__init__.py @@ -1,4 +1,4 @@ # Copyright 2024 John Sirois. # Licensed under the Apache License, Version 2.0 (see LICENSE). -__version__ = "0.32.2" +__version__ = "0.32.3" diff --git a/pyproject.toml b/pyproject.toml index 4290438..d581674 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,30 @@ [build-system] -requires = ["setuptools"] -backend-path = ["build-backend", ""] -build-backend = "dev_cmd_build.setuptools.build" +requires = [ + # 1st publication of pex.build_backend.wrap was in Pex 2.50.0. + "pex>=2.50", + + # 1st support for license expressions was in setuptools 77.0.0. + "setuptools>=77", +] +build-backend = "pex.build_backend.wrap" + +[tool.pex.build_backend] +delegate-build-backend = "setuptools.build_meta" + +[[tool.pex.build_backend.script-locks]] +command = [ + "uv", + "export", + "--format", + "pylock.toml", + "--no-header", + "--no-emit-project", + "--all-extras", + "--no-dev", + "-q", + "-o", + "{lock_path}", +] [project] name = "dev-cmd"