From 7bf0af7a588911984236e29b097dc967c9c74eeb Mon Sep 17 00:00:00 2001 From: Pablo Hoffman Date: Tue, 4 Sep 2012 19:00:32 -0300 Subject: [PATCH] fixed some bugs in get_func_args() and added more test cases --- scrapy/tests/test_utils_python.py | 5 +++++ scrapy/utils/python.py | 18 +++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/scrapy/tests/test_utils_python.py b/scrapy/tests/test_utils_python.py index e97833195..0e28a28e4 100644 --- a/scrapy/tests/test_utils_python.py +++ b/scrapy/tests/test_utils_python.py @@ -181,6 +181,11 @@ class UtilsPythonTestCase(unittest.TestCase): self.assertEqual(get_func_args(A), ['a', 'b', 'c']) self.assertEqual(get_func_args(a.method), ['a', 'b', 'c']) self.assertEqual(get_func_args(cal), ['a', 'b', 'c']) + self.assertEqual(get_func_args(object), []) + + # TODO: how do we fix this to return the actual argument names? + self.assertEqual(get_func_args(unicode.split), []) + self.assertEqual(get_func_args(" ".join), []) if __name__ == "__main__": unittest.main() diff --git a/scrapy/utils/python.py b/scrapy/utils/python.py index 64577415f..aff8720ae 100644 --- a/scrapy/utils/python.py +++ b/scrapy/utils/python.py @@ -146,21 +146,25 @@ def isbinarytext(text): assert isinstance(text, str), "text must be str, got '%s'" % type(text).__name__ return any(c in _BINARYCHARS for c in text) -def get_func_args(func): +def get_func_args(func, stripself=False): """Return the argument name list of a callable""" if inspect.isfunction(func): func_args, _, _, _ = inspect.getargspec(func) elif inspect.isclass(func): - func_args, _, _, _ = inspect.getargspec(func.__init__) - func_args.pop(0) # self + return get_func_args(func.__init__, True) elif inspect.ismethod(func): - func_args, _, _, _ = inspect.getargspec(func.__func__) - func_args.pop(0) # self + return get_func_args(func.__func__, True) + elif inspect.ismethoddescriptor(func): + return [] elif hasattr(func, '__call__'): - func_args, _, _, _ = inspect.getargspec(func.__call__) - func_args.pop(0) # self + if inspect.isroutine(func): + return [] + else: + return get_func_args(func.__call__, True) else: raise TypeError('%s is not callable' % type(func)) + if stripself: + func_args.pop(0) # self return func_args def equal_attributes(obj1, obj2, attributes):