| 
									
										
										
										
											2021-09-20 11:36:57 +03:00
										 |  |  | import doctest | 
					
						
							|  |  |  | import unittest | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-09-24 21:36:52 +00:00
										 |  |  | 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, c = l | 
					
						
							|  |  |  |     >>> a == 4 and b == 5 and c == 6 | 
					
						
							|  |  |  |     True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-10 20:37:30 +05:30
										 |  |  | Unpack dict | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     >>> d = {4: 'four', 5: 'five', 6: 'six'} | 
					
						
							|  |  |  |     >>> a, b, c = d | 
					
						
							|  |  |  |     >>> a == 4 and b == 5 and c == 6 | 
					
						
							|  |  |  |     True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-09-24 21:36:52 +00:00
										 |  |  | Unpack implied tuple | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     >>> a, b, c = 7, 8, 9 | 
					
						
							|  |  |  |     >>> a == 7 and b == 8 and c == 9 | 
					
						
							|  |  |  |     True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Unpack string... fun! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     >>> a, b, c = 'one' | 
					
						
							|  |  |  |     >>> a == 'o' and b == 'n' and c == 'e' | 
					
						
							|  |  |  |     True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Unpack generic sequence | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     >>> class Seq: | 
					
						
							|  |  |  |     ...     def __getitem__(self, i): | 
					
						
							|  |  |  |     ...         if i >= 0 and i < 3: return i | 
					
						
							|  |  |  |     ...         raise IndexError | 
					
						
							|  |  |  |     ... | 
					
						
							|  |  |  |     >>> a, b, c = Seq() | 
					
						
							|  |  |  |     >>> a == 0 and b == 1 and c == 2 | 
					
						
							|  |  |  |     True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Single element unpacking, with extra syntax | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     >>> st = (99,) | 
					
						
							|  |  |  |     >>> sl = [100] | 
					
						
							|  |  |  |     >>> a, = st | 
					
						
							|  |  |  |     >>> a | 
					
						
							|  |  |  |     99 | 
					
						
							|  |  |  |     >>> b, = sl | 
					
						
							|  |  |  |     >>> b | 
					
						
							|  |  |  |     100 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Now for some failures | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Unpacking non-sequence | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     >>> a, b, c = 7 | 
					
						
							|  |  |  |     Traceback (most recent call last): | 
					
						
							|  |  |  |       ... | 
					
						
							| 
									
										
										
										
											2017-12-26 12:30:41 +02:00
										 |  |  |     TypeError: cannot unpack non-iterable int object | 
					
						
							| 
									
										
										
										
											2004-09-24 21:36:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Unpacking tuple of wrong size | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     >>> a, b = t | 
					
						
							|  |  |  |     Traceback (most recent call last): | 
					
						
							|  |  |  |       ... | 
					
						
							| 
									
										
										
										
											2024-09-10 20:37:30 +05:30
										 |  |  |     ValueError: too many values to unpack (expected 2, got 3) | 
					
						
							| 
									
										
										
										
											2004-09-24 21:36:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Unpacking tuple of wrong size | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     >>> a, b = l | 
					
						
							|  |  |  |     Traceback (most recent call last): | 
					
						
							|  |  |  |       ... | 
					
						
							| 
									
										
										
										
											2024-09-10 20:37:30 +05:30
										 |  |  |     ValueError: too many values to unpack (expected 2, got 3) | 
					
						
							| 
									
										
										
										
											2004-09-24 21:36:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Unpacking sequence too short | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     >>> a, b, c, d = Seq() | 
					
						
							|  |  |  |     Traceback (most recent call last): | 
					
						
							|  |  |  |       ... | 
					
						
							| 
									
										
										
										
											2015-04-15 17:08:45 -04:00
										 |  |  |     ValueError: not enough values to unpack (expected 4, got 3) | 
					
						
							| 
									
										
										
										
											2004-09-24 21:36:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Unpacking sequence too long | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     >>> a, b = Seq() | 
					
						
							|  |  |  |     Traceback (most recent call last): | 
					
						
							|  |  |  |       ... | 
					
						
							| 
									
										
										
										
											2010-07-10 10:32:36 +00:00
										 |  |  |     ValueError: too many values to unpack (expected 2) | 
					
						
							| 
									
										
										
										
											2004-09-24 21:36:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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): | 
					
						
							|  |  |  |       ... | 
					
						
							| 
									
										
										
										
											2006-08-26 20:37:44 +00:00
										 |  |  |     test.test_unpack.BozoError | 
					
						
							| 
									
										
										
										
											2004-09-24 21:36:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Trigger code while expecting an IndexError (unpack sequence too short, wrong | 
					
						
							|  |  |  | error) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     >>> a, b, c = BadSeq() | 
					
						
							|  |  |  |     Traceback (most recent call last): | 
					
						
							|  |  |  |       ... | 
					
						
							| 
									
										
										
										
											2006-08-26 20:37:44 +00:00
										 |  |  |     test.test_unpack.BozoError | 
					
						
							| 
									
										
										
										
											2004-09-24 21:36:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-18 08:44:29 +03:00
										 |  |  | Allow unpacking empty iterables | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     >>> () = [] | 
					
						
							|  |  |  |     >>> [] = () | 
					
						
							|  |  |  |     >>> [] = [] | 
					
						
							|  |  |  |     >>> () = () | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Unpacking non-iterables should raise TypeError | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     >>> () = 42 | 
					
						
							|  |  |  |     Traceback (most recent call last): | 
					
						
							|  |  |  |       ... | 
					
						
							| 
									
										
										
										
											2017-12-26 12:30:41 +02:00
										 |  |  |     TypeError: cannot unpack non-iterable int object | 
					
						
							| 
									
										
										
										
											2016-05-18 08:44:29 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | Unpacking to an empty iterable should raise ValueError | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     >>> () = [42] | 
					
						
							|  |  |  |     Traceback (most recent call last): | 
					
						
							|  |  |  |       ... | 
					
						
							| 
									
										
										
										
											2024-09-10 20:37:30 +05:30
										 |  |  |     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 | 
					
						
							| 
									
										
										
										
											2016-05-18 08:44:29 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-10 20:37:30 +05:30
										 |  |  |     >>> 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) | 
					
						
							| 
									
										
										
										
											2004-09-24 21:36:52 +00:00
										 |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | __test__ = {'doctests' : doctests} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 11:36:57 +03:00
										 |  |  | def load_tests(loader, tests, pattern): | 
					
						
							|  |  |  |     tests.addTest(doctest.DocTestSuite()) | 
					
						
							|  |  |  |     return tests | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-09-24 21:36:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-17 14:04:29 -04:00
										 |  |  | class TestCornerCases(unittest.TestCase): | 
					
						
							|  |  |  |     def test_extended_oparg_not_ignored(self): | 
					
						
							|  |  |  |         # https://github.com/python/cpython/issues/91625 | 
					
						
							|  |  |  |         target = "(" + "y,"*400 + ")" | 
					
						
							|  |  |  |         code = f"""def unpack_400(x):
 | 
					
						
							|  |  |  |             {target} = x | 
					
						
							|  |  |  |             return y | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         ns = {} | 
					
						
							|  |  |  |         exec(code, ns) | 
					
						
							|  |  |  |         unpack_400 = ns["unpack_400"] | 
					
						
							| 
									
										
										
										
											2023-09-20 18:58:23 +02:00
										 |  |  |         # Warm up the function for quickening (PEP 659) | 
					
						
							| 
									
										
										
										
											2022-04-17 14:04:29 -04:00
										 |  |  |         for _ in range(30): | 
					
						
							|  |  |  |             y = unpack_400(range(400)) | 
					
						
							|  |  |  |             self.assertEqual(y, 399) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-09-24 21:36:52 +00:00
										 |  |  | if __name__ == "__main__": | 
					
						
							| 
									
										
										
										
											2021-09-20 11:36:57 +03:00
										 |  |  |     unittest.main() |