Source code for checkQC.qc_engine
from collections import defaultdict
import logging
from checkQC.handlers.qc_handler_factory import QCHandlerFactory
from checkQC.exceptions import ConfigurationError
log = logging.getLogger(__name__)
[docs]class QCEngine(object):
"""
The QCEngine will provide a method to apply all specified handler on the specified runfolder.
Internally it will run a number of methods which will do the following:
- create all handlers specified in the handler config
- validate all the configs provided, so that all necessary values are preset
- initiate the parsers based on which parsers are found in the handlers
- connect the handlers and parsers so that each parser gets the correct
subscribers
- run the parsers, i.e. pick up data and pass it to the handlers
- compile all reports from the handlers
The QCEngine has a `exit_status` field which can be checked after calling the `run` method,
to determine if all handlers were successful or not (zero indicates success, 1 indicates failure)
"""
def __init__(self, runfolder, parser_configurations, handler_config, qc_handler_factory=None):
"""
Create a instance of QCEngine
:param runfolder: the path to the runfolder which should be analyzed
:param parser_configurations: dict containing configurations for the parsers
:param handler_config: a dict which configurations for the handlers
:param qc_handler_factory: A QCHandlerFactory, if None default QCHandlerFactory will be used
"""
self.runfolder = runfolder
self.parser_configurations = parser_configurations
self.handlers_config = handler_config
self._handlers = []
self._parsers_and_handlers = defaultdict(list)
self.exit_status = 0
if qc_handler_factory:
self._qc_handler_factory = qc_handler_factory
else:
self._qc_handler_factory = QCHandlerFactory()
[docs] def run(self):
"""
Run the specified parsers and handlers and compile their reports. Will set the `exit_status` depending
on if there were any errors or not.
:return: a dict representing the reports gathers.
"""
try:
self._create_handlers()
self._validate_configurations()
self._initiate_parsers()
self._subscribe_handlers_to_parsers()
self._run_parsers()
reports = self._compile_reports()
return reports
except ConfigurationError:
self.exit_status = 1
def _create_handlers(self):
for clazz_config in self.handlers_config:
self._handlers.append(self._qc_handler_factory.
create_subclass_instance(clazz_config["name"], clazz_config))
def _validate_configurations(self):
try:
for handler in self._handlers:
handler.validate_configuration()
return True
except ConfigurationError as e:
log.error("Error in configuration found for handler: {}. {}".format(type(handler).__name__, e))
raise e
def _initiate_parsers(self):
for handler in self._handlers:
if isinstance(handler.parser(), list):
parsers = handler.parser()
else:
parsers = [handler.parser()]
for parser_factory in parsers:
parser_instance = parser_factory(runfolder=self.runfolder,
parser_configurations=self.parser_configurations)
self._parsers_and_handlers[parser_instance].append(handler)
def _subscribe_handlers_to_parsers(self):
for parser, handlers in self._parsers_and_handlers.items():
parser.add_subscribers(handlers)
def _run_parsers(self):
for parser in self._parsers_and_handlers.keys():
parser.run()
def _compile_reports(self):
reports = {"exit_status": 0}
for handler in self._handlers:
handler_report = handler.report()
if handler_report:
reports[type(handler).__name__] = list(map(lambda x: x.as_dict(), handler_report))
if handler.exit_status() != 0:
self.exit_status = 1
reports["exit_status"] = 1
return reports