pyproject-api

1.10.0 · active · verified Sun Apr 05

pyproject-api is a Python library that provides an abstract API for interacting with `pyproject.toml`-based projects. It standardizes the communication with various build backends (like setuptools, Hatchling, Flit) as defined by PEP 517 and PEP 660, allowing tools to build, inspect, and manage Python packages without direct knowledge of the underlying build system. The library is actively maintained by the tox-dev team and is currently at version 1.10.0, with regular releases to support new Python versions and address issues.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to use `pyproject_api.Frontend` to programmatically interact with a project structured around `pyproject.toml`. It sets up a minimal project with a dummy build backend, then uses `Frontend` to query build requirements and simulate building a wheel. The `backend_paths` argument is essential for `pyproject-api` to locate and import your custom build backend module.

import sys
from pathlib import Path
import tempfile
import shutil

# Create a temporary project directory
temp_dir = Path(tempfile.mkdtemp())
project_root = temp_dir / "my_project"
project_root.mkdir()

# Create a minimal pyproject.toml
pyproject_toml_content = '''
[build-system]
requires = ["my-dummy-backend"]
build-backend = "my_dummy_backend:MyDummyBackend"

[project]
name = "my-example-package"
version = "0.0.1"
'''
(project_root / "pyproject.toml").write_text(pyproject_toml_content)

# Create a dummy build backend module (my_dummy_backend.py)
backend_module_content = '''
from pathlib import Path

class MyDummyBackend:
    def __init__(self, directory): # pyproject-api passes the project directory
        self.directory = Path(directory)
        self.name = "my-example-package"

    def get_requires_for_build_wheel(self, config_settings=None):
        return []

    def build_wheel(self, wheel_directory, config_settings=None, metadata_directory=None):
        # Simulate building a wheel file
        wheel_name = f"{self.name}-0.0.1-py3-none-any.whl"
        (Path(wheel_directory) / wheel_name).touch()
        return wheel_name
'''
(project_root / "my_dummy_backend.py").write_text(backend_module_content)

from pyproject_api import Frontend, BackendFailed

print(f"Created temporary project at: {project_root}")

try:
    # Initialize the Frontend to interact with our dummy project
    # backend_paths is crucial to make 'my_dummy_backend' importable
    frontend = Frontend(
        root=project_root,
        backend_paths=[project_root],
        backend_module="my_dummy_backend",
        backend_obj="MyDummyBackend", # The class name to instantiate
        requires=[], # Our dummy backend doesn't have build requirements itself
        reuse_backend=False
    )

    # Get build requirements (should be empty for our dummy backend)
    build_requirements = frontend.get_requires_for_build_wheel()
    print(f"Build requirements reported by backend: {build_requirements.requires}")

    # Build a wheel
    build_dir = temp_dir / "dist"
    build_dir.mkdir()
    print(f"Attempting to build wheel into: {build_dir}")
    wheel_result = frontend.build_wheel(build_dir)
    print(f"Successfully built wheel: {wheel_result.path.name}")
    print(f"Wheel file location: {wheel_result.path}")

except BackendFailed as e:
    print(f"Backend operation failed: {e.exc_msg}")
    print(f"Backend stdout: {e.out}")
    print(f"Backend stderr: {e.err}")
except Exception as e:
    print(f"An unexpected error occurred: {e}")
finally:
    # Clean up the temporary directory
    if temp_dir.exists():
        shutil.rmtree(temp_dir)
        print(f"Cleaned up temporary directory: {temp_dir}")

view raw JSON →