예제 #1
0
    def __init__(self,
                 poll_interval: Union[int, float] = 0,
                 loop: Optional[asyncio.AbstractEventLoop] = None,
                 communicator: Optional[kiwipy.Communicator] = None,
                 rmq_submit: bool = False,
                 persister: Optional[Persister] = None):
        """Construct a new runner.

        :param poll_interval: interval in seconds between polling for status of active sub processes
        :param loop: an asyncio event loop, if none is suppled a new one will be created
        :param communicator: the communicator to use
        :param rmq_submit: if True, processes will be submitted to RabbitMQ, otherwise they will be scheduled here
        :param persister: the persister to use to persist processes

        """
        assert not (rmq_submit and persister is None), \
            'Must supply a persister if you want to submit using communicator'

        set_event_loop_policy()
        self._loop = loop if loop is not None else asyncio.get_event_loop()
        self._poll_interval = poll_interval
        self._rmq_submit = rmq_submit
        self._transport = transports.TransportQueue(self._loop)
        self._job_manager = manager.JobManager(self._transport)
        self._persister = persister
        self._plugin_version_provider = PluginVersionProvider()

        if communicator is not None:
            self._communicator = wrap_communicator(communicator, self._loop)
            self._controller = RemoteProcessThreadController(communicator)
        elif self._rmq_submit:
            LOGGER.warning(
                'Disabling RabbitMQ submission, no communicator provided')
            self._rmq_submit = False
예제 #2
0
    def __init__(self, poll_interval=0, loop=None, communicator=None, rmq_submit=False, persister=None):
        """
        Construct a new runner

        :param poll_interval: interval in seconds between polling for status of active calculations
        :param loop: an event loop to use, if none is suppled a new one will be created
        :type loop: :class:`tornado.ioloop.IOLoop`
        :param communicator: the communicator to use
        :type communicator: :class:`kiwipy.Communicator`
        :param rmq_submit: if True, processes will be submitted to RabbitMQ, otherwise they will be scheduled here
        :param persister: the persister to use to persist processes
        :type persister: :class:`plumpy.Persister`
        """
        assert not (rmq_submit and persister is None), \
            'Must supply a persister if you want to submit using communicator'

        self._loop = loop if loop is not None else tornado.ioloop.IOLoop()
        self._poll_interval = poll_interval
        self._rmq_submit = rmq_submit
        self._transport = transports.TransportQueue(self._loop)
        self._job_manager = manager.JobManager(self._transport)
        self._persister = persister
        self._plugin_version_provider = PluginVersionProvider()

        if communicator is not None:
            self._communicator = communicator
            self._controller = plumpy.RemoteProcessThreadController(communicator)
        elif self._rmq_submit:
            LOGGER.warning('Disabling RabbitMQ submission, no communicator provided')
            self._rmq_submit = False
예제 #3
0
 def setUp(self):
     super(TestPluginVersionProvider, self).setUp()
     self.provider = PluginVersionProvider()
예제 #4
0
class TestPluginVersionProvider(AiidaTestCase):
    """Tests for the :py:class:`~aiida.plugins.utils.PluginVersionProvider` utility class."""

    # pylint: disable=no-init,old-style-class,too-few-public-methods,no-member

    def setUp(self):
        super(TestPluginVersionProvider, self).setUp()
        self.provider = PluginVersionProvider()

    @staticmethod
    def create_dynamic_plugin_module(plugin,
                                     plugin_version,
                                     add_module_to_sys=True,
                                     add_version=True):
        """Create a fake dynamic module with a certain `plugin` entity, a class or function and the given version."""
        import sys
        import types
        import uuid

        # Create a new module with a unique name and add the `plugin` and `plugin_version` as attributes
        module_name = 'TestModule{}'.format(str(uuid.uuid4())[:5])
        dynamic_module = types.ModuleType(
            module_name, 'Dynamically created module for testing purposes')
        setattr(plugin, '__module__', dynamic_module.__name__)
        setattr(dynamic_module, plugin.__name__, plugin)

        # For tests that need to fail, this flag can be set to `False`
        if add_version:
            setattr(dynamic_module, '__version__', plugin_version)

        # Get the `DummyClass` plugin from the dynamically created test module
        dynamic_plugin = getattr(dynamic_module, plugin.__name__)

        # Make the dynamic module importable unless the test requests not to, to test an unimportable module
        if add_module_to_sys:
            sys.modules[dynamic_module.__name__] = dynamic_module

        return dynamic_plugin

    def test_external_module_import_fail(self):
        """Test that mapper does not except even if external module cannot be imported."""
        class DummyCalcJob():
            pass

        version_plugin = '0.1.01'
        dynamic_plugin = self.create_dynamic_plugin_module(
            DummyCalcJob, version_plugin, add_module_to_sys=False)

        expected_version = {'version': {'core': version_core}}
        self.assertEqual(self.provider.get_version_info(dynamic_plugin),
                         expected_version)

    def test_external_module_no_version_attribute(self):
        """Test that mapper does not except even if external module does not define `__version__` attribute."""
        class DummyCalcJob():
            pass

        version_plugin = '0.1.02'
        dynamic_plugin = self.create_dynamic_plugin_module(DummyCalcJob,
                                                           version_plugin,
                                                           add_version=False)

        expected_version = {'version': {'core': version_core}}
        self.assertEqual(self.provider.get_version_info(dynamic_plugin),
                         expected_version)

    def test_external_module_class(self):
        """Test the mapper works for a class from an external module."""
        class DummyCalcJob():
            pass

        version_plugin = '0.1.17'
        dynamic_plugin = self.create_dynamic_plugin_module(
            DummyCalcJob, version_plugin)

        expected_version = {
            'version': {
                'core': version_core,
                'plugin': version_plugin
            }
        }
        self.assertEqual(self.provider.get_version_info(dynamic_plugin),
                         expected_version)

    def test_external_module_function(self):
        """Test the mapper works for a function from an external module."""
        @calcfunction
        def test_calcfunction():
            return

        version_plugin = '0.2.19'
        dynamic_plugin = self.create_dynamic_plugin_module(
            test_calcfunction, version_plugin)

        expected_version = {
            'version': {
                'core': version_core,
                'plugin': version_plugin
            }
        }
        self.assertEqual(self.provider.get_version_info(dynamic_plugin),
                         expected_version)

    def test_calcfunction(self):
        """Test the mapper for a `calcfunction`."""
        @calcfunction
        def test_calcfunction():
            return

        expected_version = {
            'version': {
                'core': version_core,
                'plugin': version_core
            }
        }
        self.assertEqual(self.provider.get_version_info(test_calcfunction),
                         expected_version)

    def test_calc_job(self):
        """Test the mapper for a `CalcJob`."""
        AddArithmeticCalculation = CalculationFactory('arithmetic.add')  # pylint: disable=invalid-name

        expected_version = {
            'version': {
                'core': version_core,
                'plugin': version_core
            }
        }
        self.assertEqual(
            self.provider.get_version_info(AddArithmeticCalculation),
            expected_version)

    def test_work_chain(self):
        """Test the mapper for a `WorkChain`."""
        class SomeWorkChain(WorkChain):
            """Need to create a dummy class since there is no built-in work chain with entry point in `aiida-core`."""

        expected_version = {
            'version': {
                'core': version_core,
                'plugin': version_core
            }
        }
        self.assertEqual(self.provider.get_version_info(SomeWorkChain),
                         expected_version)