| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | """Tests for futures.py.""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import concurrent.futures | 
					
						
							| 
									
										
										
										
											2017-08-01 23:31:07 -07:00
										 |  |  | import gc | 
					
						
							| 
									
										
										
										
											2014-06-25 21:41:58 +02:00
										 |  |  | import re | 
					
						
							| 
									
										
										
										
											2014-06-27 13:52:20 +02:00
										 |  |  | import sys | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | import threading | 
					
						
							| 
									
										
										
										
											2024-04-04 11:13:32 +08:00
										 |  |  | import traceback | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | import unittest | 
					
						
							| 
									
										
										
										
											2014-02-26 10:25:02 +01:00
										 |  |  | from unittest import mock | 
					
						
							| 
									
										
										
										
											2022-01-22 16:58:53 +05:30
										 |  |  | from types import GenericAlias | 
					
						
							| 
									
										
										
										
											2014-01-25 15:32:06 +01:00
										 |  |  | import asyncio | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  | from asyncio import futures | 
					
						
							| 
									
										
										
										
											2022-09-30 16:43:02 +08:00
										 |  |  | import warnings | 
					
						
							| 
									
										
										
										
											2017-12-11 10:04:40 -05:00
										 |  |  | from test.test_asyncio import utils as test_utils | 
					
						
							|  |  |  | from test import support | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 20:34:09 -07:00
										 |  |  | def tearDownModule(): | 
					
						
							|  |  |  |     asyncio.set_event_loop_policy(None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | def _fakefunc(f): | 
					
						
							|  |  |  |     return f | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-01 23:31:07 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-25 21:41:58 +02:00
										 |  |  | def first_cb(): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-01 23:31:07 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-25 21:41:58 +02:00
										 |  |  | def last_cb(): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-09 14:26:31 -07:00
										 |  |  | class DuckFuture: | 
					
						
							|  |  |  |     # Class that does not inherit from Future but aims to be duck-type | 
					
						
							|  |  |  |     # compatible with it. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _asyncio_future_blocking = False | 
					
						
							|  |  |  |     __cancelled = False | 
					
						
							|  |  |  |     __result = None | 
					
						
							|  |  |  |     __exception = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def cancel(self): | 
					
						
							|  |  |  |         if self.done(): | 
					
						
							|  |  |  |             return False | 
					
						
							|  |  |  |         self.__cancelled = True | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def cancelled(self): | 
					
						
							|  |  |  |         return self.__cancelled | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def done(self): | 
					
						
							|  |  |  |         return (self.__cancelled | 
					
						
							|  |  |  |                 or self.__result is not None | 
					
						
							|  |  |  |                 or self.__exception is not None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def result(self): | 
					
						
							| 
									
										
										
										
											2021-12-20 12:23:05 +02:00
										 |  |  |         self.assertFalse(self.cancelled()) | 
					
						
							| 
									
										
										
										
											2016-09-09 14:26:31 -07:00
										 |  |  |         if self.__exception is not None: | 
					
						
							|  |  |  |             raise self.__exception | 
					
						
							|  |  |  |         return self.__result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def exception(self): | 
					
						
							| 
									
										
										
										
											2021-12-20 12:23:05 +02:00
										 |  |  |         self.assertFalse(self.cancelled()) | 
					
						
							| 
									
										
										
										
											2016-09-09 14:26:31 -07:00
										 |  |  |         return self.__exception | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def set_result(self, result): | 
					
						
							| 
									
										
										
										
											2021-12-20 12:23:05 +02:00
										 |  |  |         self.assertFalse(self.done()) | 
					
						
							|  |  |  |         self.assertIsNotNone(result) | 
					
						
							| 
									
										
										
										
											2016-09-09 14:26:31 -07:00
										 |  |  |         self.__result = result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def set_exception(self, exception): | 
					
						
							| 
									
										
										
										
											2021-12-20 12:23:05 +02:00
										 |  |  |         self.assertFalse(self.done()) | 
					
						
							|  |  |  |         self.assertIsNotNone(exception) | 
					
						
							| 
									
										
										
										
											2016-09-09 14:26:31 -07:00
										 |  |  |         self.__exception = exception | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __iter__(self): | 
					
						
							|  |  |  |         if not self.done(): | 
					
						
							|  |  |  |             self._asyncio_future_blocking = True | 
					
						
							|  |  |  |             yield self | 
					
						
							| 
									
										
										
										
											2021-12-20 12:23:05 +02:00
										 |  |  |         self.assertTrue(self.done()) | 
					
						
							| 
									
										
										
										
											2016-09-09 14:26:31 -07:00
										 |  |  |         return self.result() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class DuckTests(test_utils.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def setUp(self): | 
					
						
							| 
									
										
										
										
											2016-11-04 14:29:28 -04:00
										 |  |  |         super().setUp() | 
					
						
							| 
									
										
										
										
											2016-09-09 14:26:31 -07:00
										 |  |  |         self.loop = self.new_test_loop() | 
					
						
							|  |  |  |         self.addCleanup(self.loop.close) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_wrap_future(self): | 
					
						
							|  |  |  |         f = DuckFuture() | 
					
						
							|  |  |  |         g = asyncio.wrap_future(f) | 
					
						
							| 
									
										
										
										
											2021-12-20 12:23:05 +02:00
										 |  |  |         self.assertIs(g, f) | 
					
						
							| 
									
										
										
										
											2016-09-09 14:26:31 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_ensure_future(self): | 
					
						
							|  |  |  |         f = DuckFuture() | 
					
						
							|  |  |  |         g = asyncio.ensure_future(f) | 
					
						
							| 
									
										
										
										
											2021-12-20 12:23:05 +02:00
										 |  |  |         self.assertIs(g, f) | 
					
						
							| 
									
										
										
										
											2016-09-09 14:26:31 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  | class BaseFutureTests: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-03 08:10:14 +03:00
										 |  |  |     def _new_future(self,  *args, **kwargs): | 
					
						
							|  |  |  |         return self.cls(*args, **kwargs) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def setUp(self): | 
					
						
							| 
									
										
										
										
											2016-11-04 14:29:28 -04:00
										 |  |  |         super().setUp() | 
					
						
							| 
									
										
										
										
											2014-06-18 01:36:32 +02:00
										 |  |  |         self.loop = self.new_test_loop() | 
					
						
							| 
									
										
										
										
											2015-01-15 00:04:21 +01:00
										 |  |  |         self.addCleanup(self.loop.close) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-22 16:58:53 +05:30
										 |  |  |     def test_generic_alias(self): | 
					
						
							|  |  |  |         future = self.cls[str] | 
					
						
							|  |  |  |         self.assertEqual(future.__args__, (str,)) | 
					
						
							|  |  |  |         self.assertIsInstance(future, GenericAlias) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-07 16:00:50 -05:00
										 |  |  |     def test_isfuture(self): | 
					
						
							|  |  |  |         class MyFuture: | 
					
						
							|  |  |  |             _asyncio_future_blocking = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             def __init__(self): | 
					
						
							|  |  |  |                 self._asyncio_future_blocking = False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertFalse(asyncio.isfuture(MyFuture)) | 
					
						
							|  |  |  |         self.assertTrue(asyncio.isfuture(MyFuture())) | 
					
						
							|  |  |  |         self.assertFalse(asyncio.isfuture(1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # As `isinstance(Mock(), Future)` returns `False` | 
					
						
							|  |  |  |         self.assertFalse(asyncio.isfuture(mock.Mock())) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-07 16:07:30 -05:00
										 |  |  |         f = self._new_future(loop=self.loop) | 
					
						
							|  |  |  |         self.assertTrue(asyncio.isfuture(f)) | 
					
						
							|  |  |  |         self.assertFalse(asyncio.isfuture(type(f))) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-07 16:00:50 -05:00
										 |  |  |         # As `isinstance(Mock(Future), Future)` returns `True` | 
					
						
							| 
									
										
										
										
											2016-11-07 16:07:30 -05:00
										 |  |  |         self.assertTrue(asyncio.isfuture(mock.Mock(type(f)))) | 
					
						
							| 
									
										
										
										
											2016-11-07 16:00:50 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         f.cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     def test_initial_state(self): | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertFalse(f.cancelled()) | 
					
						
							|  |  |  |         self.assertFalse(f.done()) | 
					
						
							|  |  |  |         f.cancel() | 
					
						
							|  |  |  |         self.assertTrue(f.cancelled()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-25 13:40:44 +03:00
										 |  |  |     def test_constructor_without_loop(self): | 
					
						
							| 
									
										
										
										
											2022-12-06 19:42:12 +02:00
										 |  |  |         with self.assertRaisesRegex(RuntimeError, 'no current event loop'): | 
					
						
							|  |  |  |             self._new_future() | 
					
						
							| 
									
										
										
										
											2021-04-25 13:40:44 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_constructor_use_running_loop(self): | 
					
						
							|  |  |  |         async def test(): | 
					
						
							|  |  |  |             return self._new_future() | 
					
						
							|  |  |  |         f = self.loop.run_until_complete(test()) | 
					
						
							|  |  |  |         self.assertIs(f._loop, self.loop) | 
					
						
							|  |  |  |         self.assertIs(f.get_loop(), self.loop) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_constructor_use_global_loop(self): | 
					
						
							| 
									
										
										
										
											2022-12-06 19:42:12 +02:00
										 |  |  |         # Deprecated in 3.10, undeprecated in 3.12 | 
					
						
							| 
									
										
										
										
											2014-06-18 01:36:32 +02:00
										 |  |  |         asyncio.set_event_loop(self.loop) | 
					
						
							| 
									
										
										
										
											2021-04-25 13:40:44 +03:00
										 |  |  |         self.addCleanup(asyncio.set_event_loop, None) | 
					
						
							| 
									
										
										
										
											2022-12-06 19:42:12 +02:00
										 |  |  |         f = self._new_future() | 
					
						
							| 
									
										
										
										
											2014-06-18 01:36:32 +02:00
										 |  |  |         self.assertIs(f._loop, self.loop) | 
					
						
							| 
									
										
										
										
											2017-12-23 15:04:15 -05:00
										 |  |  |         self.assertIs(f.get_loop(), self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_constructor_positional(self): | 
					
						
							| 
									
										
										
										
											2014-02-18 22:27:48 -05:00
										 |  |  |         # Make sure Future doesn't accept a positional argument | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         self.assertRaises(TypeError, self._new_future, 42) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-03 08:10:14 +03:00
										 |  |  |     def test_uninitialized(self): | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  |         # Test that C Future doesn't crash when Future.__init__() | 
					
						
							|  |  |  |         # call was skipped. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-03 08:10:14 +03:00
										 |  |  |         fut = self.cls.__new__(self.cls, loop=self.loop) | 
					
						
							|  |  |  |         self.assertRaises(asyncio.InvalidStateError, fut.result) | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-03 08:10:14 +03:00
										 |  |  |         fut = self.cls.__new__(self.cls, loop=self.loop) | 
					
						
							|  |  |  |         self.assertRaises(asyncio.InvalidStateError, fut.exception) | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-03 08:10:14 +03:00
										 |  |  |         fut = self.cls.__new__(self.cls, loop=self.loop) | 
					
						
							|  |  |  |         with self.assertRaises((RuntimeError, AttributeError)): | 
					
						
							|  |  |  |             fut.set_result(None) | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-03 08:10:14 +03:00
										 |  |  |         fut = self.cls.__new__(self.cls, loop=self.loop) | 
					
						
							|  |  |  |         with self.assertRaises((RuntimeError, AttributeError)): | 
					
						
							|  |  |  |             fut.set_exception(Exception) | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-03 08:10:14 +03:00
										 |  |  |         fut = self.cls.__new__(self.cls, loop=self.loop) | 
					
						
							|  |  |  |         with self.assertRaises((RuntimeError, AttributeError)): | 
					
						
							|  |  |  |             fut.cancel() | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-03 08:10:14 +03:00
										 |  |  |         fut = self.cls.__new__(self.cls, loop=self.loop) | 
					
						
							|  |  |  |         with self.assertRaises((RuntimeError, AttributeError)): | 
					
						
							|  |  |  |             fut.add_done_callback(lambda f: None) | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-03 08:10:14 +03:00
										 |  |  |         fut = self.cls.__new__(self.cls, loop=self.loop) | 
					
						
							|  |  |  |         with self.assertRaises((RuntimeError, AttributeError)): | 
					
						
							|  |  |  |             fut.remove_done_callback(lambda f: None) | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-03 08:10:14 +03:00
										 |  |  |         fut = self.cls.__new__(self.cls, loop=self.loop) | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             repr(fut) | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  |         except (RuntimeError, AttributeError): | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fut = self.cls.__new__(self.cls, loop=self.loop) | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             fut.__await__() | 
					
						
							|  |  |  |         except RuntimeError: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fut = self.cls.__new__(self.cls, loop=self.loop) | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             iter(fut) | 
					
						
							|  |  |  |         except RuntimeError: | 
					
						
							| 
									
										
										
										
											2017-09-03 08:10:14 +03:00
										 |  |  |             pass | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-03 08:10:14 +03:00
										 |  |  |         fut = self.cls.__new__(self.cls, loop=self.loop) | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  |         self.assertFalse(fut.cancelled()) | 
					
						
							|  |  |  |         self.assertFalse(fut.done()) | 
					
						
							| 
									
										
										
										
											2017-09-03 08:10:14 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-15 16:55:50 -07:00
										 |  |  |     def test_future_cancel_message_getter(self): | 
					
						
							|  |  |  |         f = self._new_future(loop=self.loop) | 
					
						
							|  |  |  |         self.assertTrue(hasattr(f, '_cancel_message')) | 
					
						
							|  |  |  |         self.assertEqual(f._cancel_message, None) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-06 17:30:27 -07:00
										 |  |  |         f.cancel('my message') | 
					
						
							| 
									
										
										
										
											2020-05-15 16:55:50 -07:00
										 |  |  |         with self.assertRaises(asyncio.CancelledError): | 
					
						
							|  |  |  |             self.loop.run_until_complete(f) | 
					
						
							|  |  |  |         self.assertEqual(f._cancel_message, 'my message') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_future_cancel_message_setter(self): | 
					
						
							|  |  |  |         f = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2022-10-06 17:30:27 -07:00
										 |  |  |         f.cancel('my message') | 
					
						
							| 
									
										
										
										
											2020-05-15 16:55:50 -07:00
										 |  |  |         f._cancel_message = 'my new message' | 
					
						
							|  |  |  |         self.assertEqual(f._cancel_message, 'my new message') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Also check that the value is used for cancel(). | 
					
						
							|  |  |  |         with self.assertRaises(asyncio.CancelledError): | 
					
						
							|  |  |  |             self.loop.run_until_complete(f) | 
					
						
							|  |  |  |         self.assertEqual(f._cancel_message, 'my new message') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     def test_cancel(self): | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertTrue(f.cancel()) | 
					
						
							|  |  |  |         self.assertTrue(f.cancelled()) | 
					
						
							|  |  |  |         self.assertTrue(f.done()) | 
					
						
							| 
									
										
										
										
											2014-01-25 15:32:06 +01:00
										 |  |  |         self.assertRaises(asyncio.CancelledError, f.result) | 
					
						
							|  |  |  |         self.assertRaises(asyncio.CancelledError, f.exception) | 
					
						
							|  |  |  |         self.assertRaises(asyncio.InvalidStateError, f.set_result, None) | 
					
						
							|  |  |  |         self.assertRaises(asyncio.InvalidStateError, f.set_exception, None) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertFalse(f.cancel()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_result(self): | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2014-01-25 15:32:06 +01:00
										 |  |  |         self.assertRaises(asyncio.InvalidStateError, f.result) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         f.set_result(42) | 
					
						
							|  |  |  |         self.assertFalse(f.cancelled()) | 
					
						
							|  |  |  |         self.assertTrue(f.done()) | 
					
						
							|  |  |  |         self.assertEqual(f.result(), 42) | 
					
						
							|  |  |  |         self.assertEqual(f.exception(), None) | 
					
						
							| 
									
										
										
										
											2014-01-25 15:32:06 +01:00
										 |  |  |         self.assertRaises(asyncio.InvalidStateError, f.set_result, None) | 
					
						
							|  |  |  |         self.assertRaises(asyncio.InvalidStateError, f.set_exception, None) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertFalse(f.cancel()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_exception(self): | 
					
						
							|  |  |  |         exc = RuntimeError() | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2014-01-25 15:32:06 +01:00
										 |  |  |         self.assertRaises(asyncio.InvalidStateError, f.exception) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         f.set_exception(exc) | 
					
						
							|  |  |  |         self.assertFalse(f.cancelled()) | 
					
						
							|  |  |  |         self.assertTrue(f.done()) | 
					
						
							|  |  |  |         self.assertRaises(RuntimeError, f.result) | 
					
						
							|  |  |  |         self.assertEqual(f.exception(), exc) | 
					
						
							| 
									
										
										
										
											2014-01-25 15:32:06 +01:00
										 |  |  |         self.assertRaises(asyncio.InvalidStateError, f.set_result, None) | 
					
						
							|  |  |  |         self.assertRaises(asyncio.InvalidStateError, f.set_exception, None) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertFalse(f.cancel()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-10 16:21:00 +11:00
										 |  |  |     def test_stop_iteration_exception(self, stop_iteration_class=StopIteration): | 
					
						
							|  |  |  |         exc = stop_iteration_class() | 
					
						
							|  |  |  |         f = self._new_future(loop=self.loop) | 
					
						
							|  |  |  |         f.set_exception(exc) | 
					
						
							|  |  |  |         self.assertFalse(f.cancelled()) | 
					
						
							|  |  |  |         self.assertTrue(f.done()) | 
					
						
							|  |  |  |         self.assertRaises(RuntimeError, f.result) | 
					
						
							|  |  |  |         exc = f.exception() | 
					
						
							|  |  |  |         cause = exc.__cause__ | 
					
						
							|  |  |  |         self.assertIsInstance(exc, RuntimeError) | 
					
						
							|  |  |  |         self.assertRegex(str(exc), 'StopIteration .* cannot be raised') | 
					
						
							|  |  |  |         self.assertIsInstance(cause, stop_iteration_class) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_stop_iteration_subclass_exception(self): | 
					
						
							|  |  |  |         class MyStopIteration(StopIteration): | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.test_stop_iteration_exception(MyStopIteration) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-30 16:01:54 -08:00
										 |  |  |     def test_exception_class(self): | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2014-01-30 16:01:54 -08:00
										 |  |  |         f.set_exception(RuntimeError) | 
					
						
							|  |  |  |         self.assertIsInstance(f.exception(), RuntimeError) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     def test_yield_from_twice(self): | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         def fixture(): | 
					
						
							|  |  |  |             yield 'A' | 
					
						
							|  |  |  |             x = yield from f | 
					
						
							|  |  |  |             yield 'B', x | 
					
						
							|  |  |  |             y = yield from f | 
					
						
							|  |  |  |             yield 'C', y | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         g = fixture() | 
					
						
							|  |  |  |         self.assertEqual(next(g), 'A')  # yield 'A'. | 
					
						
							|  |  |  |         self.assertEqual(next(g), f)  # First yield from f. | 
					
						
							|  |  |  |         f.set_result(42) | 
					
						
							|  |  |  |         self.assertEqual(next(g), ('B', 42))  # yield 'B', x. | 
					
						
							|  |  |  |         # The second "yield from f" does not yield f. | 
					
						
							|  |  |  |         self.assertEqual(next(g), ('C', 42))  # yield 'C', y. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-25 21:41:58 +02:00
										 |  |  |     def test_future_repr(self): | 
					
						
							| 
									
										
										
										
											2014-07-29 12:58:23 +02:00
										 |  |  |         self.loop.set_debug(True) | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f_pending_debug = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2014-07-29 12:58:23 +02:00
										 |  |  |         frame = f_pending_debug._source_traceback[-1] | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             repr(f_pending_debug), | 
					
						
							|  |  |  |             f'<{self.cls.__name__} pending created at {frame[0]}:{frame[1]}>') | 
					
						
							| 
									
										
										
										
											2014-07-29 12:58:23 +02:00
										 |  |  |         f_pending_debug.cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.loop.set_debug(False) | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f_pending = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  |         self.assertEqual(repr(f_pending), f'<{self.cls.__name__} pending>') | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         f_pending.cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f_cancelled = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         f_cancelled.cancel() | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  |         self.assertEqual(repr(f_cancelled), f'<{self.cls.__name__} cancelled>') | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f_result = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         f_result.set_result(4) | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             repr(f_result), f'<{self.cls.__name__} finished result=4>') | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual(f_result.result(), 4) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         exc = RuntimeError() | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f_exception = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         f_exception.set_exception(exc) | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             repr(f_exception), | 
					
						
							|  |  |  |             f'<{self.cls.__name__} finished exception=RuntimeError()>') | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertIs(f_exception.exception(), exc) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-25 21:41:58 +02:00
										 |  |  |         def func_repr(func): | 
					
						
							|  |  |  |             filename, lineno = test_utils.get_function_source(func) | 
					
						
							|  |  |  |             text = '%s() at %s:%s' % (func.__qualname__, filename, lineno) | 
					
						
							|  |  |  |             return re.escape(text) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f_one_callbacks = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2014-06-25 21:41:58 +02:00
										 |  |  |         f_one_callbacks.add_done_callback(_fakefunc) | 
					
						
							|  |  |  |         fake_repr = func_repr(_fakefunc) | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  |         self.assertRegex( | 
					
						
							|  |  |  |             repr(f_one_callbacks), | 
					
						
							|  |  |  |             r'<' + self.cls.__name__ + r' pending cb=\[%s\]>' % fake_repr) | 
					
						
							| 
									
										
										
										
											2014-06-25 21:41:58 +02:00
										 |  |  |         f_one_callbacks.cancel() | 
					
						
							|  |  |  |         self.assertEqual(repr(f_one_callbacks), | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  |                          f'<{self.cls.__name__} cancelled>') | 
					
						
							| 
									
										
										
										
											2014-06-25 21:41:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f_two_callbacks = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2014-06-25 21:41:58 +02:00
										 |  |  |         f_two_callbacks.add_done_callback(first_cb) | 
					
						
							|  |  |  |         f_two_callbacks.add_done_callback(last_cb) | 
					
						
							|  |  |  |         first_repr = func_repr(first_cb) | 
					
						
							|  |  |  |         last_repr = func_repr(last_cb) | 
					
						
							|  |  |  |         self.assertRegex(repr(f_two_callbacks), | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  |                          r'<' + self.cls.__name__ + r' pending cb=\[%s, %s\]>' | 
					
						
							| 
									
										
										
										
											2014-06-25 21:41:58 +02:00
										 |  |  |                          % (first_repr, last_repr)) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f_many_callbacks = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2014-06-25 21:41:58 +02:00
										 |  |  |         f_many_callbacks.add_done_callback(first_cb) | 
					
						
							|  |  |  |         for i in range(8): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |             f_many_callbacks.add_done_callback(_fakefunc) | 
					
						
							| 
									
										
										
										
											2014-06-25 21:41:58 +02:00
										 |  |  |         f_many_callbacks.add_done_callback(last_cb) | 
					
						
							|  |  |  |         cb_regex = r'%s, <8 more>, %s' % (first_repr, last_repr) | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  |         self.assertRegex( | 
					
						
							|  |  |  |             repr(f_many_callbacks), | 
					
						
							|  |  |  |             r'<' + self.cls.__name__ + r' pending cb=\[%s\]>' % cb_regex) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         f_many_callbacks.cancel() | 
					
						
							| 
									
										
										
										
											2014-06-25 21:41:58 +02:00
										 |  |  |         self.assertEqual(repr(f_many_callbacks), | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  |                          f'<{self.cls.__name__} cancelled>') | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_copy_state(self): | 
					
						
							| 
									
										
										
										
											2015-11-17 12:19:41 -05:00
										 |  |  |         from asyncio.futures import _copy_future_state | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         f.set_result(10) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         newf = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2015-11-17 12:19:41 -05:00
										 |  |  |         _copy_future_state(f, newf) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertTrue(newf.done()) | 
					
						
							|  |  |  |         self.assertEqual(newf.result(), 10) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f_exception = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         f_exception.set_exception(RuntimeError()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         newf_exception = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2015-11-17 12:19:41 -05:00
										 |  |  |         _copy_future_state(f_exception, newf_exception) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertTrue(newf_exception.done()) | 
					
						
							|  |  |  |         self.assertRaises(RuntimeError, newf_exception.result) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f_cancelled = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         f_cancelled.cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         newf_cancelled = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2015-11-17 12:19:41 -05:00
										 |  |  |         _copy_future_state(f_cancelled, newf_cancelled) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertTrue(newf_cancelled.cancelled()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-04 11:13:32 +08:00
										 |  |  |         try: | 
					
						
							|  |  |  |             raise concurrent.futures.InvalidStateError | 
					
						
							|  |  |  |         except BaseException as e: | 
					
						
							|  |  |  |             f_exc = e | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         f_conexc = self._new_future(loop=self.loop) | 
					
						
							|  |  |  |         f_conexc.set_exception(f_exc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         newf_conexc = self._new_future(loop=self.loop) | 
					
						
							|  |  |  |         _copy_future_state(f_conexc, newf_conexc) | 
					
						
							|  |  |  |         self.assertTrue(newf_conexc.done()) | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             newf_conexc.result() | 
					
						
							|  |  |  |         except BaseException as e: | 
					
						
							|  |  |  |             newf_exc = e # assertRaises context manager drops the traceback | 
					
						
							|  |  |  |         newf_tb = ''.join(traceback.format_tb(newf_exc.__traceback__)) | 
					
						
							|  |  |  |         self.assertEqual(newf_tb.count('raise concurrent.futures.InvalidStateError'), 1) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     def test_iter(self): | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         fut = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         def coro(): | 
					
						
							|  |  |  |             yield from fut | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def test(): | 
					
						
							|  |  |  |             arg1, arg2 = coro() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-25 10:48:15 -05:00
										 |  |  |         with self.assertRaisesRegex(RuntimeError, "await wasn't used"): | 
					
						
							|  |  |  |             test() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         fut.cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-25 16:16:10 -05:00
										 |  |  |     def test_log_traceback(self): | 
					
						
							|  |  |  |         fut = self._new_future(loop=self.loop) | 
					
						
							|  |  |  |         with self.assertRaisesRegex(ValueError, 'can only be set to False'): | 
					
						
							|  |  |  |             fut._log_traceback = True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 10:25:02 +01:00
										 |  |  |     @mock.patch('asyncio.base_events.logger') | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     def test_tb_logger_abandoned(self, m_log): | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         fut = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         del fut | 
					
						
							|  |  |  |         self.assertFalse(m_log.error.called) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-11 13:49:18 +00:00
										 |  |  |     @mock.patch('asyncio.base_events.logger') | 
					
						
							|  |  |  |     def test_tb_logger_not_called_after_cancel(self, m_log): | 
					
						
							|  |  |  |         fut = self._new_future(loop=self.loop) | 
					
						
							|  |  |  |         fut.set_exception(Exception()) | 
					
						
							|  |  |  |         fut.cancel() | 
					
						
							|  |  |  |         del fut | 
					
						
							|  |  |  |         self.assertFalse(m_log.error.called) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 10:25:02 +01:00
										 |  |  |     @mock.patch('asyncio.base_events.logger') | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     def test_tb_logger_result_unretrieved(self, m_log): | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         fut = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         fut.set_result(42) | 
					
						
							|  |  |  |         del fut | 
					
						
							|  |  |  |         self.assertFalse(m_log.error.called) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 10:25:02 +01:00
										 |  |  |     @mock.patch('asyncio.base_events.logger') | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     def test_tb_logger_result_retrieved(self, m_log): | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         fut = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         fut.set_result(42) | 
					
						
							|  |  |  |         fut.result() | 
					
						
							|  |  |  |         del fut | 
					
						
							|  |  |  |         self.assertFalse(m_log.error.called) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 10:25:02 +01:00
										 |  |  |     @mock.patch('asyncio.base_events.logger') | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     def test_tb_logger_exception_unretrieved(self, m_log): | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         fut = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         fut.set_exception(RuntimeError('boom')) | 
					
						
							|  |  |  |         del fut | 
					
						
							|  |  |  |         test_utils.run_briefly(self.loop) | 
					
						
							| 
									
										
										
										
											2016-05-13 16:10:43 -04:00
										 |  |  |         support.gc_collect() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertTrue(m_log.error.called) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 10:25:02 +01:00
										 |  |  |     @mock.patch('asyncio.base_events.logger') | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     def test_tb_logger_exception_retrieved(self, m_log): | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         fut = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         fut.set_exception(RuntimeError('boom')) | 
					
						
							|  |  |  |         fut.exception() | 
					
						
							|  |  |  |         del fut | 
					
						
							|  |  |  |         self.assertFalse(m_log.error.called) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 10:25:02 +01:00
										 |  |  |     @mock.patch('asyncio.base_events.logger') | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     def test_tb_logger_exception_result_retrieved(self, m_log): | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         fut = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         fut.set_exception(RuntimeError('boom')) | 
					
						
							|  |  |  |         self.assertRaises(RuntimeError, fut.result) | 
					
						
							|  |  |  |         del fut | 
					
						
							|  |  |  |         self.assertFalse(m_log.error.called) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_wrap_future(self): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def run(arg): | 
					
						
							|  |  |  |             return (arg, threading.get_ident()) | 
					
						
							|  |  |  |         ex = concurrent.futures.ThreadPoolExecutor(1) | 
					
						
							|  |  |  |         f1 = ex.submit(run, 'oi') | 
					
						
							| 
									
										
										
										
											2014-01-25 15:32:06 +01:00
										 |  |  |         f2 = asyncio.wrap_future(f1, loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         res, ident = self.loop.run_until_complete(f2) | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         self.assertTrue(asyncio.isfuture(f2)) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual(res, 'oi') | 
					
						
							|  |  |  |         self.assertNotEqual(ident, threading.get_ident()) | 
					
						
							| 
									
										
										
										
											2017-09-01 14:46:06 +02:00
										 |  |  |         ex.shutdown(wait=True) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_wrap_future_future(self): | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         f1 = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2014-01-25 15:32:06 +01:00
										 |  |  |         f2 = asyncio.wrap_future(f1) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertIs(f1, f2) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-25 13:40:44 +03:00
										 |  |  |     def test_wrap_future_without_loop(self): | 
					
						
							|  |  |  |         def run(arg): | 
					
						
							|  |  |  |             return (arg, threading.get_ident()) | 
					
						
							|  |  |  |         ex = concurrent.futures.ThreadPoolExecutor(1) | 
					
						
							|  |  |  |         f1 = ex.submit(run, 'oi') | 
					
						
							| 
									
										
										
										
											2022-12-06 19:42:12 +02:00
										 |  |  |         with self.assertRaisesRegex(RuntimeError, 'no current event loop'): | 
					
						
							|  |  |  |             asyncio.wrap_future(f1) | 
					
						
							| 
									
										
										
										
											2021-04-25 13:40:44 +03:00
										 |  |  |         ex.shutdown(wait=True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_wrap_future_use_running_loop(self): | 
					
						
							|  |  |  |         def run(arg): | 
					
						
							|  |  |  |             return (arg, threading.get_ident()) | 
					
						
							|  |  |  |         ex = concurrent.futures.ThreadPoolExecutor(1) | 
					
						
							|  |  |  |         f1 = ex.submit(run, 'oi') | 
					
						
							|  |  |  |         async def test(): | 
					
						
							|  |  |  |             return asyncio.wrap_future(f1) | 
					
						
							|  |  |  |         f2 = self.loop.run_until_complete(test()) | 
					
						
							|  |  |  |         self.assertIs(self.loop, f2._loop) | 
					
						
							|  |  |  |         ex.shutdown(wait=True) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-16 15:38:39 -04:00
										 |  |  |     def test_wrap_future_use_global_loop(self): | 
					
						
							| 
									
										
										
										
											2022-12-06 19:42:12 +02:00
										 |  |  |         # Deprecated in 3.10, undeprecated in 3.12 | 
					
						
							| 
									
										
										
										
											2021-04-25 13:40:44 +03:00
										 |  |  |         asyncio.set_event_loop(self.loop) | 
					
						
							|  |  |  |         self.addCleanup(asyncio.set_event_loop, None) | 
					
						
							|  |  |  |         def run(arg): | 
					
						
							|  |  |  |             return (arg, threading.get_ident()) | 
					
						
							|  |  |  |         ex = concurrent.futures.ThreadPoolExecutor(1) | 
					
						
							|  |  |  |         f1 = ex.submit(run, 'oi') | 
					
						
							| 
									
										
										
										
											2022-12-06 19:42:12 +02:00
										 |  |  |         f2 = asyncio.wrap_future(f1) | 
					
						
							| 
									
										
										
										
											2021-04-25 13:40:44 +03:00
										 |  |  |         self.assertIs(self.loop, f2._loop) | 
					
						
							|  |  |  |         ex.shutdown(wait=True) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-22 11:47:22 -08:00
										 |  |  |     def test_wrap_future_cancel(self): | 
					
						
							|  |  |  |         f1 = concurrent.futures.Future() | 
					
						
							| 
									
										
										
										
											2014-01-25 15:32:06 +01:00
										 |  |  |         f2 = asyncio.wrap_future(f1, loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-11-22 11:47:22 -08:00
										 |  |  |         f2.cancel() | 
					
						
							|  |  |  |         test_utils.run_briefly(self.loop) | 
					
						
							|  |  |  |         self.assertTrue(f1.cancelled()) | 
					
						
							|  |  |  |         self.assertTrue(f2.cancelled()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_wrap_future_cancel2(self): | 
					
						
							|  |  |  |         f1 = concurrent.futures.Future() | 
					
						
							| 
									
										
										
										
											2014-01-25 15:32:06 +01:00
										 |  |  |         f2 = asyncio.wrap_future(f1, loop=self.loop) | 
					
						
							| 
									
										
										
										
											2013-11-22 11:47:22 -08:00
										 |  |  |         f1.set_result(42) | 
					
						
							|  |  |  |         f2.cancel() | 
					
						
							|  |  |  |         test_utils.run_briefly(self.loop) | 
					
						
							|  |  |  |         self.assertFalse(f1.cancelled()) | 
					
						
							|  |  |  |         self.assertEqual(f1.result(), 42) | 
					
						
							|  |  |  |         self.assertTrue(f2.cancelled()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-27 13:52:20 +02:00
										 |  |  |     def test_future_source_traceback(self): | 
					
						
							|  |  |  |         self.loop.set_debug(True) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         future = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2014-06-27 13:52:20 +02:00
										 |  |  |         lineno = sys._getframe().f_lineno - 1 | 
					
						
							|  |  |  |         self.assertIsInstance(future._source_traceback, list) | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         self.assertEqual(future._source_traceback[-2][:3], | 
					
						
							| 
									
										
										
										
											2014-06-27 13:52:20 +02:00
										 |  |  |                          (__file__, | 
					
						
							|  |  |  |                           lineno, | 
					
						
							|  |  |  |                           'test_future_source_traceback')) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @mock.patch('asyncio.base_events.logger') | 
					
						
							| 
									
										
										
										
											2014-11-20 14:16:31 +01:00
										 |  |  |     def check_future_exception_never_retrieved(self, debug, m_log): | 
					
						
							|  |  |  |         self.loop.set_debug(debug) | 
					
						
							| 
									
										
										
										
											2014-06-27 13:52:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-08 11:29:25 +02:00
										 |  |  |         def memory_error(): | 
					
						
							| 
									
										
										
										
											2014-06-27 13:52:20 +02:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 raise MemoryError() | 
					
						
							|  |  |  |             except BaseException as exc: | 
					
						
							|  |  |  |                 return exc | 
					
						
							| 
									
										
										
										
											2014-07-08 11:29:25 +02:00
										 |  |  |         exc = memory_error() | 
					
						
							| 
									
										
										
										
											2014-06-27 13:52:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         future = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2014-06-27 13:52:20 +02:00
										 |  |  |         future.set_exception(exc) | 
					
						
							|  |  |  |         future = None | 
					
						
							|  |  |  |         test_utils.run_briefly(self.loop) | 
					
						
							|  |  |  |         support.gc_collect() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-13 17:28:02 +03:00
										 |  |  |         regex = f'^{self.cls.__name__} exception was never retrieved\n' | 
					
						
							|  |  |  |         exc_info = (type(exc), exc, exc.__traceback__) | 
					
						
							|  |  |  |         m_log.error.assert_called_once_with(mock.ANY, exc_info=exc_info) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-27 13:52:20 +02:00
										 |  |  |         message = m_log.error.call_args[0][0] | 
					
						
							|  |  |  |         self.assertRegex(message, re.compile(regex, re.DOTALL)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-20 14:16:31 +01:00
										 |  |  |     def test_future_exception_never_retrieved(self): | 
					
						
							|  |  |  |         self.check_future_exception_never_retrieved(False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_future_exception_never_retrieved_debug(self): | 
					
						
							|  |  |  |         self.check_future_exception_never_retrieved(True) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-05 15:29:41 +02:00
										 |  |  |     def test_set_result_unless_cancelled(self): | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         fut = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2014-07-05 15:29:41 +02:00
										 |  |  |         fut.cancel() | 
					
						
							| 
									
										
										
										
											2015-11-17 12:19:41 -05:00
										 |  |  |         futures._set_result_unless_cancelled(fut, 2) | 
					
						
							| 
									
										
										
										
											2014-07-05 15:29:41 +02:00
										 |  |  |         self.assertTrue(fut.cancelled()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-20 15:54:20 -04:00
										 |  |  |     def test_future_stop_iteration_args(self): | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         fut = self._new_future(loop=self.loop) | 
					
						
							| 
									
										
										
										
											2016-10-20 15:54:20 -04:00
										 |  |  |         fut.set_result((1, 2)) | 
					
						
							|  |  |  |         fi = fut.__iter__() | 
					
						
							|  |  |  |         result = None | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             fi.send(None) | 
					
						
							|  |  |  |         except StopIteration as ex: | 
					
						
							|  |  |  |             result = ex.args[0] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.fail('StopIteration was expected') | 
					
						
							|  |  |  |         self.assertEqual(result, (1, 2)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-14 00:15:44 -08:00
										 |  |  |     def test_future_iter_throw(self): | 
					
						
							|  |  |  |         fut = self._new_future(loop=self.loop) | 
					
						
							|  |  |  |         fi = iter(fut) | 
					
						
							| 
									
										
										
										
											2022-09-30 16:43:02 +08:00
										 |  |  |         with self.assertWarns(DeprecationWarning): | 
					
						
							|  |  |  |             self.assertRaises(Exception, fi.throw, Exception, Exception("zebra"), None) | 
					
						
							|  |  |  |         with warnings.catch_warnings(): | 
					
						
							|  |  |  |             warnings.filterwarnings("ignore", category=DeprecationWarning) | 
					
						
							|  |  |  |             self.assertRaises(TypeError, fi.throw, | 
					
						
							|  |  |  |                             Exception, Exception("elephant"), 32) | 
					
						
							|  |  |  |             self.assertRaises(TypeError, fi.throw, | 
					
						
							|  |  |  |                             Exception("elephant"), Exception("elephant")) | 
					
						
							| 
									
										
										
										
											2023-01-25 12:01:01 -08:00
										 |  |  |             # https://github.com/python/cpython/issues/101326 | 
					
						
							|  |  |  |             self.assertRaises(ValueError, fi.throw, ValueError, None, None) | 
					
						
							| 
									
										
										
										
											2016-11-14 00:15:44 -08:00
										 |  |  |         self.assertRaises(TypeError, fi.throw, list) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-01 23:31:07 -07:00
										 |  |  |     def test_future_del_collect(self): | 
					
						
							|  |  |  |         class Evil: | 
					
						
							|  |  |  |             def __del__(self): | 
					
						
							|  |  |  |                 gc.collect() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for i in range(100): | 
					
						
							|  |  |  |             fut = self._new_future(loop=self.loop) | 
					
						
							|  |  |  |             fut.set_result(Evil()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  | @unittest.skipUnless(hasattr(futures, '_CFuture'), | 
					
						
							|  |  |  |                      'requires the C _asyncio module') | 
					
						
							|  |  |  | class CFutureTests(BaseFutureTests, test_utils.TestCase): | 
					
						
							| 
									
										
										
										
											2018-01-22 19:11:18 -05:00
										 |  |  |     try: | 
					
						
							|  |  |  |         cls = futures._CFuture | 
					
						
							|  |  |  |     except AttributeError: | 
					
						
							|  |  |  |         cls = None | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-17 07:52:45 -07:00
										 |  |  |     def test_future_del_segfault(self): | 
					
						
							|  |  |  |         fut = self._new_future(loop=self.loop) | 
					
						
							|  |  |  |         with self.assertRaises(AttributeError): | 
					
						
							|  |  |  |             del fut._asyncio_future_blocking | 
					
						
							|  |  |  |         with self.assertRaises(AttributeError): | 
					
						
							|  |  |  |             del fut._log_traceback | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | @unittest.skipUnless(hasattr(futures, '_CFuture'), | 
					
						
							|  |  |  |                      'requires the C _asyncio module') | 
					
						
							|  |  |  | class CSubFutureTests(BaseFutureTests, test_utils.TestCase): | 
					
						
							| 
									
										
										
										
											2018-01-22 19:11:18 -05:00
										 |  |  |     try: | 
					
						
							|  |  |  |         class CSubFuture(futures._CFuture): | 
					
						
							|  |  |  |             pass | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-22 19:11:18 -05:00
										 |  |  |         cls = CSubFuture | 
					
						
							|  |  |  |     except AttributeError: | 
					
						
							|  |  |  |         cls = None | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class PyFutureTests(BaseFutureTests, test_utils.TestCase): | 
					
						
							| 
									
										
										
										
											2017-09-03 08:10:14 +03:00
										 |  |  |     cls = futures._PyFuture | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class BaseFutureDoneCallbackTests(): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def setUp(self): | 
					
						
							| 
									
										
										
										
											2016-11-04 14:29:28 -04:00
										 |  |  |         super().setUp() | 
					
						
							| 
									
										
										
										
											2014-06-18 01:36:32 +02:00
										 |  |  |         self.loop = self.new_test_loop() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def run_briefly(self): | 
					
						
							|  |  |  |         test_utils.run_briefly(self.loop) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _make_callback(self, bag, thing): | 
					
						
							|  |  |  |         # Create a callback function that appends thing to bag. | 
					
						
							|  |  |  |         def bag_appender(future): | 
					
						
							|  |  |  |             bag.append(thing) | 
					
						
							|  |  |  |         return bag_appender | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _new_future(self): | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  |         raise NotImplementedError | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  |     def test_callbacks_remove_first_callback(self): | 
					
						
							|  |  |  |         bag = [] | 
					
						
							|  |  |  |         f = self._new_future() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cb1 = self._make_callback(bag, 42) | 
					
						
							|  |  |  |         cb2 = self._make_callback(bag, 17) | 
					
						
							|  |  |  |         cb3 = self._make_callback(bag, 100) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         f.add_done_callback(cb1) | 
					
						
							|  |  |  |         f.add_done_callback(cb2) | 
					
						
							|  |  |  |         f.add_done_callback(cb3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         f.remove_done_callback(cb1) | 
					
						
							|  |  |  |         f.remove_done_callback(cb1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(bag, []) | 
					
						
							|  |  |  |         f.set_result('foo') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.run_briefly() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(bag, [17, 100]) | 
					
						
							|  |  |  |         self.assertEqual(f.result(), 'foo') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_callbacks_remove_first_and_second_callback(self): | 
					
						
							|  |  |  |         bag = [] | 
					
						
							|  |  |  |         f = self._new_future() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cb1 = self._make_callback(bag, 42) | 
					
						
							|  |  |  |         cb2 = self._make_callback(bag, 17) | 
					
						
							|  |  |  |         cb3 = self._make_callback(bag, 100) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         f.add_done_callback(cb1) | 
					
						
							|  |  |  |         f.add_done_callback(cb2) | 
					
						
							|  |  |  |         f.add_done_callback(cb3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         f.remove_done_callback(cb1) | 
					
						
							|  |  |  |         f.remove_done_callback(cb2) | 
					
						
							|  |  |  |         f.remove_done_callback(cb1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(bag, []) | 
					
						
							|  |  |  |         f.set_result('foo') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.run_briefly() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(bag, [100]) | 
					
						
							|  |  |  |         self.assertEqual(f.result(), 'foo') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_callbacks_remove_third_callback(self): | 
					
						
							|  |  |  |         bag = [] | 
					
						
							|  |  |  |         f = self._new_future() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cb1 = self._make_callback(bag, 42) | 
					
						
							|  |  |  |         cb2 = self._make_callback(bag, 17) | 
					
						
							|  |  |  |         cb3 = self._make_callback(bag, 100) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         f.add_done_callback(cb1) | 
					
						
							|  |  |  |         f.add_done_callback(cb2) | 
					
						
							|  |  |  |         f.add_done_callback(cb3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         f.remove_done_callback(cb3) | 
					
						
							|  |  |  |         f.remove_done_callback(cb3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(bag, []) | 
					
						
							|  |  |  |         f.set_result('foo') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.run_briefly() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(bag, [42, 17]) | 
					
						
							|  |  |  |         self.assertEqual(f.result(), 'foo') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     def test_callbacks_invoked_on_set_result(self): | 
					
						
							|  |  |  |         bag = [] | 
					
						
							|  |  |  |         f = self._new_future() | 
					
						
							|  |  |  |         f.add_done_callback(self._make_callback(bag, 42)) | 
					
						
							|  |  |  |         f.add_done_callback(self._make_callback(bag, 17)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(bag, []) | 
					
						
							|  |  |  |         f.set_result('foo') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.run_briefly() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(bag, [42, 17]) | 
					
						
							|  |  |  |         self.assertEqual(f.result(), 'foo') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_callbacks_invoked_on_set_exception(self): | 
					
						
							|  |  |  |         bag = [] | 
					
						
							|  |  |  |         f = self._new_future() | 
					
						
							|  |  |  |         f.add_done_callback(self._make_callback(bag, 100)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(bag, []) | 
					
						
							|  |  |  |         exc = RuntimeError() | 
					
						
							|  |  |  |         f.set_exception(exc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.run_briefly() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(bag, [100]) | 
					
						
							|  |  |  |         self.assertEqual(f.exception(), exc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_remove_done_callback(self): | 
					
						
							|  |  |  |         bag = [] | 
					
						
							|  |  |  |         f = self._new_future() | 
					
						
							|  |  |  |         cb1 = self._make_callback(bag, 1) | 
					
						
							|  |  |  |         cb2 = self._make_callback(bag, 2) | 
					
						
							|  |  |  |         cb3 = self._make_callback(bag, 3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Add one cb1 and one cb2. | 
					
						
							|  |  |  |         f.add_done_callback(cb1) | 
					
						
							|  |  |  |         f.add_done_callback(cb2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # One instance of cb2 removed. Now there's only one cb1. | 
					
						
							|  |  |  |         self.assertEqual(f.remove_done_callback(cb2), 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Never had any cb3 in there. | 
					
						
							|  |  |  |         self.assertEqual(f.remove_done_callback(cb3), 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # After this there will be 6 instances of cb1 and one of cb2. | 
					
						
							|  |  |  |         f.add_done_callback(cb2) | 
					
						
							|  |  |  |         for i in range(5): | 
					
						
							|  |  |  |             f.add_done_callback(cb1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Remove all instances of cb1. One cb2 remains. | 
					
						
							|  |  |  |         self.assertEqual(f.remove_done_callback(cb1), 6) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(bag, []) | 
					
						
							|  |  |  |         f.set_result('foo') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.run_briefly() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(bag, [2]) | 
					
						
							|  |  |  |         self.assertEqual(f.result(), 'foo') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-02 23:46:56 -05:00
										 |  |  |     def test_remove_done_callbacks_list_mutation(self): | 
					
						
							|  |  |  |         # see http://bugs.python.org/issue28963 for details | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fut = self._new_future() | 
					
						
							|  |  |  |         fut.add_done_callback(str) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for _ in range(63): | 
					
						
							|  |  |  |             fut.add_done_callback(id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class evil: | 
					
						
							|  |  |  |             def __eq__(self, other): | 
					
						
							|  |  |  |                 fut.remove_done_callback(id) | 
					
						
							|  |  |  |                 return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fut.remove_done_callback(evil()) | 
					
						
							| 
									
										
										
										
											2022-09-30 12:57:09 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_remove_done_callbacks_list_clear(self): | 
					
						
							|  |  |  |         # see https://github.com/python/cpython/issues/97592 for details | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fut = self._new_future() | 
					
						
							|  |  |  |         fut.add_done_callback(str) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for _ in range(63): | 
					
						
							|  |  |  |             fut.add_done_callback(id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class evil: | 
					
						
							|  |  |  |             def __eq__(self, other): | 
					
						
							|  |  |  |                 fut.remove_done_callback(other) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fut.remove_done_callback(evil()) | 
					
						
							| 
									
										
										
										
											2017-03-02 23:46:56 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-05 13:32:03 -04:00
										 |  |  |     def test_schedule_callbacks_list_mutation_1(self): | 
					
						
							| 
									
										
										
										
											2017-03-02 23:46:56 -05:00
										 |  |  |         # see http://bugs.python.org/issue28963 for details | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def mut(f): | 
					
						
							|  |  |  |             f.remove_done_callback(str) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fut = self._new_future() | 
					
						
							|  |  |  |         fut.add_done_callback(mut) | 
					
						
							|  |  |  |         fut.add_done_callback(str) | 
					
						
							|  |  |  |         fut.add_done_callback(str) | 
					
						
							|  |  |  |         fut.set_result(1) | 
					
						
							|  |  |  |         test_utils.run_briefly(self.loop) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-05 13:32:03 -04:00
										 |  |  |     def test_schedule_callbacks_list_mutation_2(self): | 
					
						
							|  |  |  |         # see http://bugs.python.org/issue30828 for details | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fut = self._new_future() | 
					
						
							|  |  |  |         fut.add_done_callback(str) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for _ in range(63): | 
					
						
							|  |  |  |             fut.add_done_callback(id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         max_extra_cbs = 100 | 
					
						
							|  |  |  |         extra_cbs = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class evil: | 
					
						
							|  |  |  |             def __eq__(self, other): | 
					
						
							|  |  |  |                 nonlocal extra_cbs | 
					
						
							|  |  |  |                 extra_cbs += 1 | 
					
						
							|  |  |  |                 if extra_cbs < max_extra_cbs: | 
					
						
							|  |  |  |                     fut.add_done_callback(id) | 
					
						
							|  |  |  |                 return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fut.remove_done_callback(evil()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  | @unittest.skipUnless(hasattr(futures, '_CFuture'), | 
					
						
							|  |  |  |                      'requires the C _asyncio module') | 
					
						
							|  |  |  | class CFutureDoneCallbackTests(BaseFutureDoneCallbackTests, | 
					
						
							|  |  |  |                                test_utils.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _new_future(self): | 
					
						
							|  |  |  |         return futures._CFuture(loop=self.loop) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 20:19:47 -05:00
										 |  |  | @unittest.skipUnless(hasattr(futures, '_CFuture'), | 
					
						
							|  |  |  |                      'requires the C _asyncio module') | 
					
						
							|  |  |  | class CSubFutureDoneCallbackTests(BaseFutureDoneCallbackTests, | 
					
						
							|  |  |  |                                   test_utils.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _new_future(self): | 
					
						
							|  |  |  |         class CSubFuture(futures._CFuture): | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         return CSubFuture(loop=self.loop) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-23 22:34:35 -04:00
										 |  |  | class PyFutureDoneCallbackTests(BaseFutureDoneCallbackTests, | 
					
						
							|  |  |  |                                 test_utils.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _new_future(self): | 
					
						
							|  |  |  |         return futures._PyFuture(loop=self.loop) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-13 23:36:46 +02:00
										 |  |  | class BaseFutureInheritanceTests: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _get_future_cls(self): | 
					
						
							|  |  |  |         raise NotImplementedError | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def setUp(self): | 
					
						
							|  |  |  |         super().setUp() | 
					
						
							|  |  |  |         self.loop = self.new_test_loop() | 
					
						
							|  |  |  |         self.addCleanup(self.loop.close) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_inherit_without_calling_super_init(self): | 
					
						
							|  |  |  |         # See https://bugs.python.org/issue38785 for the context | 
					
						
							|  |  |  |         cls = self._get_future_cls() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class MyFut(cls): | 
					
						
							|  |  |  |             def __init__(self, *args, **kwargs): | 
					
						
							|  |  |  |                 # don't call super().__init__() | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fut = MyFut(loop=self.loop) | 
					
						
							|  |  |  |         with self.assertRaisesRegex( | 
					
						
							|  |  |  |             RuntimeError, | 
					
						
							|  |  |  |             "Future object is not initialized." | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             fut.get_loop() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class PyFutureInheritanceTests(BaseFutureInheritanceTests, | 
					
						
							|  |  |  |                                test_utils.TestCase): | 
					
						
							|  |  |  |     def _get_future_cls(self): | 
					
						
							|  |  |  |         return futures._PyFuture | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-26 15:48:24 +03:00
										 |  |  | @unittest.skipUnless(hasattr(futures, '_CFuture'), | 
					
						
							|  |  |  |                      'requires the C _asyncio module') | 
					
						
							| 
									
										
										
										
											2019-11-13 23:36:46 +02:00
										 |  |  | class CFutureInheritanceTests(BaseFutureInheritanceTests, | 
					
						
							|  |  |  |                               test_utils.TestCase): | 
					
						
							|  |  |  |     def _get_future_cls(self): | 
					
						
							|  |  |  |         return futures._CFuture | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     unittest.main() |