Skip to content
Browse files

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>
  • Loading branch information...
1 parent 42fbe31 commit 83098c78d0b296b5d5212033a1ab41886aac298a @dhellmann dhellmann committed
Showing with 43 additions and 8 deletions.
  1. +3 −0 docs/source/history.rst
  2. +13 −5 stevedore/named.py
  3. +27 −3 stevedore/tests/test_named.py
View
3 docs/source/history.rst
@@ -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
18 stevedore/named.py
@@ -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
30 stevedore/tests/test_named.py
@@ -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.
Something went wrong with that request. Please try again.