Source code for benchbuild.extensions.base

"""
Extension base-classes for compile-time and run-time experiments.
"""
import collections as c
import logging
import typing as t
from abc import ABCMeta

from benchbuild.utils import run

LOG = logging.getLogger(__name__)


[docs]class Extension(metaclass=ABCMeta): """An experiment functor to implement composable experiments. An experiment extension is always callable with an arbitrary amount of arguments. The varargs component of an extension's `__call__` operator is fed the binary command that we currently execute and all arguments to the binary. Any customization necessary for the extension (e.g, dynamic configuration options) has to be passed by keyword argument. Args: *extensions: Variable length list of child extensions we manage. config (:obj:`dict`, optional): Dictionary of name value pairs to be stored for this extension. Attributes: next_extensions: Variable length list of child extensions we manage. config (:obj:`dict`, optional): Dictionary of name value pairs to be stored for this extension. """ def __init__(self, *extensions, config=None, **kwargs): """Initialize an extension with an arbitrary number of children.""" del kwargs self.next_extensions = extensions self.config = config
[docs] def call_next(self, *args, **kwargs) -> t.List[run.RunInfo]: """Call all child extensions with the given arguments. This calls all child extensions and collects the results for our own parent. Use this to control the execution of your nested extensions from your own extension. Returns: :obj:`list` of :obj:`RunInfo`: A list of collected results of our child extensions. """ all_results = [] for ext in self.next_extensions: LOG.debug(" %s ", ext) results = ext(*args, **kwargs) LOG.debug(" %s => %s", ext, results) if results is None: LOG.warning("No result from: %s", ext) continue result_list = [] if isinstance(results, c.Iterable): result_list.extend(results) else: result_list.append(results) all_results.extend(result_list) return all_results
def __lshift__(self, rhs): rhs.next_extensions = [self] return rhs
[docs] def print(self, indent=0): """Print a structural view of the registered extensions.""" LOG.info("%s:: %s", indent * " ", self.__class__) for ext in self.next_extensions: ext.print(indent=indent + 2)
def __call__(self, *args, **kwargs): return self.call_next(*args, **kwargs) def __str__(self): return "Extension"