Dynamic version generation from version control system tags supporting multiple VCS and versioning standards.
—
Convert Version objects to standards-compliant version strings with support for PEP 440, Semantic Versioning, Haskell PVP, and custom formats.
Convert Version objects to formatted strings with extensive customization options.
def serialize(
self,
metadata: Optional[bool] = None,
dirty: bool = False,
format: Optional[Union[str, Callable[["Version"], str]]] = None,
style: Optional[Style] = None,
bump: bool = False,
tagged_metadata: bool = False,
commit_prefix: Optional[str] = None,
escape_with: Optional[str] = None,
) -> strParameters:
metadata: Include commit ID and dirty flag (None=auto, True=always, False=never)dirty: Include dirty flag when metadata is enabledformat: Custom format string or callable for output formattingstyle: Built-in format style (PEP 440, SemVer, PVP)bump: Increment version automaticallytagged_metadata: Include tagged metadata in outputcommit_prefix: Prefix for commit ID (e.g., "g" for Git)escape_with: Character replacement for branch escapingReturns: Formatted version string
Usage Examples:
from dunamai import Version, Style
version = Version("1.2.3", stage=("rc", 1), distance=7, commit="29045e8", dirty=True)
# Default PEP 440 format
print(version.serialize())
# "1.2.3rc1.post7.dev0+29045e8"
# Force metadata inclusion
print(version.serialize(metadata=True))
# "1.2.3rc1.post7.dev0+29045e8"
# Include dirty flag
print(version.serialize(dirty=True))
# "1.2.3rc1.post7.dev0+29045e8.dirty"
# Semantic Versioning style
print(version.serialize(style=Style.SemVer))
# "1.2.3-rc.1.post.7+29045e8"
# Custom format string
print(version.serialize(format="v{base}-{stage}.{revision}+{distance}"))
# "v1.2.3-rc.1+7"
# Bump version automatically
print(version.serialize(bump=True))
# "1.2.4rc1"Use format strings with placeholder substitution for complete control over output format.
Available Placeholders:
{base} - Base version (e.g., "1.2.3"){stage} - Pre-release stage (e.g., "rc"){revision} - Pre-release revision (e.g., "1"){distance} - Commits since tag (e.g., "7"){commit} - Commit hash (e.g., "29045e8"){dirty} - "dirty" or "clean"{tagged_metadata} - Metadata from tag{epoch} - PEP 440 epoch{branch} - Branch name{branch_escaped} - Branch with special chars removed{timestamp} - Timestamp as YYYYmmddHHMMSS UTC{major} - Major version component{minor} - Minor version component{patch} - Patch version componentUsage Examples:
from dunamai import Version
version = Version(
"1.2.3",
stage=("beta", 2),
distance=5,
commit="g29045e8",
branch="feature/new-api",
tagged_metadata="linux"
)
# Docker-style tags
print(version.serialize(format="{base}-{stage}.{revision}"))
# "1.2.3-beta.2"
# Build number format
print(version.serialize(format="{base}.{distance}"))
# "1.2.3.5"
# Full descriptive format
print(version.serialize(format="v{base}-{stage}.{revision}+{commit}.{dirty}"))
# "v1.2.3-beta.2+g29045e8.clean"
# Branch-aware format
print(version.serialize(format="{base}-{branch_escaped}+{commit}"))
# "1.2.3-featurenewapi+g29045e8"
# Component access
print(version.serialize(format="{major}.{minor}.{patch}-dev.{distance}"))
# "1.2.3-dev.5"Use callable functions for complex formatting logic.
Usage Examples:
from dunamai import Version
def custom_formatter(version):
if version.distance == 0:
return f"{version.base}"
elif version.stage:
return f"{version.base}-{version.stage}.{version.revision or 0}+dev.{version.distance}"
else:
return f"{version.base}+dev.{version.distance}"
version = Version("1.2.3", distance=5)
print(version.serialize(format=custom_formatter))
# "1.2.3+dev.5"
# Conditional formatting based on VCS
def vcs_aware_formatter(version):
prefix = {"git": "g", "mercurial": "hg"}.get(version.vcs.value, "")
return f"{version.base}+{prefix}{version.commit}"
version = Version("1.2.3", commit="29045e8", vcs=Vcs.Git)
print(version.serialize(format=vcs_aware_formatter))
# "1.2.3+g29045e8"Create PEP 440 compliant version strings with fine-grained control over components.
def serialize_pep440(
base: str,
stage: Optional[str] = None,
revision: Optional[int] = None,
post: Optional[int] = None,
dev: Optional[int] = None,
epoch: Optional[int] = None,
metadata: Optional[Sequence[Union[str, int]]] = None,
) -> strParameters:
base: Release segment (e.g., "1.2.3")stage: Pre-release stage ("a", "b", "rc")revision: Pre-release revision numberpost: Post-release numberdev: Development release numberepoch: Epoch numbermetadata: Local version segmentsUsage Examples:
from dunamai import serialize_pep440
# Basic release
print(serialize_pep440("1.2.3"))
# "1.2.3"
# Pre-release
print(serialize_pep440("1.2.3", stage="rc", revision=1))
# "1.2.3rc1"
# Post-release
print(serialize_pep440("1.2.3", post=7))
# "1.2.3.post7"
# Development release
print(serialize_pep440("1.2.3", dev=0))
# "1.2.3.dev0"
# Complex version with all components
print(serialize_pep440(
"1.2.3",
stage="rc",
revision=1,
post=7,
dev=0,
epoch=2,
metadata=["g29045e8", "dirty"]
))
# "2!1.2.3rc1.post7.dev0+g29045e8.dirty"Create Semantic Versioning compliant version strings.
def serialize_semver(
base: str,
pre: Optional[Sequence[Union[str, int]]] = None,
metadata: Optional[Sequence[Union[str, int]]] = None,
) -> strParameters:
base: Version core (e.g., "1.2.3")pre: Pre-release identifiersmetadata: Build metadata identifiersUsage Examples:
from dunamai import serialize_semver
# Basic semantic version
print(serialize_semver("1.2.3"))
# "1.2.3"
# Pre-release
print(serialize_semver("1.2.3", pre=["rc", 1]))
# "1.2.3-rc.1"
# With build metadata
print(serialize_semver("1.2.3", metadata=["20230501", "g29045e8"]))
# "1.2.3+20230501.g29045e8"
# Pre-release with metadata
print(serialize_semver("1.2.3", pre=["beta", 2], metadata=["exp", "sha", "5"]))
# "1.2.3-beta.2+exp.sha.5"Create Haskell Package Versioning Policy compliant version strings.
def serialize_pvp(base: str, metadata: Optional[Sequence[Union[str, int]]] = None) -> strParameters:
base: Version core (e.g., "1.2.3")metadata: Version tag metadataUsage Examples:
from dunamai import serialize_pvp
# Basic PVP version
print(serialize_pvp("1.2.3"))
# "1.2.3"
# PVP with metadata
print(serialize_pvp("1.2.3", metadata=["candidate", "1"]))
# "1.2.3-candidate-1"Automatically increment version components during serialization.
def bump(self, index: int = -1, increment: int = 1, smart: bool = False) -> "Version"Usage Examples:
from dunamai import Version
version = Version("1.2.3", distance=5)
# Bump with serialize
print(version.serialize(bump=True))
# "1.2.4.dev5"
# Manual bump
bumped = version.bump()
print(bumped.serialize())
# "1.2.4.dev5"
# Bump specific component
bumped = version.bump(index=1) # Bump minor version
print(bumped.base)
# "1.3.0"
# Smart bump (considers pre-release state)
version = Version("1.2.3", stage=("rc", 1))
bumped = version.bump(smart=True)
print(bumped.serialize())
# "1.2.3rc2"All serialization functions validate output against their respective standards and raise ValueError for invalid versions.
Usage Examples:
from dunamai import Version, Style, check_version
version = Version("1.2.3", distance=5)
# This will validate the output
try:
result = version.serialize(format="v{base}", style=Style.Pep440)
except ValueError as e:
print(f"Invalid PEP 440 version: {e}")
# Manual validation
try:
check_version("v1.2.3", Style.Pep440)
except ValueError as e:
print(f"Version 'v1.2.3' is not PEP 440 compliant: {e}")Install with Tessl CLI
npx tessl i tessl/pypi-dunamai