CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-versioningit

Versioning It with your Version In Git - automatic package versioning based on VCS tags

Pending
Overview
Eval results
Files

builtin-methods.mddocs/

Built-in Methods

Pre-built implementations for each pipeline step including VCS querying, version formatting, file writing, and onbuild processing. These methods provide sensible defaults and can be customized through configuration parameters.

Capabilities

Tag to Version Conversion

Convert VCS tags to version strings with prefix/suffix removal and regex processing.

def basic_tag2version(*, tag: str, params: dict[str, Any]) -> str:
    """
    Implements the "basic" tag2version method for converting tags to versions.

    Parameters:
    - tag: The VCS tag string
    - params: Configuration parameters:
        - rmprefix (str, optional): Prefix to remove from tag
        - rmsuffix (str, optional): Suffix to remove from tag  
        - regex (str, optional): Regex to extract version from tag
        - require-match (bool, default False): Whether regex must match

    Returns:
    str: Version string extracted from tag (with leading 'v' stripped)

    Raises:
    - InvalidTagError: if require-match is True and regex doesn't match
    """

Version Formatting

Apply formatting templates based on repository state and calculated versions.

def basic_format(
    *,
    description: VCSDescription,
    base_version: str,
    next_version: str,
    params: dict[str, Any],
) -> str:
    """
    Implements the "basic" format method for version formatting.

    Parameters:
    - description: VCS repository state
    - base_version: Version extracted from tag
    - next_version: Calculated next version
    - params: Format templates keyed by repository state:
        - distance (str): Template for commits ahead of tag
        - dirty (str): Template for uncommitted changes
        - distance-dirty (str): Template for both conditions

    Returns:
    str: Formatted version string

    Raises:
    - ConfigError: if no format template found for repository state
    """

# Default format templates
DEFAULT_FORMATS = {
    "distance": "{version}.post{distance}+{vcs}{rev}",
    "dirty": "{version}+d{build_date:%Y%m%d}",
    "distance-dirty": "{version}.post{distance}+{vcs}{rev}.d{build_date:%Y%m%d}",
}

File Writing

Write version information to files using configurable templates.

def basic_write(
    *,
    project_dir: str | Path,
    template_fields: dict[str, Any],
    params: dict[str, Any],
) -> None:
    """
    Implements the "basic" write method for writing version to files.

    Parameters:
    - project_dir: Path to project root
    - template_fields: Variables for template substitution
    - params: Configuration parameters:
        - file (str): Relative path to file to write
        - encoding (str, default "utf-8"): File encoding
        - template (str, optional): Template string (auto-detected by extension)

    Raises:
    - ConfigError: if template not specified and file extension unknown
    """

Template Fields Generation

Generate template variables for use in write and onbuild steps.

def basic_template_fields(
    *,
    version: str,
    description: Optional[VCSDescription],
    base_version: Optional[str],
    next_version: Optional[str],
    params: dict[str, Any],
) -> dict[str, Any]:
    """
    Implements the "basic" template-fields method.

    Parameters:
    - version: Final version string
    - description: VCS repository state or None
    - base_version: Version from tag or None
    - next_version: Calculated next version or None
    - params: Configuration parameters:
        - version-tuple: Dict configuring version tuple generation:
            - pep440 (bool, default False): Use PEP 440 parsing
            - epoch (bool, optional): Include epoch in tuple
            - split-on (str, optional): Characters to split on (ignored if pep440=True)
            - double-quote (bool, default True): Use double quotes in tuple

    Returns:
    dict[str, Any]: Template fields including version, version_tuple, normalized_version, etc.
    """

Next Version Calculation

Built-in methods for calculating the next version after the current tag.

def next_minor_version(
    *,
    version: str,
    branch: Optional[str],
    params: dict[str, Any],
) -> str:
    """
    Implements the "minor" next-version method.
    Increments the minor version and sets patch to 0.

    Parameters:
    - version: Base version string
    - branch: Current branch name (unused)
    - params: Configuration parameters (none used)

    Returns:
    str: Next minor version (e.g., "1.2.3" -> "1.3.0")
    """

def next_smallest_version(
    *,
    version: str,
    branch: Optional[str],
    params: dict[str, Any],
) -> str:
    """
    Implements the "smallest" next-version method.
    Increments the smallest (rightmost) version component.

    Parameters:
    - version: Base version string
    - branch: Current branch name (unused)
    - params: Configuration parameters (none used)

    Returns:
    str: Next smallest version (e.g., "1.2.3" -> "1.2.4")
    """

def next_minor_release_version(
    *,
    version: str,
    branch: Optional[str],
    params: dict[str, Any],
) -> str:
    """
    Implements the "minor-release" next-version method.
    If version is a prerelease, returns base version; otherwise increments minor.

    Parameters:
    - version: Base version string
    - branch: Current branch name (unused)  
    - params: Configuration parameters (none used)

    Returns:
    str: Next minor or base version
    """

def next_smallest_release_version(
    *,
    version: str,
    branch: Optional[str],
    params: dict[str, Any],
) -> str:
    """
    Implements the "smallest-release" next-version method.
    If version is a prerelease, returns base version; otherwise increments smallest.

    Parameters:
    - version: Base version string
    - branch: Current branch name (unused)
    - params: Configuration parameters (none used)

    Returns:
    str: Next smallest or base version
    """

def null_next_version(
    *,
    version: str,
    branch: Optional[str],
    params: dict[str, Any],
) -> str:
    """
    Implements the "null" next-version method.
    Returns the same version unchanged.

    Parameters:
    - version: Base version string
    - branch: Current branch name (unused)
    - params: Configuration parameters (none used)

    Returns:
    str: Unchanged version
    """

Onbuild Processing

Replace version strings in files during the build process.

def replace_version_onbuild(
    *,
    file_provider: OnbuildFileProvider,
    is_source: bool,
    template_fields: dict[str, Any],
    params: dict[str, Any],
) -> None:
    """
    Implements the "replace-version" onbuild method.

    Parameters:
    - file_provider: Interface for accessing build files
    - is_source: True for sdist, False for wheel
    - template_fields: Variables for template substitution
    - params: Configuration parameters:
        - source-file (str): Path in source tree
        - build-file (str): Path in build/install tree
        - encoding (str, default "utf-8"): File encoding
        - regex (str): Regex to find version line (default: __version__ pattern)
        - require-match (bool, default False): Whether regex must match
        - replacement (str): Replacement template (default: '"{version}"')
        - append-line (str, optional): Line to append if no match found

    Raises:
    - ConfigError: if regex is invalid
    - RuntimeError: if require-match is True and no match found
    """

Usage Examples

Tag2Version Configuration

# Basic prefix/suffix removal
config = {
    "tag2version": {
        "method": "basic",
        "rmprefix": "v",
        "rmsuffix": "-release"
    }
}
# v1.2.3-release -> 1.2.3

# Regex extraction
config = {
    "tag2version": {
        "method": "basic",
        "regex": r"release-(?P<version>.*)",
        "require-match": True
    }
}
# release-1.2.3 -> 1.2.3

Format Configuration

config = {
    "format": {
        "distance": "{version}.dev{distance}+g{rev}",
        "dirty": "{version}+dirty.{build_date:%Y%m%d}",
        "distance-dirty": "{version}.dev{distance}+g{rev}.dirty.{build_date:%Y%m%d}"
    }
}

# Examples:
# Exact tag: "1.2.3"
# 5 commits ahead: "1.2.3.dev5+g1234567"
# Dirty working tree: "1.2.3+dirty.20231201"
# Both: "1.2.3.dev5+g1234567.dirty.20231201"

Write Configuration

# Python file
config = {
    "write": {
        "file": "src/mypackage/_version.py",
        "template": '__version__ = "{version}"'
    }
}

# Text file
config = {
    "write": {
        "file": "VERSION",
        "template": "{version}"
    }
}

# Custom template with multiple fields
config = {
    "write": {
        "file": "src/mypackage/_build_info.py",
        "template": '''
__version__ = "{version}"
__version_tuple__ = {version_tuple}
__build_date__ = "{build_date}"
__git_revision__ = "{rev}"
'''
    }
}

Template Fields Configuration

# Basic version tuple
config = {
    "template-fields": {
        "method": "basic",
        "version-tuple": {
            "pep440": False,
            "split-on": ".",
            "double-quote": True
        }
    }
}
# "1.2.3" -> ("1", "2", "3")

# PEP 440 parsing
config = {
    "template-fields": {
        "method": "basic", 
        "version-tuple": {
            "pep440": True,
            "epoch": True,
            "double-quote": False
        }
    }
}
# "1!2.3.4a1" -> (1, 2, 3, 4, 'a', 1)

Next Version Examples

# minor: 1.2.3 -> 1.3.0
config = {"next-version": {"method": "minor"}}

# smallest: 1.2.3 -> 1.2.4  
config = {"next-version": {"method": "smallest"}}

# minor-release: 1.2.3a1 -> 1.2.3, 1.2.3 -> 1.3.0
config = {"next-version": {"method": "minor-release"}}

# smallest-release: 1.2.3a1 -> 1.2.3, 1.2.3 -> 1.2.4
config = {"next-version": {"method": "smallest-release"}}

# null: 1.2.3 -> 1.2.3 (unchanged)
config = {"next-version": {"method": "null"}}

Onbuild Configuration

# Replace __version__ in Python file
config = {
    "onbuild": {
        "method": "replace-version",
        "source-file": "src/mypackage/__init__.py",
        "build-file": "mypackage/__init__.py",
        "regex": r'^__version__ = .*$',
        "replacement": '__version__ = "{version}"'
    }
}

# Custom regex pattern
config = {
    "onbuild": {
        "method": "replace-version",
        "source-file": "version.h",
        "build-file": "version.h", 
        "regex": r'#define VERSION ".*"',
        "replacement": '#define VERSION "{version}"',
        "require-match": True
    }
}

# Append if no match found
config = {
    "onbuild": {
        "method": "replace-version",
        "source-file": "setup.cfg",
        "build-file": "setup.cfg",
        "regex": r'^version = .*$',
        "replacement": 'version = {version}',
        "append-line": 'version = {version}'
    }
}

Complete Configuration Example

config = {
    "default-version": "0.0.0.dev0",
    "vcs": {
        "method": "git",
        "match": ["v*.*.*"],
        "exclude": ["*rc*"]
    },
    "tag2version": {
        "method": "basic",
        "rmprefix": "v"
    },
    "next-version": {
        "method": "smallest"
    },
    "format": {
        "distance": "{version}.post{distance}+{vcs}{rev}",
        "dirty": "{version}+d{build_date:%Y%m%d}",
        "distance-dirty": "{version}.post{distance}+{vcs}{rev}.d{build_date:%Y%m%d}"
    },
    "template-fields": {
        "method": "basic",
        "version-tuple": {
            "pep440": True,
            "double-quote": False
        }
    },
    "write": {
        "file": "src/mypackage/_version.py",
        "template": '__version__ = "{version}"\n__version_tuple__ = {version_tuple}'
    },
    "onbuild": {
        "method": "replace-version",
        "source-file": "src/mypackage/__init__.py",
        "build-file": "mypackage/__init__.py"
    }
}

Install with Tessl CLI

npx tessl i tessl/pypi-versioningit

docs

build-integration.md

builtin-methods.md

core-operations.md

data-models.md

exceptions.md

index.md

method-system.md

versioningit-class.md

tile.json