Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 40 additions & 9 deletions product_listings_manager/products.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import logging
import os
import re
from itertools import zip_longest

import koji
from opentelemetry.instrumentation.requests import RequestsInstrumentor
Expand Down Expand Up @@ -66,16 +67,46 @@ def score(release):
return -1


def my_sort(x, y):
if len(x) > len(y) and y == x[: len(y)]:
return -1
if len(y) > len(x) and x == y[: len(x)]:
return 1
def to_number_tuple(x) -> tuple[str | int, ...]:
"""
Return a tuple with all series of digits converted to integers anything else remains a string.

Examples:
"U1-beta" -> ("U", 1, "-beta")
"6.18.3" -> (6, 18, 3)
"""
return tuple(
int(x) if x.isdigit() else x
for x in re.split(r"(\d+)", x)
if x not in (".", "")
)


def product_version_sort(x, y):
x_score = score(x)
y_score = score(y)
if x_score == y_score:
return _cmp(x, y)
return _cmp(x_score, y_score)
if x_score != y_score:
return _cmp(x_score, y_score)

x_tuple = to_number_tuple(x.lower())
y_tuple = to_number_tuple(y.lower())

for a, b in zip_longest(x_tuple, y_tuple):
if type(a) is not type(b):
# 1.2.3 > 1.2-beta
if isinstance(a, int):
return 1
if isinstance(b, int):
return -1
# U1 > U1-beta
if a is None:
return 1
return -1

result = _cmp(a, b)
if result != 0:
return result
return 0


def get_product_info(db, label):
Expand All @@ -84,7 +115,7 @@ def get_product_info(db, label):
versions = [x.version for x in products]
# Use functools.cmp_to_key for python3
# https://docs.python.org/3/library/functools.html#functools.cmp_to_key
versions.sort(key=functools.cmp_to_key(my_sort))
versions.sort(key=functools.cmp_to_key(product_version_sort))
versions.reverse()

if not versions:
Expand Down
30 changes: 18 additions & 12 deletions tests/test_products.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
get_product_info,
get_product_labels,
get_product_listings,
my_sort,
precalc_treelist,
product_version_sort,
score,
)

Expand All @@ -41,24 +41,30 @@ def test_score(self):
assert 5 == score("U1-beta")
assert -1 == score("other")

def test_my_sort(self):
def test_product_version_sort(self):
# x starts with y
assert -1 == my_sort("U1-beta", "U1")
assert -1 == product_version_sort("U1-beta", "U1")
assert 1 == product_version_sort("U10", "U1")

# y starts with x
assert 1 == my_sort("U1", "U1-beta")
assert 1 == product_version_sort("U1", "U1-beta")

# score(x) == score(y)
assert -1 == my_sort("7.1", "7.2")
assert -1 == my_sort("U3", "U4")
assert 1 == my_sort("7.2", "7.1")
assert 1 == my_sort("U4", "U3")
assert 0 == my_sort("8.0.0", "8.0.0")
assert -1 == product_version_sort("7.1", "7.2")
assert -1 == product_version_sort("U3", "U4")
assert 1 == product_version_sort("7.2", "7.1")
assert 1 == product_version_sort("U4", "U3")
assert 1 == product_version_sort("U30", "U9")
assert 0 == product_version_sort("u1", "U1")
assert 0 == product_version_sort("8.0.0", "8.0.0")
assert 1 == product_version_sort("6.9", "6.3")
assert 1 == product_version_sort("8.1", "8.0.0")
assert 1 == product_version_sort("8.0.1", "8.0")
assert -1 == product_version_sort("8.0", "8.0.1")
assert 1 == product_version_sort("6.18.3", "6.18")

# score(x) != score(y)
assert -1 == my_sort("Beta1", "Gold")
assert 1 == my_sort("6.9", "6.3")
assert 1 == my_sort("8.1", "8.0.0")
assert -1 == product_version_sort("Beta1", "Gold")

def test_get_product_info(self, db):
label = "RHEL-7"
Expand Down