cpython/Lib/test/test_unpack_ex.py

182 lines
4.3 KiB
Python

# Tests for extended unpacking, starred expressions.
doctests = """
Unpack tuple
>>> t = (1, 2, 3)
>>> a, *b, c = t
>>> a == 1 and b == [2] and c == 3
True
Unpack list
>>> l = [4, 5, 6]
>>> a, *b = l
>>> a == 4 and b == [5, 6]
True
Unpack implied tuple
>>> *a, = 7, 8, 9
>>> a == [7, 8, 9]
True
Unpack string... fun!
>>> a, *b = 'one'
>>> a == 'o' and b == ['n', 'e']
True
Unpack long sequence
>>> a, b, c, *d, e, f, g = range(10)
>>> (a, b, c, d, e, f, g) == (0, 1, 2, [3, 4, 5, 6], 7, 8, 9)
True
Unpack short sequence
>>> a, *b, c = (1, 2)
>>> a == 1 and c == 2 and b == []
True
Unpack generic sequence
>>> class Seq:
... def __getitem__(self, i):
... if i >= 0 and i < 3: return i
... raise IndexError
...
>>> a, *b = Seq()
>>> a == 0 and b == [1, 2]
True
Unpack in for statement
>>> for a, *b, c in [(1,2,3), (4,5,6,7)]:
... print(a, b, c)
...
1 [2] 3
4 [5, 6] 7
Unpack in list
>>> [a, *b, c] = range(5)
>>> a == 0 and b == [1, 2, 3] and c == 4
True
Multiple targets
>>> a, *b, c = *d, e = range(5)
>>> a == 0 and b == [1, 2, 3] and c == 4 and d == [0, 1, 2, 3] and e == 4
True
Now for some failures
Unpacking non-sequence
>>> a, *b = 7
Traceback (most recent call last):
...
TypeError: 'int' object is not iterable
Unpacking sequence too short
>>> a, *b, c, d, e = Seq()
Traceback (most recent call last):
...
ValueError: not enough values to unpack (expected at least 4, got 3)
Unpacking sequence too short and target appears last
>>> a, b, c, d, *e = Seq()
Traceback (most recent call last):
...
ValueError: not enough values to unpack (expected at least 4, got 3)
Unpacking a sequence where the test for too long raises a different kind of
error
>>> class BozoError(Exception):
... pass
...
>>> class BadSeq:
... def __getitem__(self, i):
... if i >= 0 and i < 3:
... return i
... elif i == 3:
... raise BozoError
... else:
... raise IndexError
...
Trigger code while not expecting an IndexError (unpack sequence too long, wrong
error)
>>> a, *b, c, d, e = BadSeq()
Traceback (most recent call last):
...
test.test_unpack_ex.BozoError
Now some general starred expressions (all fail).
>>> a, *b, c, *d, e = range(10) # doctest:+ELLIPSIS
Traceback (most recent call last):
...
SyntaxError: two starred expressions in assignment
>>> [*b, *c] = range(10) # doctest:+ELLIPSIS
Traceback (most recent call last):
...
SyntaxError: two starred expressions in assignment
>>> *a = range(10) # doctest:+ELLIPSIS
Traceback (most recent call last):
...
SyntaxError: starred assignment target must be in a list or tuple
>>> *a # doctest:+ELLIPSIS
Traceback (most recent call last):
...
SyntaxError: can use starred expression only as assignment target
>>> *1 # doctest:+ELLIPSIS
Traceback (most recent call last):
...
SyntaxError: can use starred expression only as assignment target
>>> x = *a # doctest:+ELLIPSIS
Traceback (most recent call last):
...
SyntaxError: can use starred expression only as assignment target
Some size constraints (all fail.)
>>> s = ", ".join("a%d" % i for i in range(1<<8)) + ", *rest = range(1<<8 + 1)"
>>> compile(s, 'test', 'exec') # doctest:+ELLIPSIS
Traceback (most recent call last):
...
SyntaxError: too many expressions in star-unpacking assignment
>>> s = ", ".join("a%d" % i for i in range(1<<8 + 1)) + ", *rest = range(1<<8 + 2)"
>>> compile(s, 'test', 'exec') # doctest:+ELLIPSIS
Traceback (most recent call last):
...
SyntaxError: too many expressions in star-unpacking assignment
(there is an additional limit, on the number of expressions after the
'*rest', but it's 1<<24 and testing it takes too much memory.)
"""
__test__ = {'doctests' : doctests}
def test_main(verbose=False):
import sys
from test import support
from test import test_unpack_ex
support.run_doctest(test_unpack_ex, verbose)
if __name__ == "__main__":
test_main(verbose=True)