Преглед на файлове

Tasks: Fixes type checking for function with kwargs and kwonlyargs. Closes #3678

Ask Solem преди 8 години
родител
ревизия
a260de094b
променени са 2 файла, в които са добавени 21 реда и са изтрити 13 реда
  1. 5 3
      celery/utils/functional.py
  2. 16 10
      t/unit/utils/test_functional.py

+ 5 - 3
celery/utils/functional.py

@@ -235,6 +235,8 @@ def _argsfromspec(spec, replace_defaults=True):
     else:
         positional, optional = spec.args, []
 
+    varargs = spec.varargs
+    varkw = spec.varkw
     if spec.kwonlydefaults:
         split = len(spec.kwonlydefaults)
         kwonlyargs = spec.kwonlyargs[:-split]
@@ -249,9 +251,9 @@ def _argsfromspec(spec, replace_defaults=True):
     return ', '.join(filter(None, [
         ', '.join(positional),
         ', '.join('{0}={1}'.format(k, v) for k, v in optional),
-        '*{0}'.format(spec.varargs) if spec.varargs else None,
-        '**{0}'.format(spec.varkw) if spec.varkw else None,
-        '*' if kwonlyargs or kwonlyargs_optional else None,
+        '*{0}'.format(varargs) if varargs else None,
+        '**{0}'.format(varkw) if varkw else None,
+        '*' if (kwonlyargs or kwonlyargs_optional) and not varargs else None,
         ', '.join(kwonlyargs) if kwonlyargs else None,
         ', '.join('{0}="{1}"'.format(k, v) for k, v in kwonlyargs_optional),
     ]))

+ 16 - 10
t/unit/utils/test_functional.py

@@ -162,15 +162,25 @@ class test_head_from_fun:
         g(1, 2)
         g(1, 2, kwarg=3)
 
+    @skip.unless_python3()
+    def test_regression_3678(self):
+        local = {}
+        fun = ('def f(foo, *args, bar=""):'
+               '    return foo, args, bar')
+        exec(fun, {}, local)
+
+        g = head_from_fun(local['f'])
+        g(1)
+        g(1, 2, 3, 4, bar=100)
+        with pytest.raises(TypeError):
+            g(bar=100)
+
+    @skip.unless_python3()
     def test_from_fun_with_hints(self):
         local = {}
         fun = ('def f_hints(x: int, y: int, kwarg: int=1):'
                '    pass')
-        try:
-            exec(fun, {}, local)
-        except SyntaxError:
-            # py2
-            return
+        exec(fun, {}, local)
         f_hints = local['f_hints']
 
         g = head_from_fun(f_hints)
@@ -184,11 +194,7 @@ class test_head_from_fun:
         local = {}
         fun = ('def f_kwargs(*, a, b="b", c=None):'
                '    return')
-        try:
-            exec(fun, {}, local)
-        except SyntaxError:
-            # Python 2.
-            return
+        exec(fun, {}, local)
         f_kwargs = local['f_kwargs']
 
         g = head_from_fun(f_kwargs)