Skip to content

Commit

Permalink
Initial docs draft
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Tyler Goodlet committed Jan 31, 2017
1 parent 5182582 commit 1c5350c
Show file tree
Hide file tree
Showing 6 changed files with 656 additions and 17 deletions.
4 changes: 0 additions & 4 deletions docs/api_reference.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@


Api Reference
=============

.. automodule:: pluggy
:members:
:undoc-members:
:show-inheritance:


96 changes: 96 additions & 0 deletions docs/calling.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
Calling Hooks
=============
The core functionality of ``pluggy`` enables an extension provider
to override function calls made at certain points throughout a program.

A particular *hook* is invoked by calling an instance of
a :py:class:`pluggy._HookCaller` which in turn *loops* through the
``1:N`` registered *hookimpls* and calls them in sequence.

Every :py:class:`pluggy.PluginManager` has a ``hook`` attribute
which is an instance of a :py:class:`pluggy._HookRelay`.
The ``_HookRelay`` itself contains references (by hook name) to each
registered *hookimpl*'s ``_HookCaller`` instance.

More practically you call a *hook* like so:

.. code-block:: python
import sys
import pluggy
import mypluginspec
import myplugin
from configuration import config
pm = pluggy.PluginManager("myproject")
pm.add_hookspecs(mypluginspec)
pm.register(myplugin)
# we invoke the _HookCaller and thus all underlying hookimpls
result_list = pm.hook.myhook(config=config, args=sys.argv)
Note that you **must** call hooks using keyword `arguments`_ syntax!


Collecting results
------------------
By default calling a hook results in all underlying :ref:`hookimpls
<impls>` functions to be invoked in sequence via a loop. Any function
which returns a none ``None`` result will have that result appended to
a :py:class:`list` which is returned by the call.

The only exception to this behaviour is if the hook has been marked to return
its :ref:`firstresult` in which case only the first single none ``None`` value
will be returned.

.. _call_historic:

Historic calls
--------------
You can invoke certain hooks with all call *history* provided to each *hookimpl*
at register time. Put more simply, a *historic call* allows for all newly
registered functions to receive all hook calls that happened before their
registration. The implication is that this is only useful
if you expect that some *hookimpls* may be registered **after** the hook is
initially invoked.

Historic hooks must be :ref:`specially marked <historic>` and called
using the :py:meth:`pluggy._HookCaller.call_historic()` method:

.. code-block:: python
# call with history; no results returned
pm.hook.myhook.call_historic(config=config, args=sys.argv)
# ... more of our program ...
# late loading of some plugin
import mylateplugin
# historic call back is done 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.

Calling with extras
-------------------
You can call a hook with temporarily participating *implementation* functions
(that aren't in the registry) using the
:py:meth:`pluggy._HookCaller.call_extra()` method.


Calling with a subset of registered plugins
-------------------------------------------
You can make a call using a subset of plugins by asking the
``PluginManager`` first for a ``_HookCaller`` with those plugins removed
using the :py:meth:`pluggy.PluginManger.subset_hook_caller()` method.

You then can use that ``_HookCaller`` to make normal, ``call_historic()``,
or ``call_extra()`` calls as necessary.


.. links
.. _arguments:
https://docs.python.org/3/glossary.html#term-argument
Loading

0 comments on commit 1c5350c

Please sign in to comment.