Hello, there is a regression in the beta (alpha 4 was ok) for this kind of code: print("Complex call with both invalid star list and star arguments:") try: a = 1 b = 2.0 functionWithDefaults(1,c = 3,*a,**b) except TypeError as e: print(repr(e)) try: a = 1 b = 2.0 functionWithDefaults(1,*a,**b) except TypeError as e: print(repr(e)) try: a = 1 b = 2.0 functionWithDefaults(c = 1, *a,**b) except TypeError as e: print(repr(e)) try: a = 1 b = 2.0 functionWithDefaults(*a,**b) except TypeError as e: print(repr(e)) This prints with beta1 3.6 Complex call with both invalid star list and star arguments: TypeError("'int' object is not iterable",) TypeError("'int' object is not iterable",) TypeError("'float' object is not iterable",) TypeError('functionWithDefaults() argument after ** must be a mapping, not float',) The later message is what they all probably should be like. This is 3.5 output: Complex call with both invalid star list and star arguments: TypeError('functionWithDefaults() argument after ** must be a mapping, not float',) TypeError('functionWithDefaults() argument after ** must be a mapping, not float',) TypeError('functionWithDefaults() argument after ** must be a mapping, not float',) TypeError('functionWithDefaults() argument after ** must be a mapping, not float',) The function itself doesn't matter obviously, it's never called. Please restore the old behavior, thanks. Yours, Kay |
This is a consequence of issue27213. Actually there are two issues: with var-positional and var-keyword arguments. But Python 3.5 is not consistent. It raises an exception with less detailed message if there are multiple var-positional or var-keyword arguments. Var-positional arguments: >>> f(*0) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f() argument after * must be an iterable, not int >>> f(1, *0) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f() argument after * must be an iterable, not int >>> f(*[], *0) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not iterable Python 3.6 just raises the latter message in case of positional arguments and single var-positional argument. >>> f(*0) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f() argument after * must be an iterable, not int >>> f(1, *0) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not iterable >>> f(*[], *0) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not iterable This issue can't be fixed without adding new bytecode (BUILD_TUPLE_UNPACK_WITH_CALL). If it will be decided to fix it in 3.6, it may be worth to backport this to 3.5. Var-keyword arguments: Python 3.5: >>> f(**[]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f() argument after ** must be a mapping, not list >>> f(x=1, **0) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f() argument after ** must be a mapping, not int >>> f(x=1, **[]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f() argument after ** must be a mapping, not list >>> f(**{}, **0) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not iterable >>> f(**{}, **[]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'list' object is not a mapping Python 3.6 raises less detailed error message in case of keyword arguments and single var-keyword argument. >>> f(**0) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f() argument after ** must be a mapping, not int >>> f(**[]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f() argument after ** must be a mapping, not list >>> f(x=1, **0) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not iterable >>> f(x=1, **[]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'list' object is not a mapping >>> f(**{}, **0) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not a mapping >>> f(**{}, **[]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'list' object is not a mapping This issue can be fixed without changing bytecode. The patch faster_build_map_unpack_with_call.patch for issue27358 fixes it. |
Proposed patch fixes error message for var-positional arguments. It adds new opcode BUILD_TUPLE_UNPACK_WITH_CALL. >>> min(1, *2) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: min() argument after * must be an iterable, not int >>> min(*[1], *2) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: min() argument after * must be an iterable, not int |
Here is a patch with smaller (in comparison with issue27358) change for 3.5 that improves error message when pass a non-mapping as second var-keyword argument. Unpatched: >>> f(**{'a': 1}, **[]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'list' object is not a mapping >>> f(**{'a': 1}, **0) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not iterable Patched: >>> f(**{'a': 1}, **[]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f() argument after ** must be a mapping, not list >>> f(**{'a': 1}, **0) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: f() argument after ** must be a mapping, not int |