import re
import uuid
from typing import Tuple
LATEST_VERSION = "latest"
_VERSION_PATTERN = re.compile(r"^v(?:ersion)?(\d+)$", re.IGNORECASE)
def parse_version(version: str) -> Tuple[bool, int]:
"""Parse a version string into (is_latest, version_number).
Accepts "latest", "vN", or "versionN" (case-insensitive).
Returns (True, 0) for "latest", (False, N) for pinned versions.
Raises:
ValueError: If the version string is invalid.
"""
if not version or version.lower() == LATEST_VERSION:
return True, 0
match = _VERSION_PATTERN.match(version)
if not match:
raise ValueError(
f"Invalid version string '{version}'. "
f"Expected 'latest', 'vN', or 'versionN' (e.g. 'v2', 'version3')."
)
return False, int(match.group(1))
def normalize_version_string(version: str) -> str:
"""Normalize a version string for comparison.
Empty string and "latest" both normalize to "latest".
"v2" and "version2" both normalize to "v2".
"""
if not version or version.lower() == LATEST_VERSION:
return LATEST_VERSION
is_latest, num = parse_version(version)
if is_latest:
return LATEST_VERSION
return version_tag(num)
def version_tag(n: int) -> str:
"""Convert an integer version number to the canonical short form 'vN'."""
return f"v{n}"
def generate_version_id() -> str:
"""Generate a UUID for a version record."""
return str(uuid.uuid4())