import collections import inspect FullArgSpec = collections.namedtuple( "FullArgSpec", [ "args", "varargs", "varkw", "defaults", "kwonlyargs", "kwonlydefaults", "annotations", ], ) ArgSpec = collections.namedtuple( "ArgSpec", ["args", "varargs", "keywords", "defaults"] ) def inspect_getfullargspec(func): """Fully vendored version of getfullargspec from Python 3.3. This version is more performant than the one which appeared in later Python 3 versions. """ # if a Signature is already present, as is the case with newer # "decorator" package, defer back to built in if hasattr(func, "__signature__"): return inspect.getfullargspec(func) if inspect.ismethod(func): func = func.__func__ if not inspect.isfunction(func): raise TypeError("{!r} is not a Python function".format(func)) co = func.__code__ if not inspect.iscode(co): raise TypeError("{!r} is not a code object".format(co)) nargs = co.co_argcount names = co.co_varnames nkwargs = co.co_kwonlyargcount args = list(names[:nargs]) kwonlyargs = list(names[nargs : nargs + nkwargs]) nargs += nkwargs varargs = None if co.co_flags & inspect.CO_VARARGS: varargs = co.co_varnames[nargs] nargs = nargs + 1 varkw = None if co.co_flags & inspect.CO_VARKEYWORDS: varkw = co.co_varnames[nargs] return FullArgSpec( args, varargs, varkw, func.__defaults__, kwonlyargs, func.__kwdefaults__, func.__annotations__, ) def inspect_getargspec(func): return ArgSpec(*inspect_getfullargspec(func)[0:4])