CODE-0002 · gpt-5.5-pro (high)import re
_SEMVER_RE = re.compile(
r"(?P<major>0|[1-9][0-9]*)\."
r"(?P<minor>0|[1-9][0-9]*)\."
r"(?P<patch>0|[1-9][0-9]*)"
r"(?:-(?P<prerelease>(?:0|[1-9][0-9]*|[0-9A-Za-z-]*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9][0-9]*|[0-9A-Za-z-]*[A-Za-z-][0-9A-Za-z-]*))*))?"
r"(?:\+(?P<build>[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?"
)
def parse_semver(s):
if not isinstance(s, str):
return None
match = _SEMVER_RE.fullmatch(s)
if match is None:
return None
numbers = []
for name in ("major", "minor", "patch"):
text = match.group(name)
try:
numbers.append(int(text))
except ValueError:
value = 0
for char in text:
value = value * 10 + (ord(char) - 48)
numbers.append(value)
return {
"major": numbers[0],
"minor": numbers[1],
"patch": numbers[2],
"prerelease": match.group("prerelease"),
"build": match.group("build"),
}