CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-commitizen

Python commitizen client tool for standardized commit conventions and automated version management

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

version-management.mddocs/

Version Management

Comprehensive version management with support for semantic versioning, PEP 440, automatic file updates, and multiple version schemes. Commitizen provides intelligent version bumping based on commit history analysis and supports various versioning standards used across different ecosystems.

Capabilities

Version Increment Detection

Analyzes commit history to determine appropriate version increment based on commit message patterns.

def find_increment(
    commits: list[GitCommit],
    regex: Pattern[str],
    incremental_rev: str = ""
) -> str:
    """
    Determine version increment type from commit history.
    
    Analyzes commits using the provided regex pattern to identify
    BREAKING changes, features, and fixes to determine if version
    should be bumped MAJOR, MINOR, or PATCH.
    
    Parameters:
    - commits: List of git commits to analyze
    - regex: Compiled regex pattern for parsing commit messages
    - incremental_rev: Starting revision for analysis
    
    Returns:
    Version increment type: "MAJOR", "MINOR", "PATCH", or None
    """

Version File Updates

Updates version information across multiple files in the project automatically.

def update_version_in_files(
    current_version: str,
    new_version: str,
    files: list[str]
) -> None:
    """
    Update version strings in specified files.
    
    Supports various file formats and version string patterns:
    - Python files: __version__ = "1.0.0"
    - JSON files: "version": "1.0.0"  
    - TOML files: version = "1.0.0"
    - Plain text files: version replacement
    
    Parameters:
    - current_version: Current version string to replace
    - new_version: New version string
    - files: List of file paths, optionally with specific keys (file.json:version)
    """

Tag Normalization

Normalizes git tag names according to configured format templates.

def normalize_tag(tag: str, tag_format: str) -> str:
    """
    Normalize tag name according to format template.
    
    Converts between different tag formats and ensures consistency
    with configured tag_format setting.
    
    Parameters:
    - tag: Original tag name
    - tag_format: Tag format template (e.g., "v$version", "$version")
    
    Returns:
    Normalized tag name
    """

Version Schemes

Version Protocol

Interface definition for all version scheme implementations.

class VersionProtocol(Protocol):
    """Protocol defining the interface for version schemes."""
    
    def parse(self, version: str) -> Any:
        """
        Parse version string into version object.
        
        Parameters:
        - version: Version string to parse
        
        Returns:
        Parsed version object
        """
    
    def bump(self, version: Any, increment: str) -> Any:
        """
        Bump version by specified increment.
        
        Parameters:
        - version: Parsed version object
        - increment: Increment type (MAJOR, MINOR, PATCH)
        
        Returns:
        Bumped version object
        """
    
    def serialize(self, version: Any) -> str:
        """
        Serialize version object to string.
        
        Parameters:
        - version: Version object to serialize
        
        Returns:
        Version string
        """

Base Version Class

Abstract base implementation providing common version functionality.

class BaseVersion:
    """Abstract base class for version implementations."""
    
    def __init__(self, version_string: str):
        """
        Initialize version from string.
        
        Parameters:
        - version_string: Version string to parse
        """
    
    def bump(self, increment: str) -> "BaseVersion":
        """
        Create new version with specified increment.
        
        Parameters:
        - increment: Increment type (MAJOR, MINOR, PATCH)
        
        Returns:
        New version instance
        """
    
    def __str__(self) -> str:
        """Return string representation of version."""
    
    def __eq__(self, other: Any) -> bool:
        """Compare versions for equality."""
    
    def __lt__(self, other: Any) -> bool:
        """Compare versions for ordering."""

PEP 440 Version Scheme

Python ecosystem version scheme following PEP 440 specification.

class Pep440(BaseVersion):
    """
    PEP 440 version scheme for Python packages.
    
    Supports development releases, pre-releases, post-releases, and local versions.
    Format examples: 1.0.0, 1.0.0a1, 1.0.0b2, 1.0.0rc1, 1.0.0.post1, 1.0.0+local
    """
    def parse(self, version: str) -> dict[str, Any]:
        """
        Parse PEP 440 version string.
        
        Returns:
        Dictionary with version components (major, minor, patch, pre, post, local)
        """
    
    def bump(self, version: dict[str, Any], increment: str) -> dict[str, Any]:
        """
        Bump PEP 440 version.
        
        Handles pre-release and post-release versioning according to PEP 440.
        """
    
    def serialize(self, version: dict[str, Any]) -> str:
        """Serialize PEP 440 version to string."""

Semantic Versioning

Standard semantic versioning scheme (semver.org).

class SemVer(BaseVersion):
    """
    Semantic versioning scheme (semver.org).
    
    Format: MAJOR.MINOR.PATCH[-PRERELEASE][+BUILD]
    Example: 1.0.0, 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0+build.1
    """
    def parse(self, version: str) -> dict[str, Any]:
        """
        Parse semantic version string.
        
        Returns:
        Dictionary with version components (major, minor, patch, prerelease, build)
        """
    
    def bump(self, version: dict[str, Any], increment: str) -> dict[str, Any]:
        """
        Bump semantic version.
        
        Follows semantic versioning rules for pre-release handling.
        """
    
    def serialize(self, version: dict[str, Any]) -> str:
        """Serialize semantic version to string."""

Alternative Semantic Versioning

Alternative semantic versioning implementation with different pre-release handling.

class SemVer2(BaseVersion):
    """
    Alternative semantic versioning with different pre-release rules.
    
    Similar to SemVer but with alternative handling of pre-release versions.
    """
    def parse(self, version: str) -> dict[str, Any]:
        """Parse alternative semantic version string."""
    
    def bump(self, version: dict[str, Any], increment: str) -> dict[str, Any]:
        """Bump alternative semantic version."""
    
    def serialize(self, version: dict[str, Any]) -> str:
        """Serialize alternative semantic version to string."""

Version Scheme Management

KNOWN_SCHEMES: dict[str, type[BaseVersion]]
"""Dictionary of available version schemes."""

DEFAULT_SCHEME: str
"""Default version scheme name."""

def get_version_scheme(name: str = "pep440") -> VersionProtocol:
    """
    Get version scheme instance by name.
    
    Parameters:
    - name: Version scheme name (pep440, semver, semver2)
    
    Returns:
    Version scheme instance implementing VersionProtocol
    
    Raises:
    ValueError: If version scheme is not found
    """

Type Definitions

Increment = Literal["MAJOR", "MINOR", "PATCH"]
"""Type alias for version increment types."""

Prerelease = Literal["alpha", "beta", "rc"]
"""Type alias for pre-release identifiers."""

Usage Examples

Basic Version Management

from commitizen.bump import find_increment, update_version_in_files
from commitizen.version_schemes import get_version_scheme
from commitizen.git import get_commits
import re

# Analyze commits for version increment
commits = get_commits(start="v1.0.0", end="HEAD")
pattern = re.compile(r"^(feat|fix|BREAKING)")
increment = find_increment(commits, pattern)

print(f"Recommended increment: {increment}")  # "MINOR"

# Update version in files
update_version_in_files(
    current_version="1.0.0",
    new_version="1.1.0", 
    files=[
        "src/__version__.py",
        "pyproject.toml:version",
        "package.json:version"
    ]
)

Working with Version Schemes

from commitizen.version_schemes import get_version_scheme

# PEP 440 version scheme
pep440 = get_version_scheme("pep440")
version = pep440.parse("1.0.0")
new_version = pep440.bump(version, "MINOR")
print(pep440.serialize(new_version))  # "1.1.0"

# Semantic versioning
semver = get_version_scheme("semver")
version = semver.parse("1.0.0-alpha.1")
new_version = semver.bump(version, "PATCH")
print(semver.serialize(new_version))  # "1.0.0"

# Pre-release versions
version = semver.parse("1.0.0")
prerelease = semver.bump(version, "PRERELEASE")
print(semver.serialize(prerelease))  # "1.0.1-alpha.1"

Custom Version Scheme

from commitizen.version_schemes import BaseVersion
from typing import Any

class CustomVersion(BaseVersion):
    """Custom version scheme for internal projects."""
    
    def parse(self, version: str) -> dict[str, Any]:
        # Parse custom format: YEAR.MONTH.BUILD
        parts = version.split('.')
        return {
            "year": int(parts[0]),
            "month": int(parts[1]), 
            "build": int(parts[2]) if len(parts) > 2 else 0
        }
    
    def bump(self, version: dict[str, Any], increment: str) -> dict[str, Any]:
        from datetime import datetime
        now = datetime.now()
        
        if increment == "MAJOR":
            return {"year": now.year, "month": now.month, "build": 0}
        elif increment == "MINOR":
            return {
                "year": version["year"],
                "month": now.month,
                "build": 0
            }
        else:  # PATCH
            return {
                "year": version["year"],
                "month": version["month"],
                "build": version["build"] + 1
            }
    
    def serialize(self, version: dict[str, Any]) -> str:
        return f"{version['year']}.{version['month']}.{version['build']}"

# Register custom scheme
custom = CustomVersion("2024.1.0")
new_version = custom.bump(custom.parse("2024.1.5"), "PATCH")
print(str(new_version))  # "2024.1.6"

Version Provider Integration

from commitizen.providers import get_provider

# Get version from different sources
poetry_provider = get_provider("poetry")
current_version = poetry_provider.get_version()

npm_provider = get_provider("npm") 
npm_version = npm_provider.get_version()

# Update version in provider
poetry_provider.set_version("2.0.0")
npm_provider.set_version("2.0.0")

Configuration-Driven Version Management

[tool.commitizen]
version_scheme = "semver"
version_files = [
    "src/__version__.py",
    "pyproject.toml:version",
    "package.json:version",
    "VERSION"
]

# Custom bump patterns
bump_pattern = "^(feat|fix|BREAKING|perf)"
bump_map = {
    "BREAKING" = "MAJOR",
    "feat" = "MINOR",
    "fix" = "PATCH", 
    "perf" = "PATCH"
}

# Major version zero handling
major_version_zero = true
bump_map_major_version_zero = {
    "BREAKING" = "MINOR",
    "feat" = "PATCH",
    "fix" = "PATCH"
}

Install with Tessl CLI

npx tessl i tessl/pypi-commitizen

docs

commands.md

configuration.md

git-operations.md

index.md

plugins.md

version-management.md

tile.json