Skip to content

Commit b7860ae

Browse files
committed
remove 'upper' helper and simplify prefix matching
1 parent a302509 commit b7860ae

File tree

3 files changed

+44
-59
lines changed

3 files changed

+44
-59
lines changed

python/private/py_wheel_normalize_pep440.bzl

Lines changed: 17 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -518,28 +518,6 @@ def normalize_pep440(version):
518518
)
519519
return parser.context()["norm"]
520520

521-
def _upper(*, epoch = 0, release, pre = "", post = "", dev = "", local = ""):
522-
epoch = epoch
523-
_release = list(release[:-1])
524-
pre = pre
525-
post = post
526-
dev = dev
527-
local = local
528-
529-
if pre or dev or local:
530-
return _new_version(
531-
epoch = epoch,
532-
release = release,
533-
)
534-
535-
_release[-1] = _release[-1] + 1
536-
release = ".".join([str(d) for d in _release])
537-
538-
return _new_version(
539-
epoch = epoch,
540-
release = release,
541-
)
542-
543521
def _pad_zeros(release, n):
544522
if len(release) >= n:
545523
return release
@@ -550,35 +528,25 @@ def _pad_zeros(release, n):
550528

551529
# TODO @aignas 2025-05-04: add tests for the comparison
552530
def _version_eq(left, right):
531+
if left.is_prefix and right.is_prefix:
532+
fail("Invalid comparison: both versions cannot be prefix matching")
533+
if left.is_prefix:
534+
return right.norm.startswith("{}.".format(left.norm))
535+
if right.is_prefix:
536+
return left.norm.startswith("{}.".format(right.norm))
537+
553538
if left.epoch != right.epoch:
554539
return False
555540

556-
if left.is_prefix:
557-
right_release = right.release[:len(left.release)]
558-
else:
559-
##right_release = _pad_zeros(right.release, len(left.release))
560-
right_release = right.release
541+
##right_release = _pad_zeros(right.release, len(left.release))
542+
right_release = right.release
561543

562-
if right.is_prefix:
563-
left_release = left.release[:len(right.release)]
564-
else:
565-
##left_release = _pad_zeros(left.release, len(right.release))
566-
left_release = left.release
544+
##left_release = _pad_zeros(left.release, len(right.release))
545+
left_release = left.release
567546

568-
##print("left is prefix?", left.is_prefix)
569-
##print("left.release:", left.release, len(left.release))
570-
##print("left_release:", left_release)
571-
572-
##print("right is prefix?", right.is_prefix)
573-
##print("right.release:", right.release, len(right.release))
574-
##print("right_release:", right_release)
575547
if left_release != right_release:
576548
return False
577549

578-
print("is prefix?", left.is_prefix, right.is_prefix)
579-
if left.is_prefix or right.is_prefix:
580-
return True
581-
582550
return (
583551
left.pre == right.pre and
584552
left.post == right.post and
@@ -628,7 +596,7 @@ def _version_gt(left, right):
628596

629597
return left.release > right.release
630598

631-
def _new_version(*, epoch = 0, release, pre = "", post = "", dev = "", local = "", is_prefix = False):
599+
def _new_version(*, epoch = 0, release, pre = "", post = "", dev = "", local = "", is_prefix = False, norm):
632600
epoch = epoch or 0
633601
_release = tuple([int(d) for d in release.split(".")])
634602
pre = pre or ""
@@ -644,14 +612,7 @@ def _new_version(*, epoch = 0, release, pre = "", post = "", dev = "", local = "
644612
dev = dev,
645613
local = local,
646614
is_prefix = is_prefix,
647-
upper = lambda: _upper(
648-
epoch = epoch,
649-
release = _release,
650-
pre = pre,
651-
post = post,
652-
dev = dev,
653-
local = local,
654-
),
615+
norm = norm,
655616
# TODO @aignas 2025-05-04: add tests for the comparison
656617
eq = lambda x: _version_eq(self, x), # buildifier: disable=uninitialized
657618
ne = lambda x: not _version_eq(self, x), # buildifier: disable=uninitialized
@@ -679,7 +640,9 @@ def parse_version(version):
679640
"""
680641

681642
parser = _new(version.strip(" .*")) # PEP 440: Leading and Trailing Whitespace and .*
643+
parser_2 = _new(version.strip(" .*")) # PEP 440: Leading and Trailing Whitespace and .*
682644
accept(parser, _is("v"), "") # PEP 440: Preceding v character
645+
accept(parser_2, _is("v"), "") # PEP 440: Preceding v character
683646

684647
parts = {}
685648
fns = [
@@ -693,6 +656,7 @@ def parse_version(version):
693656

694657
for p, fn in fns:
695658
fn(parser)
659+
fn(parser_2)
696660
parts[p] = parser.context()["norm"]
697661
parser.context()["norm"] = "" # Clear out the buffer so that it is easy to separate the fields
698662

@@ -708,4 +672,5 @@ def parse_version(version):
708672
# If we fail to parse the version return None
709673
return None
710674

675+
parts["norm"] = parser_2.context()["norm"]
711676
return _new_version(**parts)

python/private/pypi/pep508_evaluate.bzl

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,13 @@ def _version_expr(left, op, right):
350350
# > simple string equality operations
351351
return _env_expr(left, "==", right)
352352

353+
if left.endswith(".*") and right.endswith(".*"):
354+
fail("PEP440: only one of the sides can have '.*' suffix: {} {} {}".format(
355+
left,
356+
op,
357+
right,
358+
))
359+
353360
_left = parse_version(left)
354361
_right = parse_version(right)
355362
if _left == None or _right == None:
@@ -358,21 +365,32 @@ def _version_expr(left, op, right):
358365
# or `platform_release`, which vary depending on platform.
359366
return _env_expr(left, op, right)
360367

361-
if op == "<":
368+
if op == "!=":
369+
return _left.ne(_right)
370+
elif op == "==":
371+
# Matching of major, minor, patch only
372+
return _left.eq(_right)
373+
elif left.endswith(".*") or right.endswith(".*"):
374+
fail("PEP440: only '==' and '!=' operators can use prefix matching: {} {} {}".format(
375+
left,
376+
op,
377+
right,
378+
))
379+
elif op == "<":
362380
return _left.lt(_right)
363381
elif op == ">":
364382
return _left.gt(_right)
365383
elif op == "<=":
366384
return _left.le(_right)
367385
elif op == ">=":
368386
return _left.ge(_right)
369-
elif op == "!=":
370-
return _left.ne(_right)
371-
elif op == "==":
372-
# Matching of major, minor, patch only
373-
return _left.eq(_right)
374387
elif op == "~=":
375-
return _left.ge(_right) and _left.lt(_right.upper())
388+
# https://peps.python.org/pep-0440/#compatible-release
389+
# Note, the ~= operator can be also expressed as:
390+
# >= V.N, == V.*
391+
head, _, _ = right.partition(".")
392+
_right_star = parse_version("{}.*".format(head))
393+
return _left.ge(_right) and _left.eq(_right_star)
376394
else:
377395
return False # Let's just ignore the invalid ops
378396

tests/pypi/pep508/evaluate_tests.bzl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,8 @@ def _expr_case(expr, want, env):
271271

272272
_MISC_EXPRESSIONS = [
273273
_expr_case('python_version == "3.*"', True, {"python_version": "3.10.1"}),
274+
_expr_case('python_version != "3.10.*"', False, {"python_version": "3.10.1"}),
275+
_expr_case('python_version != "3.11.*"', True, {"python_version": "3.10.1"}),
274276
]
275277

276278
def _misc_expressions(env):

0 commit comments

Comments
 (0)