From 8e34a5089176588a7c582f0cd437a4e1d4c86b39 Mon Sep 17 00:00:00 2001 From: PatchOfScotland Date: Wed, 15 Feb 2023 00:41:39 +0100 Subject: [PATCH] added implemenation and test for module versioning --- functionality/requirements.py | 52 +++++++++++++++++++++++++++ tests/test_functionality.py | 67 +++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) diff --git a/functionality/requirements.py b/functionality/requirements.py index 4b2643d..815d043 100644 --- a/functionality/requirements.py +++ b/functionality/requirements.py @@ -5,6 +5,7 @@ requirements, and assessed by handlers and conductors. Author(s): David Marchant """ +from importlib.metadata import version, PackageNotFoundError from importlib.util import find_spec from os.path import basename from sys import version_info, prefix, base_prefix @@ -71,10 +72,61 @@ def check_python_requirements(reqs:Dict[str,Any])->bool: # TODO expand these so you can specify versions if REQ_PYTHON_MODULES in reqs: for module in reqs[REQ_PYTHON_MODULES]: + module_version = None + relation = None + for r in ["==", ">=", "<=", ">", "<"]: + if r in module: + module, module_version = module.split(r) + relation = r + break + found_spec = find_spec(module) if found_spec is None: return False, f"Could not find module '{module}'." + if module_version is None: + continue + + try: + installed_version = version(module) + except PackageNotFoundError: + return False, f"Could not find module '{module}'." + + if relation == "==" and module_version != installed_version: + return ( + False, + f"Installed {module} version '{installed_version}' " + f"differs from requested '{module_version}'" + ) + + if relation == ">=" and module_version > installed_version: + return ( + False, + f"Installed {module} version '{installed_version}' " + f"is more that requested '{module_version}'" + ) + + if relation == "<=" and module_version < installed_version: + return ( + False, + f"Installed {module} version '{installed_version}' " + f"is less that requested '{module_version}'" + ) + + if relation == ">" and module_version > installed_version: + return ( + False, + f"Installed {module} version '{installed_version}' " + f"is more that requested '{module_version}'" + ) + + if relation == "<" and module_version < installed_version: + return ( + False, + f"Installed {module} version '{installed_version}' " + f"is less that requested '{module_version}'" + ) + if REQ_PYTHON_VERSION in reqs: major, minor, micro = parse_versions(reqs[REQ_PYTHON_VERSION]) diff --git a/tests/test_functionality.py b/tests/test_functionality.py index 0fd915a..7ac0759 100644 --- a/tests/test_functionality.py +++ b/tests/test_functionality.py @@ -1044,6 +1044,73 @@ class RequirementsTest(unittest.TestCase): self.assertFalse(status) + def testPythonRequirementModuleVersions(self)->None: + key, python_reqs = create_python_requirements( + modules="papermill==2.4.0") + reqs = { key: python_reqs } + status, _ = check_requirements(reqs) + self.assertTrue(status) + + key, python_reqs = create_python_requirements( + modules="papermill<4") + reqs = { key: python_reqs } + status, _ = check_requirements(reqs) + self.assertTrue(status) + + key, python_reqs = create_python_requirements( + modules="papermill<1.0") + reqs = { key: python_reqs } + status, _ = check_requirements(reqs) + self.assertFalse(status) + + key, python_reqs = create_python_requirements( + modules="papermill>4") + reqs = { key: python_reqs } + status, _ = check_requirements(reqs) + self.assertFalse(status) + + key, python_reqs = create_python_requirements( + modules="papermill>1.0") + reqs = { key: python_reqs } + status, _ = check_requirements(reqs) + self.assertTrue(status) + + key, python_reqs = create_python_requirements( + modules="papermill<=4") + reqs = { key: python_reqs } + status, _ = check_requirements(reqs) + self.assertTrue(status) + + key, python_reqs = create_python_requirements( + modules="papermill<=2.4.0") + reqs = { key: python_reqs } + status, _ = check_requirements(reqs) + self.assertTrue(status) + + key, python_reqs = create_python_requirements( + modules="papermill<=1.0") + reqs = { key: python_reqs } + status, _ = check_requirements(reqs) + self.assertFalse(status) + + key, python_reqs = create_python_requirements( + modules="papermill>=4") + reqs = { key: python_reqs } + status, _ = check_requirements(reqs) + self.assertFalse(status) + + key, python_reqs = create_python_requirements( + modules="papermill>=2.4.0") + reqs = { key: python_reqs } + status, _ = check_requirements(reqs) + self.assertTrue(status) + + key, python_reqs = create_python_requirements( + modules="papermill>=1.0") + reqs = { key: python_reqs } + status, _ = check_requirements(reqs) + self.assertTrue(status) + # Test environment value of Python requirement testings def testPythonRequirementsEnvironment(self)->None: # TODO rework this test so that it actually create and runs in a new