Skip to content

Commit

Permalink
Check the names of plugins before importing them
Browse files Browse the repository at this point in the history
Update NamedExtensionManager to check the names of the plugins
before loading any code to avoid importing anything we are not going
to use.

Fixes issue #4

Change-Id: I27b19cb42ca3d165ce45953281b82e394c4539a2
Signed-off-by: Doug Hellmann <doug.hellmann@dreamhost.com>
  • Loading branch information
Doug Hellmann committed Jan 5, 2013
1 parent 42fbe31 commit 83098c7
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 8 deletions.
3 changes: 3 additions & 0 deletions docs/source/history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ dev

- Ignore AssertionError exceptions generated when plugins are
loaded.
- Update :class:`~stevedore.named.NamedExtensionManager` to check
the name of a plugin before loading its code to avoid importing
anything we are not going to use.

0.7.2

Expand Down
18 changes: 13 additions & 5 deletions stevedore/named.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .enabled import EnabledExtensionManager
from .extension import ExtensionManager


class NamedExtensionManager(EnabledExtensionManager):
class NamedExtensionManager(ExtensionManager):
"""Loads only the named extensions.
This is useful for explictly enabling extensions in a
Expand All @@ -26,12 +26,20 @@ class NamedExtensionManager(EnabledExtensionManager):

def __init__(self, namespace, names,
invoke_on_load=False, invoke_args=(), invoke_kwds={}):
def check(ep):
return ep.name in names
self._names = names
super(NamedExtensionManager, self).__init__(
namespace,
check,
invoke_on_load=invoke_on_load,
invoke_args=invoke_args,
invoke_kwds=invoke_kwds,
)

def _load_one_plugin(self, ep, invoke_on_load, invoke_args, invoke_kwds):
# Check the name before going any further to prevent
# undesirable code from being loaded at all if we are not
# going to use it.
if ep.name not in self._names:
return None
return super(NamedExtensionManager, self)._load_one_plugin(
ep, invoke_on_load, invoke_args, invoke_kwds,
)
30 changes: 27 additions & 3 deletions stevedore/tests/test_named.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,37 @@
from stevedore import named

import mock


def test_named():
em = named.NamedExtensionManager(
'stevedore.test.extension',
['t1'],
names=['t1'],
invoke_on_load=True,
invoke_args=('a',),
invoke_kwds={'b': 'B'},
)
assert len(em.extensions) == 1
assert em.names() == ['t1']
actual = em.names()
assert actual == ['t1']


def test_enabled_before_load():
# Set up the constructor for the FauxExtension to cause an
# AssertionError so the test fails if the class is instantiated,
# which should only happen if it is loaded before the name of the
# extension is compared against the names that should be loaded by
# the manager.
init_name = 'stevedore.tests.test_extension.FauxExtension.__init__'
with mock.patch(init_name) as m:
m.side_effect = AssertionError
em = named.NamedExtensionManager(
'stevedore.test.extension',
# Look for an extension that does not exist so the
# __init__ we mocked should never be invoked.
names=['no-such-extension'],
invoke_on_load=True,
invoke_args=('a',),
invoke_kwds={'b': 'B'},
)
actual = em.names()
assert actual == []

0 comments on commit 83098c7

Please sign in to comment.