From cdfb371ea9d8615b83e3cb50bb4e68b75e091b8a Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Fri, 3 Feb 2023 23:07:58 +0900 Subject: [PATCH 1/8] Attempt to fix issues with packaging.version.parse Defined a new class "ArchPkgVersion" to handle versions. May replace usage of `packaging.version.parse(...)`. --- update.py | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 177 insertions(+), 2 deletions(-) diff --git a/update.py b/update.py index 1456fdf..d1d5be7 100755 --- a/update.py +++ b/update.py @@ -24,6 +24,172 @@ AUR_GIT_REPO_PATH = "https://aur.archlinux.org" AUR_GIT_REPO_PATH_TEMPLATE = AUR_GIT_REPO_PATH + "/{}.git" GLOBAL_LOG_FILE = "log.txt" DEFAULT_EDITOR = "/usr/bin/nano" +ENDS_WITH_DIGIT_REGEX = re.compile("^(.*?)([0-9]+)$") + + +class ArchPkgVersion(): + def __init__(self, version_str): + self.versions = [] + self.pkgver = 0 + end_dash_idx = version_str.rfind('-') + if end_dash_idx != -1: + try: + self.pkgver = int(version_str[end_dash_idx+1:]) + except ValueError: + self.pkgver = version_str[end_dash_idx+1:] + version_str = version_str[:end_dash_idx] + + for sub in version_str.split('.'): + try: + integer = int(sub) + self.versions.append(integer) + except ValueError: + match = ENDS_WITH_DIGIT_REGEX.match(sub) + if match is not None: + subversion = [] + subversion.append(match.groups()[0]) + subversion.append(int(match.groups()[1])) + self.versions.append(tuple(subversion)) + else: + self.versions.append(sub) + + def compare_with(self, other_self): + self_count = len(self.versions) + other_count = len(other_self.versions) + if other_count < self_count: + count = other_count + else: + count = self_count + for i in range(count): + if type(self.versions[i]) is tuple: + if type(other_self.versions[i]) is tuple: + self_subcount = len(self.versions[i]) + other_subcount = len(other_self.versions[i]) + if other_subcount < self_subcount: + subcount = other_subcount + else: + subcount = self_subcount + for j in range(subcount): + try: + if self.versions[i][j] < other_self.versions[i][j]: + return -1 + elif self.versions[i][j] > other_self.versions[i][j]: + return 1 + except TypeError: + if str(self.versions[i][j]) < str(other_self.versions[i][j]): + return -1 + elif str(self.versions[i][j]) > str(other_self.versions[i][j]): + return 1 + if self_subcount < other_subcount: + return -1 + elif self_subcount > other_subcount: + return 1 + else: + # self is tuple but other is not + return 1 + elif type(other_self.versions[i]) is tuple: + # other is tuple but self is not + return -1 + else: + try: + if self.versions[i] < other_self.versions[i]: + return -1 + elif self.versions[i] > other_self.versions[i]: + return 1 + except TypeError: + if str(self.versions[i]) < str(other_self.versions[i]): + return -1 + elif str(self.versions[i]) > str(other_self.versions[i]): + return 1 + if self_count < other_count: + return -1 + elif self_count > other_count: + return 1 + else: + try: + if self.pkgver < other_self.pkgver: + return -1 + elif self.pkgver > other_self.pkgver: + return 1 + else: + return 0 + except TypeError: + if str(self.pkgver) < str(other_self.pkgver): + return -1 + elif str(self.pkgver) > str(other_self.pkgver): + return 1 + else: + return 0 + + + def __eq__(self, other): + if isinstance(other, version.Version): + other = ArchPkgVersion(str(other)) + + if isinstance(other, ArchPkgVersion): + return self.compare_with(other) == 0 + else: + return False + + def __ne__(self, other): + if isinstance(other, version.Version): + other = ArchPkgVersion(str(other)) + + if isinstance(other, ArchPkgVersion): + return self.compare_with(other) != 0 + else: + return False + + def __lt__(self, other): + if isinstance(other, version.Version): + other = ArchPkgVersion(str(other)) + + if isinstance(other, ArchPkgVersion): + return self.compare_with(other) < 0 + else: + return False + + def __le__(self, other): + if isinstance(other, version.Version): + other = ArchPkgVersion(str(other)) + + if isinstance(other, ArchPkgVersion): + result = self.compare_with(other) + return result <= 0 + else: + return False + + def __gt__(self, other): + if isinstance(other, version.Version): + other = ArchPkgVersion(str(other)) + + if isinstance(other, ArchPkgVersion): + return self.compare_with(other) > 0 + else: + return False + + def __ge__(self, other): + if isinstance(other, version.Version): + other = ArchPkgVersion(str(other)) + + if isinstance(other, ArchPkgVersion): + result = self.compare_with(other) + return result >= 0 + else: + return False + + def __str__(self): + self_str = "" + for idx in range(len(self.versions)): + if type(self.versions[idx]) is tuple: + for sub in self.versions[idx]: + self_str += str(sub) + else: + self_str += str(self.versions[idx]) + if idx + 1 < len(self.versions): + self_str += '.' + self_str += "-" + str(self.pkgver) + return self_str def log_print(*args, **kwargs): @@ -506,6 +672,15 @@ def get_pkgbuild_version( return False, None, None, None +def version_parse_checked(version_str: str): + try: + return version.parse(version_str) + except version.InvalidVersion: + self_version = ArchPkgVersion(version_str) + log_print(f'WARNING: version.parse(\"{version_str}\") failed to parse! Defaulting to self-defined version \"{self_version}\".') + return self_version + + def get_srcinfo_check_result( current_epoch: Union[str, None], current_version: str, @@ -554,8 +729,8 @@ def get_srcinfo_check_result( elif ( pkgver is not None and pkgrel is not None - and version.parse(current_version) - < version.parse(pkgver + "-" + pkgrel) + and version_parse_checked(current_version) + < version_parse_checked(pkgver + "-" + pkgrel) ): log_print( 'Current installed version of "{}" is out of date (older version).'.format( From 74133fb363e08f637fc75a1000c0d3ceff6e0a8e Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Sat, 4 Feb 2023 13:12:23 +0900 Subject: [PATCH 2/8] More robust handling of non-digits in version class ArchPkgVersion now handles non-digit version subsections by splitting them based on them being digits or not. ArchPkgVersion.versions is now a tuple after initialization. --- update.py | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/update.py b/update.py index d1d5be7..8f4b6e4 100755 --- a/update.py +++ b/update.py @@ -24,7 +24,7 @@ AUR_GIT_REPO_PATH = "https://aur.archlinux.org" AUR_GIT_REPO_PATH_TEMPLATE = AUR_GIT_REPO_PATH + "/{}.git" GLOBAL_LOG_FILE = "log.txt" DEFAULT_EDITOR = "/usr/bin/nano" -ENDS_WITH_DIGIT_REGEX = re.compile("^(.*?)([0-9]+)$") +IS_DIGIT_REGEX = re.compile("^[0-9]+$") class ArchPkgVersion(): @@ -40,18 +40,37 @@ class ArchPkgVersion(): version_str = version_str[:end_dash_idx] for sub in version_str.split('.'): - try: - integer = int(sub) - self.versions.append(integer) - except ValueError: - match = ENDS_WITH_DIGIT_REGEX.match(sub) - if match is not None: - subversion = [] - subversion.append(match.groups()[0]) - subversion.append(int(match.groups()[1])) - self.versions.append(tuple(subversion)) - else: - self.versions.append(sub) + if IS_DIGIT_REGEX.match(sub) is not None: + self.versions.append(int(sub)) + else: + subversion = [] + string = None + integer = None + for char in sub: + if IS_DIGIT_REGEX.match(char) is not None: + if string is not None: + subversion.append(string) + string = None + if integer is None: + integer = int(char) + else: + integer = integer * 10 + int(char) + else: + if integer is not None: + subversion.append(integer) + integer = None + if string is None: + string = char + else: + string = string + char + if string is not None: + subversion.append(string) + string = None + if integer is not None: + subversion.append(integer) + integer = None + self.versions.append(tuple(subversion)) + self.versions = tuple(self.versions) def compare_with(self, other_self): self_count = len(self.versions) @@ -121,7 +140,6 @@ class ArchPkgVersion(): else: return 0 - def __eq__(self, other): if isinstance(other, version.Version): other = ArchPkgVersion(str(other)) From 9e5b5d4d54956cf0c789d2affbcbd75f66c2b29d Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Sat, 4 Feb 2023 13:14:06 +0900 Subject: [PATCH 3/8] Formatting with python black --- update.py | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/update.py b/update.py index 8f4b6e4..4c8a0f2 100755 --- a/update.py +++ b/update.py @@ -27,19 +27,19 @@ DEFAULT_EDITOR = "/usr/bin/nano" IS_DIGIT_REGEX = re.compile("^[0-9]+$") -class ArchPkgVersion(): +class ArchPkgVersion: def __init__(self, version_str): self.versions = [] self.pkgver = 0 - end_dash_idx = version_str.rfind('-') + end_dash_idx = version_str.rfind("-") if end_dash_idx != -1: try: - self.pkgver = int(version_str[end_dash_idx+1:]) + self.pkgver = int(version_str[end_dash_idx + 1 :]) except ValueError: - self.pkgver = version_str[end_dash_idx+1:] + self.pkgver = version_str[end_dash_idx + 1 :] version_str = version_str[:end_dash_idx] - for sub in version_str.split('.'): + for sub in version_str.split("."): if IS_DIGIT_REGEX.match(sub) is not None: self.versions.append(int(sub)) else: @@ -92,12 +92,18 @@ class ArchPkgVersion(): try: if self.versions[i][j] < other_self.versions[i][j]: return -1 - elif self.versions[i][j] > other_self.versions[i][j]: + elif ( + self.versions[i][j] > other_self.versions[i][j] + ): return 1 except TypeError: - if str(self.versions[i][j]) < str(other_self.versions[i][j]): + if str(self.versions[i][j]) < str( + other_self.versions[i][j] + ): return -1 - elif str(self.versions[i][j]) > str(other_self.versions[i][j]): + elif str(self.versions[i][j]) > str( + other_self.versions[i][j] + ): return 1 if self_subcount < other_subcount: return -1 @@ -205,7 +211,7 @@ class ArchPkgVersion(): else: self_str += str(self.versions[idx]) if idx + 1 < len(self.versions): - self_str += '.' + self_str += "." self_str += "-" + str(self.pkgver) return self_str @@ -695,7 +701,9 @@ def version_parse_checked(version_str: str): return version.parse(version_str) except version.InvalidVersion: self_version = ArchPkgVersion(version_str) - log_print(f'WARNING: version.parse(\"{version_str}\") failed to parse! Defaulting to self-defined version \"{self_version}\".') + log_print( + f'WARNING: version.parse("{version_str}") failed to parse! Defaulting to self-defined version "{self_version}".' + ) return self_version From 9335a4336026ee0c6719b8e317a51610fd0558fd Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Sat, 4 Feb 2023 16:57:43 +0900 Subject: [PATCH 4/8] Minor fix --- update.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/update.py b/update.py index 4c8a0f2..31719f3 100755 --- a/update.py +++ b/update.py @@ -32,7 +32,7 @@ class ArchPkgVersion: self.versions = [] self.pkgver = 0 end_dash_idx = version_str.rfind("-") - if end_dash_idx != -1: + if end_dash_idx != -1 and end_dash_idx + 1 < len(version_str): try: self.pkgver = int(version_str[end_dash_idx + 1 :]) except ValueError: From 63928cf9ee529ec7f21ff1214adf8bcdb9a785b9 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Sat, 4 Feb 2023 16:58:00 +0900 Subject: [PATCH 5/8] Update LICENSE year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index df39565..21072c0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 Stephen Seo +Copyright (c) 2022-2023 Stephen Seo Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 913a3c2f5c3d7959cc590eefce5f43352ac7255a Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Sat, 4 Feb 2023 17:01:25 +0900 Subject: [PATCH 6/8] Remove usage of python-packaging, minor fixes --- README.md | 3 +-- update.py | 40 ++++------------------------------------ 2 files changed, 5 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index cb84377..46d5809 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,7 @@ The AUR Helper requires several things: The `devtools` package is required. -The `python-packaging` and `python-toml` packages are required for the Python -script to run. +The `python-toml` package is required for the Python script to run. ## Create the CHROOT diff --git a/update.py b/update.py index 31719f3..0b6e3f4 100755 --- a/update.py +++ b/update.py @@ -6,7 +6,6 @@ import sys import argparse import subprocess import re -from packaging import version import atexit import glob import toml @@ -147,58 +146,38 @@ class ArchPkgVersion: return 0 def __eq__(self, other): - if isinstance(other, version.Version): - other = ArchPkgVersion(str(other)) - if isinstance(other, ArchPkgVersion): return self.compare_with(other) == 0 else: return False def __ne__(self, other): - if isinstance(other, version.Version): - other = ArchPkgVersion(str(other)) - if isinstance(other, ArchPkgVersion): return self.compare_with(other) != 0 else: return False def __lt__(self, other): - if isinstance(other, version.Version): - other = ArchPkgVersion(str(other)) - if isinstance(other, ArchPkgVersion): return self.compare_with(other) < 0 else: return False def __le__(self, other): - if isinstance(other, version.Version): - other = ArchPkgVersion(str(other)) - if isinstance(other, ArchPkgVersion): - result = self.compare_with(other) - return result <= 0 + return self.compare_with(other) <= 0 else: return False def __gt__(self, other): - if isinstance(other, version.Version): - other = ArchPkgVersion(str(other)) - if isinstance(other, ArchPkgVersion): return self.compare_with(other) > 0 else: return False def __ge__(self, other): - if isinstance(other, version.Version): - other = ArchPkgVersion(str(other)) - if isinstance(other, ArchPkgVersion): - result = self.compare_with(other) - return result >= 0 + return self.compare_with(other) >= 0 else: return False @@ -696,17 +675,6 @@ def get_pkgbuild_version( return False, None, None, None -def version_parse_checked(version_str: str): - try: - return version.parse(version_str) - except version.InvalidVersion: - self_version = ArchPkgVersion(version_str) - log_print( - f'WARNING: version.parse("{version_str}") failed to parse! Defaulting to self-defined version "{self_version}".' - ) - return self_version - - def get_srcinfo_check_result( current_epoch: Union[str, None], current_version: str, @@ -755,8 +723,8 @@ def get_srcinfo_check_result( elif ( pkgver is not None and pkgrel is not None - and version_parse_checked(current_version) - < version_parse_checked(pkgver + "-" + pkgrel) + and ArchPkgVersion(current_version) + < ArchPkgVersion(pkgver + "-" + pkgrel) ): log_print( 'Current installed version of "{}" is out of date (older version).'.format( From c811080e579b8c2ab1fa44080dfa290a40b1bf90 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Sat, 4 Feb 2023 17:04:56 +0900 Subject: [PATCH 7/8] Add some docstrings to the ArchPkgVersion class --- update.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/update.py b/update.py index 0b6e3f4..d124edf 100755 --- a/update.py +++ b/update.py @@ -27,6 +27,8 @@ IS_DIGIT_REGEX = re.compile("^[0-9]+$") class ArchPkgVersion: + """Holds a version (typically of an ArchLinux package) for comparison.""" + def __init__(self, version_str): self.versions = [] self.pkgver = 0 @@ -72,6 +74,8 @@ class ArchPkgVersion: self.versions = tuple(self.versions) def compare_with(self, other_self): + """Returns -1 if self is less than other_self, 0 if they are equal, and + 1 if self is greater than other_self.""" self_count = len(self.versions) other_count = len(other_self.versions) if other_count < self_count: From 2f506fc333a52f66a024d556ca924899a93d19c5 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Sat, 4 Feb 2023 17:08:49 +0900 Subject: [PATCH 8/8] Add type annotations to ArchPkgVersion class --- update.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/update.py b/update.py index d124edf..f76658a 100755 --- a/update.py +++ b/update.py @@ -29,7 +29,7 @@ IS_DIGIT_REGEX = re.compile("^[0-9]+$") class ArchPkgVersion: """Holds a version (typically of an ArchLinux package) for comparison.""" - def __init__(self, version_str): + def __init__(self, version_str: str): self.versions = [] self.pkgver = 0 end_dash_idx = version_str.rfind("-") @@ -73,7 +73,7 @@ class ArchPkgVersion: self.versions.append(tuple(subversion)) self.versions = tuple(self.versions) - def compare_with(self, other_self): + def compare_with(self, other_self: "ArchPkgVersion"): """Returns -1 if self is less than other_self, 0 if they are equal, and 1 if self is greater than other_self.""" self_count = len(self.versions) @@ -149,37 +149,37 @@ class ArchPkgVersion: else: return 0 - def __eq__(self, other): + def __eq__(self, other: Any): if isinstance(other, ArchPkgVersion): return self.compare_with(other) == 0 else: return False - def __ne__(self, other): + def __ne__(self, other: Any): if isinstance(other, ArchPkgVersion): return self.compare_with(other) != 0 else: return False - def __lt__(self, other): + def __lt__(self, other: Any): if isinstance(other, ArchPkgVersion): return self.compare_with(other) < 0 else: return False - def __le__(self, other): + def __le__(self, other: Any): if isinstance(other, ArchPkgVersion): return self.compare_with(other) <= 0 else: return False - def __gt__(self, other): + def __gt__(self, other: Any): if isinstance(other, ArchPkgVersion): return self.compare_with(other) > 0 else: return False - def __ge__(self, other): + def __ge__(self, other: Any): if isinstance(other, ArchPkgVersion): return self.compare_with(other) >= 0 else: