67
67
import sys
68
68
import inspect
69
69
70
- __version__ = '0.2 .0'
70
+ __version__ = '0.3 .0'
71
71
__all__ = ["PluginManager" , "PluginValidationError" ,
72
72
"HookspecMarker" , "HookimplMarker" ]
73
73
@@ -294,10 +294,10 @@ def __init__(self, pluginmanager, before, after):
294
294
assert not isinstance (self .oldcall , _TracedHookExecution )
295
295
self .pluginmanager ._inner_hookexec = self
296
296
297
- def __call__ (self , hook , methods , kwargs ):
298
- self .before (hook , methods , kwargs )
299
- outcome = _CallOutcome (lambda : self .oldcall (hook , methods , kwargs ))
300
- self .after (outcome , hook , methods , kwargs )
297
+ def __call__ (self , hook , hook_impls , kwargs ):
298
+ self .before (hook . name , hook_impls , kwargs )
299
+ outcome = _CallOutcome (lambda : self .oldcall (hook , hook_impls , kwargs ))
300
+ self .after (outcome , hook . name , hook_impls , kwargs )
301
301
return outcome .get_result ()
302
302
303
303
def undo (self ):
@@ -337,20 +337,35 @@ def _hookexec(self, hook, methods, kwargs):
337
337
# enable_tracing will set its own wrapping function at self._inner_hookexec
338
338
return self ._inner_hookexec (hook , methods , kwargs )
339
339
340
+ def add_hookcall_monitoring (self , before , after ):
341
+ """ add before/after tracing functions for all hooks
342
+ and return an undo function which, when called,
343
+ will remove the added tracers.
344
+
345
+ ``before(hook_name, hook_impls, kwargs)`` will be called ahead
346
+ of all hook calls and receive a hookcaller instance, a list
347
+ of HookImpl instances and the keyword arguments for the hook call.
348
+
349
+ ``after(outcome, hook_name, hook_impls, kwargs)`` receives the
350
+ same arguments as ``before`` but also a :py:class:`_CallOutcome`` object
351
+ which represents the result of the overall hook call.
352
+ """
353
+ return _TracedHookExecution (self , before , after ).undo
354
+
340
355
def enable_tracing (self ):
341
356
""" enable tracing of hook calls and return an undo function. """
342
357
hooktrace = self .hook ._trace
343
358
344
- def before (hook , methods , kwargs ):
359
+ def before (hook_name , methods , kwargs ):
345
360
hooktrace .root .indent += 1
346
- hooktrace (hook . name , kwargs )
361
+ hooktrace (hook_name , kwargs )
347
362
348
- def after (outcome , hook , methods , kwargs ):
363
+ def after (outcome , hook_name , methods , kwargs ):
349
364
if outcome .excinfo is None :
350
- hooktrace ("finish" , hook . name , "-->" , outcome .result )
365
+ hooktrace ("finish" , hook_name , "-->" , outcome .result )
351
366
hooktrace .root .indent -= 1
352
367
353
- return _TracedHookExecution ( self , before , after ). undo
368
+ return self . add_hookcall_monitoring ( before , after )
354
369
355
370
def subset_hook_caller (self , name , remove_plugins ):
356
371
""" Return a new _HookCaller instance for the named method
@@ -394,7 +409,7 @@ def register(self, plugin, name=None):
394
409
if hookimpl_opts is not None :
395
410
normalize_hookimpl_opts (hookimpl_opts )
396
411
method = getattr (plugin , name )
397
- hookimpl = _HookImpl (plugin , plugin_name , method , hookimpl_opts )
412
+ hookimpl = HookImpl (plugin , plugin_name , method , hookimpl_opts )
398
413
hook = getattr (self .hook , name , None )
399
414
if hook is None :
400
415
hook = _HookCaller (name , self ._hookexec )
@@ -561,8 +576,8 @@ class _MultiCall:
561
576
# so we can remove it soon, allowing to avoid the below recursion
562
577
# in execute() and simplify/speed up the execute loop.
563
578
564
- def __init__ (self , methods , kwargs , specopts = {}):
565
- self .methods = methods
579
+ def __init__ (self , hook_impls , kwargs , specopts = {}):
580
+ self .hook_impls = hook_impls
566
581
self .kwargs = kwargs
567
582
self .kwargs ["__multicall__" ] = self
568
583
self .specopts = specopts
@@ -572,12 +587,12 @@ def execute(self):
572
587
self .results = results = []
573
588
firstresult = self .specopts .get ("firstresult" )
574
589
575
- while self .methods :
576
- method = self .methods .pop ()
577
- args = [all_kwargs [argname ] for argname in method .argnames ]
578
- if method .hookwrapper :
579
- return _wrapped_call (method .function (* args ), self .execute )
580
- res = method .function (* args )
590
+ while self .hook_impls :
591
+ hook_impl = self .hook_impls .pop ()
592
+ args = [all_kwargs [argname ] for argname in hook_impl .argnames ]
593
+ if hook_impl .hookwrapper :
594
+ return _wrapped_call (hook_impl .function (* args ), self .execute )
595
+ res = hook_impl .function (* args )
581
596
if res is not None :
582
597
if firstresult :
583
598
return res
@@ -587,7 +602,7 @@ def execute(self):
587
602
return results
588
603
589
604
def __repr__ (self ):
590
- status = "%d meths" % (len (self .methods ),)
605
+ status = "%d meths" % (len (self .hook_impls ),)
591
606
if hasattr (self , "results" ):
592
607
status = ("%d results, " % len (self .results )) + status
593
608
return "<_MultiCall %s, kwargs=%r>" % (status , self .kwargs )
@@ -718,7 +733,7 @@ def call_extra(self, methods, kwargs):
718
733
old = list (self ._nonwrappers ), list (self ._wrappers )
719
734
for method in methods :
720
735
opts = dict (hookwrapper = False , trylast = False , tryfirst = False )
721
- hookimpl = _HookImpl (None , "<temp>" , method , opts )
736
+ hookimpl = HookImpl (None , "<temp>" , method , opts )
722
737
self ._add_hookimpl (hookimpl )
723
738
try :
724
739
return self (** kwargs )
@@ -733,7 +748,7 @@ def _maybe_apply_history(self, method):
733
748
proc (res [0 ])
734
749
735
750
736
- class _HookImpl :
751
+ class HookImpl :
737
752
def __init__ (self , plugin , plugin_name , function , hook_impl_opts ):
738
753
self .function = function
739
754
self .argnames = varnames (self .function )
0 commit comments