Skip to content

Commit

Permalink
Merge pull request #143 from tgoodlet/deprecate_proc_arg
Browse files Browse the repository at this point in the history
Deprecate `proc` kwarg to call_historic()
  • Loading branch information
goodboy authored May 19, 2018
2 parents 88fe9b9 + 0faf6cb commit aeb1f67
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 14 deletions.
19 changes: 16 additions & 3 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -749,20 +749,33 @@ using the :py:meth:`pluggy._HookCaller.call_historic()` method:

.. code-block:: python
def callback(result):
print("historic call result is {result}".format(result=result))
# call with history; no results returned
pm.hook.myhook.call_historic(config=config, args=sys.argv)
pm.hook.myhook.call_historic(
config=config, args=sys.argv,
result_callback=callback
)
# ... more of our program ...
# late loading of some plugin
import mylateplugin
# historic call back is done here
# historic callback is invoked here
pm.register(mylateplugin)
Note that if you ``call_historic()`` the ``_HookCaller`` (and thus your
calling code) can not receive results back from the underlying *hookimpl*
functions.
functions. Instead you can provide a *callback* for processing results
(like the ``callback`` function above) which will be called as each
new plugin is registered.

.. note::
*historic* calls are incompatible with :ref:`firstresult` marked
hooks since only the first registered plugin's hook(s) would
ever be called.

Calling with extras
-------------------
Expand Down
32 changes: 22 additions & 10 deletions pluggy/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,20 +257,32 @@ def __call__(self, *args, **kwargs):
)
return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)

def call_historic(self, proc=None, kwargs=None):
""" call the hook with given ``kwargs`` for all registered plugins and
def call_historic(self, result_callback=None, kwargs=None, proc=None):
"""Call the hook with given ``kwargs`` for all registered plugins and
for all plugins which will be registered afterwards.
If ``proc`` is not None it will be called for for each non-None result
obtained from a hook implementation.
If ``result_callback`` is not ``None`` it will be called for for each
non-None result obtained from a hook implementation.
.. note::
The ``proc`` argument is now deprecated.
"""
self._call_history.append((kwargs or {}, proc))
if proc is not None:
warnings.warn(
"Support for `proc` argument is now deprecated and will be"
"removed in an upcoming release.",
DeprecationWarning
)
result_callback = proc

self._call_history.append((kwargs or {}, result_callback))
# historizing hooks don't return results
res = self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
if proc is None:
if result_callback is None:
return
# XXX: remember firstresult isn't compat with historic
for x in res or []:
proc(x)
result_callback(x)

def call_extra(self, methods, kwargs):
""" Call the hook with some additional temporarily participating
Expand All @@ -289,10 +301,10 @@ def _maybe_apply_history(self, method):
"""Apply call history to a new hookimpl if it is marked as historic.
"""
if self.is_historic():
for kwargs, proc in self._call_history:
for kwargs, result_callback in self._call_history:
res = self._hookexec(self, [method], kwargs)
if res and proc is not None:
proc(res[0])
if res and result_callback is not None:
result_callback(res[0])


class HookImpl(object):
Expand Down
19 changes: 18 additions & 1 deletion testing/test_pluginmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ def he_method1(self, arg):
pm.register(Plugin1())

he_method1 = pm.hook.he_method1
he_method1.call_historic(proc=callback, kwargs=dict(arg=1))
he_method1.call_historic(result_callback=callback, kwargs=dict(arg=1))

class Plugin2(object):
@hookimpl
Expand Down Expand Up @@ -399,3 +399,20 @@ def example_hook():
assert getattr(pm.hook, 'example_hook', None) # conftest.example_hook should be collected
assert pm.parse_hookimpl_opts(conftest, 'example_blah') is None
assert pm.parse_hookimpl_opts(conftest, 'example_hook') == {}


def test_callhistoric_proc_deprecated(pm):
"""``proc`` kwarg to `PluginMananger.call_historic()` is now officially
deprecated.
"""
class P1(object):
@hookspec(historic=True)
@hookimpl
def m(self, x):
pass

p1 = P1()
pm.add_hookspecs(p1)
pm.register(p1)
with pytest.deprecated_call():
pm.hook.m.call_historic(kwargs=dict(x=10), proc=lambda res: res)

0 comments on commit aeb1f67

Please sign in to comment.