-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Expand file tree
/
Copy pathversion_utils.py
More file actions
51 lines (38 loc) · 1.45 KB
/
version_utils.py
File metadata and controls
51 lines (38 loc) · 1.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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())