CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-poetry-core

Poetry PEP 517 Build Backend for building Python packages with lightweight, compliant, self-contained build system

Pending
Overview
Eval results
Files

builders.mddocs/

Package Builders

Poetry Core provides a modern package building system supporting wheels, source distributions (sdists), and editable installs. The builders handle file collection, metadata generation, and package creation according to Python packaging standards.

Core Imports

from poetry.core.masonry.builders.builder import Builder
from poetry.core.masonry.builders.wheel import WheelBuilder
from poetry.core.masonry.builders.sdist import SdistBuilder
from poetry.core.masonry.metadata import Metadata
``` { .api }

## Base Builder Class

### Builder

Abstract base class for all package builders providing common functionality.

```python
class Builder:
    """
    Abstract base class for package builders.
    
    Provides common functionality for file discovery, exclusion handling,
    and metadata generation across different package formats.
    """
    
    format: str | None = None  # Format identifier ("wheel", "sdist", etc.)
    
    def __init__(
        self,
        poetry: Poetry,
        executable: Path | None = None,
        config_settings: dict[str, Any] | None = None,
    ) -> None:
        """
        Initialize builder.
        
        Args:
            poetry: Poetry instance representing the project
            executable: Python executable to use (defaults to current)
            config_settings: Build configuration settings
            
        Raises:
            RuntimeError: If project is not in package mode
            
        Example:
            >>> from poetry.core.factory import Factory
            >>> poetry = Factory().create_poetry()
            >>> builder = SdistBuilder(poetry)
        """
        
    @property
    def executable(self) -> Path:
        """Python executable used for building."""
        
    @property
    def default_target_dir(self) -> Path:
        """Default directory for build outputs (typically ./dist)."""
        
    def build(self, target_dir: Path | None) -> Path:
        """
        Build package to target directory.
        
        Args:
            target_dir: Directory to write package file
            
        Returns:
            Path to built package file
            
        Note:
            Must be implemented by subclasses
        """
        raise NotImplementedError
        
    def find_files_to_add(self) -> list[BuildIncludeFile]:
        """
        Find all files to include in the package.
        
        Returns:
            List of files to add to package with their metadata
            
        Note:
            Handles package discovery, file includes/excludes,
            and VCS integration for determining files.
        """
        
    def find_excluded_files(self, fmt: str | None = None) -> set[str]:
        """
        Find files excluded from packaging.
        
        Args:
            fmt: Format to check exclusions for
            
        Returns:
            Set of excluded file paths
            
        Note:
            Uses VCS ignore files, Poetry configuration excludes,
            and format-specific exclusion rules.
        """
``` { .api }

## Wheel Builder

### WheelBuilder

Builds wheel packages according to PEP 427.

```python
class WheelBuilder(Builder):
    """
    Wheel package builder implementing PEP 427.
    
    Creates .whl files containing compiled Python packages
    with proper metadata and installation support.
    """
    
    format = "wheel"
    
    def __init__(
        self,
        poetry: Poetry,
        original: Path | None = None,
        executable: Path | None = None,
        editable: bool = False,
        metadata_directory: Path | None = None,
        config_settings: dict[str, Any] | None = None,
    ) -> None:
        """
        Initialize wheel builder.
        
        Args:
            poetry: Poetry project instance
            original: Original project path (for advanced scenarios)
            executable: Python executable for building
            editable: Whether to build editable wheel
            metadata_directory: Pre-built metadata directory
            config_settings: Build configuration settings
            
        Example:
            >>> builder = WheelBuilder(poetry, editable=True)
            >>> builder = WheelBuilder(poetry, config_settings={"--build-option": ["--plat-name", "linux_x86_64"]})
        """
``` { .api }

### Class Methods

#### make_in

```python
@classmethod
def make_in(
    cls,
    poetry: Poetry,
    directory: Path | None = None,
    original: Path | None = None,
    executable: Path | None = None,
    editable: bool = False,
    metadata_directory: Path | None = None,
    config_settings: dict[str, Any] | None = None,
) -> str:
    """
    Build wheel in specified directory (class method).
    
    Args:
        poetry: Poetry project instance
        directory: Target directory for wheel file
        original: Original project path
        executable: Python executable for building  
        editable: Whether to build editable wheel
        metadata_directory: Pre-built metadata directory
        config_settings: Build configuration settings
        
    Returns:
        Filename of built wheel
        
    Example:
        >>> filename = WheelBuilder.make_in(poetry, Path("./dist"))
        >>> print(f"Built: {filename}")
        Built: mypackage-1.0.0-py3-none-any.whl
        
        >>> # Editable wheel
        >>> filename = WheelBuilder.make_in(poetry, Path("./dist"), editable=True)
        
        >>> # With configuration
        >>> filename = WheelBuilder.make_in(
        ...     poetry, 
        ...     Path("./dist"),
        ...     config_settings={"--build-option": ["--verbose"]}
        ... )
    """
``` { .api }

#### make

```python
@classmethod  
def make(cls, poetry: Poetry, executable: Path | None = None) -> None:
    """
    Build wheel in default location (./dist).
    
    Args:
        poetry: Poetry project instance
        executable: Python executable for building
        
    Example:
        >>> WheelBuilder.make(poetry)
        # Creates wheel in ./dist/ directory
    """
``` { .api }

### Properties

```python
@property
def wheel_filename(self) -> str:
    """
    Generated wheel filename.
    
    Returns:
        Wheel filename following PEP 427 naming convention
        Format: {name}-{version}-{python tag}-{abi tag}-{platform tag}.whl
        
    Example:
        >>> builder.wheel_filename
        'mypackage-1.0.0-py3-none-any.whl'
    """

@property
def tag(self) -> packaging.tags.Tag:
    """
    Wheel compatibility tag.
    
    Returns:
        Tag object describing Python/ABI/platform compatibility
    """

@property
def supports_tags(self) -> list[packaging.tags.Tag]:
    """List of all compatible tags for this wheel."""
``` { .api }

### Methods

```python
def build(self, target_dir: Path | None = None) -> Path:
    """
    Build wheel package.
    
    Args:
        target_dir: Directory to write wheel file
        
    Returns:
        Path to built wheel file
        
    Example:
        >>> wheel_path = builder.build(Path("./dist"))
        >>> print(f"Wheel created: {wheel_path}")
    """

def prepare_metadata(self, metadata_dir: Path) -> Path:
    """
    Prepare wheel metadata without building full wheel.
    
    Args:
        metadata_dir: Directory to write metadata
        
    Returns:
        Path to .dist-info directory containing metadata
        
    Note:
        Used by PEP 517 prepare_metadata_for_build_wheel hook
        for faster installation planning.
    """
``` { .api }

## Source Distribution Builder

### SdistBuilder

Builds source distribution packages according to PEP 518.

```python
class SdistBuilder(Builder):
    """
    Source distribution builder implementing PEP 518.
    
    Creates .tar.gz files containing source code and metadata
    for distribution and installation from source.
    """
    
    format = "sdist"
    
    def __init__(
        self,
        poetry: Poetry,
        executable: Path | None = None,
        config_settings: dict[str, Any] | None = None,
    ) -> None:
        """
        Initialize sdist builder.
        
        Args:
            poetry: Poetry project instance
            executable: Python executable for building
            config_settings: Build configuration settings
            
        Example:
            >>> builder = SdistBuilder(poetry)
            >>> builder = SdistBuilder(poetry, config_settings={"--formats": ["gztar"]})
        """
``` { .api }

### Methods

```python
def build(self, target_dir: Path | None = None) -> Path:
    """
    Build source distribution package.
    
    Args:
        target_dir: Directory to write sdist file
        
    Returns:
        Path to built sdist file (.tar.gz)
        
    Example:
        >>> sdist_path = builder.build(Path("./dist"))
        >>> print(f"Sdist created: {sdist_path}")
        Sdist created: ./dist/mypackage-1.0.0.tar.gz
    """

@property  
def sdist_filename(self) -> str:
    """
    Generated sdist filename.
    
    Returns:
        Sdist filename in format: {name}-{version}.tar.gz
        
    Example:
        >>> builder.sdist_filename
        'mypackage-1.0.0.tar.gz'
    """
``` { .api }

## Metadata Handling

### Metadata

Handles package metadata generation for distributions.

```python
class Metadata:
    """
    Package metadata generator for distributions.
    
    Creates standard metadata files (METADATA, WHEEL, entry_points.txt)
    according to packaging specifications.
    """
    
    @classmethod
    def from_package(cls, package: ProjectPackage) -> Metadata:
        """
        Create metadata from package information.
        
        Args:
            package: Project package instance
            
        Returns:
            Metadata instance ready for distribution generation
        """
        
    def write_to_directory(
        self, 
        directory: Path, 
        fmt: str | None = None
    ) -> None:
        """
        Write metadata files to directory.
        
        Args:
            directory: Target directory (typically .dist-info or .egg-info)
            fmt: Format context ("wheel" or "sdist")
            
        Note:
            Creates standard metadata files:
            - METADATA (core metadata)  
            - WHEEL (wheel-specific, for wheels only)
            - entry_points.txt (if entry points defined)
            - RECORD (for wheels, file hashes and sizes)
        """
``` { .api }

## Build Configuration

### Configuration Options

```python
# Common config_settings for builders
config_settings = {
    # Build options
    "--build-option": ["--verbose", "--plat-name", "linux_x86_64"],
    
    # Global options
    "--global-option": ["--quiet"],
    
    # Format-specific options
    "--formats": ["gztar"],  # For sdist
    
    # Local version label
    "local-version": "dev123",
    
    # Environment variables
    "env": {
        "POETRY_CORE_DEBUG": "1",
        "MAKEFLAGS": "-j4"
    }
}
``` { .api }

## Usage Examples

### Basic Package Building

```python
from pathlib import Path
from poetry.core.factory import Factory
from poetry.core.masonry.builders.wheel import WheelBuilder
from poetry.core.masonry.builders.sdist import SdistBuilder

def build_project(project_path: Path, output_dir: Path):
    """Build both wheel and sdist for a project."""
    
    # Create Poetry instance
    factory = Factory()
    poetry = factory.create_poetry(project_path)
    
    # Create output directory
    output_dir.mkdir(exist_ok=True, parents=True)
    
    print(f"Building {poetry.package.name} v{poetry.package.version}")
    
    try:
        # Build wheel
        print("Building wheel...")
        wheel_builder = WheelBuilder(poetry)
        wheel_path = wheel_builder.build(output_dir)
        print(f"✅ Wheel: {wheel_path.name}")
        
        # Build source distribution  
        print("Building sdist...")
        sdist_builder = SdistBuilder(poetry)
        sdist_path = sdist_builder.build(output_dir)
        print(f"✅ Sdist: {sdist_path.name}")
        
        return wheel_path, sdist_path
        
    except Exception as e:
        print(f"❌ Build failed: {e}")
        return None, None

# Usage
wheel, sdist = build_project(Path("./my-project"), Path("./dist"))
``` { .api }

### Advanced Wheel Building

```python
from poetry.core.masonry.builders.wheel import WheelBuilder

def build_specialized_wheels(poetry):
    """Build wheels with different configurations."""
    
    dist_dir = Path("./dist")
    dist_dir.mkdir(exist_ok=True)
    
    # Regular wheel
    print("Building regular wheel...")
    regular_wheel = WheelBuilder.make_in(poetry, dist_dir)
    print(f"Regular wheel: {regular_wheel}")
    
    # Editable wheel (for development)
    print("Building editable wheel...")
    editable_wheel = WheelBuilder.make_in(
        poetry, 
        dist_dir,
        editable=True
    )
    print(f"Editable wheel: {editable_wheel}")
    
    # Platform-specific wheel
    print("Building platform-specific wheel...")
    platform_config = {
        "--build-option": ["--plat-name", "linux_x86_64"]
    }
    platform_wheel = WheelBuilder.make_in(
        poetry,
        dist_dir, 
        config_settings=platform_config
    )
    print(f"Platform wheel: {platform_wheel}")
    
    # Development version wheel
    print("Building development wheel...")
    dev_config = {
        "local-version": f"dev{datetime.now().strftime('%Y%m%d')}"
    }
    dev_wheel = WheelBuilder.make_in(
        poetry,
        dist_dir,
        config_settings=dev_config
    )
    print(f"Dev wheel: {dev_wheel}")

# Usage
build_specialized_wheels(poetry)
``` { .api }

### Metadata Preparation

```python
from pathlib import Path
from poetry.core.masonry.builders.wheel import WheelBuilder

def prepare_metadata_only(poetry, metadata_dir: Path):
    """Prepare wheel metadata without building full wheel."""
    
    metadata_dir.mkdir(exist_ok=True, parents=True)
    
    # Create wheel builder
    builder = WheelBuilder(poetry)
    
    # Prepare metadata
    dist_info_dir = builder.prepare_metadata(metadata_dir)
    
    print(f"Metadata prepared in: {dist_info_dir}")
    
    # List metadata files
    print("Metadata files:")
    for file in dist_info_dir.iterdir():
        print(f"  {file.name}")
        
    # Read core metadata
    metadata_file = dist_info_dir / "METADATA"
    if metadata_file.exists():
        print(f"\nCore metadata preview:")
        print(metadata_file.read_text()[:500] + "...")
        
    return dist_info_dir

# Usage
metadata_dir = prepare_metadata_only(poetry, Path("./metadata"))
``` { .api }

### Custom Build Process

```python
from poetry.core.masonry.builders.wheel import WheelBuilder
from poetry.core.masonry.builders.sdist import SdistBuilder

class CustomBuilder:
    """Custom builder with additional processing."""
    
    def __init__(self, poetry):
        self.poetry = poetry
        
    def build_with_checks(self, target_dir: Path):
        """Build packages with pre/post checks."""
        
        # Pre-build validation
        print("🔍 Pre-build validation...")
        if not self._validate_project():
            print("❌ Validation failed")
            return
            
        # Build packages
        print("🏗️  Building packages...")
        results = {}
        
        try:
            # Build wheel
            wheel_builder = WheelBuilder(self.poetry)
            wheel_path = wheel_builder.build(target_dir)
            results['wheel'] = wheel_path
            print(f"✅ Wheel: {wheel_path.name}")
            
            # Build sdist
            sdist_builder = SdistBuilder(self.poetry)
            sdist_path = sdist_builder.build(target_dir)
            results['sdist'] = sdist_path
            print(f"✅ Sdist: {sdist_path.name}")
            
            # Post-build verification
            print("🔍 Post-build verification...")
            if self._verify_builds(results):
                print("✅ Build verification passed")
            else:
                print("⚠️  Build verification issues found")
                
            return results
            
        except Exception as e:
            print(f"❌ Build failed: {e}")
            return None
            
    def _validate_project(self) -> bool:
        """Validate project before building."""
        package = self.poetry.package
        
        # Check required metadata
        if not package.name or not package.version:
            print("Missing name or version")
            return False
            
        # Check for README
        if not package.readmes:
            print("⚠️  No README file found")
            
        # Check for license
        if not package.license:
            print("⚠️  No license specified")
            
        return True
        
    def _verify_builds(self, results: dict) -> bool:
        """Verify built packages."""
        issues = []
        
        for build_type, path in results.items():
            if not path.exists():
                issues.append(f"{build_type} file not found: {path}")
                continue
                
            # Check file size
            size = path.stat().st_size
            if size < 1024:  # Less than 1KB seems suspicious
                issues.append(f"{build_type} seems too small: {size} bytes")
                
        if issues:
            for issue in issues:
                print(f"⚠️  {issue}")
            return False
            
        return True

# Usage
custom_builder = CustomBuilder(poetry)
results = custom_builder.build_with_checks(Path("./dist"))
``` { .api }

### Build Monitoring and Progress

```python
import time
from pathlib import Path
from poetry.core.masonry.builders.wheel import WheelBuilder

def build_with_progress(poetry, target_dir: Path):
    """Build with progress monitoring."""
    
    print(f"🎯 Target directory: {target_dir}")
    target_dir.mkdir(exist_ok=True, parents=True)
    
    # Track build time
    start_time = time.time()
    
    try:
        print("📦 Initializing wheel builder...")
        builder = WheelBuilder(poetry)
        
        print("📝 Package information:")
        print(f"   Name: {poetry.package.name}")
        print(f"   Version: {poetry.package.version}")
        print(f"   Dependencies: {len(poetry.package.requires)}")
        
        print("🔍 Discovering files...")
        files = builder.find_files_to_add()
        print(f"   Found {len(files)} files to include")
        
        print("🚫 Finding excluded files...")
        excluded = builder.find_excluded_files()
        print(f"   Excluding {len(excluded)} files")
        
        print("🏗️  Building wheel...")
        wheel_path = builder.build(target_dir)
        
        # Build statistics
        build_time = time.time() - start_time
        wheel_size = wheel_path.stat().st_size
        
        print("✅ Build completed!")
        print(f"   Wheel: {wheel_path.name}")
        print(f"   Size: {wheel_size:,} bytes ({wheel_size/1024:.1f} KB)")
        print(f"   Time: {build_time:.2f} seconds")
        
        return wheel_path
        
    except Exception as e:
        build_time = time.time() - start_time
        print(f"❌ Build failed after {build_time:.2f} seconds: {e}")
        raise

# Usage
wheel_path = build_with_progress(poetry, Path("./dist"))
``` { .api }

## Error Handling

### Build Error Handling

```python
from poetry.core.masonry.builders.wheel import WheelBuilder
from poetry.core.masonry.builders.sdist import SdistBuilder

def safe_build_packages(poetry, target_dir: Path):
    """Build packages with comprehensive error handling."""
    
    results = {"success": [], "failed": []}
    
    builders = [
        ("wheel", WheelBuilder),
        ("sdist", SdistBuilder)
    ]
    
    for build_type, builder_class in builders:
        try:
            print(f"Building {build_type}...")
            
            builder = builder_class(poetry)
            package_path = builder.build(target_dir)
            
            results["success"].append({
                "type": build_type,
                "path": package_path,
                "size": package_path.stat().st_size
            })
            
            print(f"✅ {build_type.title()}: {package_path.name}")
            
        except RuntimeError as e:
            if "non-package mode" in str(e):
                print(f"❌ Cannot build {build_type}: Project not in package mode")
                results["failed"].append({"type": build_type, "error": "non-package mode"})
            else:
                print(f"❌ {build_type.title()} build failed: {e}")
                results["failed"].append({"type": build_type, "error": str(e)})
                
        except PermissionError as e:
            print(f"❌ Permission error building {build_type}: {e}")
            results["failed"].append({"type": build_type, "error": f"permission: {e}"})
            
        except OSError as e:
            print(f"❌ OS error building {build_type}: {e}")
            results["failed"].append({"type": build_type, "error": f"os: {e}"})
            
        except Exception as e:
            print(f"❌ Unexpected error building {build_type}: {e}")
            results["failed"].append({"type": build_type, "error": f"unexpected: {e}"})
    
    # Summary
    print(f"\n📊 Build Summary:")
    print(f"   Successful: {len(results['success'])}")
    print(f"   Failed: {len(results['failed'])}")
    
    if results["success"]:
        print(f"   Built packages:")
        for pkg in results["success"]:
            print(f"     {pkg['type']}: {pkg['path'].name} ({pkg['size']:,} bytes)")
    
    return results

# Usage
results = safe_build_packages(poetry, Path("./dist"))
``` { .api }

## Type Definitions

```python
from typing import Any, Dict, List, Tuple
from pathlib import Path

# Build configuration types
BuildConfig = Dict[str, Any]
ConfigSettings = Dict[str, Any] | None

# File handling types
BuildIncludeFile = Any  # Internal build file representation
ExcludedFiles = set[str]

# Builder result types
BuildResult = Path
WheelTag = str
MetadataPath = Path
``` { .api }

Install with Tessl CLI

npx tessl i tessl/pypi-poetry-core

docs

build-backend.md

builders.md

configuration.md

constraints.md

factory-core.md

index.md

json-validation.md

packages.md

utilities.md

vcs-support.md

version-system.md

tile.json