CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-towncrier

Building newsfiles for your project.

Overview
Eval results
Files

configuration.mddocs/

Configuration Management

Load and manage towncrier configuration from TOML files with validation, defaults, and flexible discovery.

Capabilities

Configuration Loading

Load configuration from directories or specific files with automatic discovery.

def load_config_from_options(
    directory: str | None,
    config_path: str | None
) -> tuple[str, Config]:
    """
    Load configuration from directory or file.
    
    Args:
        directory: Directory to search for config (None for current)
        config_path: Explicit config file path (None for auto-discovery)
        
    Returns:
        tuple: (base_directory, config_object)
        
    Raises:
        ConfigError: If configuration is invalid or not found
    """

def load_config(directory: str) -> Config | None:
    """
    Load configuration from a directory.
    
    Args:
        directory: Directory to search for towncrier configuration
        
    Returns:
        Config | None: Configuration object or None if not found
    """

def traverse_for_config(path: str | None) -> tuple[str, Config]:
    """
    Search for configuration in current and parent directories.
    
    Args:
        path: Starting directory (None for current directory)
        
    Returns:
        tuple: (base_directory, config_object)
        
    Raises:
        ConfigError: If no configuration found in directory tree
    """

File Operations

Load and parse TOML configuration files.

def load_config_from_file(directory: str, config_file: str) -> Config:
    """
    Load configuration from a specific file.
    
    Args:
        directory: Base directory for relative paths
        config_file: Path to configuration file
        
    Returns:
        Config: Parsed configuration object
        
    Raises:
        ConfigError: If file cannot be loaded or parsed
    """

def load_toml_from_file(config_file: str) -> Mapping[str, Any]:
    """
    Load raw TOML data from file.
    
    Args:
        config_file: Path to TOML file
        
    Returns:
        Mapping[str, Any]: Raw TOML data
        
    Raises:
        ConfigError: If file cannot be read or parsed
    """

def parse_toml(base_path: str, config: Mapping[str, Any]) -> Config:
    """
    Parse TOML data into Config object.
    
    Args:
        base_path: Base directory for resolving relative paths
        config: Raw TOML configuration data
        
    Returns:
        Config: Validated configuration object
        
    Raises:
        ConfigError: If configuration is invalid
    """

Configuration Object

Config Class

The main configuration dataclass containing all towncrier settings.

@dataclasses.dataclass
class Config:
    """Complete towncrier configuration."""
    
    # Required fields
    sections: Mapping[str, str]
    types: Mapping[str, Mapping[str, Any]]
    template: str | tuple[str, str]
    start_string: str
    
    # Optional fields with defaults
    package: str = ""
    package_dir: str = "."
    single_file: bool = True
    filename: str = "NEWS.rst"
    directory: str | None = None
    version: str | None = None
    name: str = ""
    title_format: str | Literal[False] = ""
    issue_format: str | None = None
    underlines: Sequence[str] = ("=", "-", "~")
    wrap: bool = False
    all_bullets: bool = True
    orphan_prefix: str = "+"
    create_eof_newline: bool = True
    create_add_extension: bool = True
    ignore: list[str] | None = None
    issue_pattern: str = ""

ConfigError Exception

Exception raised for configuration validation errors.

class ConfigError(ClickException):
    """Configuration validation or loading error."""
    
    def __init__(self, *args: str, **kwargs: str):
        """
        Initialize configuration error.
        
        Args:
            *args: Error message components
            **kwargs: Additional error context
                failing_option: The configuration option that failed
        """
        self.failing_option = kwargs.get("failing_option")
        super().__init__(*args)

Configuration Discovery

File Discovery Order

Towncrier searches for configuration files in this order:

  1. Explicit --config parameter
  2. towncrier.toml in current/parent directories
  3. pyproject.toml with [tool.towncrier] section
  4. Continue searching up directory tree

Section Locations

Configuration sections are searched in:

  • [tool.towncrier] in pyproject.toml
  • Root level in towncrier.toml

Configuration Options

Core Settings

[tool.towncrier]
package = "mypackage"           # Package name for version detection
package_dir = "src"             # Directory containing package
filename = "CHANGELOG.md"       # Output changelog filename
directory = "news"              # Fragment directory (alternative to package-based)

Template Configuration

template = "path/to/template.j2"          # Local template file
template = "mypackage:template.j2"        # Package resource template
start_string = "<!-- towncrier release notes start -->"  # Insertion marker

Fragment Types

[[tool.towncrier.type]]
directory = "feature"
name = "Features"
showcontent = true

[[tool.towncrier.type]]
directory = "bugfix"  
name = "Bugfixes"
showcontent = true

[[tool.towncrier.type]]
directory = "doc"
name = "Improved Documentation"
showcontent = true

[[tool.towncrier.type]]
directory = "removal"
name = "Deprecations and Removals"
showcontent = true

[[tool.towncrier.type]]
directory = "misc"
name = "Misc"
showcontent = false

Multi-Section Configuration

[[tool.towncrier.section]]
name = ""           # Main section
path = ""

[[tool.towncrier.section]]
name = "Web"
path = "web"

[[tool.towncrier.section]]
name = "Core"
path = "core"

Formatting Options

title_format = "{name} {version} ({date})"
issue_format = "`#{issue} <https://github.com/user/repo/issues/{issue}>`_"
underlines = ["=", "-", "~"]
wrap = false
all_bullets = true

File Management

create_eof_newline = true       # Add newline at end of fragments
create_add_extension = true     # Auto-add file extensions
orphan_prefix = "+"            # Prefix for orphan fragments
ignore = ["README.rst"]        # Files to ignore in fragment directory

Usage Examples

Basic Configuration Loading

from towncrier._settings import load_config_from_options

# Load from current directory
base_dir, config = load_config_from_options(
    directory=None,      # Current directory
    config_path=None     # Auto-discover config file
)

print(f"Base directory: {base_dir}")
print(f"Package: {config.package}")
print(f"Fragment types: {list(config.types.keys())}")

Custom Configuration File

# Load specific config file
base_dir, config = load_config_from_options(
    directory="/path/to/project",
    config_path="/path/to/custom-towncrier.toml"
)

Configuration Traversal

from towncrier._settings.load import traverse_for_config

# Search up directory tree
base_dir, config = traverse_for_config("/deep/nested/directory")

Template Resolution

# Template can be file path or package resource
if isinstance(config.template, tuple):
    # Package resource: ("package.name", "template.j2")
    package_name, template_name = config.template
    print(f"Using template {template_name} from package {package_name}")
else:
    # File path: "path/to/template.j2"  
    print(f"Using template file: {config.template}")

Validation Rules

Required Settings

  • At least one fragment type must be defined
  • Template must be specified (file path or package resource)
  • Start string must be provided for file insertion

Path Resolution

  • Relative paths are resolved against the configuration file directory
  • Package resources use the format "package:resource"
  • Fragment directories are resolved based on package structure or explicit directory

Type Validation

  • Fragment types must have directory and name fields
  • showcontent is optional (defaults to true)
  • Type directories must be valid filesystem names

Error Handling

Configuration loading handles these error scenarios:

  • File not found: Configuration file doesn't exist
  • Parse errors: Invalid TOML syntax
  • Validation errors: Missing required fields or invalid values
  • Template errors: Template file/resource not found
  • Permission errors: Cannot read configuration files
  • Path resolution errors: Invalid relative paths or package resources

Integration with CLI

The configuration system integrates with CLI commands through the config_option_help constant:

config_option_help = (
    "Pass a custom config file at FILE_PATH. "
    "Default: towncrier.toml or pyproject.toml file, "
    "if both files exist, the first will take precedence."
)

This help text is used across all CLI commands that accept a --config option.

Install with Tessl CLI

npx tessl i tessl/pypi-towncrier

docs

build.md

check.md

configuration.md

create.md

fragments.md

index.md

project.md

vcs.md

tile.json