Skip to content

Commit 1c5350c

Browse files
author
Tyler Goodlet
committed
Initial docs draft
Covers everything in the original pluggy.py module's doc string in much more detail with links to external resources as seemed fit. Resolves pytest-dev#14
1 parent 5182582 commit 1c5350c

File tree

6 files changed

+656
-17
lines changed

6 files changed

+656
-17
lines changed

docs/api_reference.rst

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
1-
2-
31
Api Reference
42
=============
53

64
.. automodule:: pluggy
75
:members:
86
:undoc-members:
97
:show-inheritance:
10-
11-

docs/calling.rst

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
Calling Hooks
2+
=============
3+
The core functionality of ``pluggy`` enables an extension provider
4+
to override function calls made at certain points throughout a program.
5+
6+
A particular *hook* is invoked by calling an instance of
7+
a :py:class:`pluggy._HookCaller` which in turn *loops* through the
8+
``1:N`` registered *hookimpls* and calls them in sequence.
9+
10+
Every :py:class:`pluggy.PluginManager` has a ``hook`` attribute
11+
which is an instance of a :py:class:`pluggy._HookRelay`.
12+
The ``_HookRelay`` itself contains references (by hook name) to each
13+
registered *hookimpl*'s ``_HookCaller`` instance.
14+
15+
More practically you call a *hook* like so:
16+
17+
.. code-block:: python
18+
19+
import sys
20+
import pluggy
21+
import mypluginspec
22+
import myplugin
23+
from configuration import config
24+
25+
pm = pluggy.PluginManager("myproject")
26+
pm.add_hookspecs(mypluginspec)
27+
pm.register(myplugin)
28+
29+
# we invoke the _HookCaller and thus all underlying hookimpls
30+
result_list = pm.hook.myhook(config=config, args=sys.argv)
31+
32+
Note that you **must** call hooks using keyword `arguments`_ syntax!
33+
34+
35+
Collecting results
36+
------------------
37+
By default calling a hook results in all underlying :ref:`hookimpls
38+
<impls>` functions to be invoked in sequence via a loop. Any function
39+
which returns a none ``None`` result will have that result appended to
40+
a :py:class:`list` which is returned by the call.
41+
42+
The only exception to this behaviour is if the hook has been marked to return
43+
its :ref:`firstresult` in which case only the first single none ``None`` value
44+
will be returned.
45+
46+
.. _call_historic:
47+
48+
Historic calls
49+
--------------
50+
You can invoke certain hooks with all call *history* provided to each *hookimpl*
51+
at register time. Put more simply, a *historic call* allows for all newly
52+
registered functions to receive all hook calls that happened before their
53+
registration. The implication is that this is only useful
54+
if you expect that some *hookimpls* may be registered **after** the hook is
55+
initially invoked.
56+
57+
Historic hooks must be :ref:`specially marked <historic>` and called
58+
using the :py:meth:`pluggy._HookCaller.call_historic()` method:
59+
60+
.. code-block:: python
61+
62+
# call with history; no results returned
63+
pm.hook.myhook.call_historic(config=config, args=sys.argv)
64+
65+
# ... more of our program ...
66+
67+
# late loading of some plugin
68+
import mylateplugin
69+
70+
# historic call back is done here
71+
pm.register(mylateplugin)
72+
73+
Note that if you ``call_historic()`` the ``_HookCaller`` (and thus your
74+
calling code) can not receive results back from the underlying
75+
*hookimpl* functions.
76+
77+
Calling with extras
78+
-------------------
79+
You can call a hook with temporarily participating *implementation* functions
80+
(that aren't in the registry) using the
81+
:py:meth:`pluggy._HookCaller.call_extra()` method.
82+
83+
84+
Calling with a subset of registered plugins
85+
-------------------------------------------
86+
You can make a call using a subset of plugins by asking the
87+
``PluginManager`` first for a ``_HookCaller`` with those plugins removed
88+
using the :py:meth:`pluggy.PluginManger.subset_hook_caller()` method.
89+
90+
You then can use that ``_HookCaller`` to make normal, ``call_historic()``,
91+
or ``call_extra()`` calls as necessary.
92+
93+
94+
.. links
95+
.. _arguments:
96+
https://docs.python.org/3/glossary.html#term-argument

0 commit comments

Comments
 (0)