update: make uv run paperlib --help works
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
"""A tiny local build backend for paperlib.
|
||||
|
||||
This keeps `uv run paperlib ...` working without requiring network access
|
||||
to download a third-party build backend.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
from zipfile import ZIP_DEFLATED, ZipFile
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parent
|
||||
SRC_ROOT = PROJECT_ROOT / "src"
|
||||
PACKAGE_ROOT = SRC_ROOT / "paperlib"
|
||||
NAME = "paperlib"
|
||||
VERSION = "0.1.0"
|
||||
|
||||
|
||||
def _dist_info_dir() -> str:
|
||||
return f"{NAME}-{VERSION}.dist-info"
|
||||
|
||||
|
||||
def _wheel_name() -> str:
|
||||
return f"{NAME}-{VERSION}-py3-none-any.whl"
|
||||
|
||||
|
||||
def _metadata_contents() -> bytes:
|
||||
return "\n".join(
|
||||
[
|
||||
"Metadata-Version: 2.1",
|
||||
f"Name: {NAME}",
|
||||
f"Version: {VERSION}",
|
||||
"Summary: Local-first CLI toolkit for managing a paper library",
|
||||
"",
|
||||
]
|
||||
).encode("utf-8")
|
||||
|
||||
|
||||
def _wheel_contents() -> bytes:
|
||||
return "\n".join(
|
||||
[
|
||||
"Wheel-Version: 1.0",
|
||||
"Generator: paperlib_build_backend",
|
||||
"Root-Is-Purelib: true",
|
||||
"Tag: py3-none-any",
|
||||
"",
|
||||
]
|
||||
).encode("utf-8")
|
||||
|
||||
|
||||
def _entry_points_contents() -> bytes:
|
||||
return b"[console_scripts]\npaperlib = paperlib.cli:main\n"
|
||||
|
||||
|
||||
def _hash_bytes(data: bytes) -> tuple[str, str]:
|
||||
digest = hashlib.sha256(data).digest()
|
||||
encoded = base64.urlsafe_b64encode(digest).rstrip(b"=").decode("ascii")
|
||||
return f"sha256={encoded}", str(len(data))
|
||||
|
||||
|
||||
def _package_files() -> list[tuple[str, bytes]]:
|
||||
files: list[tuple[str, bytes]] = []
|
||||
for path in sorted(PACKAGE_ROOT.rglob("*")):
|
||||
if path.is_file():
|
||||
relative = path.relative_to(SRC_ROOT).as_posix()
|
||||
files.append((relative, path.read_bytes()))
|
||||
return files
|
||||
|
||||
|
||||
def _build_records(files: list[tuple[str, bytes]]) -> bytes:
|
||||
record_path = f"{_dist_info_dir()}/RECORD"
|
||||
rows: list[list[str]] = []
|
||||
for path, data in files:
|
||||
digest, size = _hash_bytes(data)
|
||||
rows.append([path, digest, size])
|
||||
rows.append([record_path, "", ""])
|
||||
|
||||
output: list[str] = []
|
||||
for row in rows:
|
||||
output.append(",".join(row))
|
||||
return ("\n".join(output) + "\n").encode("utf-8")
|
||||
|
||||
|
||||
def _build_wheel_archive(target: Path) -> str:
|
||||
files = _package_files()
|
||||
files.extend(
|
||||
[
|
||||
(f"{_dist_info_dir()}/METADATA", _metadata_contents()),
|
||||
(f"{_dist_info_dir()}/WHEEL", _wheel_contents()),
|
||||
(f"{_dist_info_dir()}/entry_points.txt", _entry_points_contents()),
|
||||
]
|
||||
)
|
||||
files.append((f"{_dist_info_dir()}/RECORD", _build_records(files)))
|
||||
|
||||
wheel_path = target / _wheel_name()
|
||||
with ZipFile(wheel_path, "w", compression=ZIP_DEFLATED) as zf:
|
||||
for archive_path, data in files:
|
||||
zf.writestr(archive_path, data)
|
||||
return wheel_path.name
|
||||
|
||||
|
||||
def build_wheel(
|
||||
wheel_directory: str,
|
||||
config_settings: dict[str, object] | None = None,
|
||||
metadata_directory: str | None = None,
|
||||
) -> str:
|
||||
"""Build a wheel for paperlib."""
|
||||
del config_settings, metadata_directory
|
||||
target = Path(wheel_directory)
|
||||
target.mkdir(parents=True, exist_ok=True)
|
||||
return _build_wheel_archive(target)
|
||||
|
||||
|
||||
def build_editable(
|
||||
wheel_directory: str,
|
||||
config_settings: dict[str, object] | None = None,
|
||||
metadata_directory: str | None = None,
|
||||
) -> str:
|
||||
"""Build an installable wheel for editable requests.
|
||||
|
||||
For now, we return a normal pure-Python wheel; that is sufficient for the
|
||||
project's current bootstrap needs.
|
||||
"""
|
||||
return build_wheel(wheel_directory, config_settings, metadata_directory)
|
||||
|
||||
|
||||
def get_requires_for_build_wheel(
|
||||
config_settings: dict[str, object] | None = None,
|
||||
) -> list[str]:
|
||||
"""This backend has no external build requirements."""
|
||||
del config_settings
|
||||
return []
|
||||
|
||||
|
||||
def get_requires_for_build_editable(
|
||||
config_settings: dict[str, object] | None = None,
|
||||
) -> list[str]:
|
||||
"""This backend has no external build requirements."""
|
||||
del config_settings
|
||||
return []
|
||||
|
||||
|
||||
def prepare_metadata_for_build_wheel(
|
||||
metadata_directory: str,
|
||||
config_settings: dict[str, object] | None = None,
|
||||
) -> str:
|
||||
"""Write minimal dist-info metadata for frontends that request it."""
|
||||
del config_settings
|
||||
dist_info = Path(metadata_directory) / _dist_info_dir()
|
||||
dist_info.mkdir(parents=True, exist_ok=True)
|
||||
(dist_info / "METADATA").write_bytes(_metadata_contents())
|
||||
(dist_info / "WHEEL").write_bytes(_wheel_contents())
|
||||
(dist_info / "entry_points.txt").write_bytes(_entry_points_contents())
|
||||
(dist_info / "RECORD").write_text("", encoding="utf-8")
|
||||
return dist_info.name
|
||||
|
||||
|
||||
def prepare_metadata_for_build_editable(
|
||||
metadata_directory: str,
|
||||
config_settings: dict[str, object] | None = None,
|
||||
) -> str:
|
||||
"""Alias editable metadata generation to the wheel metadata implementation."""
|
||||
return prepare_metadata_for_build_wheel(metadata_directory, config_settings)
|
||||
Reference in New Issue
Block a user