Skip to content

Commit

Permalink
NamedExtensionManager: call a callback when some names cannot be found
Browse files Browse the repository at this point in the history
This will allow users to find out errors in their code that are currently
silently ignored.

Change-Id: I405511f9acc5319b1e4373be084f6a7c97556acf
  • Loading branch information
CyrilRoelandteNovance committed Jun 24, 2016
1 parent f33b810 commit 6f81f6f
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 0 deletions.
16 changes: 16 additions & 0 deletions 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.
Expand Down Expand Up @@ -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
Expand All @@ -44,6 +52,7 @@ def __init__(self, namespace, names,
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,
Expand All @@ -53,6 +62,13 @@ def __init__(self, namespace, names,
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
Expand Down
18 changes: 18 additions & 0 deletions 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


Expand All @@ -23,3 +25,19 @@ def failure_callback(manager, entrypoint, error):
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'})

0 comments on commit 6f81f6f

Please sign in to comment.