Merge pull request #27 from jd/master
Add map_method function to managers
This commit is contained in:
commit
974f4fbc5a
@ -73,6 +73,29 @@ class DispatchExtensionManager(EnabledExtensionManager):
|
|||||||
self._invoke_one_plugin(response.append, func, e, args, kwds)
|
self._invoke_one_plugin(response.append, func, e, args, kwds)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
def map_method(self, filter_func, method_name, *args, **kwds):
|
||||||
|
"""Iterate over the extensions invoking each one's object method called
|
||||||
|
`method_name` for any where filter_func() returns True.
|
||||||
|
|
||||||
|
This is equivalent of using :meth:`map` with func set to
|
||||||
|
`lambda x: x.obj.method_name()`
|
||||||
|
while being more convenient.
|
||||||
|
|
||||||
|
Exceptions raised from within the called method are propagated up
|
||||||
|
and processing stopped if self.propagate_map_exceptions is True,
|
||||||
|
otherwise they are logged and ignored.
|
||||||
|
|
||||||
|
.. versionadded:: 0.12
|
||||||
|
|
||||||
|
:param filter_func: Callable to test each extension.
|
||||||
|
:param method_name: The extension method name to call for each extension.
|
||||||
|
:param args: Variable arguments to pass to method
|
||||||
|
:param kwds: Keyword arguments to pass to method
|
||||||
|
:returns: List of values returned from methods
|
||||||
|
"""
|
||||||
|
return self.map(filter_func, self._call_extension_method,
|
||||||
|
method_name, *args, **kwds)
|
||||||
|
|
||||||
|
|
||||||
class NameDispatchExtensionManager(DispatchExtensionManager):
|
class NameDispatchExtensionManager(DispatchExtensionManager):
|
||||||
"""Loads all plugins and filters on execution.
|
"""Loads all plugins and filters on execution.
|
||||||
@ -151,3 +174,26 @@ class NameDispatchExtensionManager(DispatchExtensionManager):
|
|||||||
else:
|
else:
|
||||||
self._invoke_one_plugin(response.append, func, e, args, kwds)
|
self._invoke_one_plugin(response.append, func, e, args, kwds)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
def map_method(self, names, method_name, *args, **kwds):
|
||||||
|
"""Iterate over the extensions invoking each one's object method called
|
||||||
|
`method_name` for any where the name is in the given list of names.
|
||||||
|
|
||||||
|
This is equivalent of using :meth:`map` with func set to
|
||||||
|
`lambda x: x.obj.method_name()`
|
||||||
|
while being more convenient.
|
||||||
|
|
||||||
|
Exceptions raised from within the called method are propagated up
|
||||||
|
and processing stopped if self.propagate_map_exceptions is True,
|
||||||
|
otherwise they are logged and ignored.
|
||||||
|
|
||||||
|
.. versionadded:: 0.12
|
||||||
|
|
||||||
|
:param names: List or set of name(s) of extension(s) to invoke.
|
||||||
|
:param method_name: The extension method name to call for each extension.
|
||||||
|
:param args: Variable arguments to pass to method
|
||||||
|
:param kwds: Keyword arguments to pass to method
|
||||||
|
:returns: List of values returned from methods
|
||||||
|
"""
|
||||||
|
return self.map(names, self._call_extension_method,
|
||||||
|
method_name, *args, **kwds)
|
||||||
|
@ -140,6 +140,30 @@ class ExtensionManager(object):
|
|||||||
self._invoke_one_plugin(response.append, func, e, args, kwds)
|
self._invoke_one_plugin(response.append, func, e, args, kwds)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _call_extension_method(extension, method_name, *args, **kwds):
|
||||||
|
return getattr(extension.obj, method_name)(*args, **kwds)
|
||||||
|
|
||||||
|
def map_method(self, method_name, *args, **kwds):
|
||||||
|
"""Iterate over the extensions invoking each one's object method called `method_name`.
|
||||||
|
|
||||||
|
This is equivalent of using :meth:`map` with func set to
|
||||||
|
`lambda x: x.obj.method_name()`
|
||||||
|
while being more convenient.
|
||||||
|
|
||||||
|
Exceptions raised from within the called method are propagated up
|
||||||
|
and processing stopped if self.propagate_map_exceptions is True,
|
||||||
|
otherwise they are logged and ignored.
|
||||||
|
|
||||||
|
.. versionadded:: 0.12
|
||||||
|
|
||||||
|
:param method_name: The extension method name to call for each extension.
|
||||||
|
:param args: Variable arguments to pass to method
|
||||||
|
:param kwds: Keyword arguments to pass to method
|
||||||
|
:returns: List of values returned from methods
|
||||||
|
"""
|
||||||
|
return self.map(self._call_extension_method, method_name, *args, **kwds)
|
||||||
|
|
||||||
def _invoke_one_plugin(self, response_callback, func, e, args, kwds):
|
def _invoke_one_plugin(self, response_callback, func, e, args, kwds):
|
||||||
try:
|
try:
|
||||||
response_callback(func(e, *args, **kwds))
|
response_callback(func(e, *args, **kwds))
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
from stevedore import dispatch
|
from stevedore import dispatch
|
||||||
|
|
||||||
|
|
||||||
def test_dispatch():
|
def check_dispatch(ep, *args, **kwds):
|
||||||
|
return ep.name == 't2'
|
||||||
|
|
||||||
def check_dispatch(ep, *args, **kwds):
|
|
||||||
return ep.name == 't2'
|
def test_dispatch():
|
||||||
|
|
||||||
def invoke(ep, *args, **kwds):
|
def invoke(ep, *args, **kwds):
|
||||||
return (ep.name, args, kwds)
|
return (ep.name, args, kwds)
|
||||||
@ -28,6 +29,20 @@ def test_dispatch():
|
|||||||
assert results == expected
|
assert results == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_dispatch_map_method():
|
||||||
|
em = dispatch.DispatchExtensionManager(
|
||||||
|
'stevedore.test.extension',
|
||||||
|
lambda *args, **kwds: True,
|
||||||
|
invoke_on_load=True,
|
||||||
|
invoke_args=('a',),
|
||||||
|
invoke_kwds={'b': 'B'},
|
||||||
|
)
|
||||||
|
|
||||||
|
results = em.map_method(check_dispatch, 'get_args_and_data',
|
||||||
|
'first')
|
||||||
|
assert results == [(('a',), {'b': 'B'}, 'first')]
|
||||||
|
|
||||||
|
|
||||||
def test_name_dispatch():
|
def test_name_dispatch():
|
||||||
|
|
||||||
def invoke(ep, *args, **kwds):
|
def invoke(ep, *args, **kwds):
|
||||||
@ -72,3 +87,16 @@ def test_name_dispatch_ignore_missing():
|
|||||||
)
|
)
|
||||||
expected = [('t1', ('first',), {'named': 'named value'})]
|
expected = [('t1', ('first',), {'named': 'named value'})]
|
||||||
assert results == expected
|
assert results == expected
|
||||||
|
|
||||||
|
def test_name_dispatch_map_method():
|
||||||
|
em = dispatch.NameDispatchExtensionManager(
|
||||||
|
'stevedore.test.extension',
|
||||||
|
lambda *args, **kwds: True,
|
||||||
|
invoke_on_load=True,
|
||||||
|
invoke_args=('a',),
|
||||||
|
invoke_kwds={'b': 'B'},
|
||||||
|
)
|
||||||
|
|
||||||
|
results = em.map_method(['t3', 't1'], 'get_args_and_data',
|
||||||
|
'first')
|
||||||
|
assert results == [(('a',), {'b': 'B'}, 'first')]
|
||||||
|
@ -11,6 +11,9 @@ class FauxExtension(object):
|
|||||||
self.args = args
|
self.args = args
|
||||||
self.kwds = kwds
|
self.kwds = kwds
|
||||||
|
|
||||||
|
def get_args_and_data(self, data):
|
||||||
|
return self.args, self.kwds, data
|
||||||
|
|
||||||
|
|
||||||
def test_detect_plugins():
|
def test_detect_plugins():
|
||||||
em = extension.ExtensionManager('stevedore.test.extension')
|
em = extension.ExtensionManager('stevedore.test.extension')
|
||||||
@ -155,3 +158,12 @@ def test_map_errors_when_no_plugins():
|
|||||||
em.map(mapped, 1, 2, a='A', b='B')
|
em.map(mapped, 1, 2, a='A', b='B')
|
||||||
except RuntimeError as err:
|
except RuntimeError as err:
|
||||||
assert 'No stevedore.test.extension.none extensions found' == str(err)
|
assert 'No stevedore.test.extension.none extensions found' == str(err)
|
||||||
|
|
||||||
|
|
||||||
|
def test_map_method():
|
||||||
|
em = extension.ExtensionManager('stevedore.test.extension',
|
||||||
|
invoke_on_load=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
result = em.map_method('get_args_and_data', 42)
|
||||||
|
assert set(r[2] for r in result) == set([42])
|
||||||
|
Loading…
Reference in New Issue
Block a user