コード例 #1
0
    def run(self):

        try:
            self.stdout = PyNRNEngine.compile_modfiles(self.modelpath)
        except sp.CalledProcessError as err:
            self.stderr = err.output
            self.returncode = err.returncode
            inform('Error compiling modfiles:', self.stderr, indent=2)

        try:
            inform("Running file %s with %s" %
                   (trim_path(self.modelpath), self.name),
                   indent=1)
            self.stdout = check_output([
                'mpiexec', '-np', '2', 'nrniv', '-mpi', self.modelpath,
                '-nogui'
            ],
                                       cwd=os.path.dirname(self.modelpath))
            self.returncode = 0
        except sp.CalledProcessError as err:
            self.returncode = err.returncode
            self.stdout = err.output
            raise EngineExecutionError
        except Exception as err:
            inform("Another error with running %s: " % self.name,
                   err,
                   indent=1)
            self.returncode = -1
            self.stdout = "???"
コード例 #2
0
    def run(self):
        try:
            nml2_comp_type_def_dir = os.path.join(default_nml2_dir,
                                                  'NeuroML2CoreTypes')

            inform(
                "Running file %s with %s, including path: %s" %
                (trim_path(self.modelpath), self.name, nml2_comp_type_def_dir),
                indent=1)

            self.stdout = sp.check_output([
                'pylems', '-I', nml2_comp_type_def_dir, self.modelpath,
                '-nogui'
            ],
                                          cwd=os.path.dirname(self.modelpath))
            self.returncode = 0
        except sp.CalledProcessError as err:
            self.returncode = err.returncode
            self.stdout = err.output
            raise EngineExecutionError
        except Exception as err:
            inform("Another error with running %s: " % self.name,
                   err,
                   indent=1)
            self.returncode = -1
            self.stdout = "???"
コード例 #3
0
    def run(self):

        np = 2

        try:
            inform("Running file %s with %s" %
                   (trim_path(self.modelpath), JNeuroMLNetPyNEEngine.name),
                   indent=1)

            from omv.engines.jneuroml import JNeuroMLEngine
            jnml = JNeuroMLEngine.get_executable()
            self.stdout = check_output([
                jnml, self.modelpath, '-netpyne', '-nogui', '-run', '-np',
                '%s' % np
            ],
                                       cwd=os.path.dirname(self.modelpath),
                                       env=JNeuroMLEngine.get_environment())
            inform("Success with running ",
                   JNeuroMLNetPyNEEngine.name,
                   indent=1)
            self.returncode = 0
        except sp.CalledProcessError as err:
            inform("Error with ", JNeuroMLNetPyNEEngine.name, indent=1)
            self.returncode = err.returncode
            self.stdout = err.output
            raise EngineExecutionError
コード例 #4
0
 def run(self):
     try:
         inform("Running file %s with %s" % (trim_path(self.modelpath), self.name),
                indent=1)
         self.stdout = sp.check_output(['pynml' if os.name != 'nt' else 'pynml.bat', self.modelpath, '-nogui'],
                                       cwd=os.path.dirname(self.modelpath))
         self.returncode = 0
     except sp.CalledProcessError as err:
         self.returncode = err.returncode
         self.stdout = err.output
         raise EngineExecutionError
コード例 #5
0
 def run(self):
     try:
         inform("Running file %s with %s" % (trim_path(self.modelpath), JNeuroMLMooseEngine.name), indent=1)
         self.stdout = check_output(['jnml' if os.name != 'nt' else 'jnml.bat', self.modelpath, '-moose'], cwd=os.path.dirname(self.modelpath))
         self.stdout += check_output(['python', self.modelpath.replace('.xml', '_moose.py'), '-nogui'], cwd=os.path.dirname(self.modelpath))
         inform("Success with running ", JNeuroMLMooseEngine.name, indent=1)
         self.returncode = 0
     except sp.CalledProcessError as err:
         inform("Error with ", JNeuroMLMooseEngine.name, indent=1)
         self.returncode = err.returncode
         self.stdout = err.output
         raise EngineExecutionError
コード例 #6
0
 def run(self):
     try:
         inform("Running file %s with %s" % (trim_path(self.modelpath), JNeuroMLBrianEngine.name), indent=1)
         self.stdout = check_output(['jnml' if os.name != 'nt' else 'jnml.bat', self.modelpath, '-brian'], cwd=os.path.dirname(self.modelpath))
         self.stdout += check_output(['python', self.modelpath.replace('.xml', '_brian.py'), '-nogui'], cwd=os.path.dirname(self.modelpath))
         inform("Success with running ", JNeuroMLBrianEngine.name, indent=1)
         self.returncode = 0
     except sp.CalledProcessError as err:
         inform("Error with ", JNeuroMLBrianEngine.name, indent=1)
         self.returncode = err.returncode
         self.stdout = err.output
         raise EngineExecutionError
コード例 #7
0
 def run(self):
     
     try:
         inform("Running file %s with Py_neuroConstruct" % trim_path(self.modelpath), indent=1)
         
         nC_sh = os.path.join(PyneuroConstructEngine.get_nC_environment()['NC_HOME'], 'nC.sh')
         self.stdout = co([nC_sh, '-python', self.modelpath, '-nogui'],
                                       cwd=os.path.dirname(self.modelpath))
         self.returncode = 0
     except Exception as err:
         inform("Error with running Py_neuroConstruct:", err, indent=1)
         self.returncode = -1
         self.stdout = "???"
コード例 #8
0
 def run(self):
     
     try:
         inform("Running file %s with Py_neuroConstruct" % trim_path(self.modelpath), indent=1)
         
         nC_sh = os.path.join(PyneuroConstructEngine.get_nC_environment()['NC_HOME'], 'nC.sh')
         self.stdout = co([nC_sh, '-python', self.modelpath, '-nogui'],
                                       cwd=os.path.dirname(self.modelpath))
         self.returncode = 0
     except Exception as err:
         inform("Error with running Py_neuroConstruct:", err, indent=1)
         self.returncode = -1
         self.stdout = "???"
コード例 #9
0
def parse_omt(omt_path, do_not_run=False):
    inform('')
    action = 'Running'
    if do_not_run:
        action = 'Checking'
    inform(action+" the tests defined in ", trim_path(omt_path),
           underline='=', center=False)
    
    mepomt = OMVTestParser(omt_path)
    if not mepomt.engine in OMVEngines:
        inform("Error! Unrecognised engine: %s (try running: omv list-engines)"%mepomt.engine)
        exit(1)
    engine = OMVEngines[mepomt.engine](mepomt.modelpath, do_not_run)
    experiments = [exp for exp in mepomt.generate_exps(engine)]
    
    tally = Tallyman(mepomt)
    
    inform('Found %i experiment(s) to run on engine: %s '%(len(experiments), engine.name), indent=1)
    
    if not do_not_run:
        try:
            engine.run()
            some_failed = False
            for exp in experiments:
                inform('Running checks for experiment: ', exp.name, indent=1)
                inform('')
                results = exp.check_all()
                inform('{:<30}{:^20}'.format('Observable', 'Test Passed'),
                       underline='-', indent=3)
                for rn, rv in results.items():
                    if sys.version_info >= (3,0):
                        inform('{:<30}{:^20}'.format(rn, check(rv)), indent=3)
                    else:
                        inform(u'{:<30}{:^20}'.format(rn, check(rv)), indent=3)
                    if not rv:
                        some_failed = True
                tally.add_experiment(exp, results)

            if some_failed:
                inform("+++++++++++++++++++++ Error info ++++++++++++++++++", indent=3)
                inform(" Return code: %s"%engine.returncode, indent=3)
                if hasattr(engine,'stdout'):
                    inform(" Output: %s"%engine.stdout.replace('\n','\n       '), indent=3)
                inform("+++++++++++++++++++++++++++++++++++++++++++++++++++", indent=3)

        except (EngineInstallationError, EngineExecutionError):
            # TODO: serialize exception info
            inform('ERROR running engine ', engine.name, indent=1,
                   underline='-', overline='-')

    return tally
コード例 #10
0
 def run(self):
     try:
         inform("Running file %s with jLEMS" % trim_path(self.modelpath), indent=1)
         self.stdout = sp.check_output(['lems', self.modelpath, '-nogui'],
                                       cwd=os.path.dirname(self.modelpath))
         self.returncode = 0
     except sp.CalledProcessError as err:
         self.returncode = err.returncode
         self.stdout = err.output
         raise EngineExecutionError
     except Exception as err:
         inform("Another error with running jLEMS:", err, indent=1)
         self.returncode = -1
         self.stdout = "???"
コード例 #11
0
 def run(self):
     try:
         inform("Running file %s with %s" % (trim_path(self.modelpath), self.name), indent=1)
         self.stdout = sp.check_output(['pylems', self.modelpath, '-nogui'],
                                       cwd=os.path.dirname(self.modelpath))
         self.returncode = 0
     except sp.CalledProcessError as err:
         self.returncode = err.returncode
         self.stdout = err.output
         raise EngineExecutionError
     except Exception as err:
         inform("Another error with running %s: "%self.name, err, indent=1)
         self.returncode = -1
         self.stdout = "???"
コード例 #12
0
 def run(self):
     try:
         inform("Running file %s with %s" % (trim_path(self.modelpath), JNeuroMLPyNNNRNEngine.name), indent=1)
         self.stdout = check_output(
             ['jnml' if os.name != 'nt' else 'jnml.bat', self.modelpath, '-pynn', '-run-neuron'],
             cwd=os.path.dirname(self.modelpath))
         inform("Success with running ",
                JNeuroMLPyNNNRNEngine.name, indent=1)
         self.returncode = 0
     except sp.CalledProcessError as err:
         inform("Error with ", JNeuroMLPyNNNRNEngine.name, indent=1)
         self.returncode = err.returncode
         self.stdout = err.output
         raise EngineExecutionError
コード例 #13
0
 def run(self):
     try:
         inform("Running file %s with %s" % (trim_path(self.modelpath), self.name), indent=1)
         self.stdout = check_output(['python', self.modelpath, 'brian'],
                                       cwd=os.path.dirname(self.modelpath))
         self.returncode = 0
     except sp.CalledProcessError as err:
         self.returncode = err.returncode
         self.stdout = err.output
         raise EngineExecutionError
     except Exception as err:
         inform("Another error with running %s: "%self.name, err, indent=1)
         self.returncode = -1
         self.stdout = "???"
コード例 #14
0
    def run(self):
        try:
            inform("Running file %s with %s" %
                   (trim_path(self.modelpath), self.name),
                   indent=1)

            jnml = JNeuroMLEngine.get_executable()
            self.stdout = sp.check_output([jnml, self.modelpath, '-nogui'],
                                          cwd=os.path.dirname(self.modelpath),
                                          env=JNeuroMLEngine.get_environment())
            self.returncode = 0
        except sp.CalledProcessError as err:
            self.returncode = err.returncode
            self.stdout = err.output
            raise EngineExecutionError
コード例 #15
0
 def run(self):
     try:
         inform("Running file %s with %s" %
                (trim_path(self.modelpath), self.name),
                indent=1)
         self.stdout = co([
             'pynml' if os.name != 'nt' else 'pynml.bat', self.modelpath,
             '-nogui'
         ],
                          cwd=os.path.dirname(self.modelpath))
         self.returncode = 0
     except sp.CalledProcessError as err:
         self.returncode = err.returncode
         self.stdout = err.output
         raise EngineExecutionError
コード例 #16
0
 def add(self, tally):
     
     if not tally.engine in self.all_engines:
         self.all_engines.append(tally.engine)
         
     mp = trim_path(tally.modelpath)
     
     if not mp in self.tallies:
         self.tallies[mp] = {}
     
     mptallies = self.tallies[mp]
     
     if not tally.engine in mptallies:
         mptallies[tally.engine] = []
         
     mptallies[tally.engine].append(tally)
コード例 #17
0
    def add(self, tally):

        if not tally.engine in self.all_engines:
            self.all_engines.append(tally.engine)

        mp = trim_path(tally.modelpath)

        if not mp in self.tallies:
            self.tallies[mp] = {}

        mptallies = self.tallies[mp]

        if not tally.engine in mptallies:
            mptallies[tally.engine] = []

        mptallies[tally.engine].append(tally)
コード例 #18
0
 def run(self):
     try:
         inform("Running file %s with %s" % (trim_path(self.modelpath), JNeuroMLBrianEngine.name), indent=1)
         
         from omv.engines.jneuroml import JNeuroMLEngine
         jnml = JNeuroMLEngine.get_executable()
         
         self.stdout = check_output([jnml, self.modelpath, '-brian'], cwd=os.path.dirname(self.modelpath),env=JNeuroMLEngine.get_environment())
         self.stdout += check_output(['python', self.modelpath.replace('.xml', '_brian.py'), '-nogui'], cwd=os.path.dirname(self.modelpath))
         inform("Success with running ", JNeuroMLBrianEngine.name, indent=1)
         self.returncode = 0
     except sp.CalledProcessError as err:
         inform("Error with ", JNeuroMLBrianEngine.name, indent=1)
         self.returncode = err.returncode
         self.stdout = err.output
         raise EngineExecutionError
コード例 #19
0
    def run(self):

        self.environment_vars = NestEngine.get_nest_environment()
        self.set_environment()

        try:
            inform("Running file %s with %s" % (trim_path(self.modelpath), self.name), indent=1)
            self.stdout = check_output([self.environment_vars['NEST_HOME']+'bin/nest', self.modelpath],
                                          cwd=os.path.dirname(self.modelpath))
            self.returncode = 0
        except sp.CalledProcessError as err:
            self.returncode = err.returncode
            self.stdout = err.output
            raise EngineExecutionError
        except Exception as err:
            inform("Another error with running %s: "%self.name, err, indent=1)
            self.returncode = -1
            self.stdout = "???"
コード例 #20
0
    def run(self):

        self.environment_vars = NestEngine.get_nest_environment()
        self.set_environment()

        try:
            inform("Running file %s with %s" % (trim_path(self.modelpath), self.name), indent=1)
            self.stdout = check_output([self.environment_vars['NEST_HOME']+'bin/nest', self.modelpath],
                                          cwd=os.path.dirname(self.modelpath))
            self.returncode = 0
        except sp.CalledProcessError as err:
            self.returncode = err.returncode
            self.stdout = err.output
            raise EngineExecutionError
        except Exception as err:
            inform("Another error with running %s: "%self.name, err, indent=1)
            self.returncode = -1
            self.stdout = "???"
コード例 #21
0
 def run(self):
     try:
         inform("Running file %s with %s" %
                (trim_path(self.modelpath), JNeuroMLPyNNNRNEngine.name),
                indent=1)
         self.stdout = check_output([
             'jnml' if os.name != 'nt' else 'jnml.bat', self.modelpath,
             '-pynn', '-run-neuron'
         ],
                                    cwd=os.path.dirname(self.modelpath))
         inform("Success with running ",
                JNeuroMLPyNNNRNEngine.name,
                indent=1)
         self.returncode = 0
     except sp.CalledProcessError as err:
         inform("Error with ", JNeuroMLPyNNNRNEngine.name, indent=1)
         self.returncode = err.returncode
         self.stdout = err.output
         raise EngineExecutionError
コード例 #22
0
    def run(self):
        try:

            inform("Env vars: %s" % self.environment_vars, indent=2)

            inform("Running file %s with %s" %
                   (trim_path(self.modelpath), self.name),
                   indent=1)
            self.stdout = check_output(['python', self.modelpath, 'neuroml'],
                                       cwd=os.path.dirname(self.modelpath))
            self.returncode = 0
        except sp.CalledProcessError as err:
            self.returncode = err.returncode
            self.stdout = err.output
            raise EngineExecutionError
        except Exception as err:
            inform("Another error with running %s: " % self.name,
                   err,
                   indent=1)
            self.returncode = -1
            self.stdout = "???"
コード例 #23
0
    def run(self):


        try:
            self.stdout = PyNRNEngine.compile_modfiles(self.modelpath)
        except sp.CalledProcessError as err:
            self.stderr = err.output
            self.returncode = err.returncode
            inform('Error compiling modfiles:', self.stderr, indent=2)

        try:            
            inform("Running file %s with %s" % (trim_path(self.modelpath), self.name), indent=1)
            self.stdout = check_output(['mpiexec','-np','4','nrniv','-mpi', self.modelpath, '-nogui'],
                                          cwd=os.path.dirname(self.modelpath))
            self.returncode = 0
        except sp.CalledProcessError as err:
            self.returncode = err.returncode
            self.stdout = err.output
            raise EngineExecutionError
        except Exception as err:
            inform("Another error with running %s: "%self.name, err, indent=1)
            self.returncode = -1
            self.stdout = "???"
コード例 #24
0
    def run_using_jnmlnrn_env(engine, modelpath, args):

        try:
            env = JNeuroMLNRNEngine.get_jnmlnrnenv()
            inform("Running file %s with %s, env: %s" %
                   (trim_path(modelpath), engine, env),
                   indent=1)
            from omv.engines.jneuroml import JNeuroMLEngine
            jnml = JNeuroMLEngine.get_executable()
            cmds = [jnml, modelpath]
            cmds.extend(args)
            stdout = check_output(cmds,
                                  cwd=os.path.dirname(modelpath),
                                  env=env)

            inform("Success with running ", engine, indent=1)
            returncode = 0
            return stdout, returncode
        except sp.CalledProcessError as err:
            inform("Error with ", engine, indent=1)
            returncode = err.returncode
            stdout = err.output
            return stdout, returncode
コード例 #25
0
def test_all(do_not_run=False,
             only_this_engine=None,
             include_temp_tests=False):
    cwd = Path(getcwd())
    all_omts = [p.as_posix() for p in cwd.glob('**/*.omt')]
    if include_temp_tests:
        all_omts += [p.as_posix() for p in cwd.glob('**/*.omt_')]

    th = TallyHolder()
    if environ.get('TRAVIS'):
        if not environ.get('OMV_ENGINE'):
            tallies = [parse_omt(t) for t in all_omts]
        else:
            engine = environ.get('OMV_ENGINE').lower()
            tallies = [
                parse_omt(t) for t in all_omts
                if load_yaml(t)['engine'].lower() == engine
            ]
    elif only_this_engine:

        inform('Only running tests for engine: %s' % only_this_engine)
        tallies = [
            parse_omt(t) for t in all_omts
            if load_yaml(t)['engine'].lower() == only_this_engine.lower()
        ]
    else:
        tallies = []
        failed = 0
        for i in range(len(all_omts)):
            t = all_omts[i]
            inform('')
            tally = parse_omt(t, do_not_run)
            if not tally.all_passed(): failed += 1
            if not do_not_run:
                inform('')
                inform('')
                inform('      [ Test %i of %i complete - failed so far: %s ]' %
                       (i + 1, len(all_omts), failed))
            tallies.append(tally)

    tallies.sort()

    if not do_not_run:
        for t in tallies:
            th.add(t)

        results = []
        for i in range(len(tallies)):
            t = tallies[i]
            results.append(t.all_passed())
        inform('')
        inform("%i test(s) run" % len(tallies),
               overline='-',
               underline='-',
               center=True)
        inform('')
        if len(results) == 0:
            inform("No tests found!", underline='=', center=True)
        elif all(results):
            inform("All tests passing!", underline='=', center=True)
        else:
            failed = [trim_path(t.omt) for t in tallies if not t.all_passed()]
            inform("Some test(s) failed: ", failed, underline='=')

        if is_verbose():
            print('\n' + th.summary() + '\n')

        assert len(results) > 0
        assert all(results)

    else:
        engs = {}
        tot_tests = 0
        for t in tallies:
            if not t.engine in engs:
                engs[t.engine] = 0
            engs[t.engine] += 1
            tot_tests += 1
        inform('')
        for e in sorted(engs):
            inform('  Engine %s has %s tests' % (e, engs[e]))
        inform('')
        inform('  %s OMV tests in total' % (tot_tests))
        inform('')
コード例 #26
0
def parse_omt(omt_path, do_not_run=False, engine_version=None, ignore_non_py3=False):
    inform('')
    action = 'Running'
    if do_not_run:
        action = 'Checking'
    inform(action+" the tests defined in ", trim_path(omt_path),
           underline='=', center=False)
    
    mepomt = OMVTestParser(omt_path)
    if not mepomt.engine in OMVEngines:
        inform("Error! Unrecognised engine: %s (try running: omv list-engines)"%mepomt.engine)
        exit(1)
    engine = OMVEngines[mepomt.engine](mepomt.modelpath, 
                                       do_not_check_install=do_not_run, 
                                       engine_version=engine_version)
                                       
    experiments = [exp for exp in mepomt.generate_exps(engine)]
    
    tally = Tallyman(mepomt)
    
    inform('Found %i experiment(s) to run on engine: %s '%(len(experiments), engine.name), indent=1)
    #print('%s, %s, %s'%(platform.python_version_tuple()[0],ignore_non_py3,engine.python3_compatible))
    
    if platform.python_version_tuple()[0]=='3' and \
       ignore_non_py3 and \
       not engine.python3_compatible:
           
        inform('Not running experiment(s) on: %s, as this is Python %s and engine is not Python 3 compatible...'%(engine.name, platform.python_version()), indent=1)
        tally.report_passing_if_no_exps = True
    
    elif not do_not_run:
        try:
            engine.run()
            some_failed = False
            for exp in experiments:
                inform('Running checks for experiment: ', exp.name, indent=1)
                inform('')
                results = exp.check_all()
                inform('{:<30}{:^20}'.format('Observable', 'Test Passed'),
                       underline='-', indent=3)
                for rn, rv in results.items():
                    if sys.version_info >= (3,0):
                        inform('{:<30}{:^20}'.format(rn, check(rv)), indent=3)
                    else:
                        inform(u'{:<30}{:^20}'.format(rn, check(rv)), indent=3)
                    if not rv:
                        some_failed = True
                tally.add_experiment(exp, results)

            if some_failed:
                inform("+++++++++++++++++++++ Error info ++++++++++++++++++", indent=3)
                inform(" Return code: %s"%engine.returncode, indent=3)
                if hasattr(engine,'stdout'):
                    inform(" Output: %s"%engine.stdout.replace('\n','\n       '), indent=3)
                inform("+++++++++++++++++++++++++++++++++++++++++++++++++++", indent=3)

        except (EngineInstallationError, EngineExecutionError):
            # TODO: serialize exception info
            inform('ERROR running engine ', engine.name, indent=1,
                   underline='-', overline='-')

    return tally
コード例 #27
0
def parse_omt(omt_path,
              do_not_run=False,
              engine_version=None,
              ignore_non_py3=False):
    inform('')
    action = 'Running'
    if do_not_run:
        action = 'Checking'
    inform(action + " the tests defined in ",
           trim_path(omt_path),
           underline='=',
           center=False)

    mepomt = OMVTestParser(omt_path)
    if not mepomt.engine in OMVEngines:
        inform(
            "Error! Unrecognised engine: %s (try running: omv list-engines)" %
            mepomt.engine)
        exit(1)
    engine = OMVEngines[mepomt.engine](mepomt.modelpath,
                                       do_not_check_install=do_not_run,
                                       engine_version=engine_version)

    experiments = [exp for exp in mepomt.generate_exps(engine)]

    tally = Tallyman(mepomt)

    inform('Found %i experiment(s) to run on engine: %s ' %
           (len(experiments), engine.name),
           indent=1)
    #print('%s, %s, %s'%(platform.python_version_tuple()[0],ignore_non_py3,engine.python3_compatible))

    if platform.python_version_tuple()[0]=='3' and \
       ignore_non_py3 and \
       not engine.python3_compatible:

        inform(
            'Not running experiment(s) on: %s, as this is Python %s and engine is not Python 3 compatible...'
            % (engine.name, platform.python_version()),
            indent=1)
        tally.report_passing_if_no_exps = True

    elif not do_not_run:
        try:
            engine.run()
            some_failed = False
            for exp in experiments:
                inform('Running checks for experiment: ', exp.name, indent=1)
                inform('')
                results = exp.check_all()
                inform('{:<30}{:^20}'.format('Observable', 'Test Passed'),
                       underline='-',
                       indent=3)
                for rn, rv in results.items():
                    if sys.version_info >= (3, 0):
                        inform('{:<30}{:^20}'.format(rn, check(rv)), indent=3)
                    else:
                        inform(u'{:<30}{:^20}'.format(rn, check(rv)), indent=3)
                    if not rv:
                        some_failed = True
                tally.add_experiment(exp, results)

            if some_failed:
                inform("+++++++++++++++++++++ Error info ++++++++++++++++++",
                       indent=3)
                inform(" Return code: %s" % engine.returncode, indent=3)
                if hasattr(engine, 'stdout'):
                    if isinstance(engine.stdout, str):
                        out = engine.stdout
                    else:
                        out = str(engine.stdout.decode())
                    inform(" Output: %s" % out.replace(
                        '\n', '\n[omv] %s:%s > ' %
                        (mepomt.omt_path, exp.name)),
                           indent=3)
                inform("+++++++++++++++++++++++++++++++++++++++++++++++++++",
                       indent=3)

        except (EngineInstallationError, EngineExecutionError):
            # TODO: serialize exception info
            inform('ERROR running engine ',
                   engine.name,
                   indent=1,
                   underline='-',
                   overline='-')

    return tally