73 lines
2.1 KiB
Python
73 lines
2.1 KiB
Python
"""
|
|
Copy/paste from scrapy source at the moment, to ensure tests are working.
|
|
Refactoring to come later
|
|
"""
|
|
import inspect
|
|
from functools import partial
|
|
|
|
from itemadapter import is_item
|
|
|
|
|
|
_ITERABLE_SINGLE_VALUES = str, bytes
|
|
|
|
|
|
def arg_to_iter(arg):
|
|
"""Convert an argument to an iterable. The argument can be a None, single
|
|
value, or an iterable.
|
|
|
|
Exception: if arg is a dict, [arg] will be returned
|
|
"""
|
|
if arg is None:
|
|
return []
|
|
elif (
|
|
hasattr(arg, '__iter__')
|
|
and not isinstance(arg, _ITERABLE_SINGLE_VALUES)
|
|
and not is_item(arg)
|
|
):
|
|
return arg
|
|
else:
|
|
return [arg]
|
|
|
|
|
|
def get_func_args(func, stripself=False):
|
|
"""Return the argument name list of a callable"""
|
|
if inspect.isfunction(func):
|
|
func_args, _, _, _ = _getargspec_py23(func)
|
|
elif inspect.isclass(func):
|
|
return get_func_args(func.__init__, True)
|
|
elif inspect.ismethod(func):
|
|
return get_func_args(func.__func__, True)
|
|
elif inspect.ismethoddescriptor(func):
|
|
return []
|
|
elif isinstance(func, partial):
|
|
return [x for x in get_func_args(func.func)[len(func.args):]
|
|
if not (func.keywords and x in func.keywords)]
|
|
elif hasattr(func, '__call__'):
|
|
if inspect.isroutine(func):
|
|
return []
|
|
elif getattr(func, '__name__', None) == '__call__':
|
|
return []
|
|
else:
|
|
return get_func_args(func.__call__, True)
|
|
else:
|
|
raise TypeError('%s is not callable' % type(func))
|
|
if stripself:
|
|
func_args.pop(0)
|
|
return func_args
|
|
|
|
|
|
def _getargspec_py23(func):
|
|
"""_getargspec_py23(function) -> named tuple ArgSpec(args, varargs, keywords,
|
|
defaults)
|
|
|
|
Was identical to inspect.getargspec() in python2, but uses
|
|
inspect.getfullargspec() for python3 behind the scenes to avoid
|
|
DeprecationWarning.
|
|
|
|
>>> def f(a, b=2, *ar, **kw):
|
|
... pass
|
|
|
|
>>> _getargspec_py23(f)
|
|
ArgSpec(args=['a', 'b'], varargs='ar', keywords='kw', defaults=(2,))
|
|
"""
|
|
return inspect.ArgSpec(*inspect.getfullargspec(func)[:4])
|