Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cca3299

Browse files
committed
Issue #4806: Merge * unpacking fix from 3.5
2 parents 03178a5 + b594422 commit cca3299

3 files changed

Lines changed: 58 additions & 13 deletions

File tree

Lib/test/test_extcall.py

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@
114114
>>> g(*Nothing())
115115
Traceback (most recent call last):
116116
...
117-
TypeError: g() argument after * must be a sequence, not Nothing
117+
TypeError: g() argument after * must be an iterable, not Nothing
118118
119119
>>> class Nothing:
120120
... def __len__(self): return 5
@@ -123,7 +123,7 @@
123123
>>> g(*Nothing())
124124
Traceback (most recent call last):
125125
...
126-
TypeError: g() argument after * must be a sequence, not Nothing
126+
TypeError: g() argument after * must be an iterable, not Nothing
127127
128128
>>> class Nothing():
129129
... def __len__(self): return 5
@@ -149,6 +149,45 @@
149149
>>> g(*Nothing())
150150
0 (1, 2, 3) {}
151151
152+
Check for issue #4806: Does a TypeError in a generator get propagated with the
153+
right error message? (Also check with other iterables.)
154+
155+
>>> def broken(): raise TypeError("myerror")
156+
...
157+
158+
>>> g(*(broken() for i in range(1)))
159+
Traceback (most recent call last):
160+
...
161+
TypeError: myerror
162+
163+
>>> class BrokenIterable1:
164+
... def __iter__(self):
165+
... raise TypeError('myerror')
166+
...
167+
>>> g(*BrokenIterable1())
168+
Traceback (most recent call last):
169+
...
170+
TypeError: myerror
171+
172+
>>> class BrokenIterable2:
173+
... def __iter__(self):
174+
... yield 0
175+
... raise TypeError('myerror')
176+
...
177+
>>> g(*BrokenIterable2())
178+
Traceback (most recent call last):
179+
...
180+
TypeError: myerror
181+
182+
>>> class BrokenSequence:
183+
... def __getitem__(self, idx):
184+
... raise TypeError('myerror')
185+
...
186+
>>> g(*BrokenSequence())
187+
Traceback (most recent call last):
188+
...
189+
TypeError: myerror
190+
152191
Make sure that the function doesn't stomp the dictionary
153192
154193
>>> d = {'a': 1, 'b': 2, 'c': 3}
@@ -188,17 +227,17 @@
188227
>>> h(*h)
189228
Traceback (most recent call last):
190229
...
191-
TypeError: h() argument after * must be a sequence, not function
230+
TypeError: h() argument after * must be an iterable, not function
192231
193232
>>> dir(*h)
194233
Traceback (most recent call last):
195234
...
196-
TypeError: dir() argument after * must be a sequence, not function
235+
TypeError: dir() argument after * must be an iterable, not function
197236
198237
>>> None(*h)
199238
Traceback (most recent call last):
200239
...
201-
TypeError: NoneType object argument after * must be a sequence, \
240+
TypeError: NoneType object argument after * must be an iterable, \
202241
not function
203242
204243
>>> h(**h)

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ Release date: tba
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #4806: Avoid masking the original TypeError exception when using star
14+
(*) unpacking in function calls. Based on patch by Hagen Fürstenau and
15+
Daniel Urban.
16+
1317
- Issue #26146: Add a new kind of AST node: ``ast.Constant``. It can be used
1418
by external AST optimizers, but the compiler does not emit directly such
1519
node.

Python/ceval.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4999,16 +4999,18 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)
49994999
stararg = EXT_POP(*pp_stack);
50005000
if (!PyTuple_Check(stararg)) {
50015001
PyObject *t = NULL;
5002+
if (Py_TYPE(stararg)->tp_iter == NULL &&
5003+
!PySequence_Check(stararg)) {
5004+
PyErr_Format(PyExc_TypeError,
5005+
"%.200s%.200s argument after * "
5006+
"must be an iterable, not %.200s",
5007+
PyEval_GetFuncName(func),
5008+
PyEval_GetFuncDesc(func),
5009+
stararg->ob_type->tp_name);
5010+
goto ext_call_fail;
5011+
}
50025012
t = PySequence_Tuple(stararg);
50035013
if (t == NULL) {
5004-
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
5005-
PyErr_Format(PyExc_TypeError,
5006-
"%.200s%.200s argument after * "
5007-
"must be a sequence, not %.200s",
5008-
PyEval_GetFuncName(func),
5009-
PyEval_GetFuncDesc(func),
5010-
stararg->ob_type->tp_name);
5011-
}
50125014
goto ext_call_fail;
50135015
}
50145016
Py_DECREF(stararg);

0 commit comments

Comments
 (0)