@@ -212,7 +212,10 @@ def __init__(self, project_name, implprefix=None):
212212 self ._implprefix = implprefix
213213 self ._inner_hookexec = lambda hook , methods , kwargs : \
214214 hook .multicall (
215- methods , kwargs , specopts = hook .spec_opts , hook = hook
215+ methods ,
216+ kwargs ,
217+ specopts = hook .spec .opts ['firstresult' ] if hook .spec else False ,
218+ hook = hook
216219 )
217220
218221 def _hookexec (self , hook , methods , kwargs ):
@@ -360,7 +363,7 @@ def _verify_hook(self, hook, hookimpl):
360363 (hookimpl .plugin_name , hook .name ))
361364
362365 # positional arg checking
363- notinspec = set (hookimpl .argnames ) - set (hook .argnames )
366+ notinspec = set (hookimpl .argnames ) - set (hook .spec . argnames )
364367 if notinspec :
365368 raise PluginValidationError (
366369 "Plugin %r for hook %r\n hookimpl definition: %s\n "
@@ -453,8 +456,8 @@ def subset_hook_caller(self, name, remove_plugins):
453456 orig = getattr (self .hook , name )
454457 plugins_to_remove = [plug for plug in remove_plugins if hasattr (plug , name )]
455458 if plugins_to_remove :
456- hc = _HookCaller (orig .name , orig ._hookexec , orig ._specmodule_or_class ,
457- orig .spec_opts )
459+ hc = _HookCaller (orig .name , orig ._hookexec , orig .spec . namespace ,
460+ orig .spec . opts )
458461 for hookimpl in (orig ._wrappers + orig ._nonwrappers ):
459462 plugin = hookimpl .plugin
460463 if plugin not in plugins_to_remove :
@@ -536,26 +539,23 @@ def __init__(self, name, hook_execute, specmodule_or_class=None, spec_opts=None)
536539 self .argnames = None
537540 self .kwargnames = None
538541 self .multicall = _multicall
542+ self .spec = None
543+ self ._call_history = None
539544 if specmodule_or_class is not None :
540545 assert spec_opts is not None
541546 self .set_specification (specmodule_or_class , spec_opts )
542547
543548 def has_spec (self ):
544- return hasattr ( self , "_specmodule_or_class" )
549+ return self . spec is not None
545550
546551 def set_specification (self , specmodule_or_class , spec_opts ):
547552 assert not self .has_spec ()
548- self ._specmodule_or_class = specmodule_or_class
549- specfunc = getattr (specmodule_or_class , self .name )
550- # get spec arg signature
551- argnames , self .kwargnames = varnames (specfunc )
552- self .argnames = ["__multicall__" ] + list (argnames )
553- self .spec_opts = spec_opts
553+ self .spec = HookSpec (specmodule_or_class , self .name , spec_opts )
554554 if spec_opts .get ("historic" ):
555555 self ._call_history = []
556556
557557 def is_historic (self ):
558- return hasattr ( self , " _call_history" )
558+ return self . _call_history is not None
559559
560560 def _remove_plugin (self , plugin ):
561561 def remove (wrappers ):
@@ -601,8 +601,8 @@ def __call__(self, *args, **kwargs):
601601 if args :
602602 raise TypeError ("hook calling supports only keyword arguments" )
603603 assert not self .is_historic ()
604- if self .argnames :
605- notincall = set (self .argnames ) - set (['__multicall__' ]) - set (
604+ if self .spec :
605+ notincall = set (self .spec . argnames ) - set (['__multicall__' ]) - set (
606606 kwargs .keys ())
607607 if notincall :
608608 warnings .warn (
@@ -649,6 +649,16 @@ def _maybe_apply_history(self, method):
649649 proc (res [0 ])
650650
651651
652+ class HookSpec (object ):
653+ def __init__ (self , namespace , name , opts ):
654+ self .namespace = namespace
655+ self .function = function = getattr (namespace , name )
656+ self .name = name
657+ self .argnames , self .kwargnames = varnames (function )
658+ self .opts = opts
659+ self .argnames = ["__multicall__" ] + list (self .argnames )
660+
661+
652662class HookImpl (object ):
653663 def __init__ (self , plugin , plugin_name , function , hook_impl_opts ):
654664 self .function = function
0 commit comments