added requirement tests
This commit is contained in:
@ -221,3 +221,5 @@ def valid_non_existing_path(variable:str, allow_base:bool=False):
|
|||||||
if dirname(variable) and not exists(dirname(variable)):
|
if dirname(variable) and not exists(dirname(variable)):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Route to requested path '{variable}' does not exist.")
|
f"Route to requested path '{variable}' does not exist.")
|
||||||
|
|
||||||
|
# TODO add validation for requirement functions
|
@ -5,6 +5,9 @@ requirements, and assessed by handlers and conductors.
|
|||||||
Author(s): David Marchant
|
Author(s): David Marchant
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from importlib.util import find_spec
|
||||||
|
from os.path import basename
|
||||||
|
from sys import version_info, prefix, base_prefix
|
||||||
from typing import Any, Dict, List, Tuple, Union
|
from typing import Any, Dict, List, Tuple, Union
|
||||||
|
|
||||||
from core.correctness.validation import check_type
|
from core.correctness.validation import check_type
|
||||||
@ -14,7 +17,6 @@ REQ_PYTHON_MODULES = "modules"
|
|||||||
REQ_PYTHON_VERSION = "version"
|
REQ_PYTHON_VERSION = "version"
|
||||||
REQ_PYTHON_ENVIRONMENT = "environment"
|
REQ_PYTHON_ENVIRONMENT = "environment"
|
||||||
|
|
||||||
|
|
||||||
def create_requirement_dict(key:str, entires:Dict[str,Any]
|
def create_requirement_dict(key:str, entires:Dict[str,Any]
|
||||||
)->Tuple[str,Dict[str,Any]]:
|
)->Tuple[str,Dict[str,Any]]:
|
||||||
return key, entires
|
return key, entires
|
||||||
@ -41,3 +43,65 @@ def create_python_requirements(modules:Union[str,List[str]]="",
|
|||||||
python_reqs[REQ_PYTHON_ENVIRONMENT] = environment
|
python_reqs[REQ_PYTHON_ENVIRONMENT] = environment
|
||||||
|
|
||||||
return create_requirement_dict(REQUIREMENT_PYTHON, python_reqs)
|
return create_requirement_dict(REQUIREMENT_PYTHON, python_reqs)
|
||||||
|
|
||||||
|
def check_requirements(requirements:Dict[str,Any])->bool:
|
||||||
|
check_type(requirements, dict, hint="check_requirements.requirements")
|
||||||
|
result = True
|
||||||
|
reason = ""
|
||||||
|
for key, value in SUPPORTERD_REQS.items():
|
||||||
|
if key in requirements:
|
||||||
|
status, msg = value(requirements[key])
|
||||||
|
if not status:
|
||||||
|
result = False
|
||||||
|
reason = msg
|
||||||
|
return result, reason
|
||||||
|
|
||||||
|
# TODO integrate me into conductors
|
||||||
|
def check_python_requirements(reqs:Dict[str,Any])->bool:
|
||||||
|
check_type(reqs, dict,
|
||||||
|
hint=f"check_requirements.reqs[{REQUIREMENT_PYTHON}]")
|
||||||
|
|
||||||
|
if REQ_PYTHON_ENVIRONMENT in reqs:
|
||||||
|
if base_prefix == prefix:
|
||||||
|
return False, ""
|
||||||
|
|
||||||
|
if basename(prefix) != reqs[REQ_PYTHON_ENVIRONMENT]:
|
||||||
|
return False, ""
|
||||||
|
|
||||||
|
# TODO expand these so you can specify versions
|
||||||
|
if REQ_PYTHON_MODULES in reqs:
|
||||||
|
for module in reqs[REQ_PYTHON_MODULES]:
|
||||||
|
found_spec = find_spec(module)
|
||||||
|
if found_spec is None:
|
||||||
|
return False, f"Could not find module '{module}'."
|
||||||
|
|
||||||
|
if REQ_PYTHON_VERSION in reqs:
|
||||||
|
major, minor, micro = parse_versions(reqs[REQ_PYTHON_VERSION])
|
||||||
|
|
||||||
|
msg = f"Avaiable Python version number '{version_info[0]}." \
|
||||||
|
f"{version_info[1]}.{version_info[2]}' does not meet requested " \
|
||||||
|
f"{reqs[REQ_PYTHON_VERSION]}."
|
||||||
|
if major and int(version_info[0]) < major:
|
||||||
|
return False, msg
|
||||||
|
if minor and int(version_info[0]) <= major \
|
||||||
|
and int(version_info[1]) < minor:
|
||||||
|
return False, msg
|
||||||
|
if micro and int(version_info[0]) <= major \
|
||||||
|
and int(version_info[1]) <= minor \
|
||||||
|
and int(version_info[2]) < micro:
|
||||||
|
return False, msg
|
||||||
|
|
||||||
|
return True, ""
|
||||||
|
|
||||||
|
def parse_versions(version:str)->None:
|
||||||
|
parts = version.split('.')
|
||||||
|
if len(parts) == 1:
|
||||||
|
return int(parts[0]), None, None
|
||||||
|
elif len(parts) == 2:
|
||||||
|
return int(parts[0]), int(parts[1]), None
|
||||||
|
else:
|
||||||
|
return int(parts[0]), int(parts[1]), int(parts[2])
|
||||||
|
|
||||||
|
SUPPORTERD_REQS = {
|
||||||
|
REQUIREMENT_PYTHON: check_python_requirements,
|
||||||
|
}
|
||||||
|
@ -6,6 +6,8 @@ import os
|
|||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from multiprocessing import Pipe, Queue
|
from multiprocessing import Pipe, Queue
|
||||||
|
from os.path import basename
|
||||||
|
from sys import prefix, base_prefix
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
@ -32,6 +34,7 @@ from functionality.parameterisation import parameterize_jupyter_notebook, \
|
|||||||
parameterize_python_script
|
parameterize_python_script
|
||||||
from functionality.process_io import wait
|
from functionality.process_io import wait
|
||||||
from functionality.requirements import create_python_requirements, \
|
from functionality.requirements import create_python_requirements, \
|
||||||
|
check_requirements, \
|
||||||
REQUIREMENT_PYTHON, REQ_PYTHON_ENVIRONMENT, REQ_PYTHON_MODULES, \
|
REQUIREMENT_PYTHON, REQ_PYTHON_ENVIRONMENT, REQ_PYTHON_MODULES, \
|
||||||
REQ_PYTHON_VERSION
|
REQ_PYTHON_VERSION
|
||||||
from patterns import FileEventPattern
|
from patterns import FileEventPattern
|
||||||
@ -899,8 +902,8 @@ class RequirementsTest(unittest.TestCase):
|
|||||||
super().tearDown()
|
super().tearDown()
|
||||||
teardown()
|
teardown()
|
||||||
|
|
||||||
# Test Python requirement testings
|
# Test structure of Python requirement testings
|
||||||
def testPythonRequirementCreation(self)->None:
|
def testPythonRequirementStructuring(self)->None:
|
||||||
key, reqs = create_python_requirements()
|
key, reqs = create_python_requirements()
|
||||||
|
|
||||||
self.assertIsInstance(key, str)
|
self.assertIsInstance(key, str)
|
||||||
@ -971,5 +974,99 @@ class RequirementsTest(unittest.TestCase):
|
|||||||
self.assertIsInstance(reqs[REQ_PYTHON_ENVIRONMENT], str)
|
self.assertIsInstance(reqs[REQ_PYTHON_ENVIRONMENT], str)
|
||||||
self.assertEqual(reqs[REQ_PYTHON_ENVIRONMENT], "env")
|
self.assertEqual(reqs[REQ_PYTHON_ENVIRONMENT], "env")
|
||||||
|
|
||||||
# TODO expand me and add values for other attributes
|
# Test version values of Python requirement testings
|
||||||
|
def testPythonRequirementsVersion(self)->None:
|
||||||
|
key, python_reqs = create_python_requirements(version="3.10.6")
|
||||||
|
|
||||||
|
reqs = {
|
||||||
|
key: python_reqs
|
||||||
|
}
|
||||||
|
|
||||||
|
status, _ = check_requirements(reqs)
|
||||||
|
|
||||||
|
self.assertTrue(status)
|
||||||
|
|
||||||
|
key, python_reqs = create_python_requirements(version="2.5.9")
|
||||||
|
|
||||||
|
reqs = {
|
||||||
|
key: python_reqs
|
||||||
|
}
|
||||||
|
|
||||||
|
status, _ = check_requirements(reqs)
|
||||||
|
|
||||||
|
self.assertTrue(status)
|
||||||
|
|
||||||
|
key, python_reqs = create_python_requirements(version="4.1.1")
|
||||||
|
|
||||||
|
reqs = {
|
||||||
|
key: python_reqs
|
||||||
|
}
|
||||||
|
|
||||||
|
status, _ = check_requirements(reqs)
|
||||||
|
|
||||||
|
self.assertFalse(status)
|
||||||
|
|
||||||
|
# Test module values of Python requirement testings
|
||||||
|
def testPythonRequirementsModules(self)->None:
|
||||||
|
key, python_reqs = create_python_requirements(modules=[
|
||||||
|
"papermill", "sys", "typing"
|
||||||
|
])
|
||||||
|
|
||||||
|
reqs = {
|
||||||
|
key: python_reqs
|
||||||
|
}
|
||||||
|
|
||||||
|
status, _ = check_requirements(reqs)
|
||||||
|
|
||||||
|
self.assertTrue(status)
|
||||||
|
|
||||||
|
key, python_reqs = create_python_requirements(modules=[
|
||||||
|
"does", "not", "exist"
|
||||||
|
])
|
||||||
|
|
||||||
|
reqs = {
|
||||||
|
key: python_reqs
|
||||||
|
}
|
||||||
|
|
||||||
|
status, _ = check_requirements(reqs)
|
||||||
|
|
||||||
|
self.assertFalse(status)
|
||||||
|
|
||||||
|
key, python_reqs = create_python_requirements(modules=[
|
||||||
|
"papermill", "sys", "doesnotexist"
|
||||||
|
])
|
||||||
|
|
||||||
|
reqs = {
|
||||||
|
key: python_reqs
|
||||||
|
}
|
||||||
|
|
||||||
|
status, _ = check_requirements(reqs)
|
||||||
|
|
||||||
|
self.assertFalse(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
|
||||||
|
# environment
|
||||||
|
if prefix != base_prefix:
|
||||||
|
key, python_reqs = create_python_requirements(
|
||||||
|
environment=basename(prefix)
|
||||||
|
)
|
||||||
|
|
||||||
|
reqs = {
|
||||||
|
key: python_reqs
|
||||||
|
}
|
||||||
|
|
||||||
|
status, _ = check_requirements(reqs)
|
||||||
|
|
||||||
|
self.assertTrue(status)
|
||||||
|
|
||||||
|
key, python_reqs = create_python_requirements(environment="bad_env")
|
||||||
|
|
||||||
|
reqs = {
|
||||||
|
key: python_reqs
|
||||||
|
}
|
||||||
|
|
||||||
|
status, _ = check_requirements(reqs)
|
||||||
|
|
||||||
|
self.assertFalse(status)
|
||||||
|
Reference in New Issue
Block a user