def getargspec(func):
"""Variation of inspect.getargspec that works for more functions.
This function works for Cythonized, non-cpdef functions, which expose argspec information but
are not accepted by getargspec. It also works for Python 3 functions that use annotations, which
are simply ignored. However, keyword-only arguments are not supported.
"""
if inspect.ismethod(func):
func = func.__func__
# Cythonized functions have a .__code__, but don't pass inspect.isfunction()
try:
code = func.__code__
except AttributeError:
raise TypeError('{!r} is not a Python function'.format(func))
if hasattr(code, 'co_kwonlyargcount') and code.co_kwonlyargcount > 0:
raise ValueError('keyword-only arguments are not supported by getargspec()')
args, varargs, varkw = inspect.getargs(code)
return inspect.ArgSpec(args, varargs, varkw, func.__defaults__)
python类getargs()的实例源码
def _get_argspec(func):
"""Returns an inspect.ArgSpec instance given a function object.
We prefer this implementation rather than the inspect module's getargspec
since the latter has a strict check that the passed function is an instance
of FunctionType. Cython functions do not pass this check, but they do implement
the `func_code` and `func_defaults` attributes that we need to produce an Argspec.
This implementation re-uses much of inspect.getargspec but removes the strict
check allowing interface failures to be raised as AttributeError.
See Also:
https://github.com/python/cpython/blob/2.7/Lib/inspect.py
"""
if inspect.ismethod(func):
func = func.im_func
args, varargs, varkw = inspect.getargs(func.func_code)
return inspect.ArgSpec(args, varargs, varkw, func.func_defaults)
def with_patch_inspect(f):
"""
Deprecated since IPython 6.0
decorator for monkeypatching inspect.findsource
"""
def wrapped(*args, **kwargs):
save_findsource = inspect.findsource
save_getargs = inspect.getargs
inspect.findsource = findsource
inspect.getargs = getargs
try:
return f(*args, **kwargs)
finally:
inspect.findsource = save_findsource
inspect.getargs = save_getargs
return wrapped
def getargspec(obj):
"""Get the names and default values of a function's arguments.
A tuple of four things is returned: (args, varargs, varkw, defaults).
'args' is a list of the argument names (it may contain nested lists).
'varargs' and 'varkw' are the names of the * and ** arguments or None.
'defaults' is an n-tuple of the default values of the last n arguments.
Modified version of inspect.getargspec from the Python Standard
Library."""
if inspect.isfunction(obj):
func_obj = obj
elif inspect.ismethod(obj):
func_obj = obj.__func__
else:
raise TypeError('arg is not a Python function')
args, varargs, varkw = inspect.getargs(func_obj.__code__)
return args, varargs, varkw, func_obj.__defaults__
#-----------------------------------------------------------------------------
# Testing functions
def run(self):
"""Call the specific method
"""
command = getattr(self, self.command)
try:
func_code = command.func_code
except AttributeError:
# Renamed in Python 3
func_code = command.__code__
kwargs = {}
for argument, value in self.data.items():
if argument in inspect.getargs(func_code).args:
kwargs[argument] = value
command(**kwargs)
def getargspec(obj):
"""Get the names and default values of a function's arguments.
A tuple of four things is returned: (args, varargs, varkw, defaults).
'args' is a list of the argument names (it may contain nested lists).
'varargs' and 'varkw' are the names of the * and ** arguments or None.
'defaults' is an n-tuple of the default values of the last n arguments.
Modified version of inspect.getargspec from the Python Standard
Library."""
if inspect.isfunction(obj):
func_obj = obj
elif inspect.ismethod(obj):
func_obj = obj.__func__
else:
raise TypeError('arg is not a Python function')
args, varargs, varkw = inspect.getargs(func_obj.__code__)
return args, varargs, varkw, func_obj.__defaults__
#-----------------------------------------------------------------------------
# Testing functions
def getargspec(obj):
"""Get the names and default values of a function's arguments.
A tuple of four things is returned: (args, varargs, varkw, defaults).
'args' is a list of the argument names (it may contain nested lists).
'varargs' and 'varkw' are the names of the * and ** arguments or None.
'defaults' is an n-tuple of the default values of the last n arguments.
Modified version of inspect.getargspec from the Python Standard
Library."""
if inspect.isfunction(obj):
func_obj = obj
elif inspect.ismethod(obj):
func_obj = obj.__func__
else:
raise TypeError('arg is not a Python function')
args, varargs, varkw = inspect.getargs(func_obj.__code__)
return args, varargs, varkw, func_obj.__defaults__
#-----------------------------------------------------------------------------
# Testing functions
def with_patch_inspect(f):
"""
Deprecated since IPython 6.0
decorator for monkeypatching inspect.findsource
"""
def wrapped(*args, **kwargs):
save_findsource = inspect.findsource
save_getargs = inspect.getargs
inspect.findsource = findsource
inspect.getargs = getargs
try:
return f(*args, **kwargs)
finally:
inspect.findsource = save_findsource
inspect.getargs = save_getargs
return wrapped
def getargspec(obj):
"""Get the names and default values of a function's arguments.
A tuple of four things is returned: (args, varargs, varkw, defaults).
'args' is a list of the argument names (it may contain nested lists).
'varargs' and 'varkw' are the names of the * and ** arguments or None.
'defaults' is an n-tuple of the default values of the last n arguments.
Modified version of inspect.getargspec from the Python Standard
Library."""
if inspect.isfunction(obj):
func_obj = obj
elif inspect.ismethod(obj):
func_obj = obj.__func__
else:
raise TypeError('arg is not a Python function')
args, varargs, varkw = inspect.getargs(func_obj.__code__)
return args, varargs, varkw, func_obj.__defaults__
#-----------------------------------------------------------------------------
# Testing functions
def getfuncargnames(function, startindex=None):
# XXX merge with main.py's varnames
#assert not isclass(function)
realfunction = function
while hasattr(realfunction, "__wrapped__"):
realfunction = realfunction.__wrapped__
if startindex is None:
startindex = inspect.ismethod(function) and 1 or 0
if realfunction != function:
startindex += num_mock_patch_args(function)
function = realfunction
if isinstance(function, functools.partial):
argnames = inspect.getargs(_pytest._code.getrawcode(function.func))[0]
partial = function
argnames = argnames[len(partial.args):]
if partial.keywords:
for kw in partial.keywords:
argnames.remove(kw)
else:
argnames = inspect.getargs(_pytest._code.getrawcode(function))[0]
defaults = getattr(function, 'func_defaults',
getattr(function, '__defaults__', None)) or ()
numdefaults = len(defaults)
if numdefaults:
return tuple(argnames[startindex:-numdefaults])
return tuple(argnames[startindex:])
def dump_create_instance(self, typename, code, init_args):
args, varargs, kwargs = inspect.getargs(code)
params = ', '.join(
[repr(init_args[arg]) for arg in args[1:]] +
[repr(arg) for arg in init_args.get(varargs, [])] +
['%s=%s' % (k, repr(v)) for k, v in init_args.get(kwargs, {})]
)
self.output_.append(indent(2) + '%s_instance = %s(%s)' % (
typename.lower(),
typename,
params
))
def getmethparlist(ob):
"""Get strings describing the arguments for the given object
Returns a pair of strings representing function parameter lists
including parenthesis. The first string is suitable for use in
function definition and the second is suitable for use in function
call. The "self" parameter is not included.
"""
defText = callText = ""
# bit of a hack for methods - turn it into a function
# but we drop the "self" param.
# Try and build one for Python defined functions
args, varargs, varkw = inspect.getargs(ob.__code__)
items2 = args[1:]
realArgs = args[1:]
defaults = ob.__defaults__ or []
defaults = ["=%r" % (value,) for value in defaults]
defaults = [""] * (len(realArgs)-len(defaults)) + defaults
items1 = [arg + dflt for arg, dflt in zip(realArgs, defaults)]
if varargs is not None:
items1.append("*" + varargs)
items2.append("*" + varargs)
if varkw is not None:
items1.append("**" + varkw)
items2.append("**" + varkw)
defText = ", ".join(items1)
defText = "(%s)" % defText
callText = ", ".join(items2)
callText = "(%s)" % callText
return defText, callText
def getmethparlist(ob):
"""Get strings describing the arguments for the given object
Returns a pair of strings representing function parameter lists
including parenthesis. The first string is suitable for use in
function definition and the second is suitable for use in function
call. The "self" parameter is not included.
"""
defText = callText = ""
# bit of a hack for methods - turn it into a function
# but we drop the "self" param.
# Try and build one for Python defined functions
args, varargs, varkw = inspect.getargs(ob.__code__)
items2 = args[1:]
realArgs = args[1:]
defaults = ob.__defaults__ or []
defaults = ["=%r" % (value,) for value in defaults]
defaults = [""] * (len(realArgs)-len(defaults)) + defaults
items1 = [arg + dflt for arg, dflt in zip(realArgs, defaults)]
if varargs is not None:
items1.append("*" + varargs)
items2.append("*" + varargs)
if varkw is not None:
items1.append("**" + varkw)
items2.append("**" + varkw)
defText = ", ".join(items1)
defText = "(%s)" % defText
callText = ", ".join(items2)
callText = "(%s)" % callText
return defText, callText
def getargspec(func):
"""Like inspect.getargspec but supports functools.partial as well."""
if inspect.ismethod(func):
func = func.__func__
parts = 0, ()
if type(func) is partial:
keywords = func.keywords
if keywords is None:
keywords = {}
parts = len(func.args), keywords.keys()
func = func.func
if not inspect.isfunction(func):
raise TypeError('%r is not a Python function' % func)
args, varargs, varkw = inspect.getargs(func.__code__)
func_defaults = func.__defaults__
if func_defaults is None:
func_defaults = []
else:
func_defaults = list(func_defaults)
if parts[0]:
args = args[parts[0]:]
if parts[1]:
for arg in parts[1]:
i = args.index(arg) - len(args)
del args[i]
try:
del func_defaults[i]
except IndexError:
pass
return inspect.ArgSpec(args, varargs, varkw, func_defaults)
def getmethparlist(ob):
"""Get strings describing the arguments for the given object
Returns a pair of strings representing function parameter lists
including parenthesis. The first string is suitable for use in
function definition and the second is suitable for use in function
call. The "self" parameter is not included.
"""
defText = callText = ""
# bit of a hack for methods - turn it into a function
# but we drop the "self" param.
# Try and build one for Python defined functions
args, varargs, varkw = inspect.getargs(ob.__code__)
items2 = args[1:]
realArgs = args[1:]
defaults = ob.__defaults__ or []
defaults = ["=%r" % (value,) for value in defaults]
defaults = [""] * (len(realArgs)-len(defaults)) + defaults
items1 = [arg + dflt for arg, dflt in zip(realArgs, defaults)]
if varargs is not None:
items1.append("*" + varargs)
items2.append("*" + varargs)
if varkw is not None:
items1.append("**" + varkw)
items2.append("**" + varkw)
defText = ", ".join(items1)
defText = "(%s)" % defText
callText = ", ".join(items2)
callText = "(%s)" % callText
return defText, callText
def argnames(self):
return inspect.getargs(self.func.__code__)[0]
def from_code(cls, code, copy_lineno=False):
import inspect
self = cls.from_spec(code.co_name, *inspect.getargs(code))
if copy_lineno:
self.set_lineno(code.co_firstlineno)
self.co_filename = code.co_filename
self.co_freevars = code.co_freevars # XXX untested!
return self
def getfuncargnames(function, startindex=None):
# XXX merge with main.py's varnames
#assert not isclass(function)
realfunction = function
while hasattr(realfunction, "__wrapped__"):
realfunction = realfunction.__wrapped__
if startindex is None:
startindex = inspect.ismethod(function) and 1 or 0
if realfunction != function:
startindex += num_mock_patch_args(function)
function = realfunction
if isinstance(function, functools.partial):
argnames = inspect.getargs(_pytest._code.getrawcode(function.func))[0]
partial = function
argnames = argnames[len(partial.args):]
if partial.keywords:
for kw in partial.keywords:
argnames.remove(kw)
else:
argnames = inspect.getargs(_pytest._code.getrawcode(function))[0]
defaults = getattr(function, 'func_defaults',
getattr(function, '__defaults__', None)) or ()
numdefaults = len(defaults)
if numdefaults:
return tuple(argnames[startindex:-numdefaults])
return tuple(argnames[startindex:])
def get_open_params(cls):
"""
Returns the params for the cls.open() class method. Feel free to overwrite this in a sub-class if this default
implementation doesn't fit your protocol's needs.
:return: A list of parameter names
:rtype: list
"""
# get the arguments
# (don't use argspec because it is needlesly strict and fails on perfectly valid Cython functions)
args, varargs, varkw = inspect.getargs(cls.open.func_code)
return args[2:] # remove 'cls' and 'broker'
def getargspec_permissive(func):
"""
An `inspect.getargspec` with a relaxed sanity check to support Cython.
Motivation:
A Cython-compiled function is *not* an instance of Python's
types.FunctionType. That is the sanity check the standard Py2
library uses in `inspect.getargspec()`. So, an exception is raised
when calling `argh.dispatch_command(cythonCompiledFunc)`. However,
the CyFunctions do have perfectly usable `.func_code` and
`.func_defaults` which is all `inspect.getargspec` needs.
This function just copies `inspect.getargspec()` from the standard
library but relaxes the test to a more duck-typing one of having
both `.func_code` and `.func_defaults` attributes.
"""
if inspect.ismethod(func):
func = func.im_func
# Py2 Stdlib uses isfunction(func) which is too strict for Cython-compiled
# functions though such have perfectly usable func_code, func_defaults.
if not (hasattr(func, "func_code") and hasattr(func, "func_defaults")):
raise TypeError('{!r} missing func_code or func_defaults'.format(func))
args, varargs, varkw = inspect.getargs(func.func_code)
return inspect.ArgSpec(args, varargs, varkw, func.func_defaults)
def getfuncargnames(function, startindex=None):
# XXX merge with main.py's varnames
#assert not isclass(function)
realfunction = function
while hasattr(realfunction, "__wrapped__"):
realfunction = realfunction.__wrapped__
if startindex is None:
startindex = inspect.ismethod(function) and 1 or 0
if realfunction != function:
startindex += num_mock_patch_args(function)
function = realfunction
if isinstance(function, functools.partial):
argnames = inspect.getargs(_pytest._code.getrawcode(function.func))[0]
partial = function
argnames = argnames[len(partial.args):]
if partial.keywords:
for kw in partial.keywords:
argnames.remove(kw)
else:
argnames = inspect.getargs(_pytest._code.getrawcode(function))[0]
defaults = getattr(function, 'func_defaults',
getattr(function, '__defaults__', None)) or ()
numdefaults = len(defaults)
if numdefaults:
return tuple(argnames[startindex:-numdefaults])
return tuple(argnames[startindex:])
def getfuncargnames(function, startindex=None):
# XXX merge with main.py's varnames
#assert not isclass(function)
realfunction = function
while hasattr(realfunction, "__wrapped__"):
realfunction = realfunction.__wrapped__
if startindex is None:
startindex = inspect.ismethod(function) and 1 or 0
if realfunction != function:
startindex += num_mock_patch_args(function)
function = realfunction
if isinstance(function, functools.partial):
argnames = inspect.getargs(_pytest._code.getrawcode(function.func))[0]
partial = function
argnames = argnames[len(partial.args):]
if partial.keywords:
for kw in partial.keywords:
argnames.remove(kw)
else:
argnames = inspect.getargs(_pytest._code.getrawcode(function))[0]
defaults = getattr(function, 'func_defaults',
getattr(function, '__defaults__', None)) or ()
numdefaults = len(defaults)
if numdefaults:
return tuple(argnames[startindex:-numdefaults])
return tuple(argnames[startindex:])
def _repr(self,I=None):
'''return a repr style string with named fixed args first, then keywords'''
if isinstance(self,float):
return fp_str(self)
elif isSeq(self):
s = ''
for v in self:
s = s + '%s,' % _repr(v,I)
if isinstance(self,list):
return '[%s]' % s[:-1]
else:
return '(%s%s)' % (s[:-1],len(self)==1 and ',' or '')
elif self is EmptyClipPath:
if I: _addObjImport(self,I,'EmptyClipPath')
return 'EmptyClipPath'
elif isinstance(self,Shape):
if I: _addObjImport(self,I)
from inspect import getargs
args, varargs, varkw = getargs(self.__init__.__func__.__code__)
P = self.getProperties()
s = self.__class__.__name__+'('
for n in args[1:]:
v = P[n]
del P[n]
s = s + '%s,' % _repr(v,I)
for n,v in P.items():
v = P[n]
s = s + '%s=%s,' % (n, _repr(v,I))
return s[:-1]+')'
else:
return repr(self)
def getargspec(func):
"""Like inspect.getargspec but supports functools.partial as well."""
if inspect.ismethod(func):
func = func.__func__
parts = 0, ()
if type(func) is partial:
keywords = func.keywords
if keywords is None:
keywords = {}
parts = len(func.args), keywords.keys()
func = func.func
if not inspect.isfunction(func):
raise TypeError('%r is not a Python function' % func)
args, varargs, varkw = inspect.getargs(func.__code__)
func_defaults = func.__defaults__
if func_defaults is None:
func_defaults = []
else:
func_defaults = list(func_defaults)
if parts[0]:
args = args[parts[0]:]
if parts[1]:
for arg in parts[1]:
i = args.index(arg) - len(args)
del args[i]
try:
del func_defaults[i]
except IndexError:
pass
return inspect.ArgSpec(args, varargs, varkw, func_defaults)
def with_patch_inspect(f):
"""decorator for monkeypatching inspect.findsource"""
def wrapped(*args, **kwargs):
save_findsource = inspect.findsource
save_getargs = inspect.getargs
inspect.findsource = findsource
inspect.getargs = getargs
try:
return f(*args, **kwargs)
finally:
inspect.findsource = save_findsource
inspect.getargs = save_getargs
return wrapped
def getmethparlist(ob):
"""Get strings describing the arguments for the given object
Returns a pair of strings representing function parameter lists
including parenthesis. The first string is suitable for use in
function definition and the second is suitable for use in function
call. The "self" parameter is not included.
"""
defText = callText = ""
# bit of a hack for methods - turn it into a function
# but we drop the "self" param.
# Try and build one for Python defined functions
args, varargs, varkw = inspect.getargs(ob.__code__)
items2 = args[1:]
realArgs = args[1:]
defaults = ob.__defaults__ or []
defaults = ["=%r" % (value,) for value in defaults]
defaults = [""] * (len(realArgs)-len(defaults)) + defaults
items1 = [arg + dflt for arg, dflt in zip(realArgs, defaults)]
if varargs is not None:
items1.append("*" + varargs)
items2.append("*" + varargs)
if varkw is not None:
items1.append("**" + varkw)
items2.append("**" + varkw)
defText = ", ".join(items1)
defText = "(%s)" % defText
callText = ", ".join(items2)
callText = "(%s)" % callText
return defText, callText
def __new__(cls, cls_name, cls_parents, cls_dict):
ret = super(NoninstantiableMeta,cls).__new__(cls, cls_name, cls_parents, cls_dict)
for name in dir(ret):
value = getattr(ret, name)
if isinstance(value, MethodType):
if not getattr(ret, '_allow_self_as_first_arg', False) and 'self' in inspect.getargs(value.func_code).args[:1]:
warn_message = SELF_WARN_MESSAGE % {'cls': cls_name, 'method': name}
warnings.warn(warn_message, SyntaxWarning)
new_method = classmethod(value.im_func)
setattr(ret, name, new_method) # turn all methods to classmethods
ret.__init__ = classmethod(cls._prevent_instantiating) # You shall not pass!
return ret
def __new__(cls, cls_name, cls_parents, cls_dict):
ret = super(NoninstantiableMeta,cls).__new__(cls, cls_name, cls_parents, cls_dict)
for name in dir(ret):
value = getattr(ret, name)
if isinstance(value, MethodType):
if not getattr(ret, '_allow_self_as_first_arg', False) and 'self' in inspect.getargs(value.func_code).args[:1]:
warn_message = SELF_WARN_MESSAGE % {'cls': cls_name, 'method': name}
warnings.warn(warn_message, SyntaxWarning)
new_method = classmethod(value.im_func)
setattr(ret, name, new_method) # turn all methods to classmethods
ret.__init__ = classmethod(cls._prevent_instantiating) # You shall not pass!
return ret
def __new__(cls, cls_name, cls_parents, cls_dict):
ret = super(NoninstantiableMeta,cls).__new__(cls, cls_name, cls_parents, cls_dict)
for name in dir(ret):
value = getattr(ret, name)
if isinstance(value, MethodType):
if not getattr(ret, '_allow_self_as_first_arg', False) and 'self' in inspect.getargs(value.func_code).args[:1]:
warn_message = SELF_WARN_MESSAGE % {'cls': cls_name, 'method': name}
warnings.warn(warn_message, SyntaxWarning)
new_method = classmethod(value.im_func)
setattr(ret, name, new_method) # turn all methods to classmethods
ret.__init__ = classmethod(cls._prevent_instantiating) # You shall not pass!
return ret
def assertApplicationEqual(self, app1, app2, msg=None):
args = _inspect.getargs(ABCApplication.__init__.__code__).args[1:]
for arg in args:
if arg == 'id':
# Skip the id because our comparison objects may not have them.
continue
if getattr(app1, arg) != getattr(app2, arg):
raise self.failureException(msg)