test_unpack.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import doctest
  2. import unittest
  3. doctests = """
  4. Unpack tuple
  5. >>> t = (1, 2, 3)
  6. >>> a, b, c = t
  7. >>> a == 1 and b == 2 and c == 3
  8. True
  9. Unpack list
  10. >>> l = [4, 5, 6]
  11. >>> a, b, c = l
  12. >>> a == 4 and b == 5 and c == 6
  13. True
  14. Unpack implied tuple
  15. >>> a, b, c = 7, 8, 9
  16. >>> a == 7 and b == 8 and c == 9
  17. True
  18. Unpack string... fun!
  19. >>> a, b, c = 'one'
  20. >>> a == 'o' and b == 'n' and c == 'e'
  21. True
  22. Unpack generic sequence
  23. >>> class Seq:
  24. ... def __getitem__(self, i):
  25. ... if i >= 0 and i < 3: return i
  26. ... raise IndexError
  27. ...
  28. >>> a, b, c = Seq()
  29. >>> a == 0 and b == 1 and c == 2
  30. True
  31. Single element unpacking, with extra syntax
  32. >>> st = (99,)
  33. >>> sl = [100]
  34. >>> a, = st
  35. >>> a
  36. 99
  37. >>> b, = sl
  38. >>> b
  39. 100
  40. Now for some failures
  41. Unpacking non-sequence
  42. >>> a, b, c = 7
  43. Traceback (most recent call last):
  44. ...
  45. TypeError: cannot unpack non-iterable int object
  46. Unpacking tuple of wrong size
  47. >>> a, b = t
  48. Traceback (most recent call last):
  49. ...
  50. ValueError: too many values to unpack (expected 2)
  51. Unpacking tuple of wrong size
  52. >>> a, b = l
  53. Traceback (most recent call last):
  54. ...
  55. ValueError: too many values to unpack (expected 2)
  56. Unpacking sequence too short
  57. >>> a, b, c, d = Seq()
  58. Traceback (most recent call last):
  59. ...
  60. ValueError: not enough values to unpack (expected 4, got 3)
  61. Unpacking sequence too long
  62. >>> a, b = Seq()
  63. Traceback (most recent call last):
  64. ...
  65. ValueError: too many values to unpack (expected 2)
  66. Unpacking a sequence where the test for too long raises a different kind of
  67. error
  68. >>> class BozoError(Exception):
  69. ... pass
  70. ...
  71. >>> class BadSeq:
  72. ... def __getitem__(self, i):
  73. ... if i >= 0 and i < 3:
  74. ... return i
  75. ... elif i == 3:
  76. ... raise BozoError
  77. ... else:
  78. ... raise IndexError
  79. ...
  80. Trigger code while not expecting an IndexError (unpack sequence too long, wrong
  81. error)
  82. >>> a, b, c, d, e = BadSeq()
  83. Traceback (most recent call last):
  84. ...
  85. test.test_unpack.BozoError
  86. Trigger code while expecting an IndexError (unpack sequence too short, wrong
  87. error)
  88. >>> a, b, c = BadSeq()
  89. Traceback (most recent call last):
  90. ...
  91. test.test_unpack.BozoError
  92. Allow unpacking empty iterables
  93. >>> () = []
  94. >>> [] = ()
  95. >>> [] = []
  96. >>> () = ()
  97. Unpacking non-iterables should raise TypeError
  98. >>> () = 42
  99. Traceback (most recent call last):
  100. ...
  101. TypeError: cannot unpack non-iterable int object
  102. Unpacking to an empty iterable should raise ValueError
  103. >>> () = [42]
  104. Traceback (most recent call last):
  105. ...
  106. ValueError: too many values to unpack (expected 0)
  107. """
  108. __test__ = {'doctests' : doctests}
  109. def load_tests(loader, tests, pattern):
  110. tests.addTest(doctest.DocTestSuite())
  111. return tests
  112. class TestCornerCases(unittest.TestCase):
  113. def test_extended_oparg_not_ignored(self):
  114. # https://github.com/python/cpython/issues/91625
  115. target = "(" + "y,"*400 + ")"
  116. code = f"""def unpack_400(x):
  117. {target} = x
  118. return y
  119. """
  120. ns = {}
  121. exec(code, ns)
  122. unpack_400 = ns["unpack_400"]
  123. # Warm up the the function for quickening (PEP 659)
  124. for _ in range(30):
  125. y = unpack_400(range(400))
  126. self.assertEqual(y, 399)
  127. if __name__ == "__main__":
  128. unittest.main()