From db4d38a70f6af6907c439616d5adfedb30bdd7ef Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Thu, 14 Nov 2024 06:34:56 -0500 Subject: [PATCH] Moved version utility functions into their own python module --- python/datafed_pkg/datafed/MessageLib.py | 44 ++-------------- python/datafed_pkg/datafed/VersionUtils.py | 59 ++++++++++++++++++++++ 2 files changed, 62 insertions(+), 41 deletions(-) create mode 100644 python/datafed_pkg/datafed/VersionUtils.py diff --git a/python/datafed_pkg/datafed/MessageLib.py b/python/datafed_pkg/datafed/MessageLib.py index 83148859..eb63e0cc 100644 --- a/python/datafed_pkg/datafed/MessageLib.py +++ b/python/datafed_pkg/datafed/MessageLib.py @@ -11,8 +11,6 @@ # secure ZeroMQ link. -import re -import requests import zmq from . import Version_pb2 from . import SDMS_Anon_pb2 as anon @@ -20,43 +18,7 @@ from . import Connection from . import VERSION - -# Function to check if a string contains any letters -def contains_letters(s): - return bool(re.search("[a-zA-Z]", s)) - - -def remove_after_prefix_with_numbers(s): - # Use regular expression to match the prefix with numbers - match = re.match(r"(\d+.*?)(\D.*)", s) - if match: - return match.group(1) # Return the part before the remaining string - return s # If no match is found, return the original string - - -# Check with pypi if a newer release is available, only look for stable -# versions -def get_latest_stable_version(package_name): - try: - url = f"https://pypi.org/pypi/{package_name}/json" - response = requests.get(url) - response.raise_for_status() - data = response.json() - - # Extract release versions - releases = list(data.get("releases", {}).keys()) - # Filter the list to remove entries that contain any letters, we don't - # want to look at entries that could be a pre-release of some sort and - # recommend that the user use for instance a beta version. - releases = [release for release in releases if not contains_letters(release)] - if not releases: - return None - - return releases[0] - except Exception as e: - print(f"Unable to connect to pypi: {e}") - return None - +from . import VersionUtils ## # @class API @@ -208,7 +170,7 @@ def __init__( # Make a request to pypi package_name = "datafed" # Replace with the package name you want to check - latest_version_on_pypi = get_latest_stable_version(package_name) + latest_version_on_pypi = VersionUtils.get_latest_stable_version(package_name) self.new_client_avail = False if latest_version_on_pypi: @@ -216,7 +178,7 @@ def __init__( major, minor, patch_w_prerelease = VERSION.__version__.split(".") # Remove prerelease part from patch - patch = remove_after_prefix_with_numbers(patch_w_prerelease) + patch = VersionUtils.remove_after_prefix_with_numbers(patch_w_prerelease) if pypi_major > major: self.new_client_avail = latest_version_on_pypi diff --git a/python/datafed_pkg/datafed/VersionUtils.py b/python/datafed_pkg/datafed/VersionUtils.py new file mode 100644 index 00000000..a5399f51 --- /dev/null +++ b/python/datafed_pkg/datafed/VersionUtils.py @@ -0,0 +1,59 @@ +# @package datafed.VersionUtils +# version utilities for ensuring updated version of package are being used +# +# The functions included in here are to do version comparisons and to grab +# the registered versions that are available on pypi. + +import re +import requests + +# Function to convert version string into a tuple of integers for comparison +def version_key(version): + # Split main version and optional build number (e.g., "1.1.0-4" -> ["1.1.0", "4"]) + main_version, *build = version.split('-') + # Convert main version part to tuple of integers for correct comparison + main_version_tuple = tuple(map(int, main_version.split('.'))) + # Convert build part to integer if it exists, or set to -1 for non-build versions + build_number = int(build[0]) if build else -1 + # Return full tuple for sorting, making sure 0.x.y is distinct from x.y.z + return main_version_tuple + (build_number,) + +# Function to check if a string contains any letters +def contains_letters(s): + return bool(re.search("[a-zA-Z]", s)) + + +def remove_after_prefix_with_numbers(s): + # Use regular expression to match the prefix with numbers + match = re.match(r"(\d+.*?)(\D.*)", s) + if match: + return match.group(1) # Return the part before the remaining string + return s # If no match is found, return the original string + + +# Check with pypi if a newer release is available, only look for stable +# versions +def get_latest_stable_version(package_name): + try: + url = f"https://pypi.org/pypi/{package_name}/json" + response = requests.get(url) + response.raise_for_status() + data = response.json() + + # Extract release versions + releases = list(data.get("releases", {}).keys()) + # Filter the list to remove entries that contain any letters, we don't + # want to look at entries that could be a pre-release of some sort and + # recommend that the user use for instance a beta version. + releases = [release for release in releases if not contains_letters(release)] + if not releases: + return None + + # Sort versions using the custom key function + sorted_releases = sorted(releases, key=version_key) + return sorted_releases[-1] + except Exception as e: + print(f"Unable to connect to pypi: {e}") + return None + +