@@ -627,50 +627,51 @@ def __repr__(self):
627
627
return "<_MultiCall %s, kwargs=%r>" % (status , self .kwargs )
628
628
629
629
630
- def varnames (func , startindex = None ):
631
- """ return argument name tuple for a function, method, class or callable.
630
+ def varnames (func ):
631
+ """Return argument name tuple for a function, method, class or callable.
632
632
633
633
In case of a class, its "__init__" method is considered.
634
634
For methods the "self" parameter is not included unless you are passing
635
- an unbound method with Python3 (which has no supports for unbound methods)
635
+ an unbound method with Python3 (which has no support for unbound methods)
636
636
"""
637
637
cache = getattr (func , "__dict__" , {})
638
638
try :
639
639
return cache ["_varnames" ]
640
640
except KeyError :
641
641
pass
642
+
642
643
if inspect .isclass (func ):
643
644
try :
644
645
func = func .__init__
645
646
except AttributeError :
646
647
return ()
647
- startindex = 1
648
- else :
649
- if not inspect .isfunction (func ) and not inspect .ismethod (func ):
650
- try :
651
- func = getattr (func , '__call__' , func )
652
- except Exception :
653
- return ()
654
- if startindex is None :
655
- startindex = int (inspect .ismethod (func ))
648
+ elif not inspect .isroutine (func ): # callable object?
649
+ try :
650
+ func = getattr (func , '__call__' , func )
651
+ except Exception :
652
+ return ()
656
653
657
- try :
658
- rawcode = func . __code__
659
- except AttributeError :
654
+ try : # func MUST be a function or method here or we won't parse any args
655
+ spec = inspect . getargspec ( func )
656
+ except TypeError :
660
657
return ()
658
+
659
+ args , defaults = spec .args , spec .defaults
660
+ args = args [:- len (defaults )] if defaults else args
661
+
662
+ # strip any implicit instance arg
663
+ if args :
664
+ if inspect .ismethod (func ) or (
665
+ '.' in getattr (func , '__qualname__' , ()) and args [0 ] == 'self'
666
+ ):
667
+ args = args [1 :]
668
+
669
+ assert "self" not in args # best naming practises check?
661
670
try :
662
- x = rawcode .co_varnames [startindex :rawcode .co_argcount ]
663
- except AttributeError :
664
- x = ()
665
- else :
666
- defaults = func .__defaults__
667
- if defaults :
668
- x = x [:- len (defaults )]
669
- try :
670
- cache ["_varnames" ] = x
671
+ cache ["_varnames" ] = args
671
672
except TypeError :
672
673
pass
673
- return x
674
+ return tuple ( args )
674
675
675
676
676
677
class _HookRelay :
@@ -700,8 +701,7 @@ def set_specification(self, specmodule_or_class, spec_opts):
700
701
assert not self .has_spec ()
701
702
self ._specmodule_or_class = specmodule_or_class
702
703
specfunc = getattr (specmodule_or_class , self .name )
703
- argnames = varnames (specfunc , startindex = inspect .isclass (specmodule_or_class ))
704
- assert "self" not in argnames # sanity check
704
+ argnames = varnames (specfunc )
705
705
self .argnames = ["__multicall__" ] + list (argnames )
706
706
self .spec_opts = spec_opts
707
707
if spec_opts .get ("historic" ):
0 commit comments