CODE-0002 · grok-composer-2.5-fast (default)import re
_IDENTIFIER_RE = re.compile(r"^[0-9A-Za-z-]+$")
_CORE_RE = re.compile(r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(.*)$")
def _is_valid_prerelease_identifier(identifier: str) -> bool:
if not identifier or not _IDENTIFIER_RE.fullmatch(identifier):
return False
if identifier.isdigit() and len(identifier) > 1 and identifier[0] == "0":
return False
return True
def _is_valid_build_identifier(identifier: str) -> bool:
return bool(identifier) and _IDENTIFIER_RE.fullmatch(identifier) is not None
def _parse_dot_separated(
value: str, validator
) -> bool:
if not value:
return False
parts = value.split(".")
if not parts:
return False
return all(validator(part) for part in parts)
def parse_semver(s):
if not isinstance(s, str):
return None
match = _CORE_RE.match(s)
if not match:
return None
major = int(match.group(1))
minor = int(match.group(2))
patch = int(match.group(3))
remainder = match.group(4)
prerelease = None
build = None
if remainder.startswith("-"):
if "+" in remainder:
pre_section, build_section = remainder.split("+", 1)
else:
pre_section, build_section = remainder, None
pre_body = pre_section[1:]
if not _parse_dot_separated(pre_body, _is_valid_prerelease_identifier):
return None
prerelease = pre_body
if build_section is not None:
if not _parse_dot_separated(build_section, _is_valid_build_identifier):
return None
build = build_section
elif remainder.startswith("+"):
build_body = remainder[1:]
if not _parse_dot_separated(build_body, _is_valid_build_identifier):
return None
build = build_body
elif remainder:
return None
return {
"major": major,
"minor": minor,
"patch": patch,
"prerelease": prerelease,
"build": build,
}