diff --git a/scrapy/tests/test_utils_python.py b/scrapy/tests/test_utils_python.py
index ca73bc5ac..9122cf1be 100644
--- a/scrapy/tests/test_utils_python.py
+++ b/scrapy/tests/test_utils_python.py
@@ -65,7 +65,7 @@ class UtilsPythonTestCase(unittest.TestCase):
assert not isbinarytext("hello")
# utf-16 strings contain null bytes
- assert not isbinarytext(u"hello".encode('utf-16'))
+ assert not isbinarytext(u"hello".encode('utf-16'))
# one with encoding
assert not isbinarytext("
Price \xa3
")
@@ -175,14 +175,18 @@ class UtilsPythonTestCase(unittest.TestCase):
pass
a = A(1, 2, 3)
- partial_f1 = functools.partial(f1, None)
cal = Callable()
+ partial_f1 = functools.partial(f1, None)
+ partial_f2 = functools.partial(f1, b=None)
+ partial_f3 = functools.partial(partial_f2, None)
self.assertEqual(get_func_args(f1), ['a', 'b', 'c'])
self.assertEqual(get_func_args(f2), ['a', 'b', 'c'])
self.assertEqual(get_func_args(A), ['a', 'b', 'c'])
self.assertEqual(get_func_args(a.method), ['a', 'b', 'c'])
- self.assertEqual(get_func_args(partial_f1), ['a', 'b', 'c'])
+ self.assertEqual(get_func_args(partial_f1), ['b', 'c'])
+ self.assertEqual(get_func_args(partial_f2), ['a', 'c'])
+ self.assertEqual(get_func_args(partial_f3), ['c'])
self.assertEqual(get_func_args(cal), ['a', 'b', 'c'])
self.assertEqual(get_func_args(object), [])
diff --git a/scrapy/utils/python.py b/scrapy/utils/python.py
index 454f5a59f..566b50f17 100644
--- a/scrapy/utils/python.py
+++ b/scrapy/utils/python.py
@@ -157,7 +157,8 @@ def get_func_args(func, stripself=False):
elif inspect.ismethoddescriptor(func):
return []
elif isinstance(func, partial):
- return get_func_args(func.func)
+ 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 []