Skip to content

Commit 475c4aa

Browse files
authored
Merge pull request #429 from bluetech/typing2
Some steps towards exporting our typings
2 parents b41572e + 04e9a9b commit 475c4aa

14 files changed

+327
-163
lines changed

.readthedocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ python:
55
# Without this, sphinx can't find pluggy's version.
66
- method: pip
77
path: .
8+
- requirements: docs/requirements.txt
89

910
build:
1011
os: ubuntu-22.04

CHANGELOG.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ Features
5151

5252
- `#260 <https://github.com/pytest-dev/pluggy/issues/260>`_: Added "new-style" hook wrappers, a simpler but equally powerful alternative to the existing ``hookwrapper=True`` wrappers.
5353

54-
New-style wrappers are generator functions, similarly to ``hookwrapper``, but do away with the :class:`result <pluggy._result._Result>` object.
54+
New-style wrappers are generator functions, similarly to ``hookwrapper``, but do away with the :class:`result <pluggy.Result>` object.
5555
Instead, the return value is sent directly to the ``yield`` statement, or, if inner calls raised an exception, it is raised from the ``yield``.
5656
The wrapper is expected to return a value or raise an exception, which will become the result of the hook call.
5757

@@ -64,7 +64,7 @@ Features
6464
- `#364 <https://github.com/pytest-dev/pluggy/issues/364>`_: Python 3.11 and 3.12 are now officially supported.
6565

6666

67-
- `#394 <https://github.com/pytest-dev/pluggy/issues/394>`_: Added the :meth:`~pluggy._result._Result.force_exception` method to ``_Result``.
67+
- `#394 <https://github.com/pytest-dev/pluggy/issues/394>`_: Added the :meth:`~pluggy.Result.force_exception` method to ``_Result``.
6868

6969
``force_exception`` allows (old-style) hookwrappers to force an exception or override/adjust an existing exception of a hook invocation,
7070
in a properly behaving manner. Using ``force_exception`` is preferred over raising an exception from the hookwrapper,

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()
18+
:show-inheritance:
19+
:members:
20+
21+
.. autoclass:: pluggy.HookCaller()
22+
:members:
23+
:special-members: __call__
24+
25+
.. autoclass:: pluggy.HookCallError()
26+
:show-inheritance:
27+
:members:
28+
29+
.. autoclass:: pluggy.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: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"github_type": "star",
4848
"badge_branch": "master",
4949
"page_width": "1080px",
50+
"sidebar_width": "300px",
5051
"fixed_sidebar": "false",
5152
}
5253
html_sidebars = {
@@ -58,7 +59,7 @@
5859
# (source start file, name, description, authors, manual section).
5960
man_pages = [(master_doc, "pluggy", "pluggy Documentation", [author], 1)]
6061

61-
autodoc_typehints = "none"
62+
autodoc_member_order = "bysource"
6263

6364
# -- Options for Texinfo output -------------------------------------------
6465

docs/index.rst

Lines changed: 32 additions & 21 deletions
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

@@ -468,21 +472,21 @@ execution of all corresponding non-wrappper *hookimpls*.
468472
if config.use_defaults:
469473
outcome.force_result(defaults)
470474
471-
The generator is :py:meth:`sent <python:generator.send>` a :py:class:`pluggy._result._Result` object which can
475+
The generator is :py:meth:`sent <python:generator.send>` a :py:class:`pluggy.Result` object which can
472476
be assigned in the ``yield`` expression and used to inspect
473477
the final result(s) or exceptions returned back to the caller using the
474-
:py:meth:`~pluggy._result._Result.get_result` method, override the result
475-
using the :py:meth:`~pluggy._result._Result.force_result`, or override
476-
the exception using the :py:meth:`~pluggy._result._Result.force_exception`
478+
:py:meth:`~pluggy.Result.get_result` method, override the result
479+
using the :py:meth:`~pluggy.Result.force_result`, or override
480+
the exception using the :py:meth:`~pluggy.Result.force_exception`
477481
method.
478482

479483
.. note::
480484
Old-style hook wrappers can **not** return results; they can only modify
481-
them using the :py:meth:`~pluggy._result._Result.force_result` API.
485+
them using the :py:meth:`~pluggy.Result.force_result` API.
482486

483487
Old-style Hook wrappers should **not** raise exceptions; this will cause
484488
further hookwrappers to be skipped. They should use
485-
:py:meth:`~pluggy._result._Result.force_exception` to adjust the
489+
:py:meth:`~pluggy.Result.force_exception` to adjust the
486490
exception.
487491

488492
.. _specs:
@@ -611,7 +615,7 @@ Also see the :ref:`pytest:firstresult` section in the ``pytest`` docs.
611615
Historic hooks
612616
^^^^^^^^^^^^^^
613617
You can mark a *hookspec* as being *historic* meaning that the hook
614-
can be called with :py:meth:`~pluggy._hooks._HookCaller.call_historic()` **before**
618+
can be called with :py:meth:`~pluggy.HookCaller.call_historic()` **before**
615619
having been registered:
616620

617621
.. code-block:: python
@@ -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
@@ -733,13 +739,13 @@ The core functionality of ``pluggy`` enables an extension provider
733739
to override function calls made at certain points throughout a program.
734740

735741
A particular *hook* is invoked by calling an instance of
736-
a :py:class:`pluggy._hooks._HookCaller` which in turn *loops* through the
742+
a :py:class:`pluggy.HookCaller` which in turn *loops* through the
737743
``1:N`` registered *hookimpls* and calls them in sequence.
738744

739745
Every :py:class:`~pluggy.PluginManager` has a ``hook`` attribute
740-
which is an instance of this :py:class:`pluggy._hooks._HookRelay`.
741-
The :py:class:`~pluggy._hooks._HookRelay` itself contains references
742-
(by hook name) to each registered *hookimpl*'s :py:class:`~pluggy._hooks._HookCaller` instance.
746+
which is an instance of :py:class:`pluggy.HookRelay`.
747+
The :py:class:`~pluggy.HookRelay` itself contains references
748+
(by hook name) to each registered *hookimpl*'s :py:class:`~pluggy.HookCaller` instance.
743749

744750
More practically you call a *hook* like so:
745751

@@ -755,7 +761,7 @@ More practically you call a *hook* like so:
755761
pm.add_hookspecs(mypluginspec)
756762
pm.register(myplugin)
757763
758-
# we invoke the _HookCaller and thus all underlying hookimpls
764+
# we invoke the HookCaller and thus all underlying hookimpls
759765
result_list = pm.hook.myhook(config=config, args=sys.argv)
760766
761767
Note that you **must** call hooks using keyword :std:term:`python:argument` syntax!
@@ -874,7 +880,7 @@ only useful if you expect that some *hookimpls* may be registered **after** the
874880
hook is initially invoked.
875881

876882
Historic hooks must be :ref:`specially marked <historic>` and called
877-
using the :py:meth:`~pluggy._hooks._HookCaller.call_historic()` method:
883+
using the :py:meth:`~pluggy.HookCaller.call_historic()` method:
878884

879885
.. code-block:: python
880886
@@ -895,8 +901,8 @@ using the :py:meth:`~pluggy._hooks._HookCaller.call_historic()` method:
895901
# historic callback is invoked here
896902
pm.register(mylateplugin)
897903
898-
Note that if you :py:meth:`~pluggy._hooks._HookCaller.call_historic()`
899-
the :py:class:`~pluggy._hooks._HookCaller` (and thus your calling code)
904+
Note that if you :py:meth:`~pluggy.HookCaller.call_historic()`
905+
the :py:class:`~pluggy.HookCaller` (and thus your calling code)
900906
can not receive results back from the underlying *hookimpl* functions.
901907
Instead you can provide a *callback* for processing results (like the
902908
``callback`` function above) which will be called as each new plugin
@@ -907,23 +913,28 @@ 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
913921
(that aren't in the registry) using the
914-
:py:meth:`pluggy._hooks._HookCaller.call_extra()` method.
922+
:py:meth:`pluggy.HookCaller.call_extra()` method.
915923

916924

917925
Calling with a subset of registered plugins
918926
-------------------------------------------
919927
You can make a call using a subset of plugins by asking the
920928
:py:class:`~pluggy.PluginManager` first for a
921-
:py:class:`~pluggy._hooks._HookCaller` with those plugins removed
929+
:py:class:`~pluggy.HookCaller` with those plugins removed
922930
using the :py:meth:`pluggy.PluginManager.subset_hook_caller()` method.
923931

924-
You then can use that :py:class:`_HookCaller <pluggy._hooks._HookCaller>`
925-
to make normal, :py:meth:`~pluggy._hooks._HookCaller.call_historic`, or
926-
:py:meth:`~pluggy._hooks._HookCaller.call_extra` calls as necessary.
932+
You then can use that :py:class:`~pluggy.HookCaller`
933+
to make normal, :py:meth:`~pluggy.HookCaller.call_historic`, or
934+
:py:meth:`~pluggy.HookCaller.call_extra` calls as necessary.
935+
936+
937+
.. _tracing:
927938

928939
Built-in tracing
929940
****************

docs/requirements.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Higher bound for safety, can bump it if builds fine with new major versions.
2+
sphinx>=6,<8
3+
pygments
4+
towncrier

src/pluggy/__init__.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,23 @@
88
__all__ = [
99
"PluginManager",
1010
"PluginValidationError",
11+
"HookCaller",
1112
"HookCallError",
13+
"HookSpecOpts",
14+
"HookImplOpts",
15+
"HookRelay",
1216
"HookspecMarker",
1317
"HookimplMarker",
18+
"Result",
1419
]
1520

1621
from ._manager import PluginManager, PluginValidationError
17-
from ._result import HookCallError
18-
from ._hooks import HookspecMarker, HookimplMarker
22+
from ._result import HookCallError, Result
23+
from ._hooks import (
24+
HookspecMarker,
25+
HookimplMarker,
26+
HookCaller,
27+
HookRelay,
28+
HookSpecOpts,
29+
HookImplOpts,
30+
)

src/pluggy/_callers.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212

1313
from ._hooks import HookImpl
1414
from ._result import _raise_wrapfail
15-
from ._result import _Result
1615
from ._result import HookCallError
16+
from ._result import Result
1717

1818

1919
# Need to distinguish between old- and new-style hook wrappers.
2020
# Wrapping one a singleton tuple is the fastest type-safe way I found to do it.
2121
Teardown = Union[
22-
Tuple[Generator[None, _Result[object], None]],
22+
Tuple[Generator[None, Result[object], None]],
2323
Generator[None, object, object],
2424
]
2525

@@ -33,7 +33,7 @@ def _multicall(
3333
"""Execute a call into multiple python functions/methods and return the
3434
result(s).
3535
36-
``caller_kwargs`` comes from _HookCaller.__call__().
36+
``caller_kwargs`` comes from HookCaller.__call__().
3737
"""
3838
__tracebackhide__ = True
3939
results: list[object] = []
@@ -58,7 +58,7 @@ def _multicall(
5858
# If this cast is not valid, a type error is raised below,
5959
# which is the desired response.
6060
res = hook_impl.function(*args)
61-
wrapper_gen = cast(Generator[None, _Result[object], None], res)
61+
wrapper_gen = cast(Generator[None, Result[object], None], res)
6262
next(wrapper_gen) # first yield
6363
teardowns.append((wrapper_gen,))
6464
except StopIteration:
@@ -82,7 +82,7 @@ def _multicall(
8282
except BaseException as exc:
8383
exception = exc
8484
finally:
85-
# Fast path - only new-style wrappers, no _Result.
85+
# Fast path - only new-style wrappers, no Result.
8686
if only_new_style_wrappers:
8787
if firstresult: # first result hooks return a single value
8888
result = results[0] if results else None
@@ -117,11 +117,11 @@ def _multicall(
117117
# Slow path - need to support old-style wrappers.
118118
else:
119119
if firstresult: # first result hooks return a single value
120-
outcome: _Result[object | list[object]] = _Result(
120+
outcome: Result[object | list[object]] = Result(
121121
results[0] if results else None, exception
122122
)
123123
else:
124-
outcome = _Result(results, exception)
124+
outcome = Result(results, exception)
125125

126126
# run all wrapper post-yield blocks
127127
for teardown in reversed(teardowns):

0 commit comments

Comments
 (0)