CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-hatchling

Modern, extensible Python build backend implementing PEP 517/660 standards with plugin architecture.

Pending
Overview
Eval results
Files

metadata.mddocs/

Metadata System

Project metadata parsing, validation, and core metadata generation following Python packaging standards. The metadata system handles project configuration, dependency management, and metadata validation.

Capabilities

Project Metadata

Core project metadata container that parses and validates project configuration.

class ProjectMetadata(Generic[PluginManagerBound]):
    def __init__(
        self,
        root: str,
        plugin_manager: PluginManager | None = None,
        config: dict | None = None
    ):
        """
        Initialize project metadata.
        
        Args:
            root: Project root directory path
            plugin_manager: Optional plugin manager instance
            config: Optional metadata configuration override
        """
    
    @property
    def name(self) -> str:
        """Project name."""
    
    @property
    def version(self) -> str:
        """Project version."""
    
    @property
    def description(self) -> str:
        """Project description."""
    
    @property
    def readme(self) -> str | None:
        """Project readme content."""
    
    @property
    def authors(self) -> list[dict[str, str]]:
        """Project authors list."""
    
    @property
    def maintainers(self) -> list[dict[str, str]]:
        """Project maintainers list."""
    
    @property
    def license(self) -> str | None:
        """Project license."""
    
    @property
    def keywords(self) -> list[str]:
        """Project keywords."""
    
    @property
    def classifiers(self) -> list[str]:
        """Project classifiers."""
    
    @property
    def urls(self) -> dict[str, str]:
        """Project URLs."""
    
    @property
    def dependencies(self) -> list[str]:
        """Project runtime dependencies."""
    
    @property
    def optional_dependencies(self) -> dict[str, list[str]]:
        """Project optional dependencies (extras)."""
    
    @property
    def requires_python(self) -> str | None:
        """Required Python version specification."""
    
    @property
    def dynamic(self) -> list[str]:
        """List of dynamic metadata fields."""

Build Metadata

Build-time metadata configuration and validation.

class BuildMetadata:
    def __init__(self, root: str, config: dict):
        """
        Initialize build metadata.
        
        Args:
            root: Project root directory
            config: Build metadata configuration
        """
    
    @property
    def build_requires(self) -> list[str]:
        """Build-time dependencies."""
    
    @property
    def build_backend(self) -> str:
        """Build backend specification."""
    
    @property
    def backend_path(self) -> list[str] | None:
        """Backend path specification."""

Core Metadata

Core metadata following Python packaging standards (PEP 314, PEP 566, etc.).

class CoreMetadata:
    def __init__(self, metadata: ProjectMetadata, config: dict):
        """
        Initialize core metadata.
        
        Args:
            metadata: Project metadata instance
            config: Core metadata configuration
        """
    
    def as_string(self) -> str:
        """
        Generate core metadata as string.
        
        Returns:
            str: Core metadata in email header format
        """
    
    def as_bytes(self) -> bytes:
        """
        Generate core metadata as bytes.
        
        Returns:
            bytes: Core metadata in email header format
        """

Hatch-Specific Metadata

Extended metadata configuration specific to Hatch projects.

class HatchMetadata(Generic[PluginManagerBound]):
    def __init__(
        self,
        root: str,
        config: dict,
        plugin_manager: PluginManager
    ):
        """
        Initialize Hatch metadata.
        
        Args:
            root: Project root directory
            config: Hatch metadata configuration
            plugin_manager: Plugin manager instance
        """
    
    @property
    def version_config(self) -> HatchVersionConfig:
        """Version configuration."""
    
    @property
    def metadata_settings(self) -> HatchMetadataSettings:
        """Metadata settings."""
    
    @property
    def build_config(self) -> dict:
        """Build configuration."""

class HatchVersionConfig(Generic[PluginManagerBound]):
    def __init__(
        self,
        root: str,
        config: dict,
        plugin_manager: PluginManager
    ):
        """
        Initialize version configuration.
        
        Args:
            root: Project root directory
            config: Version configuration
            plugin_manager: Plugin manager instance
        """
    
    @property
    def source(self) -> str:
        """Version source plugin name."""
    
    @property
    def scheme(self) -> str:
        """Version scheme plugin name."""
    
    @property
    def source_config(self) -> dict:
        """Version source configuration."""
    
    @property
    def scheme_config(self) -> dict:
        """Version scheme configuration."""

class HatchMetadataSettings(Generic[PluginManagerBound]):
    def __init__(
        self,
        root: str,
        config: dict,
        plugin_manager: PluginManager
    ):
        """
        Initialize metadata settings.
        
        Args:
            root: Project root directory
            config: Metadata settings configuration
            plugin_manager: Plugin manager instance
        """
    
    @property
    def hooks(self) -> dict[str, dict]:
        """Metadata hook configurations."""

Metadata Parsing

Configuration Sources

Hatchling reads metadata from multiple sources with precedence:

  1. pyproject.toml - Primary configuration file
  2. setup.py - Legacy setup script (limited support)
  3. setup.cfg - Legacy configuration file (limited support)

pyproject.toml Structure

[project]
name = "my-package"
version = "1.0.0"
description = "My package description"
readme = "README.md"
license = {text = "MIT"}
authors = [
    {name = "Author Name", email = "author@example.com"}
]
dependencies = [
    "requests>=2.25.0",
    "click>=8.0.0"
]
optional-dependencies = {
    dev = ["pytest", "black"],
    docs = ["sphinx", "myst-parser"]
}
requires-python = ">=3.8"
keywords = ["example", "package"]
classifiers = [
    "Development Status :: 4 - Beta",
    "Programming Language :: Python :: 3"
]

[project.urls]
Homepage = "https://example.com"
Documentation = "https://example.com/docs"
Repository = "https://github.com/user/repo"

[project.scripts]
my-cli = "my_package.cli:main"

[project.gui-scripts]
my-gui = "my_package.gui:main"

[project.entry-points."my.group"]
plugin = "my_package.plugin:MyPlugin"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.version]
source = "code"
path = "src/my_package/__about__.py"

[tool.hatch.build]
include = ["src/**/*.py"]
exclude = ["tests/"]

[tool.hatch.metadata]
allow-direct-references = true

Metadata Validation

Core Metadata Constructors

def get_core_metadata_constructors() -> dict[str, Callable]:
    """
    Get available core metadata constructor functions.
    
    Returns:
        dict: Mapping of version to constructor function
    """

Dynamic Metadata

Some metadata fields can be marked as dynamic and resolved at build time:

# Dynamic fields are resolved through plugins or build hooks
dynamic = ["version", "description", "dependencies"]

Metadata Validation Rules

  • Project name must be valid Python package name
  • Version must follow PEP 440 specification
  • Dependencies must use valid requirement specifications
  • Classifiers must be from the official classifier list
  • URLs must be valid URIs

Usage Examples

Basic Metadata Loading

import os
from hatchling.metadata.core import ProjectMetadata
from hatchling.plugin.manager import PluginManager

# Load project metadata
root = os.getcwd()
metadata = ProjectMetadata(root)

# Access metadata properties
print(f"Name: {metadata.name}")
print(f"Version: {metadata.version}")
print(f"Description: {metadata.description}")
print(f"Dependencies: {metadata.dependencies}")
print(f"Optional dependencies: {metadata.optional_dependencies}")

With Plugin Manager

# Create plugin manager first
plugin_manager = PluginManager(metadata)

# Metadata with plugin support
metadata = ProjectMetadata(root, plugin_manager=plugin_manager)

# Access dynamic metadata resolved through plugins
print(f"Dynamic version: {metadata.version}")

Core Metadata Generation

from hatchling.metadata.core import CoreMetadata

# Generate core metadata
core_metadata = CoreMetadata(metadata, config={})
metadata_string = core_metadata.as_string()

# Write to METADATA file
with open("PKG-INFO", "w") as f:
    f.write(metadata_string)

Custom Metadata Configuration

# Override metadata configuration
custom_config = {
    "name": "custom-name",
    "version": "2.0.0",
    "dependencies": ["requests", "click"]
}

metadata = ProjectMetadata(root, config=custom_config)

Accessing Hatch-Specific Metadata

from hatchling.metadata.core import HatchMetadata

# Load Hatch-specific metadata
hatch_metadata = HatchMetadata(root, config, plugin_manager)

# Access version configuration
version_config = hatch_metadata.version_config
print(f"Version source: {version_config.source}")
print(f"Version scheme: {version_config.scheme}")

# Access metadata settings
metadata_settings = hatch_metadata.metadata_settings
print(f"Metadata hooks: {metadata_settings.hooks}")

Error Handling

Common metadata errors and exceptions:

  • ValueError: Invalid metadata values or configurations
  • FileNotFoundError: Missing configuration files
  • KeyError: Missing required metadata fields
  • TypeError: Incorrect metadata field types

Metadata Hooks

Custom metadata hooks can modify metadata at build time:

from hatchling.metadata.plugin.interface import MetadataHookInterface

class CustomMetadataHook(MetadataHookInterface):
    def update(self, metadata):
        # Custom metadata modifications
        metadata["custom_field"] = "custom_value"

Integration with Build System

The metadata system integrates closely with the build system:

  1. Builder Configuration: Metadata informs builder settings and dependencies
  2. Version Management: Dynamic version resolution through version sources
  3. Dependency Resolution: Build and runtime dependency specifications
  4. Distribution Metadata: Core metadata generation for wheels and sdists

This metadata system provides the foundation for hatchling's standards-compliant packaging functionality while maintaining flexibility through its plugin architecture.

Install with Tessl CLI

npx tessl i tessl/pypi-hatchling

docs

build-backend.md

builders.md

cli.md

index.md

metadata.md

plugins.md

version.md

tile.json