| 
									
										
										
										
											2023-08-24 19:21:44 +02:00
										 |  |  | import itertools | 
					
						
							|  |  |  | import time | 
					
						
							|  |  |  | import unittest | 
					
						
							|  |  |  | import weakref | 
					
						
							|  |  |  | from concurrent import futures | 
					
						
							|  |  |  | from concurrent.futures._base import ( | 
					
						
							|  |  |  |     CANCELLED_AND_NOTIFIED, FINISHED, Future) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from test import support | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from .util import ( | 
					
						
							|  |  |  |     PENDING_FUTURE, RUNNING_FUTURE, | 
					
						
							|  |  |  |     CANCELLED_AND_NOTIFIED_FUTURE, EXCEPTION_FUTURE, SUCCESSFUL_FUTURE, | 
					
						
							|  |  |  |     create_future, create_executor_tests, setup_module) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def mul(x, y): | 
					
						
							|  |  |  |     return x * y | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class AsCompletedTests: | 
					
						
							|  |  |  |     def test_no_timeout(self): | 
					
						
							|  |  |  |         future1 = self.executor.submit(mul, 2, 21) | 
					
						
							|  |  |  |         future2 = self.executor.submit(mul, 7, 6) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         completed = set(futures.as_completed( | 
					
						
							|  |  |  |                 [CANCELLED_AND_NOTIFIED_FUTURE, | 
					
						
							|  |  |  |                  EXCEPTION_FUTURE, | 
					
						
							|  |  |  |                  SUCCESSFUL_FUTURE, | 
					
						
							|  |  |  |                  future1, future2])) | 
					
						
							|  |  |  |         self.assertEqual(set( | 
					
						
							|  |  |  |                 [CANCELLED_AND_NOTIFIED_FUTURE, | 
					
						
							|  |  |  |                  EXCEPTION_FUTURE, | 
					
						
							|  |  |  |                  SUCCESSFUL_FUTURE, | 
					
						
							|  |  |  |                  future1, future2]), | 
					
						
							|  |  |  |                 completed) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_future_times_out(self): | 
					
						
							|  |  |  |         """Test ``futures.as_completed`` timing out before
 | 
					
						
							|  |  |  |         completing it's final future.""" | 
					
						
							|  |  |  |         already_completed = {CANCELLED_AND_NOTIFIED_FUTURE, | 
					
						
							|  |  |  |                              EXCEPTION_FUTURE, | 
					
						
							|  |  |  |                              SUCCESSFUL_FUTURE} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-27 10:51:44 +02:00
										 |  |  |         # Windows clock resolution is around 15.6 ms | 
					
						
							|  |  |  |         short_timeout = 0.100 | 
					
						
							|  |  |  |         for timeout in (0, short_timeout): | 
					
						
							| 
									
										
										
										
											2023-08-24 19:21:44 +02:00
										 |  |  |             with self.subTest(timeout): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 completed_futures = set() | 
					
						
							| 
									
										
										
										
											2023-09-27 10:51:44 +02:00
										 |  |  |                 future = self.executor.submit(time.sleep, short_timeout * 10) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-24 19:21:44 +02:00
										 |  |  |                 try: | 
					
						
							|  |  |  |                     for f in futures.as_completed( | 
					
						
							|  |  |  |                         already_completed | {future}, | 
					
						
							|  |  |  |                         timeout | 
					
						
							|  |  |  |                     ): | 
					
						
							|  |  |  |                         completed_futures.add(f) | 
					
						
							|  |  |  |                 except futures.TimeoutError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # Check that ``future`` wasn't completed. | 
					
						
							|  |  |  |                 self.assertEqual(completed_futures, already_completed) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_duplicate_futures(self): | 
					
						
							|  |  |  |         # Issue 20367. Duplicate futures should not raise exceptions or give | 
					
						
							|  |  |  |         # duplicate responses. | 
					
						
							|  |  |  |         # Issue #31641: accept arbitrary iterables. | 
					
						
							|  |  |  |         future1 = self.executor.submit(time.sleep, 2) | 
					
						
							|  |  |  |         completed = [ | 
					
						
							|  |  |  |             f for f in futures.as_completed(itertools.repeat(future1, 3)) | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |         self.assertEqual(len(completed), 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_free_reference_yielded_future(self): | 
					
						
							|  |  |  |         # Issue #14406: Generator should not keep references | 
					
						
							|  |  |  |         # to finished futures. | 
					
						
							|  |  |  |         futures_list = [Future() for _ in range(8)] | 
					
						
							|  |  |  |         futures_list.append(create_future(state=CANCELLED_AND_NOTIFIED)) | 
					
						
							|  |  |  |         futures_list.append(create_future(state=FINISHED, result=42)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         with self.assertRaises(futures.TimeoutError): | 
					
						
							|  |  |  |             for future in futures.as_completed(futures_list, timeout=0): | 
					
						
							|  |  |  |                 futures_list.remove(future) | 
					
						
							|  |  |  |                 wr = weakref.ref(future) | 
					
						
							|  |  |  |                 del future | 
					
						
							|  |  |  |                 support.gc_collect()  # For PyPy or other GCs. | 
					
						
							|  |  |  |                 self.assertIsNone(wr()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         futures_list[0].set_result("test") | 
					
						
							|  |  |  |         for future in futures.as_completed(futures_list): | 
					
						
							|  |  |  |             futures_list.remove(future) | 
					
						
							|  |  |  |             wr = weakref.ref(future) | 
					
						
							|  |  |  |             del future | 
					
						
							|  |  |  |             support.gc_collect()  # For PyPy or other GCs. | 
					
						
							|  |  |  |             self.assertIsNone(wr()) | 
					
						
							|  |  |  |             if futures_list: | 
					
						
							|  |  |  |                 futures_list[0].set_result("test") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_correct_timeout_exception_msg(self): | 
					
						
							|  |  |  |         futures_list = [CANCELLED_AND_NOTIFIED_FUTURE, PENDING_FUTURE, | 
					
						
							|  |  |  |                         RUNNING_FUTURE, SUCCESSFUL_FUTURE] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         with self.assertRaises(futures.TimeoutError) as cm: | 
					
						
							|  |  |  |             list(futures.as_completed(futures_list, timeout=0)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(str(cm.exception), '2 (of 4) futures unfinished') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | create_executor_tests(globals(), AsCompletedTests) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def setUpModule(): | 
					
						
							|  |  |  |     setup_module() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     unittest.main() |