51 lines
No EOL
2 KiB
Python
51 lines
No EOL
2 KiB
Python
import os
|
|
import json
|
|
import importlib.util
|
|
from typing import Dict, Any
|
|
from base_check import BaseCheck
|
|
|
|
class QCEngine:
|
|
def __init__(self, checks_dir: str, profile_path: str):
|
|
self.checks_dir = checks_dir
|
|
self.profile_path = profile_path
|
|
self.all_checks = {}
|
|
self.load_profile()
|
|
|
|
def load_profile(self):
|
|
with open(self.profile_path, "r") as f:
|
|
self.profile = json.load(f)
|
|
|
|
self.load_checks()
|
|
|
|
def load_checks(self):
|
|
# For each check specified in the profile, load its config and code
|
|
for check_def in self.profile.get("checks", []):
|
|
check_id = check_def["check_id"]
|
|
config_path = check_def["path"]
|
|
# The check_id.json file should be inside a similarly named directory.
|
|
# Derive the directory and python file from the config path.
|
|
check_dir = os.path.dirname(config_path)
|
|
check_name = os.path.splitext(os.path.basename(config_path))[0] # e.g. image_dimensions_check
|
|
check_py_path = os.path.join(check_dir, f"{check_name}.py")
|
|
|
|
if not os.path.exists(config_path) or not os.path.exists(check_py_path):
|
|
continue
|
|
|
|
# Dynamic import of the check module
|
|
spec = importlib.util.spec_from_file_location(check_id, check_py_path)
|
|
mod = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(mod)
|
|
|
|
# Find a class inheriting from BaseCheck
|
|
for attr_name in dir(mod):
|
|
attr = getattr(mod, attr_name)
|
|
if isinstance(attr, type) and issubclass(attr, BaseCheck) and attr is not BaseCheck:
|
|
check_instance = attr(config_path)
|
|
self.all_checks[check_id] = check_instance
|
|
break
|
|
|
|
def run_all_checks(self, data: Dict[str, Any]) -> Dict[str, Any]:
|
|
results = {}
|
|
for check_id, check_instance in self.all_checks.items():
|
|
results[check_id] = check_instance.run_check(data)
|
|
return results |