Skip to content

Commit 0bb165e

Browse files
committed
Issue #4806: Avoid masking TypeError when *-unpacking a generator
Based on patch by Hagen Fürstenau.
1 parent 414f8b9 commit 0bb165e

3 files changed

Lines changed: 24 additions & 7 deletions

File tree

Lib/test/test_extcall.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@
9393
>>> g(*Nothing())
9494
Traceback (most recent call last):
9595
...
96-
TypeError: g() argument after * must be a sequence, not instance
96+
TypeError: g() argument after * must be an iterable, not instance
9797
9898
>>> class Nothing:
9999
... def __len__(self): return 5
@@ -102,7 +102,7 @@
102102
>>> g(*Nothing())
103103
Traceback (most recent call last):
104104
...
105-
TypeError: g() argument after * must be a sequence, not instance
105+
TypeError: g() argument after * must be an iterable, not instance
106106
107107
>>> class Nothing():
108108
... def __len__(self): return 5
@@ -128,6 +128,17 @@
128128
>>> g(*Nothing())
129129
0 (1, 2, 3) {}
130130
131+
Check for issue #4806: Does a TypeError in a generator get propagated with the
132+
right error message?
133+
134+
>>> def broken(): raise TypeError("myerror")
135+
...
136+
137+
>>> g(*(broken() for i in range(1)))
138+
Traceback (most recent call last):
139+
...
140+
TypeError: myerror
141+
131142
Make sure that the function doesn't stomp the dictionary
132143
133144
>>> d = {'a': 1, 'b': 2, 'c': 3}
@@ -167,17 +178,17 @@
167178
>>> h(*h)
168179
Traceback (most recent call last):
169180
...
170-
TypeError: h() argument after * must be a sequence, not function
181+
TypeError: h() argument after * must be an iterable, not function
171182
172183
>>> dir(*h)
173184
Traceback (most recent call last):
174185
...
175-
TypeError: dir() argument after * must be a sequence, not function
186+
TypeError: dir() argument after * must be an iterable, not function
176187
177188
>>> None(*h)
178189
Traceback (most recent call last):
179190
...
180-
TypeError: NoneType object argument after * must be a sequence, \
191+
TypeError: NoneType object argument after * must be an iterable, \
181192
not function
182193
183194
>>> h(**h)

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ What's New in Python 2.7.12?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #4806: Avoid masking the original TypeError exception when using star
14+
(*) unpacking and the exception was raised from a generator. Based on
15+
patch by Hagen Fürstenau.
16+
1317
- Issue #26659: Make the builtin slice type support cycle collection.
1418

1519
- Issue #26718: super.__init__ no longer leaks memory if called multiple times.

Python/ceval.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4615,10 +4615,12 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)
46154615
PyObject *t = NULL;
46164616
t = PySequence_Tuple(stararg);
46174617
if (t == NULL) {
4618-
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
4618+
if (PyErr_ExceptionMatches(PyExc_TypeError) &&
4619+
/* Don't mask TypeError raised from a generator */
4620+
!PyGen_Check(stararg)) {
46194621
PyErr_Format(PyExc_TypeError,
46204622
"%.200s%.200s argument after * "
4621-
"must be a sequence, not %200s",
4623+
"must be an iterable, not %200s",
46224624
PyEval_GetFuncName(func),
46234625
PyEval_GetFuncDesc(func),
46244626
stararg->ob_type->tp_name);

0 commit comments

Comments
 (0)