Skip to content

Commit 0d2850a

Browse files
committed
docs: improve docstrings and API Reference
Refs #428
1 parent 9abeeba commit 0d2850a

File tree

6 files changed

+202
-66
lines changed

6 files changed

+202
-66
lines changed

docs/api_reference.rst

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,34 @@
33
API Reference
44
=============
55

6-
.. automodule:: pluggy
6+
.. autoclass:: pluggy.PluginManager
77
:members:
8-
:undoc-members:
98

10-
.. autoclass:: pluggy._result._Result
11-
.. automethod:: pluggy._result._Result.get_result
12-
.. automethod:: pluggy._result._Result.force_result
13-
.. automethod:: pluggy._result._Result.force_exception
9+
.. autoclass:: pluggy.PluginValidationError
10+
:show-inheritance:
11+
:members:
12+
13+
.. autodecorator:: pluggy.HookspecMarker
14+
15+
.. autodecorator:: pluggy.HookimplMarker
16+
17+
.. autoclass:: pluggy._result._Result()
18+
:show-inheritance:
19+
:members:
20+
21+
.. autoclass:: pluggy._hooks._HookCaller()
22+
:members:
23+
:special-members: __call__
24+
25+
.. autoclass:: pluggy.HookCallError()
26+
:show-inheritance:
27+
:members:
28+
29+
.. autoclass:: pluggy._hooks._HookRelay()
30+
:members:
31+
32+
.. data:: <hook name>
1433

15-
.. autoclass:: pluggy._hooks._HookCaller
16-
.. automethod:: pluggy._hooks._HookCaller.call_extra
17-
.. automethod:: pluggy._hooks._HookCaller.call_historic
34+
:type: _HookCaller
1835

19-
.. autoclass:: pluggy._hooks._HookRelay
36+
The caller for the hook with the given name.

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
# (source start file, name, description, authors, manual section).
5959
man_pages = [(master_doc, "pluggy", "pluggy Documentation", [author], 1)]
6060

61-
autodoc_typehints = "none"
61+
autodoc_member_order = "bysource"
6262

6363
# -- Options for Texinfo output -------------------------------------------
6464

docs/index.rst

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,8 @@ be matched and checked against the ``setup_project`` hookspec:
305305
306306
return config
307307
308+
.. _callorder:
309+
308310
Call time order
309311
^^^^^^^^^^^^^^^
310312
By default hooks are :ref:`called <calling>` in LIFO registered order, however,
@@ -422,6 +424,8 @@ to the hook caller.
422424

423425
Also see the :ref:`pytest:hookwrapper` section in the ``pytest`` docs.
424426

427+
.. _old_style_hookwrappers:
428+
425429
Old-style wrappers
426430
^^^^^^^^^^^^^^^^^^
427431

@@ -629,12 +633,14 @@ dynamically loaded plugins.
629633
For more info see :ref:`call_historic`.
630634

631635

636+
.. _warn_on_impl:
637+
632638
Warnings on hook implementation
633639
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
634640

635641
As projects evolve new hooks may be introduced and/or deprecated.
636642

637-
if a hookspec specifies a ``warn_on_impl``, pluggy will trigger it for any plugin implementing the hook.
643+
If a hookspec specifies a ``warn_on_impl``, pluggy will trigger it for any plugin implementing the hook.
638644

639645

640646
.. code-block:: python
@@ -907,6 +913,8 @@ is registered.
907913
hooks since only the first registered plugin's hook(s) would
908914
ever be called.
909915

916+
.. _call_extra:
917+
910918
Calling with extras
911919
-------------------
912920
You can call a hook with temporarily participating *implementation* functions
@@ -925,6 +933,9 @@ You then can use that :py:class:`_HookCaller <pluggy._hooks._HookCaller>`
925933
to make normal, :py:meth:`~pluggy._hooks._HookCaller.call_historic`, or
926934
:py:meth:`~pluggy._hooks._HookCaller.call_extra` calls as necessary.
927935

936+
937+
.. _tracing:
938+
928939
Built-in tracing
929940
****************
930941
``pluggy`` comes with some batteries included hook tracing for your

src/pluggy/_hooks.py

Lines changed: 95 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,34 @@
3838

3939

4040
class _HookSpecOpts(TypedDict):
41+
"""Options for a hook specification."""
42+
43+
#: Whether the hook is :ref:`first result only <firstresult>`.
4144
firstresult: bool
45+
#: Whether the hook is :ref:`historic <historic>`.
4246
historic: bool
47+
#: Whether the hook :ref:`warns when implemented <warn_on_impl>`.
4348
warn_on_impl: Warning | None
4449

4550

4651
class _HookImplOpts(TypedDict):
52+
"""Options for a hook implementation."""
53+
54+
#: Whether the hook implementation is a :ref:`wrapper <hookwrapper>`.
4755
wrapper: bool
56+
#: Whether the hook implementation is an :ref:`old-style wrapper
57+
#: <old_style_hookwrappers>`.
4858
hookwrapper: bool
59+
#: Whether validation against a hook specification is :ref:`optional
60+
#: <optionalhook>`.
4961
optionalhook: bool
62+
#: Whether to try to order this hook implementation :ref:`first
63+
#: <callorder>`.
5064
tryfirst: bool
65+
#: Whether to try to order this hook implementation :ref:`last
66+
#: <callorder>`.
5167
trylast: bool
68+
#: The name of the hook specification to match, see :ref:`specname`.
5269
specname: str | None
5370

5471

@@ -57,7 +74,7 @@ class HookspecMarker:
5774
5875
Instantiate it with a project_name to get a decorator.
5976
Calling :meth:`PluginManager.add_hookspecs` later will discover all marked
60-
functions if the :class:`PluginManager` uses the same project_name.
77+
functions if the :class:`PluginManager` uses the same project name.
6178
"""
6279

6380
__slots__ = ("project_name",)
@@ -98,12 +115,18 @@ def __call__( # noqa: F811
98115
If passed no function, returns a decorator which can be applied to a
99116
function later using the attributes supplied.
100117
101-
If ``firstresult`` is ``True``, the 1:N hook call (N being the number of
102-
registered hook implementation functions) will stop at I<=N when the
103-
I'th function returns a non-``None`` result.
118+
:param firstresult:
119+
If ``True``, the 1:N hook call (N being the number of registered
120+
hook implementation functions) will stop at I<=N when the I'th
121+
function returns a non-``None`` result. See :ref:`firstresult`.
104122
105-
If ``historic`` is ``True``, every call to the hook will be memorized
106-
and replayed on plugins registered after the call was made.
123+
:param historic:
124+
If ``True``, every call to the hook will be memorized and replayed
125+
on plugins registered after the call was made. See :ref:`historic`.
126+
127+
:param warn_on_impl:
128+
If given, every implementation of this hook will trigger the given
129+
warning. See :ref:`warn_on_impl`.
107130
"""
108131

109132
def setattr_hookspec_opts(func: _F) -> _F:
@@ -128,7 +151,7 @@ class HookimplMarker:
128151
129152
Instantiate it with a ``project_name`` to get a decorator.
130153
Calling :meth:`PluginManager.register` later will discover all marked
131-
functions if the :class:`PluginManager` uses the same project_name.
154+
functions if the :class:`PluginManager` uses the same project name.
132155
"""
133156

134157
__slots__ = ("project_name",)
@@ -178,36 +201,46 @@ def __call__( # noqa: F811
178201
If passed no function, returns a decorator which can be applied to a
179202
function later using the attributes supplied.
180203
181-
If ``optionalhook`` is ``True``, a missing matching hook specification
182-
will not result in an error (by default it is an error if no matching
183-
spec is found).
184-
185-
If ``tryfirst`` is ``True``, this hook implementation will run as early
186-
as possible in the chain of N hook implementations for a specification.
187-
188-
If ``trylast`` is ``True``, this hook implementation will run as late as
189-
possible in the chain of N hook implementations.
190-
191-
If ``wrapper`` is ``True``("new-style hook wrapper"), the hook
192-
implementation needs to execute exactly one ``yield``. The code before
193-
the ``yield`` is run early before any non-hook-wrapper function is run.
194-
The code after the ``yield`` is run after all non-hook-wrapper functions
195-
have run. The ``yield`` receives the result value of the inner calls, or
196-
raises the exception of inner calls (including earlier hook wrapper
197-
calls). The return value of the function becomes the return value of the
198-
hook, and a raised exception becomes the exception of the hook.
199-
200-
If ``hookwrapper`` is ``True`` ("old-style hook wrapper"), the hook
201-
implementation needs to execute exactly one ``yield``. The code before
202-
the ``yield`` is run early before any non-hook-wrapper function is run.
203-
The code after the ``yield`` is run after all non-hook-wrapper function
204-
have run The ``yield`` receives a :class:`_Result` object representing
205-
the exception or result outcome of the inner calls (including earlier
206-
hook wrapper calls). This option is mutually exclusive with ``wrapper``.
207-
208-
If ``specname`` is provided, it will be used instead of the function
209-
name when matching this hook implementation to a hook specification
210-
during registration.
204+
:param optionalhook:
205+
If ``True``, a missing matching hook specification will not result
206+
in an error (by default it is an error if no matching spec is
207+
found). See :ref:`optionalhook`.
208+
209+
:param tryfirst:
210+
If ``True``, this hook implementation will run as early as possible
211+
in the chain of N hook implementations for a specification. See
212+
:ref:`callorder`.
213+
214+
:param trylast:
215+
If ``True``, this hook implementation will run as late as possible
216+
in the chain of N hook implementations for a specification. See
217+
:ref:`callorder`.
218+
219+
:param wrapper:
220+
If ``True`` ("new-style hook wrapper"), the hook implementation
221+
needs to execute exactly one ``yield``. The code before the
222+
``yield`` is run early before any non-hook-wrapper function is run.
223+
The code after the ``yield`` is run after all non-hook-wrapper
224+
functions have run. The ``yield`` receives the result value of the
225+
inner calls, or raises the exception of inner calls (including
226+
earlier hook wrapper calls). The return value of the function
227+
becomes the return value of the hook, and a raised exception becomes
228+
the exception of the hook. See :ref:`hookwrapper`.
229+
230+
:param hookwrapper:
231+
If ``True`` ("old-style hook wrapper"), the hook implementation
232+
needs to execute exactly one ``yield``. The code before the
233+
``yield`` is run early before any non-hook-wrapper function is run.
234+
The code after the ``yield`` is run after all non-hook-wrapper
235+
function have run The ``yield`` receives a :class:`_Result` object
236+
representing the exception or result outcome of the inner calls
237+
(including earlier hook wrapper calls). This option is mutually
238+
exclusive with ``wrapper``. See :ref:`old_style_hookwrapper`.
239+
240+
:param specname:
241+
If provided, the given name will be used instead of the function
242+
name when matching this hook implementation to a hook specification
243+
during registration. See :ref:`specname`.
211244
212245
.. versionadded:: 1.2.0
213246
The ``wrapper`` parameter.
@@ -314,6 +347,9 @@ class _HookRelay:
314347

315348
__slots__ = ("__dict__",)
316349

350+
def __init__(self) -> None:
351+
""":meta private:"""
352+
317353
if TYPE_CHECKING:
318354

319355
def __getattr__(self, name: str) -> _HookCaller:
@@ -324,6 +360,8 @@ def __getattr__(self, name: str) -> _HookCaller:
324360

325361

326362
class _HookCaller:
363+
"""A caller of all registered implementations of a hook specification."""
364+
327365
__slots__ = (
328366
"name",
329367
"spec",
@@ -339,6 +377,7 @@ def __init__(
339377
specmodule_or_class: _Namespace | None = None,
340378
spec_opts: _HookSpecOpts | None = None,
341379
) -> None:
380+
""":meta private:"""
342381
self.name: Final = name
343382
self._hookexec: Final = hook_execute
344383
self._hookimpls: Final[list[HookImpl]] = []
@@ -348,9 +387,11 @@ def __init__(
348387
assert spec_opts is not None
349388
self.set_specification(specmodule_or_class, spec_opts)
350389

390+
# TODO: Document, or make private.
351391
def has_spec(self) -> bool:
352392
return self.spec is not None
353393

394+
# TODO: Document, or make private.
354395
def set_specification(
355396
self,
356397
specmodule_or_class: _Namespace,
@@ -366,6 +407,7 @@ def set_specification(
366407
self._call_history = []
367408

368409
def is_historic(self) -> bool:
410+
"""Whether this caller is :ref:`historic <historic>`."""
369411
return self._call_history is not None
370412

371413
def _remove_plugin(self, plugin: _Plugin) -> None:
@@ -376,6 +418,7 @@ def _remove_plugin(self, plugin: _Plugin) -> None:
376418
raise ValueError(f"plugin {plugin!r} not found")
377419

378420
def get_hookimpls(self) -> list[HookImpl]:
421+
"""Get all registered hook implementations for this hook."""
379422
return self._hookimpls.copy()
380423

381424
def _add_hookimpl(self, hookimpl: HookImpl) -> None:
@@ -424,6 +467,14 @@ def _verify_all_args_are_provided(self, kwargs: Mapping[str, object]) -> None:
424467
break
425468

426469
def __call__(self, **kwargs: object) -> Any:
470+
"""Call the hook.
471+
472+
Only accepts keyword arguments, which should match the hook
473+
specification.
474+
475+
Returns the result(s) of calling all registered plugins, see
476+
:ref:`calling`.
477+
"""
427478
assert (
428479
not self.is_historic()
429480
), "Cannot directly call a historic hook - use call_historic instead."
@@ -437,10 +488,12 @@ def call_historic(
437488
kwargs: Mapping[str, object] | None = None,
438489
) -> None:
439490
"""Call the hook with given ``kwargs`` for all registered plugins and
440-
for all plugins which will be registered afterwards.
491+
for all plugins which will be registered afterwards, see
492+
:ref:`historic`.
441493
442-
If ``result_callback`` is provided, it will be called for each
443-
non-``None`` result obtained from a hook implementation.
494+
:param result_callback:
495+
If provided, will be called for each non-``None`` result obtained
496+
from a hook implementation.
444497
"""
445498
assert self._call_history is not None
446499
kwargs = kwargs or {}
@@ -459,7 +512,8 @@ def call_extra(
459512
self, methods: Sequence[Callable[..., object]], kwargs: Mapping[str, object]
460513
) -> Any:
461514
"""Call the hook with some additional temporarily participating
462-
methods using the specified ``kwargs`` as call parameters."""
515+
methods using the specified ``kwargs`` as call parameters, see
516+
:ref:`call_extra`."""
463517
assert (
464518
not self.is_historic()
465519
), "Cannot directly call a historic hook - use call_historic instead."

0 commit comments

Comments
 (0)