From 9594ab31ef9da70812186f891debe2028cc6835f Mon Sep 17 00:00:00 2001 From: Bryan Gardiner Date: Sun, 18 Aug 2024 17:39:11 -0700 Subject: [PATCH] Fix some version ordering bugs. - Use @total_ordering to supply implementations of all other comparison functions from just __eq__() and __le__(). This is not done automatically. https://docs.python.org/3/library/functools.html#functools.total_ordering - An incomplete check for "pre" meant that the following would evaluate to true: VersionChunk("1pre2") < VersionChunk("1pre2") In practice this wasn't a problem because it appears that when comparing VersionChunk lists, equality is checked before ordering, but this isn't good to rely on. --- src/nvd | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/nvd b/src/nvd index 2cf9e1b..f4be70b 100755 --- a/src/nvd +++ b/src/nvd @@ -43,6 +43,7 @@ import os.path import re import subprocess import sys +from functools import total_ordering from pathlib import Path from signal import SIGPIPE, SIG_DFL, signal from subprocess import PIPE @@ -127,6 +128,7 @@ class StorePath: # For the version comparison algorithm, see: # https://nix.dev/manual/nix/stable/command-ref/nix-env/upgrade#versions +@total_ordering class VersionChunk: def __init__(self, chunk_value: Union[int, str]): assert isinstance(chunk_value, int) or isinstance(chunk_value, str) @@ -145,9 +147,9 @@ class VersionChunk: y_int = isinstance(y, int) if x_int and y_int: return x < y - elif (x == "" and y_int) or x == "pre": + elif (x == "" and y_int) or (x == "pre" and y != "pre"): return True - elif (x_int and y == "") or y == "pre": + elif (x_int and y == "") or (y == "pre" and x != "pre"): return False elif x_int: # y is a string return False @@ -162,6 +164,7 @@ class VersionChunk: return self._chunk_value == other._chunk_value +@total_ordering class Version: def __init__(self, text: Optional[str]): if text is None: