diff --git a/stevedore/named.py b/stevedore/named.py index 18fe235..c0b7af8 100644 --- a/stevedore/named.py +++ b/stevedore/named.py @@ -1,5 +1,9 @@ +import logging + from .extension import ExtensionManager +LOG = logging.getLogger(__name__) + class NamedExtensionManager(ExtensionManager): """Loads only the named extensions. @@ -34,6 +38,10 @@ class NamedExtensionManager(ExtensionManager): when this is called (when an entrypoint fails to load) are (manager, entrypoint, exception) :type on_load_failure_callback: function + :param on_missing_entrypoints_callback: Callback function that will be + called when one or more names cannot be found. The provided argument + will be a subset of the 'names' parameter. + :type on_missing_entrypoints_callback: function :param verify_requirements: Use setuptools to enforce the dependencies of the plugin(s) being loaded. Defaults to False. :type verify_requirements: bool @@ -44,6 +52,7 @@ class NamedExtensionManager(ExtensionManager): invoke_on_load=False, invoke_args=(), invoke_kwds={}, name_order=False, propagate_map_exceptions=False, on_load_failure_callback=None, + on_missing_entrypoints_callback=None, verify_requirements=False): self._init_attributes( namespace, names, name_order=name_order, @@ -53,6 +62,13 @@ class NamedExtensionManager(ExtensionManager): invoke_args, invoke_kwds, verify_requirements) + missing_entrypoints = set(names) - set([e.name for e in extensions]) + if missing_entrypoints: + if on_missing_entrypoints_callback: + on_missing_entrypoints_callback(missing_entrypoints) + else: + LOG.warning('Could not load %s' % + ', '.join(missing_entrypoints)) self._init_plugins(extensions) @classmethod diff --git a/stevedore/tests/test_callback.py b/stevedore/tests/test_callback.py index 1e9f5b1..8dc9692 100644 --- a/stevedore/tests/test_callback.py +++ b/stevedore/tests/test_callback.py @@ -1,8 +1,10 @@ """Tests for failure loading callback """ from testtools.matchers import GreaterThan +import mock from stevedore import extension +from stevedore import named from stevedore.tests import utils @@ -23,3 +25,19 @@ class TestCallback(utils.TestCase): for manager, entrypoint, error in errors: self.assertIs(manager, em) self.assertIsInstance(error, (IOError, ImportError)) + + @mock.patch('stevedore.named.NamedExtensionManager._load_plugins') + def test_missing_entrypoints_callback(self, load_fn): + errors = set() + + def callback(names): + errors.update(names) + + load_fn.return_value = [ + extension.Extension('foo', None, None, None) + ] + named.NamedExtensionManager('stevedore.test.extension', + names=['foo', 'bar'], + invoke_on_load=True, + on_missing_entrypoints_callback=callback) + self.assertEqual(errors, {'bar'})