Plugin for Poetry to enable dynamic versioning based on VCS tags
—
Configuration loading, validation, and merging functionality for poetry-dynamic-versioning settings from pyproject.toml files. Handles complex configuration hierarchies with comprehensive validation and default value management.
Load configuration from pyproject.toml files with automatic path resolution and hierarchy traversal. Supports both local configuration objects and path-based loading with intelligent fallback to default values.
def _get_config(local: Mapping) -> _Config:
"""
Parse and merge configuration from a local configuration mapping.
Parameters:
- local: Raw configuration data from pyproject.toml
Returns:
_Config: Merged configuration with defaults and validation
"""
def _get_config_from_path(start: Optional[Path] = None) -> Mapping:
"""
Load configuration starting from a given path, searching up the directory tree.
Parameters:
- start: Starting directory path (defaults to current working directory)
Returns:
Mapping: Configuration dictionary from found pyproject.toml or defaults
"""Comprehensive validation system that checks configuration structure, detects unknown keys, and validates nested configuration sections with detailed error reporting.
def _validate_config(config: Optional[Mapping] = None) -> Sequence[str]:
"""
Validate configuration structure and return error messages.
Parameters:
- config: Configuration to validate (auto-detects from pyproject.toml if None)
Returns:
Sequence[str]: List of validation error messages (empty if valid)
"""
def _validate_config_section(
config: Mapping,
default: Mapping,
path: Sequence[str]
) -> Sequence[str]:
"""
Validate a specific configuration section against its default structure.
Parameters:
- config: Configuration section to validate
- default: Default/expected structure for comparison
- path: Configuration path for error reporting
Returns:
Sequence[str]: List of validation errors for this section
"""Provide complete default configuration structure with all supported options and their default values, forming the base for configuration merging operations.
def _default_config() -> Mapping:
"""
Get the complete default configuration structure.
Returns:
Mapping: Full default configuration with all options and default values
"""Deep merge configuration dictionaries with intelligent handling of nested structures, ensuring user configurations properly override defaults while preserving unspecified default values.
def _deep_merge_dicts(base: Mapping, addition: Mapping) -> Mapping:
"""
Recursively merge two configuration dictionaries.
Parameters:
- base: Base configuration dictionary
- addition: Additional configuration to merge in (takes precedence)
Returns:
Mapping: Merged configuration dictionary
"""The configuration system supports extensive customization through the [tool.poetry-dynamic-versioning] section:
# Core enable/disable and VCS settings
enable: bool = False
vcs: str = "any" # any, git, mercurial, darcs, bazaar, subversion, fossil, pijul
dirty: bool = False
pattern: Optional[str] = None
pattern_prefix: Optional[str] = None
latest_tag: bool = False
# Version formatting and style
style: Optional[str] = None # pep440, semver, pvp
metadata: Optional[bool] = None
format: Optional[str] = None
format_jinja: Optional[str] = None
format_jinja_imports: Sequence[_JinjaImport] = []
# Version bumping
bump: Union[bool, _Bump] = False
tagged_metadata: bool = False
# VCS-specific options
full_commit: bool = False
tag_branch: Optional[str] = None
tag_dir: str = "tags"
strict: bool = False
fix_shallow_repository: bool = False
ignore_untracked: bool = False
commit_length: Optional[int] = None
commit_prefix: Optional[str] = None
escape_with: Optional[str] = None# File substitution settings
substitution: _Substitution = {
"files": ["*.py", "*/__init__.py", "*/__version__.py", "*/_version.py"],
"patterns": [
r"(^__version__\s*(?::.*?)?=\s*['\"])[^'\"]*(['\"])",
{
"value": r"(^__version_tuple__\s*(?::.*?)?=\s*\()[^)]*(\))",
"mode": "tuple"
}
],
"folders": []
}
# Per-file configuration
files: Mapping[str, _File] = {}
# File-based version source
from_file: _FromFile = {
"source": None,
"pattern": None
}from poetry_dynamic_versioning import _get_config_from_path, _validate_config
from pathlib import Path
# Load configuration for current project
config = _get_config_from_path()
# Validate configuration
errors = _validate_config()
if errors:
for error in errors:
print(f"Configuration error: {error}")import tomlkit
from poetry_dynamic_versioning import _get_config, _validate_config
# Load and parse pyproject.toml
with open("pyproject.toml", "rb") as f:
pyproject = tomlkit.parse(f.read().decode("utf-8"))
# Get merged configuration with validation
config = _get_config(pyproject)
errors = _validate_config(pyproject)
if not errors:
print("Configuration is valid")
print(f"VCS: {config['vcs']}")
print(f"Pattern: {config['pattern']}")from poetry_dynamic_versioning import _default_config, _deep_merge_dicts
# Get defaults
defaults = _default_config()
# Custom configuration
custom = {
"tool": {
"poetry-dynamic-versioning": {
"enable": True,
"vcs": "git",
"style": "semver",
"substitution": {
"files": ["src/**/*.py"]
}
}
}
}
# Merge configurations
merged = _deep_merge_dicts(defaults, custom)
final_config = merged["tool"]["poetry-dynamic-versioning"]Install with Tessl CLI
npx tessl i tessl/pypi-poetry-dynamic-versioning