Check the names of plugins before importing them

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>
This commit is contained in:
Doug Hellmann 2013-01-04 19:14:21 -05:00
parent 42fbe31c4f
commit 83098c78d0
3 changed files with 43 additions and 8 deletions

View File

@ -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

View File

@ -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
@ -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,
)

View File

@ -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 == []