CODE-0002 · claude-fable-5 (high)import re
_SEMVER_RE = re.compile(
r"^(?P<major>0|[1-9]\d*)"
r"\.(?P<minor>0|[1-9]\d*)"
r"\.(?P<patch>0|[1-9]\d*)"
r"(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)"
r"(?:\.(?:0|[1-9]\d*|\d*[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
m = _SEMVER_RE.match(s)
if m is None:
return None
return {
"major": int(m.group("major")),
"minor": int(m.group("minor")),
"patch": int(m.group("patch")),
"prerelease": m.group("prerelease"),
"build": m.group("build"),
}