diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index a14891b7fb..9b6babefd8 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: - python-version: '3.6' + python-version: '3.8' - name: Install dependencies run: | python -m pip install --upgrade sphinx sphinx-gallery sphinx_rtd_theme diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index f60cb04e59..66a9d352fa 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -78,7 +78,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: - python-version: '3.6' + python-version: '3.8' - name: Get METplus Image run: .github/jobs/docker_setup.sh env: diff --git a/.readthedocs.yaml b/.readthedocs.yaml index ea8b7fe79b..de9f518158 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -12,7 +12,7 @@ formats: [pdf] # Optionally set the version of Python and requirements required to build your # docs python: - version: 3.7 + version: 3.8 install: - requirements: docs/requirements.txt - requirements: requirements.txt diff --git a/environment.yml b/environment.yml index 59a28da556..e660f9d5d1 100644 --- a/environment.yml +++ b/environment.yml @@ -1,7 +1,7 @@ name: metplus_base channels: - - defaults + - conda-forge dependencies: - - python=3.6.3 + - python=3.8.6 - python-dateutil prefix: /home/met_test/.conda/envs/metplus_base 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 b/metplus/PYTHON_VERSION index 1ac53bb4bd..b916322161 100644 --- a/metplus/PYTHON_VERSION +++ b/metplus/PYTHON_VERSION @@ -1 +1 @@ -3.6.3 \ No newline at end of file +3.8.6 \ No newline at end of file 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) diff --git a/requirements.txt b/requirements.txt index 58e4a9f46f..9d72508e34 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -certifi==2020.6.20 -python-dateutil==2.8.1 -six==1.15.0 +certifi==2022.6.15 +python-dateutil==2.8.2 +six==1.16.0 diff --git a/setup.py b/setup.py index 379a82f704..2114a77efe 100644 --- a/setup.py +++ b/setup.py @@ -8,8 +8,8 @@ with open("metplus/VERSION", "r") as fh: version = fh.read().strip() -with open("metplus/PYTHON_VERSION", "r") as fh: - python_version = fh.read().strip() +with open("metplus/PYTHON_VERSION_MIN", "r") as fh: + python_version_req = fh.read().strip() # get list of additional files needed to add to package data_files = [] @@ -18,6 +18,7 @@ ['metplus/VERSION', 'metplus/RELEASE_DATE', 'metplus/PYTHON_VERSION', + 'metplus/PYTHON_VERSION_MIN', ])) for root, _, files in os.walk('parm'): @@ -47,7 +48,7 @@ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", ], - python_requires=f'>={python_version}', + python_requires=f'>={python_version_req}', data_files=data_files, zip_safe=False, )