class TestOptionsExpander(unittest.TestCase): def setUp(self): unittest.TestCase.setUp(self) self.ops = Options("op1") self.ops.beam.energy_eV = [5e3, 10e3, 15e3] self.expander = OptionsExpander() def tearDown(self): unittest.TestCase.tearDown(self) def testexpand(self): opss = self.expander.expand(self.ops) self.assertEqual(3, len(opss)) names = list(map(attrgetter('name'), opss)) self.assertIn('op1+energy_eV=5000.0', names) self.assertIn('op1+energy_eV=10000.0', names) self.assertIn('op1+energy_eV=15000.0', names) def testis_expandable(self): self.assertTrue(self.expander.is_expandable(self.ops)) self.ops.beam.energy_eV = [5e3] self.assertFalse(self.expander.is_expandable(self.ops))
class Exporter(object, metaclass=ABCMeta): """ Base class for all exporters. """ def __init__(self): self._expander = OptionsExpander() self._beam_exporters = {} self._geometry_exporters = {} self._detector_exporters = {} self._limit_exporters = {} self._model_exporters = {} def export(self, options, dirpath, *args, **kwargs): """ Exports options to a file inside the specified output directory. Returns the filepath of the exported options. :arg options: options to export The options must only contained a single value for each parameter. :arg dirpath: full path to output directory """ if self._expander.is_expandable(options): raise ValueError("Only options with singular value can be exported") return self._export(options, dirpath, *args, **kwargs) @abstractmethod def _export(self, options, dirpath, *args, **kwargs): """ Performs the actual export. """ raise NotImplementedError def _run_exporters(self, options, *args, **kwargs): """ Internal command to call the register export functions. """ self._export_beam(options, *args, **kwargs) self._export_geometry(options, *args, **kwargs) self._export_detectors(options, *args, **kwargs) self._export_limits(options, *args, **kwargs) self._export_models(options, *args, **kwargs) def _export_beam(self, options, *args, **kwargs): """ Exports the beam. If a exporter function is defined, it calls this function with the following arguments: * options object * beam object * optional arguments and keyword-arguments """ clasz = options.beam.__class__ method = self._beam_exporters.get(clasz) if not method: raise ExporterException("Could not export beam '%s'" % clasz.__name__) method(options, options.beam, *args, **kwargs) def _export_geometry(self, options, *args, **kwargs): """ Exports the geometry. If a exporter function is defined, it calls this function with the following arguments: * options object * geometry object * optional arguments and keyword-arguments """ clasz = options.geometry.__class__ method = self._geometry_exporters.get(clasz) if method: method(options, options.geometry, *args, **kwargs) else: raise ExporterException("Could not export geometry '%s'" % clasz.__name__) def _export_detectors(self, options, *args, **kwargs): """ Exports the detectors. If a exporter function is defined, it calls this function with the following arguments for each detector: * options object * name/key of detector * detector object * optional arguments and keyword-arguments """ for name, detector in options.detectors.items(): clasz = detector.__class__ method = self._detector_exporters.get(clasz) if not method: raise ExporterException("Could not export detector '%s' (%s)" % \ (name, clasz.__name__)) method(options, name, detector, *args, **kwargs) def _export_limits(self, options, *args, **kwargs): """ Exports the limit. If a exporter function is defined, it calls this function with the following arguments for each limit: * options object * limit object * optional arguments and keyword-arguments """ for limit in options.limits: clasz = limit.__class__ method = self._limit_exporters.get(clasz) if not method: raise ExporterException("Could not export limit '%s'" % \ clasz.__name__) method(options, limit, *args, **kwargs) def _export_models(self, options, *args, **kwargs): """ Exports the models. If a exporter function is defined, it calls this function with the following arguments for each model: * options object * model object * optional arguments and keyword-arguments """ for model in options.models: type_ = model.type method = self._model_exporters.get(type_) if not method: raise ExporterException("Could not export model of type '%s'" % \ type_.name) method(options, model, *args, **kwargs) def _export_dummy(self, options, *args, **kwargs): pass