@@ -152,9 +152,10 @@ then the *hookimpl* should be marked with the ``"optionalhook"`` option:
152
152
153
153
Call time order
154
154
^^^^^^^^^^^^^^^
155
- A *hookimpl * can influence its call-time invocation position.
156
- If marked with a ``"tryfirst" `` or ``"trylast" `` option it will be
157
- executed *first * or *last * respectively in the hook call loop:
155
+ By default hooks are :ref: `called <calling >` in LIFO registered order, however,
156
+ a *hookimpl * can influence its call-time invocation position using special
157
+ attributes. If marked with a ``"tryfirst" `` or ``"trylast" `` option it
158
+ will be executed *first * or *last * respectively in the hook call loop:
158
159
159
160
.. code-block :: python
160
161
@@ -196,12 +197,16 @@ executed *first* or *last* respectively in the hook call loop:
196
197
For another example see the `hook function ordering `_ section of the
197
198
``pytest `` docs.
198
199
200
+ .. note ::
201
+ ``tryfirst `` and ``trylast `` hooks are still invoked in LIFO order within
202
+ each category.
203
+
199
204
Wrappers
200
205
^^^^^^^^
201
206
A *hookimpl * can be marked with a ``"hookwrapper" `` option which indicates that
202
207
the function will be called to *wrap * (or surround) all other normal *hookimpl *
203
208
calls. A *hookwrapper * can thus execute some code ahead and after the execution
204
- of all corresponding non-hookwrappper *hookimpls *.
209
+ of all corresponding non-wrappper *hookimpls *.
205
210
206
211
Much in the same way as a `@contextlib.contextmanager `_, *hookwrappers * must
207
212
be implemented as generator function with a single ``yield `` in its body:
@@ -234,13 +239,15 @@ be implemented as generator function with a single ``yield`` in its body:
234
239
if config.use_defaults:
235
240
outcome.force_result(defaults)
236
241
237
- The generator is `sent `_ a :py:class: `pluggy._CallOutcome ` object which can
242
+ The generator is `sent `_ a :py:class: `pluggy._Result ` object which can
238
243
be assigned in the ``yield `` expression and used to override or inspect
239
- the final result(s) returned back to the hook caller.
244
+ the final result(s) returned back to the caller using the
245
+ :py:meth: `~pluggy._Result.force_result ` or
246
+ :py:meth: `~pluggy._Result.get_result ` methods.
240
247
241
248
.. note ::
242
249
Hook wrappers can **not ** return results (as per generator function
243
- semantics); they can only modify them using the ``_CallOutcome `` API.
250
+ semantics); they can only modify them using the ``_Result `` API.
244
251
245
252
Also see the `hookwrapper `_ section in the ``pytest `` docs.
246
253
@@ -477,6 +484,8 @@ You can retrieve the *options* applied to a particular
477
484
http://doc.pytest.org/en/latest/writing_plugins.html#setuptools-entry-points
478
485
479
486
487
+ .. _calling :
488
+
480
489
Calling Hooks
481
490
*************
482
491
The core functionality of ``pluggy `` enables an extension provider
@@ -487,7 +496,7 @@ a :py:class:`pluggy._HookCaller` which in turn *loops* through the
487
496
``1:N `` registered *hookimpls * and calls them in sequence.
488
497
489
498
Every :py:class: `pluggy.PluginManager ` has a ``hook `` attribute
490
- which is an instance of a :py:class: `pluggy._HookRelay `.
499
+ which is an instance of this :py:class: `pluggy._HookRelay `.
491
500
The ``_HookRelay `` itself contains references (by hook name) to each
492
501
registered *hookimpl *'s ``_HookCaller `` instance.
493
502
@@ -510,6 +519,40 @@ More practically you call a *hook* like so:
510
519
511
520
Note that you **must ** call hooks using keyword `arguments `_ syntax!
512
521
522
+ Hook implementations are called in LIFO registered order: *the last
523
+ registered plugin's hooks are called first *. As an example, the below
524
+ assertion should not error:
525
+
526
+ .. code-block :: python
527
+
528
+ from pluggy import PluginManager, HookimplMarker
529
+
530
+ hookimpl = HookimplMarker(' myproject' )
531
+
532
+ class Plugin1 (object ):
533
+ def myhook (self , args ):
534
+ """ Default implementation.
535
+ """
536
+ return 1
537
+
538
+ class Plugin2 (object ):
539
+ def myhook (self , args ):
540
+ """ Default implementation.
541
+ """
542
+ return 2
543
+
544
+ class Plugin3 (object ):
545
+ def myhook (self , args ):
546
+ """ Default implementation.
547
+ """
548
+ return 3
549
+
550
+ pm = PluginManager(' myproject' )
551
+ pm.register(Plugin1())
552
+ pm.register(Plugin2())
553
+ pm.register(Plugin3())
554
+
555
+ assert pm.hook.myhook(args = ()) == [3 , 2 , 1 ]
513
556
514
557
Collecting results
515
558
------------------
@@ -562,7 +605,7 @@ Calling with a subset of registered plugins
562
605
-------------------------------------------
563
606
You can make a call using a subset of plugins by asking the
564
607
``PluginManager `` first for a ``_HookCaller `` with those plugins removed
565
- using the :py:meth: `pluggy.PluginManger .subset_hook_caller() ` method.
608
+ using the :py:meth: `pluggy.PluginManager .subset_hook_caller() ` method.
566
609
567
610
You then can use that ``_HookCaller `` to make normal, ``call_historic() ``,
568
611
or ``call_extra() `` calls as necessary.
0 commit comments