@@ -312,6 +312,9 @@ For another example see the `hook function ordering`_ section of the
312
312
``tryfirst `` and ``trylast `` hooks are still invoked in LIFO order within
313
313
each category.
314
314
315
+
316
+ .. _hookwrappers :
317
+
315
318
Wrappers
316
319
^^^^^^^^
317
320
A *hookimpl * can be marked with a ``"hookwrapper" `` option which indicates that
@@ -662,18 +665,21 @@ assertion should not error:
662
665
hookimpl = HookimplMarker(' myproject' )
663
666
664
667
class Plugin1 (object ):
668
+ @hookimpl
665
669
def myhook (self , args ):
666
670
""" Default implementation.
667
671
"""
668
672
return 1
669
673
670
674
class Plugin2 (object ):
675
+ @hookimpl
671
676
def myhook (self , args ):
672
677
""" Default implementation.
673
678
"""
674
679
return 2
675
680
676
681
class Plugin3 (object ):
682
+ @hookimpl
677
683
def myhook (self , args ):
678
684
""" Default implementation.
679
685
"""
@@ -699,6 +705,57 @@ its :ref:`firstresult` in which case only the first single value (which is not
699
705
700
706
.. _call_historic :
701
707
708
+ Exception handling
709
+ ------------------
710
+ If any *hookimpl * errors with an exception no further callbacks
711
+ are invoked and the exception is packaged up and delivered to
712
+ any :ref: `hookwrappers ` before being re-raised at the hook invocation
713
+ point:
714
+
715
+ .. code-block :: python
716
+
717
+ from pluggy import PluginManager, HookimplMarker
718
+
719
+ hookimpl = HookimplMarker(' myproject' )
720
+
721
+ class Plugin1 (object ):
722
+ @hookimpl
723
+ def myhook (self , args ):
724
+ return 1
725
+
726
+ class Plugin2 (object ):
727
+ @hookimpl
728
+ def myhook (self , args ):
729
+ raise RunTimeError
730
+
731
+ class Plugin3 (object ):
732
+ @hookimpl
733
+ def myhook (self , args ):
734
+ return 3
735
+
736
+ @hookimpl (hookwrapper = True )
737
+ def myhook (self , args ):
738
+ outcome = yield
739
+
740
+ try :
741
+ outcome.get_result()
742
+ except RuntimeError :
743
+ # log the error details
744
+ print (outcome.excinfo)
745
+
746
+ pm = PluginManager(' myproject' )
747
+
748
+ # register plugins
749
+ pm.register(Plugin1())
750
+ pm.register(Plugin2())
751
+ pm.register(Plugin3())
752
+
753
+ # register wrapper
754
+ pm.register(sys.modules[__name__ ])
755
+
756
+ # this raises RuntimeError due to Plugin2
757
+ pm.hook.myhook(args = ())
758
+
702
759
Historic calls
703
760
--------------
704
761
A *historic call * allows for all newly registered functions to receive all hook
0 commit comments