From 71a6f6a35a00996180fc0aadaba8de2a46b86ac9 Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Wed, 16 Oct 2024 15:19:56 -0600 Subject: [PATCH] per #2682, created METplus component version lookup table and functions to get formatted version of requested components --- .../test_component_versions.py | 47 ++++++++++++ metplus/_external_versions.py | 24 ------- metplus/component_versions.py | 72 +++++++++++++++++++ 3 files changed, 119 insertions(+), 24 deletions(-) create mode 100644 internal/tests/pytests/component_versions/test_component_versions.py delete mode 100644 metplus/_external_versions.py create mode 100644 metplus/component_versions.py diff --git a/internal/tests/pytests/component_versions/test_component_versions.py b/internal/tests/pytests/component_versions/test_component_versions.py new file mode 100644 index 000000000..5a35d4275 --- /dev/null +++ b/internal/tests/pytests/component_versions/test_component_versions.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 + +import pytest + +from metplus import component_versions + +@pytest.mark.parametrize( + 'component, version, expected_result', [ + ('met', '11.1.1', '5.1'), + ('MET', '11.1.1', '5.1'), + ('met', '11.1', '5.1'), + ('met', '11.1.Z', '5.1'), + ('METcalcpy', '3.0.0', '6.0'), + ('metcalcpy', 'main_v3.0', '6.0'), + ('metcalcpy', 'v3.0.0', '6.0'), + ('metcalcpy', 'v3.0.0-beta3', '6.0'), + ('metcalcpy', 'v3.0.0-rc1', '6.0'), + ('METplus', '6.0-latest', '6.0'), + ('METplus', '3.0-latest', None), + ] +) +@pytest.mark.util +def test_get_coordinated_version(component, version, expected_result): + assert component_versions.get_coordinated_version(component, version) == expected_result + + +@pytest.mark.parametrize( + 'input_component, input_version, output_component, output_format, expected_result', [ + ('metplus', '5.1.0', 'met', '{X}.{Y}.{Z}{N}', '11.1.1'), + ('metplus', '5.1.0-beta3', 'met', '{X}.{Y}.{Z}{N}', '11.1.1-beta3'), + ('metplus', '5.1.0-rc1', 'met', '{X}.{Y}.{Z}{N}', '11.1.1-rc1'), + ('metplus', '5.1-latest', 'met', '{X}.{Y}{N}', '11.1-latest'), + ('metplus', '5.1.0-beta3-dev', 'met', '{X}.{Y}.{Z}{N}', 'develop'), + ('METplus', '5.1.0', 'metplotpy', 'v{X}.{Y}.{Z}{N}', 'v2.1.0'), + ('metplus', '5.1.0-beta3', 'METplotpy', 'v{X}.{Y}.{Z}{N}', 'v2.1.0-beta3'), + ('metplus', '5.1.0-dev', 'METplotpy', 'v{X}.{Y}.{Z}{N}', 'develop'), + ('metplus', '5.1.0-rc1', 'metplotpy', 'v{X}.{Y}.{Z}{N}', 'v2.1.0-rc1'), + ('metplus', '5.1.0-beta3-dev', 'metplotpy', 'v{X}.{Y}.{Z}{N}', 'develop'), + ('MET', 'main_v11.1', 'METplus', 'main_v{X}.{Y}', 'main_v5.1'), + ('MET', 'main_v11.1-ref', 'METplus', 'main_v{X}.{Y}', 'main_v5.1'), + ('MET', 'main_v11.1', 'MET', '{X}.{Y}.{Z}{N}', '11.1.1'), + ('MET', '11.1.Z', 'MET', '{X}.{Y}.{Z}{N}', '11.1.1'), + ] +) +@pytest.mark.util +def test_get_component_version(input_component, input_version, output_component, output_format, expected_result): + assert component_versions.get_component_version(input_component, input_version, output_component, output_format) == expected_result diff --git a/metplus/_external_versions.py b/metplus/_external_versions.py deleted file mode 100644 index e62c144a3..000000000 --- a/metplus/_external_versions.py +++ /dev/null @@ -1,24 +0,0 @@ -version_lookup = { - '6.0.0-beta5': { - 'met': '12.0.0-beta5', - 'metplotpy': '3.0.0-beta5', - 'metcalcpy': '3.0.0-beta5', - 'metdataio': '3.0.0-beta5', - 'metviewer': '6.0.0-beta5', - 'metexpress': '', - }, - '5.1.0': { - 'met': '11.1.1', - 'metplotpy': '2.1.0', - 'metcalcpy': '2.1.0', - 'metdataio': '2.1.0', - 'metviewer': '5.1.0', - 'metexpress': '5.3.3', - }, -} - -def get_external_version(metplus_version, repo_name): - versions = version_lookup.get(metplus_version) - if versions is None: - return None - return versions.get(repo_name.lower()) diff --git a/metplus/component_versions.py b/metplus/component_versions.py new file mode 100644 index 000000000..f0560094e --- /dev/null +++ b/metplus/component_versions.py @@ -0,0 +1,72 @@ +VERSION_LOOKUP = { + '6.0': { + 'metplus': '6.0.0', + 'met': '12.0.0', + 'metplotpy': '3.0.0', + 'metcalcpy': '3.0.0', + 'metdataio': '3.0.0', + 'metviewer': '6.0.0', + 'metexpress': None, + }, + '5.1': { + 'metplus': '5.1.0', + 'met': '11.1.1', + 'metplotpy': '2.1.0', + 'metcalcpy': '2.1.0', + 'metdataio': '2.1.0', + 'metviewer': '5.1.0', + 'metexpress': '5.3.3', + }, +} + + +def get_component_version(input_component, input_version, output_component, output_format="v{X}.{Y}.{Z}{N}"): + """!Get the version of a requested METplus component given another METplus + component and its version. Parses out X.Y version numbers of input version + to find desired version. Optionally specific format of output content. + If input version ends with "-dev", then return "develop". + + @param input_component name of METplus component to use to find version, + e.g. MET, METplus, or METplotpy (case-insensitive). + @param input_version version of input_component to search. + @param output_component name of METplus component to obtain version number + @param output_format (optional) format to use to output version number. + {X}, {Y}, and {Z} will be replaced with x, y, and z version numbers from + X.Y.Z. {N} will be replaced with development version if found in the + input version, e.g. "-beta3" or "-rc1" + @returns string of requested version number, or "develop" if input version + ends with "-dev", or None if version number could not be determined. + """ + if input_version.endswith('-dev'): + return 'develop' + coord_version = get_coordinated_version(input_component, input_version) + versions = VERSION_LOOKUP.get(coord_version) + if versions is None: + return None + output_version = versions.get(output_component.lower()) + if output_version is None: + return None + x, y, z = output_version.split('.') + dev_version = input_version.split('-')[1:] + dev_version = '' if not dev_version else f"-{dev_version[0]}" + return output_format.format(X=x, Y=y, Z=z, N=dev_version) + + +def get_coordinated_version(component, version): + """!Get coordinated release version number based on the X.Y version number + of a given METplus component. + + @param component name of METplus component to search (case-insensitive) + @param version number of version to search for. Can be formatted with main_v + prefix and development release info, e.g. main_vX.Y or X.Y.Z-beta3. + @returns string of coordinated release version number X.Y or None. + """ + # remove main_v or v prefix, remove content after dash + search_version = version.removeprefix('main_').lstrip('v').split('-')[0] + # get X.Y only + search_version = '.'.join(search_version.split('.')[:2]) + # look for component version that begins with search version + for coord_version, versions in VERSION_LOOKUP.items(): + if versions.get(component.lower()).startswith(search_version): + return coord_version + return None