pyproject-hooks
Low-level Python library for invoking PEP 517/660 build-backend hooks in an isolated subprocess.
Repository Health
Technical Analysis
pyproject-hooks is the plumbing underneath modern Python packaging: a small, dependency-free library that knows how to call a pyproject.toml-declared build backend’s hooks (build_wheel, build_sdist, build_editable, and their metadata/requirements counterparts) safely in a subprocess. It does not build packages itself, manage environments, or provide a CLI — it exists purely so that higher-level frontends like pip and build don’t each have to reimplement PEP 517/660’s subprocess protocol, JSON handshake, and fallback rules from scratch.
Maintained by the Python Packaging Authority (PyPA) as the direct successor to the older pep517 package, it’s one of the most widely depended-upon libraries in the Python ecosystem by download volume, despite almost never being imported directly by application developers — it sits quietly inside every pip install that triggers a source build.
What You Get
BuildBackendHookCallerwith methods forbuild_wheel,build_sdist,build_editable, and theirget_requires_for_*/prepare_metadata_for_*counterparts- Automatic fallback logic — e.g. deriving wheel metadata from a full
build_wheelcall when a backend doesn’t implementprepare_metadata_for_build_wheel - Pluggable
SubprocessRunnerprotocol, with a default runner and aquiet_subprocess_runnerthat captures output for error reporting - Typed public API (ships a
py.typedmarker) with first-class exception types (BackendUnavailable,HookMissing,UnsupportedOperation) instead of generic errors - Support for
backend-path-relocated backends (PEP 517’s in-tree backend mechanism), with path-traversal checks vianorm_and_check
Common Use Cases
- Build frontends (like
piporbuild) invoking a project’s declared backend to produce a wheel or sdist without linking against that backend’s internals - Custom packaging tooling that needs to call arbitrary PEP 517 backends (setuptools, flit, hatchling, poetry-core, etc.) through one uniform interface
- CI or build-isolation systems that want a controllable subprocess runner to suppress or capture backend output
- Editable-install tooling that needs
build_editable/prepare_metadata_for_build_editablesupport across backends
Under The Hood
Architecture — BuildBackendHookCaller (in src/pyproject_hooks/_impl.py) wraps subprocess execution of PEP 517/660 hooks. Each public method (build_wheel, build_sdist, prepare_metadata_for_build_wheel, etc.) funnels through a private _call_hook, which writes a JSON {"kwargs": ...} payload to a temp directory, launches a subprocess running the bundled _in_process/_in_process.py script (located via _in_proc_script_path()) with the hook name and temp directory as arguments, then reads back output.json and re-raises any reported unsupported / no_backend / hook_missing conditions as typed exceptions, or re-emits captured warnings as BuildBackendWarning. norm_and_check guards PEP 517’s backend-path feature by rejecting absolute paths and paths that resolve outside the source tree. Tech Stack — pure Python with zero runtime dependencies (dependencies = [] in pyproject.toml), built and packaged with flit_core, targets Python >=3.8, and ships a py.typed marker for downstream type checkers; the dev toolchain runs ruff (lint + isort), black, and mypy via pre-commit, with nox driving multi-environment test runs. Code Quality — the tests/ suite (473 lines across test_call_hooks.py, test_hook_fallbacks.py, test_inplace_hooks.py) exercises real hook invocation, metadata-fallback behavior, and in-tree (backend-path) backends against sample fixture projects under tests/samples; pytest.ini enables --strict-config --strict-markers and turns warnings into errors (filterwarnings = error), which is a stricter bar than most libraries of this size hold themselves to. Exception types carry structured attributes (backend_name, backend_path, traceback) rather than plain strings, making failures easy to introspect programmatically. API Design — the public surface is deliberately tiny: one class whose method names map 1:1 onto PEP 517/660 hook names, plus two ready-made subprocess runners and a context-manager override (with hook_caller.subprocess_runner(...)) for swapping runners mid-flight. Every method’s docstring documents its fallback behavior explicitly under a dedicated “Fallback” admonition, and the hosted Sphinx docs mirror this closely — unusually thorough documentation discipline for an internal-plumbing library that most of its users will never call directly.
Used by 2 apps in this directory
Agno
Devops · AI Development · Automation
Build, run, and manage agent platforms with a full production stack — SDK, runtime, and control plane included.
OSV.dev
Security
Google's open-source vulnerability database that maps CVEs to exact package versions across 50+ ecosystems with a public API and data dumps.