Skip to content

Commit e64c199

Browse files
committed
dedupe code for normalization and the actual version parsing
1 parent af8eee9 commit e64c199

1 file changed

Lines changed: 39 additions & 29 deletions

File tree

python/private/version.bzl

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -503,40 +503,31 @@ def normalize_pep440(version):
503503
Returns:
504504
string containing the normalized version.
505505
"""
506-
parser = _new(version.strip()) # PEP 440: Leading and Trailing Whitespace
507-
accept(parser, _is("v"), "") # PEP 440: Preceding v character
508-
accept_epoch(parser)
509-
accept_release(parser)
510-
accept_prerelease(parser)
511-
accept_postrelease(parser)
512-
accept_devrelease(parser)
513-
accept_local(parser)
514-
if parser.input[parser.context()["start"]:]:
515-
fail(
516-
"Failed to parse PEP 440 version identifier '%s'." % parser.input,
517-
"Parse error at '%s'" % parser.input[parser.context()["start"]:],
518-
)
519-
return parser.context()["norm"]
506+
return _parse(version, strict = True)["norm"]
520507

521-
def version(version_str, strict = False):
522-
"""Parse a PEP4408 compliant version
508+
def _parse(version_str, strict = True):
509+
"""Escape the version component of a filename.
523510
524511
See https://packaging.python.org/en/latest/specifications/binary-distribution-format/#escaping-and-unicode
525512
and https://peps.python.org/pep-0440/
526513
527514
Args:
528515
version_str: version string to be normalized according to PEP 440.
529-
strict: fail if the version is invalid.
516+
strict: fail if the version is invalid, defaults to True.
530517
531518
Returns:
532519
string containing the normalized version.
533520
"""
521+
if strict:
522+
version_str = version_str.strip() # PEP 440: Leading and Trailing Whitespace
523+
is_prefix = False
524+
else:
525+
version_str = version_str.strip() # PEP 440: Leading and Trailing Whitespace
526+
is_prefix = version_str.endswith(".*")
527+
version_str = version_str.strip(" .*") # PEP 440: Leading and Trailing Whitespace and ".*"
534528

535-
parser = _new(version_str.strip(" " if strict else " .*")) # PEP 440: Leading and Trailing Whitespace and .*
536-
529+
parser = _new(version_str)
537530
accept(parser, _is("v"), "") # PEP 440: Preceding v character
538-
539-
parts = {}
540531
fns = [
541532
("epoch", accept_epoch),
542533
("release", accept_release),
@@ -546,15 +537,15 @@ def version(version_str, strict = False):
546537
("local", accept_local),
547538
]
548539

549-
for p, fn in fns:
540+
parts = {
541+
"is_prefix": is_prefix,
542+
}
543+
for key, fn in fns:
550544
start = len(parser.context()["norm"])
551545
fn(parser)
552-
parts[p] = parser.context()["norm"][start:]
553-
546+
parts[key] = parser.context()["norm"][start:]
554547
parts["norm"] = parser.context()["norm"]
555548

556-
is_prefix = version_str.endswith(".*")
557-
parts["is_prefix"] = is_prefix
558549
if is_prefix and (parts["local"] or parts["post"] or parts["dev"] or parts["pre"]):
559550
if strict:
560551
fail("local version part has been obtained, but only public segments can have prefix matches")
@@ -569,7 +560,26 @@ def version(version_str, strict = False):
569560
"Parse error at '%s'" % parser.input[parser.context()["start"]:],
570561
)
571562

572-
# If we fail to parse the version return None
563+
return None
564+
565+
return parts
566+
567+
def version(version_str, strict = False):
568+
"""Parse a PEP4408 compliant version
569+
570+
See https://packaging.python.org/en/latest/specifications/binary-distribution-format/#escaping-and-unicode
571+
and https://peps.python.org/pep-0440/
572+
573+
Args:
574+
version_str: version string to be normalized according to PEP 440.
575+
strict: fail if the version is invalid.
576+
577+
Returns:
578+
string containing the normalized version.
579+
"""
580+
581+
parts = _parse(version_str, strict = strict)
582+
if not parts:
573583
return None
574584

575585
return _new_version(**parts)
@@ -688,9 +698,9 @@ def _version_ne(left, right):
688698
def _prefix_err(left, op, right):
689699
if left.is_prefix or right.is_prefix:
690700
fail("PEP440: only '==' and '!=' operators can use prefix matching: {} {} {}".format(
691-
left,
701+
left.str(),
692702
op,
693-
right,
703+
right.str(),
694704
))
695705

696706
def _version_lt(left, right):

0 commit comments

Comments
 (0)