@@ -231,7 +231,10 @@ def __init__(self, project_name, implprefix=None):
231
231
self ._implprefix = implprefix
232
232
self ._inner_hookexec = lambda hook , methods , kwargs : \
233
233
hook .multicall (
234
- methods , kwargs , specopts = hook .spec_opts , hook = hook
234
+ methods ,
235
+ kwargs ,
236
+ specopts = hook .spec .opts ['firstresult' ] if hook .spec else False ,
237
+ hook = hook
235
238
).execute ()
236
239
237
240
def _hookexec (self , hook , methods , kwargs ):
@@ -379,7 +382,7 @@ def _verify_hook(self, hook, hookimpl):
379
382
(hookimpl .plugin_name , hook .name ))
380
383
381
384
# positional arg checking
382
- notinspec = set (hookimpl .argnames ) - set (hook .argnames )
385
+ notinspec = set (hookimpl .argnames ) - set (hook .spec . argnames )
383
386
if notinspec :
384
387
raise PluginValidationError (
385
388
"Plugin %r for hook %r\n hookimpl definition: %s\n "
@@ -472,8 +475,8 @@ def subset_hook_caller(self, name, remove_plugins):
472
475
orig = getattr (self .hook , name )
473
476
plugins_to_remove = [plug for plug in remove_plugins if hasattr (plug , name )]
474
477
if plugins_to_remove :
475
- hc = _HookCaller (orig .name , orig ._hookexec , orig ._specmodule_or_class ,
476
- orig .spec_opts )
478
+ hc = _HookCaller (orig .name , orig ._hookexec , orig .spec . namespace ,
479
+ orig .spec . opts )
477
480
for hookimpl in (orig ._wrappers + orig ._nonwrappers ):
478
481
plugin = hookimpl .plugin
479
482
if plugin not in plugins_to_remove :
@@ -494,17 +497,18 @@ class _LegacyMultiCall(object):
494
497
# so we can remove it soon, allowing to avoid the below recursion
495
498
# in execute() and simplify/speed up the execute loop.
496
499
497
- def __init__ (self , hook_impls , kwargs , specopts = {}, hook = None ):
498
- self .hook = hook
500
+ def __init__ (self , hook_impls , kwargs , firstresult = False , hook = None ):
499
501
self .hook_impls = hook_impls
500
502
self .caller_kwargs = kwargs # come from _HookCaller.__call__()
501
503
self .caller_kwargs ["__multicall__" ] = self
502
- self .specopts = hook .spec_opts if hook else specopts
504
+ self .firstresult = firstresult
505
+ self .hook = hook
506
+ self .spec = hook .spec if hook else None
503
507
504
508
def execute (self ):
505
509
caller_kwargs = self .caller_kwargs
506
510
self .results = results = []
507
- firstresult = self .specopts . get ( " firstresult" )
511
+ firstresult = self .firstresult
508
512
509
513
while self .hook_impls :
510
514
hook_impl = self .hook_impls .pop ()
@@ -515,8 +519,10 @@ def execute(self):
515
519
if argname not in caller_kwargs :
516
520
raise HookCallError (
517
521
"hook call must provide argument %r" % (argname ,))
522
+
518
523
if hook_impl .hookwrapper :
519
524
return _wrapped_call (hook_impl .function (* args ), self .execute )
525
+
520
526
res = hook_impl .function (* args )
521
527
if res is not None :
522
528
if firstresult :
@@ -603,26 +609,23 @@ def __init__(self, name, hook_execute, specmodule_or_class=None, spec_opts=None)
603
609
self .argnames = None
604
610
self .kwargnames = None
605
611
self .multicall = _MultiCall
612
+ self .spec = None
613
+ self ._call_history = None
606
614
if specmodule_or_class is not None :
607
615
assert spec_opts is not None
608
616
self .set_specification (specmodule_or_class , spec_opts )
609
617
610
618
def has_spec (self ):
611
- return hasattr ( self , "_specmodule_or_class" )
619
+ return self . spec is not None
612
620
613
621
def set_specification (self , specmodule_or_class , spec_opts ):
614
622
assert not self .has_spec ()
615
- self ._specmodule_or_class = specmodule_or_class
616
- specfunc = getattr (specmodule_or_class , self .name )
617
- # get spec arg signature
618
- argnames , self .kwargnames = varnames (specfunc )
619
- self .argnames = ["__multicall__" ] + list (argnames )
620
- self .spec_opts = spec_opts
623
+ self .spec = HookSpec (specmodule_or_class , self .name , spec_opts )
621
624
if spec_opts .get ("historic" ):
622
625
self ._call_history = []
623
626
624
627
def is_historic (self ):
625
- return hasattr ( self , " _call_history" )
628
+ return self . _call_history is not None
626
629
627
630
def _remove_plugin (self , plugin ):
628
631
def remove (wrappers ):
@@ -668,8 +671,8 @@ def __call__(self, *args, **kwargs):
668
671
if args :
669
672
raise TypeError ("hook calling supports only keyword arguments" )
670
673
assert not self .is_historic ()
671
- if self .argnames :
672
- notincall = set (self .argnames ) - set (['__multicall__' ]) - set (
674
+ if self .spec :
675
+ notincall = set (self .spec . argnames ) - set (['__multicall__' ]) - set (
673
676
kwargs .keys ())
674
677
if notincall :
675
678
warnings .warn (
@@ -715,6 +718,16 @@ def _maybe_apply_history(self, method):
715
718
proc (res [0 ])
716
719
717
720
721
+ class HookSpec (object ):
722
+ def __init__ (self , namespace , name , opts ):
723
+ self .namespace = namespace
724
+ self .function = function = getattr (namespace , name )
725
+ self .name = name
726
+ self .argnames , self .kwargnames = varnames (function )
727
+ self .opts = opts
728
+ self .argnames = ["__multicall__" ] + list (self .argnames )
729
+
730
+
718
731
class HookImpl (object ):
719
732
def __init__ (self , plugin , plugin_name , function , hook_impl_opts ):
720
733
self .function = function
0 commit comments