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))
示例#2
0
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