From ca80c9e4c391dcf2fd9f6a5b9bbd5dda703b247d Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Thu, 27 Oct 2022 12:41:18 -0600 Subject: [PATCH] Per #1566, store the minimum version of python needed to run the wrappers in addition to the recommended version. Warn if the user's python version is less than the recommended and error if the their version is less than the minimum required --- .../util/metplus_check/test_metplus_check.py | 20 ++--- metplus/PYTHON_VERSION_MIN | 1 + metplus/__init__.py | 3 + metplus/util/metplus_check.py | 74 ++++++++++++------- 4 files changed, 62 insertions(+), 36 deletions(-) create mode 100644 metplus/PYTHON_VERSION_MIN diff --git a/internal/tests/pytests/util/metplus_check/test_metplus_check.py b/internal/tests/pytests/util/metplus_check/test_metplus_check.py index 75377c0bbe..832512dfb5 100644 --- a/internal/tests/pytests/util/metplus_check/test_metplus_check.py +++ b/internal/tests/pytests/util/metplus_check/test_metplus_check.py @@ -10,19 +10,19 @@ # a later version of python passes # an earlier version of python fails @pytest.mark.parametrize( - 'user, supported, torf', [ - ('3.6.3', '3.6.3', True), # same - ('2.7', '3.6.3', False), # earlier major - ('3.6.2', '3.6.3', False), # earlier bugfix - ('3.6.4', '3.6.3', True), # later bugfix - ('3.5.5', '3.6.3', False), # earlier minor, later bugfix - ('3.8.1', '3.6.3', True), # later minor, earlier bugfix - ('4.0.0', '3.6.3', True), # later major + 'user, torf', [ + ('3.6.3', True), # same + ('2.7', False), # earlier major + ('3.6.2', False), # earlier bugfix + ('3.6.4', True), # later bugfix + ('3.5.5', False), # earlier minor, later bugfix + ('3.8.1', True), # later minor, earlier bugfix + ('4.0.0', True), # later major ] ) @pytest.mark.util -def test_metplus_check_python(user, supported, torf): - assert metplus_check.metplus_check_python_version(user, supported) == torf +def test_metplus_check_python(user, torf): + assert metplus_check.metplus_check_python_version(user) == torf # checking METPLUS_DISABLE_PLOT_WRAPPERS and METPLUS_ENABLE_PLOT_WRAPPERS diff --git a/metplus/PYTHON_VERSION_MIN b/metplus/PYTHON_VERSION_MIN new file mode 100644 index 0000000000..1ac53bb4bd --- /dev/null +++ b/metplus/PYTHON_VERSION_MIN @@ -0,0 +1 @@ +3.6.3 \ No newline at end of file diff --git a/metplus/__init__.py b/metplus/__init__.py index 0f09074caf..2696e90ad4 100644 --- a/metplus/__init__.py +++ b/metplus/__init__.py @@ -9,6 +9,9 @@ def get_metplus_release_date(): def get_python_version(): return get_metplus_info('PYTHON_VERSION') +def get_python_version_min(): + return get_metplus_info('PYTHON_VERSION_MIN') + def get_metplus_info(info_rel_path): info_file = os.path.abspath(os.path.join(os.path.dirname(__file__), info_rel_path)) diff --git a/metplus/util/metplus_check.py b/metplus/util/metplus_check.py index b4d256b23f..8a90fdc8c2 100755 --- a/metplus/util/metplus_check.py +++ b/metplus/util/metplus_check.py @@ -7,38 +7,59 @@ import os import re -from .. import get_python_version +from .. import get_python_version, get_python_version_min -SUPPORTED_PY_VERSION = get_python_version() -def metplus_check_python_version(user_py, supported_py): - """!Test that the user's version of python is equal of higher than the - the supported version of python. Imported in each wrapper and run_metplus - to avoid confusing failures if the user's version is not current. Note: - SyntaxError from using f-strings (available in 3.6+) in earlier versions of - Python are output before the output from this function can be displayed. - Args: - @param user_py user's python version number, i.e. 3.8.1 - @param supported_py currently supported python version number, i.e. 3.6.3 - @returns True if version is at least supported, False if not +def metplus_check_python_version(user): + """!Test that the user's version of python is equal or higher than the + the supported version of python. Also check against the recommended + version of Python. This is used in the run_metplus.py script + to avoid confusing failures if the user's version is not current. Note: + SyntaxError from using f-strings (available in 3.6+) in earlier versions + of Python are output before the output from this function can be + displayed. + + @param user version of Python that the user is running + @returns True if version is at least supported, False if not """ - supported_list = supported_py.split('.') - user_list = user_py.split('.') + supported = get_python_version_min() + recommended = get_python_version() + + # check if user's Python version can run METplus wrappers + if not _python_version_is_sufficient(user, supported): + print("ERROR: Must be using Python {}".format(supported), + "or higher with the required packages installed." + " You are using {}.".format(user)) + print("See the METplus documentation for more information.") + return False + + # check if user's Python version is at least the recommended version + if not _python_version_is_sufficient(user, recommended): + print("WARNING: Python {}".format(recommended), + "or higher is recommended." + " You are using {}.".format(user)) + print("See the METplus documentation for more information.") + + return True - for user, supported in zip(user_list, supported_list): + +def _python_version_is_sufficient(user_version, test_version): + """! Check if user's version of Python is above or equal to another. + + @param user_version Python version of user, e.g. 3.7.3 + @param test_version Python version to compare, e.g. 3.8.6 + @returns True if user's version is sufficient, False otherwise + """ + for user, test in zip(user_version.split('.'), test_version.split('.')): # if the same version is used, continue - if int(user) == int(supported): + if int(user) == int(test): continue # if a higher version is used, break out of the loop - if int(user) > int(supported): + if int(user) > int(test): break - # a lower version is used - report and exit - print("ERROR: Must be using Python {} or higher ".format(supported_py)+ - "with the required packages installed.") - print("You are using {}.".format(user_py)) - print("See the METplus documentation for more information.") + # a lower version is used, return False return False return True @@ -54,6 +75,7 @@ def metplus_check_environment_variables(environ): return True + def evaluates_to_true(value): """!Check if the value matches an expression that should be interpretted as False Without this, environment variables that are set are interpretted as True no @@ -70,6 +92,7 @@ def evaluates_to_true(value): return True + def plot_wrappers_are_enabled(environ): """! Check METPLUS_[DISABLE/ENABLE]_PLOT_WRAPPERS. If both are set it should error and exit. Otherwise it should warn if DISABLE if used beacuse ENABLE should be @@ -97,13 +120,12 @@ def plot_wrappers_are_enabled(environ): # default behavior is to enable plot wrappers return True + # get user's python version and check that it is equal or # higher than the supported version -USER_PY_VERSION = sys.version.split(' ')[0] -compatible_python_version = metplus_check_python_version(USER_PY_VERSION, - SUPPORTED_PY_VERSION) +user_python_version = sys.version.split(' ')[0] +compatible_python_version = metplus_check_python_version(user_python_version) compatible_environment = metplus_check_environment_variables(os.environ) - if not compatible_python_version or not compatible_environment: sys.exit(1)