Changelog¶
Versions follow Semantic Versioning (<major>.<minor>.<patch>).
pluggy 1.7.0 (2026-10-14)¶
Deprecations and Removals¶
#632: Hookspec methods defined without
selfas the first parameter now emit aDeprecationWarning. Addselfas the first parameter or use@staticmethod.
Features¶
#170: Hookspecs can now declare default values for arguments, using the usual
def myhook(myarg="default")syntax. This is mainly a backward compatibility feature, to allow a hookspec to add new parameters to an existing hook without breaking existing callers. See Hookspec argument defaults for details.#729: Tracing now adds detail where
str()is ambiguous: empty strings and strings containing whitespace are quoted, and enums and paths show theirrepr().A value spanning several lines is now displayed as a block instead of running into the surrounding trace.
Bug Fixes¶
#629: Fix hooks failing to register on Python 3.14+ when type annotations use forward references.
#315: Source archives created by
git archive(including GitHub’s “Source code” downloads) now carry version information, so building pluggy from them no longer fails with a missing version.#442: With the addition of default values for hookspec arguments, we also changed the precedence of default values for hookimpl arguments. Previously, if a hookimpl function declared a default for an argument, it was always used, even if the hook call passed an explicit value. Now the precedence is changed to: hook call passed value > hookspec default value > hookimpl default value. See Hookimpl argument defaults.
#701: Hookimpls and hookspecs are now discovered via
inspect.getattr_static(), so properties,cached_propertyand other descriptors are no longer executed while scanning a plugin. Hooks declared through such a descriptor are not supported.As a side effect,
@hookimpl/@hookspecapplied above@classmethodor@staticmethodis now picked up; previously the marker sat on the wrapper wheregetattr()never saw it. Callables stored directly on a plugin instance – in its__dict__or in a__slots__slot – keep being called exactly asgetattr()returned them, i.e. without an implicitself.#431: Fix
HookCaller._remove_plugin()to remove all hook implementations for a plugin in a single call, instead of only the first one. Also fixPluginManager.get_hookcallers()to not return duplicateHookCallerentries when a plugin has multiple implementations on the same hook (e.g. viaspecname).#695: Fixed
subset_hook_caller()not excluding removed plugins which use@hookiml(specname="...").#424: Tracing no longer breaks hook execution when a traced object has a broken
__repr__or__str__. Such a value is now rendered as<[RuntimeError(...) raised in str()] Broken object at 0x...>, in the same style pytest uses for unpresentable objects, instead of propagating the exception out of the hook call.#681: Tracing no longer crashes with
UnicodeEncodeErrorwhen a hook argument or return value contains lone surrogates; they are escaped withbackslashreplacebefore the message reaches the writer. Trace output is otherwise unchanged.#727: Fix the warning for hookspec arguments missing from a hook call being attributed to pluggy’s own frame instead of to the code making the call. This affected
HookCaller.__call__,call_historicandcall_extra.#731:
PluginManager.register(None)is now ignored instead of having some weird behaviors.#733:
PluginManager.register()now validates all hook implementations of a plugin before registering any of them, so a plugin that fails validation no longer stays partially registered.#755: Skip already registered entry-point plugins without evaluating the plugin object’s truthiness.
#757: Restore the project URLs in the package metadata, which were lost in pluggy 1.6.0 when the packaging configuration moved to
pyproject.toml. Links to the documentation, changelog, issue tracker and funding page were added as well.#759:
PluginManager.unregister()now raisesValueErrorwhen bothpluginandnameare given but refer to different plugins, instead of removing one plugin’s hook implementations and another plugin’s registry entry. It also fully unregisters plugin objects that are falsy (e.g. define__len__returning0); previously their name stayed in the registry.#186: Fixed broken external documentation references in the list of projects using pluggy.
Trivial/Internal Changes¶
#417: Fix the
tox -e docsbuild, which failed undersphinx-build -Wbecause nitpicky mode reported unresolved references to the private names.#590: The
pluggy.__version__variable is now dynamically provided via a module-level__getattr__implementation, usingimportlibto obtain the installed version.#691: Fix outdated links in
README.rst.#703: The internal
pluggy._hooksmodule was split into role-specific modules (_caller,_config,_decorators,_executionand_impl).pluggy._hooksremains as a re-export shim, and the public API is unchanged.#776: Building
pluggywithout git metadata now yields the placeholder version1.6.0+fallbackinstead of failing, so Dependabot relocks no longer resolvepluggyas0.0.0and silently downgrade pytest and tox inuv.lock.toxwas dropped from thedevdependency group; run it as a tool withuvx tox.
pluggy 1.6.0 (2025-05-15)¶
Deprecations and Removals¶
#556: Python 3.8 is no longer supported.
Bug Fixes¶
#504: Fix a regression in pluggy 1.1.0 where using
result.get_result()on the same failedResultcauses the exception’s traceback to get longer and longer.#544: Correctly pass
StopIterationthrough hook wrappers.Raising a
StopIterationin a generator triggers aRuntimeError.If the
RuntimeErrorof a generator has the passed inStopIterationas cause resume with thatStopIterationas normal exception instead of failing with theRuntimeError.#573: Fix python 3.14 SyntaxError by rearranging code.
pluggy 1.5.0 (2024-04-19)¶
Features¶
#178: Add support for deprecating specific hook parameters, or more generally, for issuing a warning whenever a hook implementation requests certain parameters.
See Warnings on hook implementation for details.
Bug Fixes¶
#481:
PluginManager.get_plugins()no longer returnsNonefor blocked plugins.
pluggy 1.4.0 (2024-01-24)¶
Features¶
#463: A warning
PluggyTeardownRaisedWarningis now issued when an old-style hookwrapper raises an exception during teardown. See the warning documentation for more details.#471: Add
PluginManager.unblockmethod to unblock a plugin by plugin name.
Bug Fixes¶
#441: Fix
call_extra()extra methods getting ordered before everything else in some circumstances. Regressed in pluggy 1.1.0.#438: Fix plugins registering other plugins in a hook when the other plugins implement the same hook itself. Regressed in pluggy 1.1.0.
pluggy 1.3.0 (2023-08-26)¶
Deprecations and Removals¶
#426: Python 3.7 is no longer supported.
Features¶
#428: Pluggy now exposes its typings to static type checkers.
As part of this, the following changes are made:
Renamed
_ResulttoResult, and exported aspluggy.Result.Renamed
_HookRelaytoHookRelay, and exported aspluggy.HookRelay.Renamed
_HookCallertoHookCaller, and exported aspluggy.HookCaller.Exported
HookImplaspluggy.HookImpl.Renamed
_HookImplOptstoHookimplOpts, and exported aspluggy.HookimplOpts.Renamed
_HookSpecOptstoHookspecOpts, and exported aspluggy.HookspecOpts.Some fields and classes are marked
Finaland@final.The API Reference is updated to clearly delineate pluggy’s public API.
Compatibility aliases are put in place for the renamed types. We do not plan to remove the aliases, but we strongly recommend to only import from
pluggy.*to ensure future compatibility.Please note that pluggy is currently unable to provide strong typing for hook calls, e.g.
pm.hook.my_hook(...), nor to statically check that a hook implementation matches the hook specification’s type.
pluggy 1.2.0 (2023-06-21)¶
Features¶
#405: The new-style hook wrappers, added in the yanked 1.1.0 release, now require an explicit
wrapper=Truedesignation in the@hookimpl()decorator.
pluggy 1.1.0 (YANKED)¶
Note
This release was yanked because unfortunately the implicit new-style hook wrappers broke some downstream projects. See #403 for more information. This was rectified in the 1.2.0 release.
Deprecations and Removals¶
#364: Python 3.6 is no longer supported.
Features¶
#260: Added “new-style” hook wrappers, a simpler but equally powerful alternative to the existing
hookwrapper=Truewrappers.New-style wrappers are generator functions, similarly to
hookwrapper, but do away with theresultobject. Instead, the return value is sent directly to theyieldstatement, or, if inner calls raised an exception, it is raised from theyield. The wrapper is expected to return a value or raise an exception, which will become the result of the hook call.New-style wrappers are fully interoperable with old-style wrappers. We encourage users to use the new style, however we do not intend to deprecate the old style any time soon.
See Wrappers for the full documentation.
#364: Python 3.11 and 3.12 are now officially supported.
#394: Added the
force_exception()method to_Result.force_exceptionallows (old-style) hookwrappers to force an exception or override/adjust an existing exception of a hook invocation, in a properly behaving manner. Usingforce_exceptionis preferred over raising an exception from the hookwrapper, because raising an exception causes other hookwrappers to be skipped.
pluggy 1.0.0 (2021-08-25)¶
Deprecations and Removals¶
#116: Remove deprecated
implprefixsupport. Decorate hook implementations using an instance of HookimplMarker instead. The deprecation was announced in release0.7.0.#120: Remove the deprecated
procargument tocall_historic. Useresult_callbackinstead, which has the same behavior. The deprecation was announced in release0.7.0.#265: Remove the
_Result.resultproperty. Use_Result.get_result()instead. Note that unlikeresult,get_result()raises the exception if the hook raised. The deprecation was announced in release0.6.0.#267: Remove official support for Python 3.4.
#272: Dropped support for Python 2. Continue to use pluggy 0.13.x for Python 2 support.
#308: Remove official support for Python 3.5.
#313: The internal
pluggy.callers,pluggy.managerandpluggy.hooksare now explicitly marked private by a_prefix (e.g.pluggy._callers). Only API exported by the top-levelpluggymodule is considered public.#59: Remove legacy
__multicall__recursive hook calling system. The deprecation was announced in release0.5.0.
Features¶
#282: When registering a hookimpl which is declared as
hookwrapper=Truebut whose function is not a generator function, aPluginValidationErrorexception is now raised.Previously this problem would cause an error only later, when calling the hook.
In the unlikely case that you have a hookwrapper that returns a generator instead of yielding directly, for example:
def my_hook_impl(arg): print("before") yield print("after") @hookimpl(hookwrapper=True) def my_hook(arg): return my_hook_impl(arg)
change it to use
yield frominstead:@hookimpl(hookwrapper=True) def my_hook(arg): yield from my_hook_impl(arg)
#309: Add official support for Python 3.9.
#251: Add
specnameoption to@hookimpl. Ifspecnameis provided, it will be used instead of the function name when matching this hook implementation to a hook specification during registration (allowing a plugin to register a hook implementation that was not named the same thing as the corresponding@hookspec).
pluggy 0.13.1 (2019-11-21)¶
Trivial/Internal Changes¶
#236: Improved documentation, especially with regard to references.
pluggy 0.13.0 (2019-09-10)¶
Trivial/Internal Changes¶
#222: Replace
importlib_metadatabackport withimportlib.metadatafrom the standard library on Python 3.8+.
pluggy 0.12.0 (2019-05-27)¶
Features¶
#215: Switch from
pkg_resourcestoimportlib-metadatafor entrypoint detection for improved performance and import time. This time with.eggsupport.
pluggy 0.11.0 (2019-05-07)¶
Bug Fixes¶
#205: Revert changes made in 0.10.0 release breaking
.egginstalls.
pluggy 0.10.0 (2019-05-07)¶
Features¶
#199: Switch from
pkg_resourcestoimportlib-metadatafor entrypoint detection for improved performance and import time.
pluggy 0.9.0 (2019-02-21)¶
Features¶
#189:
PluginManager.load_setuptools_entrypointsnow accepts anameparameter that when given will load only entry points with that name.PluginManager.load_setuptools_entrypointsalso now returns the number of plugins loaded by the call, as opposed to the number of all plugins loaded by all calls to this method.
Bug Fixes¶
#187: Fix internal
varnamesfunction for PyPy3.
pluggy 0.8.1 (2018-11-09)¶
Trivial/Internal Changes¶
#166: Add
stacklevel=2to implprefix warning so that the reported location of warning is the caller of PluginManager.
pluggy 0.8.0 (2018-10-15)¶
Features¶
#177: Add
get_hookimpls()method to hook callers.
Trivial/Internal Changes¶
pluggy 0.7.1 (2018-07-28)¶
Deprecations and Removals¶
#116: Deprecate the
implprefixkwarg toPluginManagerand instead expect users to start using explicitHookimplMarkereverywhere.
Features¶
Bug Fixes¶
Improved Documentation¶
#123: Document how exceptions are handled and how the hook call loop terminates immediately on the first error which is then delivered to any surrounding wrappers.
#136: Docs rework including a much better introduction and comprehensive example set for new users. A big thanks goes out to @obestwalter for the great work!
Trivial/Internal Changes¶
#117: Break up the main monolithic package modules into separate modules by concern
#131: Automate
setuptoolswheels building and PyPi upload using TravisCI.#153: Reorganize tests more appropriately by modules relating to each internal component/feature. This is in an effort to avoid (future) duplication and better separation of concerns in the test set.
#156: Add
HookImpl.__repr__()for better debugging.#66: Start using
towncrierand a customtoxenvironment to prepare releases!
pluggy 0.7.0 (Unreleased)¶
#160: We discovered a deployment issue so this version was never released to PyPI, only the tag exists.
pluggy 0.6.0 (2017-11-24)¶
Add CI testing for the features, release, and master branches of
pytest(PR #79).Document public API for
_Resultobjects passed to wrappers (PR #85).Document and test hook LIFO ordering (PR #85).
Turn warnings into errors in test suite (PR #89).
Deprecate
_Result.result(PR #88).Convert
_Multicallto a simple function distinguishing it from the legacy version (PR #90).Resolve E741 errors (PR #96).
Test and bug fix for unmarked hook collection (PRs #97 and #102).
Drop support for EOL Python 2.6 and 3.3 (PR #103).
Fix
inspectbased arg introspection on py3.6 (PR #94).
pluggy 0.5.2 (2017-09-06)¶
fix bug where
firstresultwrappers were being sent an incorrectly configured_Result(a list was set instead of a single value). Add tests to check for this as well as_Result.force_result()behaviour. Thanks to @tgoodlet for the PR #72.fix incorrect
getattrofDeprecationWarningfrom thewarningsmodule. Thanks to @nicoddemus for the PR #77.hide
pytesttracebacks in certain core routines. Thanks to @nicoddemus for the PR #80.
pluggy 0.5.1 (2017-08-29)¶
fix a bug and add tests for case where
firstresulthooks returnNoneresults. Thanks to @RonnyPfannschmidt and @tgoodlet for the issue (#68) and PR (#69) respectively.
pluggy 0.5.0 (2017-08-28)¶
fix bug where callbacks for historic hooks would not be called for already registered plugins. Thanks @vodik for the PR and @hpk42 for further fixes.
fix #17 by considering only actual functions for hooks this removes the ability to register arbitrary callable objects which at first glance is a reasonable simplification, thanks @RonnyPfannschmidt for report and pr.
fix #19: allow registering hookspecs from instances. The PR from @tgoodlet also modernized the varnames implementation.
resolve #32: split up the test set into multiple modules. Thanks to @RonnyPfannschmidt for the PR and @tgoodlet for the initial request.
resolve #14: add full sphinx docs. Thanks to @tgoodlet for PR #39.
add hook call mismatch warnings. Thanks to @tgoodlet for the PR #42.
resolve #44: move to new-style classes. Thanks to @MichalTHEDUDE for PR #46.
add baseline benchmarking/speed tests using
pytest-benchmarkin PR #54. Thanks to @tgoodlet.update the README to showcase the API. Thanks to @tgoodlet for the issue and PR #55.
deprecate
__multicall__and add a faster call loop implementation. Thanks to @tgoodlet for PR #58.raise a comprehensible error when a
hookimplis called with positional args. Thanks to @RonnyPfannschmidt for the issue and @tgoodlet for PR #60.fix the
firstresulttest making it more complete and remove a duplicate of that test. Thanks to @tgoodlet for PR #62.
pluggy 0.4.0 (2016-09-25)¶
add
has_plugin(name)method to pluginmanager. thanks @nicoddemus.fix #11: make plugin parsing more resilient against exceptions from
__getattr__functions. Thanks @nicoddemus.fix issue #4: specific
HookCallErrorexception for when a hook call provides not enough arguments.better error message when loading setuptools entrypoints fails due to a
VersionConflict. Thanks @blueyed.
pluggy 0.3.1 (2015-09-17)¶
avoid using deprecated-in-python3.5 getargspec method. Thanks @mdboom.
pluggy 0.3.0 (2015-05-07)¶
initial release