CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-semantic-version

A library implementing the 'SemVer' scheme.

Pending
Overview
Eval results
Files

version-operations.mddocs/

Version Operations

Comprehensive functionality for creating, manipulating, comparing, and validating semantic version objects. The Version class provides complete SemVer 2.0.0 compliance with parsing, validation, comparison, and version bumping capabilities.

Capabilities

Version Creation

Create Version objects from strings or individual components with full SemVer 2.0.0 validation.

class Version:
    def __init__(
        self,
        version_string=None,
        major=None,
        minor=None,
        patch=None,
        prerelease=None,
        build=None,
        partial=False
    ):
        """
        Create a Version object from string or components.
        
        Args:
            version_string: SemVer string like '1.2.3-alpha.1+build.456'
            major: Major version number (required if using components)
            minor: Minor version number (required if using components)
            patch: Patch version number (required if using components)
            prerelease: Tuple of prerelease identifiers
            build: Tuple of build metadata identifiers
            partial: Allow partial versions (deprecated)
        
        Raises:
            ValueError: If version string is invalid or components are invalid
        """

Usage Examples:

# From version string
v1 = Version('1.2.3')
v2 = Version('1.2.3-alpha.1')
v3 = Version('1.2.3-alpha.1+build.456')

# From components
v4 = Version(major=1, minor=2, patch=3)
v5 = Version(major=1, minor=2, patch=3, prerelease=('alpha', '1'))
v6 = Version(major=1, minor=2, patch=3, prerelease=('alpha', '1'), build=('build', '456'))

# Invalid versions raise ValueError
try:
    invalid = Version('1.2')  # Missing patch version
except ValueError as e:
    print(f"Invalid version: {e}")

Version Parsing

Parse version strings with optional coercion for non-standard formats.

@classmethod
def parse(cls, version_string, partial=False, coerce=False):
    """
    Parse a version string into components.
    
    Args:
        version_string: Version string to parse
        partial: Allow partial versions (deprecated)
        coerce: Attempt to coerce invalid formats
    
    Returns:
        Tuple of (major, minor, patch, prerelease, build)
    
    Raises:
        ValueError: If version string cannot be parsed
    """

@classmethod
def coerce(cls, version_string, partial=False):
    """
    Coerce a version-like string into a valid SemVer version.
    
    Args:
        version_string: Version-like string to coerce
        partial: Allow partial versions (deprecated)
    
    Returns:
        Valid Version object
    
    Examples:
        Version.coerce('1') -> Version('1.0.0')
        Version.coerce('1.2.3.4.5') -> Version('1.2.3+4.5')
        Version.coerce('1.2.3a4') -> Version('1.2.3-a4')
    """

Usage Examples:

# Parse version string
components = Version.parse('1.2.3-alpha.1+build.456')
print(components)  # (1, 2, 3, ('alpha', '1'), ('build', '456'))

# Coerce non-standard formats
v1 = Version.coerce('1')           # Version('1.0.0')
v2 = Version.coerce('1.2')         # Version('1.2.0')
v3 = Version.coerce('1.2.3.4.5')   # Version('1.2.3+4.5')
v4 = Version.coerce('1.2.3a4')     # Version('1.2.3-a4')

Version Properties

Access individual components of version objects.

@property
def major(self):
    """Major version number."""

@property
def minor(self):
    """Minor version number (None only for partial versions - deprecated)."""

@property
def patch(self):
    """Patch version number (None only for partial versions - deprecated)."""

@property
def prerelease(self):
    """Tuple of prerelease identifiers."""

@property
def build(self):
    """Tuple of build metadata identifiers."""

@property
def partial(self):
    """Whether this is a partial version (deprecated)."""

@property
def precedence_key(self):
    """Key used for version sorting and comparison."""

def __iter__(self):
    """Iterate over version components: (major, minor, patch, prerelease, build)."""

def __str__(self):
    """String representation in SemVer format."""

def __repr__(self):
    """Debug representation of the Version object."""

def __hash__(self):
    """Hash for use in sets and dictionaries."""

Usage Examples:

version = Version('1.2.3-alpha.1+build.456')

print(version.major)       # 1
print(version.minor)       # 2
print(version.patch)       # 3
print(version.prerelease)  # ('alpha', '1')
print(version.build)       # ('build', '456')
print(version.partial)     # False

# Iterate over components
for component in version:
    print(component)
# Output: 1, 2, 3, ('alpha', '1'), ('build', '456')

Version Comparison

Compare versions using standard Python comparison operators following SemVer precedence rules.

def __lt__(self, other: 'Version') -> bool: ...
def __le__(self, other: 'Version') -> bool: ...
def __eq__(self, other: 'Version') -> bool: ...
def __ne__(self, other: 'Version') -> bool: ...
def __gt__(self, other: 'Version') -> bool: ...
def __ge__(self, other: 'Version') -> bool: ...

Usage Examples:

v1 = Version('1.0.0')
v2 = Version('1.0.1')
v3 = Version('1.0.0-alpha')
v4 = Version('1.0.0+build.1')

# Basic comparison
print(v1 < v2)      # True
print(v1 > v3)      # True (release > prerelease)
print(v1 == v4)     # True (build metadata ignored in comparison)

# Sorting versions
versions = [Version('2.0.0'), Version('1.0.0'), Version('1.1.0')]
sorted_versions = sorted(versions)
print([str(v) for v in sorted_versions])  # ['1.0.0', '1.1.0', '2.0.0']

Version Bumping

Generate new versions by incrementing major, minor, or patch components.

def next_major(self) -> 'Version':
    """
    Return the next major version.
    
    Returns:
        New Version with major incremented, minor/patch reset to 0,
        prerelease and build metadata removed.
    """

def next_minor(self) -> 'Version':
    """
    Return the next minor version.
    
    Returns:
        New Version with minor incremented, patch reset to 0,
        prerelease and build metadata removed.
    """

def next_patch(self) -> 'Version':
    """
    Return the next patch version.
    
    Returns:
        New Version with patch incremented,
        prerelease and build metadata removed.
    """

Usage Examples:

version = Version('1.2.3-alpha.1+build.456')

major = version.next_major()
print(major)  # Version('2.0.0')

minor = version.next_minor()
print(minor)  # Version('1.3.0')

patch = version.next_patch()
print(patch)  # Version('1.2.4')

Version Truncation

Truncate versions to specific precision levels.

def truncate(self, level: str = 'patch') -> 'Version':
    """
    Truncate version to specified level.
    
    Args:
        level: Truncation level ('major', 'minor', 'patch', 'prerelease', 'build')
    
    Returns:
        New Version truncated to specified level
    """

Usage Examples:

version = Version('1.2.3-alpha.1+build.456')

major_only = version.truncate('major')
print(major_only)  # Version('1.0.0')

minor_only = version.truncate('minor')
print(minor_only)  # Version('1.2.0')

no_build = version.truncate('prerelease')
print(no_build)  # Version('1.2.3-alpha.1')

Utility Functions

Standalone functions for common version operations.

def compare(v1: str, v2: str) -> int:
    """
    Compare two version strings.
    
    Args:
        v1: First version string
        v2: Second version string
    
    Returns:
        -1 if v1 < v2, 0 if v1 == v2, 1 if v1 > v2
    """

def validate(version_string: str) -> bool:
    """
    Check if a version string is valid SemVer.
    
    Args:
        version_string: Version string to validate
    
    Returns:
        True if valid, False otherwise
    """

Usage Examples:

# Compare version strings directly
result = compare('1.0.0', '1.0.1')
print(result)  # -1

result = compare('2.0.0', '1.9.9')
print(result)  # 1

result = compare('1.0.0', '1.0.0+build')
print(result)  # 0 (build metadata ignored)

# Validate version strings
print(validate('1.2.3'))           # True
print(validate('1.2.3-alpha.1'))   # True
print(validate('1.2'))             # False
print(validate('invalid'))         # False

Version Validation Rules

The semantic_version library enforces strict SemVer 2.0.0 validation:

Validation Patterns

# Internal regex patterns used for validation
Version.version_re  # Strict SemVer pattern for complete versions
Version.partial_version_re  # Pattern allowing partial versions (deprecated)

Validation Rules

  • Major, minor, patch: Must be non-negative integers
  • Leading zeros: Not allowed in numeric components (except single '0')
  • Prerelease identifiers: Must be non-empty, can contain alphanumeric and hyphen
  • Build identifiers: Must be non-empty, can contain alphanumeric and hyphen
  • Missing components: Minor and patch default to 0 when using components, but string parsing requires all three

Examples of validation:

# Valid versions
Version('1.2.3')
Version('1.2.3-alpha.1')
Version('1.2.3+build.456')
Version('1.2.3-alpha.1+build.456')

# Invalid versions (raise ValueError)
Version('1.2')          # Missing patch
Version('01.2.3')       # Leading zero in major
Version('1.02.3')       # Leading zero in minor
Version('1.2.03')       # Leading zero in patch
Version('1.2.3-')       # Empty prerelease identifier
Version('1.2.3+')       # Empty build identifier

Error Handling

All version operations follow consistent error handling patterns:

  • ValueError: Raised for invalid version strings or components
  • TypeError: Raised for incompatible types in comparisons
  • DeprecationWarning: Issued for deprecated functionality (partial versions)
# Handle invalid versions
try:
    invalid_version = Version('not.a.version')
except ValueError as e:
    print(f"Invalid version: {e}")

# Handle type errors in comparison
try:
    result = Version('1.0.0') < "1.0.1"  # Should use Version object
except TypeError as e:
    print(f"Type error: {e}")

# Handle leading zero errors
try:
    leading_zero = Version('01.2.3')
except ValueError as e:
    print(f"Leading zero error: {e}")

Install with Tessl CLI

npx tessl i tessl/pypi-semantic-version

docs

django-integration.md

index.md

specification-matching.md

version-operations.md

tile.json