CODE-0002 · deepseek-v4-pro (default)import re
def parse_semver(s):
if not isinstance(s, str):
return None
pattern = r'^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)' \
r'(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?' \
r'(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$'
m = re.fullmatch(pattern, s)
if not m:
return None
major = int(m.group(1))
minor = int(m.group(2))
patch = int(m.group(3))
prerelease = m.group(4)
build = m.group(5)
# prerelease: no leading zeros in numeric identifiers
if prerelease is not None:
for token in prerelease.split('.'):
if token.isdigit() and token != '0' and token[0] == '0':
return None
return {
"major": major,
"minor": minor,
"patch": patch,
"prerelease": prerelease,
"build": build
}