Skip to content
8 changes: 8 additions & 0 deletions changelog/704.removal.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Hook options are now :class:`pluggy.HookspecConfiguration` /
:class:`pluggy.HookimplConfiguration` objects (markers attach these instead of
dicts). ``PluginManager.parse_hookimpl_opts`` /
``parse_hookspec_opts`` remain as a deprecated pytest/support concession that
returns legacy dicts and are only invoked during registration when a subclass
overrides them and no modern configuration attribute was found.
``HookspecOpts`` / ``HookimplOpts`` TypedDicts remain importable for
pytest/typing compatibility.
3 changes: 3 additions & 0 deletions changelog/706.trivial.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
``HookSpec`` now stores its :class:`pluggy.HookspecConfiguration` as
``config``; the old ``opts`` attribute remains as a deprecated alias
property.
9 changes: 9 additions & 0 deletions changelog/707.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Hook implementations are now represented by dedicated types:
:class:`pluggy.NormalImpl` for normal implementations and
:class:`pluggy.WrapperImpl` for (old- and new-style) wrappers, both
subclasses of :class:`pluggy.HookImpl`.
``HookimplConfiguration.create_hookimpl()`` selects the appropriate
subclass, and ``WrapperImpl.setup_and_get_completion_hook()`` exposes
wrapper setup/teardown as a ``CompletionHook`` callback.
``HookImpl`` now stores its configuration as ``hookimpl_config``; the old
``opts`` attribute remains as a deprecated alias property.
1 change: 1 addition & 0 deletions changelog/708.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Outer hook wrappers now receive the error and complete their teardown when a new-style hook wrapper yields more than once.
12 changes: 12 additions & 0 deletions changelog/708.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
:class:`pluggy.HookCaller` is now a runtime-checkable
:class:`~typing.Protocol` implemented by the new concrete callers
:class:`pluggy.NormalHookCaller` (split normal/wrapper implementation
lists), :class:`pluggy.HistoricHookCaller` (call memorization and replay,
no wrappers) and :class:`pluggy.SubsetHookCaller`.
``isinstance(caller, HookCaller)`` keeps working for all of them.

The hook execution engine now runs a dual-sequence multicall: wrappers own
their setup/teardown through ``CompletionHook`` callbacks which run LIFO
after the normal implementations, removing all wrapper flag branching from
the hot loop. Hook call monitoring callbacks still receive a single
combined implementation list.
21 changes: 19 additions & 2 deletions docs/api_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ API Reference
:members:
:special-members: __call__

.. autoclass:: pluggy.NormalHookCaller()
:members:
:special-members: __call__

.. autoclass:: pluggy.HistoricHookCaller()
:members:
:special-members: __call__

.. autoclass:: pluggy.SubsetHookCaller()
:members:

.. autoclass:: pluggy.HookCallError()
:show-inheritance:
:members:
Expand All @@ -40,14 +51,20 @@ API Reference
.. autoclass:: pluggy.HookImpl()
:members:

.. autoclass:: pluggy.HookspecOpts()
.. autoclass:: pluggy.NormalImpl()
:show-inheritance:
:members:

.. autoclass:: pluggy.HookimplOpts()
.. autoclass:: pluggy.WrapperImpl()
:show-inheritance:
:members:

.. autoclass:: pluggy.HookspecConfiguration()
:members:

.. autoclass:: pluggy.HookimplConfiguration()
:members:


Warnings
--------
Expand Down
9 changes: 6 additions & 3 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -819,10 +819,13 @@ and particular plugins in it:

Parsing mark options
^^^^^^^^^^^^^^^^^^^^
You can retrieve the *options* applied to a particular
*hookspec* or *hookimpl* as per :ref:`marking_hooks` using the
Markers attach :class:`~pluggy.HookspecConfiguration` /
:class:`~pluggy.HookimplConfiguration` objects to functions. The
:py:meth:`~pluggy.PluginManager.parse_hookspec_opts()` and
:py:meth:`~pluggy.PluginManager.parse_hookimpl_opts()` respectively.
:py:meth:`~pluggy.PluginManager.parse_hookimpl_opts()` methods remain as a
**deprecated** pytest/support concession that returns legacy dict-shaped
options; registration only calls them when a subclass overrides them and no
modern configuration attribute was found.


.. _calling:
Expand Down
18 changes: 16 additions & 2 deletions src/pluggy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,42 @@
__all__ = [
"HistoricHookCaller",
"HookCallError",
"HookCaller",
"HookImpl",
"HookRelay",
"HookimplConfiguration",
"HookimplMarker",
"HookimplOpts",
"HookspecConfiguration",
"HookspecMarker",
"HookspecOpts",
"NormalHookCaller",
"NormalImpl",
"PluggyTeardownRaisedWarning",
"PluggyWarning",
"PluginManager",
"PluginValidationError",
"Result",
"SubsetHookCaller",
"WrapperImpl",
"__version__",
]
from ._config import HookimplConfiguration
from ._config import HookspecConfiguration
from ._hooks import HistoricHookCaller
from ._hooks import HookCaller
from ._hooks import HookImpl
from ._hooks import HookimplMarker
from ._hooks import HookimplOpts
from ._hooks import HookRelay
from ._hooks import HookspecMarker
from ._hooks import HookspecOpts
from ._hooks import NormalHookCaller
from ._hooks import NormalImpl
from ._hooks import SubsetHookCaller
from ._hooks import WrapperImpl
from ._manager import PluginManager
from ._manager import PluginValidationError
from ._pytest_compat import HookimplOpts
from ._pytest_compat import HookspecOpts
from ._result import HookCallError
from ._result import Result
from ._warnings import PluggyTeardownRaisedWarning
Expand Down
Loading
Loading