Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -222,23 +222,23 @@ Features

.. code-block:: python

def my_hook_implementation(arg):
def my_hook_impl(arg):
print("before")
yield
print("after")


@hookimpl(hookwrapper=True)
def my_hook(arg):
return my_hook_implementation(arg)
return my_hook_impl(arg)

change it to use ``yield from`` instead:

.. code-block:: python

@hookimpl(hookwrapper=True)
def my_hook(arg):
yield from my_hook_implementation(arg)
yield from my_hook_impl(arg)


- `#309 <https://github.com/pytest-dev/pluggy/issues/309>`_: Add official support for Python 3.9.
Expand Down
4 changes: 4 additions & 0 deletions changelog/703.trivial.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
The internal ``pluggy._hooks`` module was split into role-specific modules
(``_caller``, ``_config``, ``_decorators``, ``_execution`` and ``_impl``).
``pluggy._hooks`` remains as a re-export shim, and the public API is
unchanged.
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.
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 @@ -767,10 +767,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