mirror of https://github.com/python/cpython
gh-122239: Add actual count in unbalanced unpacking error message when possible (#122244)
This commit is contained in:
parent
07f0bf5aa4
commit
3597642ed5
|
@ -70,6 +70,21 @@ Summary -- Release highlights
|
|||
New Features
|
||||
============
|
||||
|
||||
Improved Error Messages
|
||||
-----------------------
|
||||
|
||||
* When unpacking assignment fails due to incorrect number of variables, the
|
||||
error message prints the received number of values in more cases than before.
|
||||
(Contributed by Tushar Sadhwani in :gh:`122239`.)
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> x, y, z = 1, 2, 3, 4
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
x, y, z = 1, 2, 3, 4
|
||||
^^^^^^^
|
||||
ValueError: too many values to unpack (expected 3, got 4)
|
||||
|
||||
|
||||
Other Language Changes
|
||||
|
|
|
@ -18,6 +18,13 @@ Unpack list
|
|||
>>> a == 4 and b == 5 and c == 6
|
||||
True
|
||||
|
||||
Unpack dict
|
||||
|
||||
>>> d = {4: 'four', 5: 'five', 6: 'six'}
|
||||
>>> a, b, c = d
|
||||
>>> a == 4 and b == 5 and c == 6
|
||||
True
|
||||
|
||||
Unpack implied tuple
|
||||
|
||||
>>> a, b, c = 7, 8, 9
|
||||
|
@ -66,14 +73,14 @@ Unpacking tuple of wrong size
|
|||
>>> a, b = t
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: too many values to unpack (expected 2)
|
||||
ValueError: too many values to unpack (expected 2, got 3)
|
||||
|
||||
Unpacking tuple of wrong size
|
||||
|
||||
>>> a, b = l
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: too many values to unpack (expected 2)
|
||||
ValueError: too many values to unpack (expected 2, got 3)
|
||||
|
||||
Unpacking sequence too short
|
||||
|
||||
|
@ -140,8 +147,52 @@ Unpacking to an empty iterable should raise ValueError
|
|||
>>> () = [42]
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: too many values to unpack (expected 0)
|
||||
ValueError: too many values to unpack (expected 0, got 1)
|
||||
|
||||
Unpacking a larger iterable should raise ValuleError, but it
|
||||
should not entirely consume the iterable
|
||||
|
||||
>>> it = iter(range(100))
|
||||
>>> x, y, z = it
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: too many values to unpack (expected 3)
|
||||
>>> next(it)
|
||||
4
|
||||
|
||||
Unpacking unbalanced dict
|
||||
|
||||
>>> d = {4: 'four', 5: 'five', 6: 'six', 7: 'seven'}
|
||||
>>> a, b, c = d
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: too many values to unpack (expected 3, got 4)
|
||||
|
||||
Ensure that custom `__len__()` is NOT called when showing the error message
|
||||
|
||||
>>> class LengthTooLong:
|
||||
... def __len__(self):
|
||||
... return 5
|
||||
... def __getitem__(self, i):
|
||||
... return i*2
|
||||
...
|
||||
>>> x, y, z = LengthTooLong()
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: too many values to unpack (expected 3)
|
||||
|
||||
For evil cases like these as well, no actual count to be shown
|
||||
|
||||
>>> class BadLength:
|
||||
... def __len__(self):
|
||||
... return 1
|
||||
... def __getitem__(self, i):
|
||||
... return i*2
|
||||
...
|
||||
>>> x, y, z = BadLength()
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: too many values to unpack (expected 3)
|
||||
"""
|
||||
|
||||
__test__ = {'doctests' : doctests}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
When a :class:`list`, :class:`tuple` or :class:`dict`
|
||||
with too many elements is unpacked, show the actual
|
||||
length in the error message.
|
|
@ -2148,6 +2148,17 @@ _PyEval_UnpackIterableStackRef(PyThreadState *tstate, _PyStackRef v_stackref,
|
|||
return 1;
|
||||
}
|
||||
Py_DECREF(w);
|
||||
|
||||
if (PyList_CheckExact(v) || PyTuple_CheckExact(v)
|
||||
|| PyDict_CheckExact(v)) {
|
||||
ll = PyDict_CheckExact(v) ? PyDict_Size(v) : Py_SIZE(v);
|
||||
if (ll > argcnt) {
|
||||
_PyErr_Format(tstate, PyExc_ValueError,
|
||||
"too many values to unpack (expected %d, got %zd)",
|
||||
argcnt, ll);
|
||||
goto Error;
|
||||
}
|
||||
}
|
||||
_PyErr_Format(tstate, PyExc_ValueError,
|
||||
"too many values to unpack (expected %d)",
|
||||
argcnt);
|
||||
|
|
Loading…
Reference in New Issue