| 
									
										
										
										
											2022-03-25 23:01:21 +01:00
										 |  |  | """Tests for locks.py""" | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | import unittest | 
					
						
							| 
									
										
										
										
											2014-02-26 10:25:02 +01:00
										 |  |  | from unittest import mock | 
					
						
							| 
									
										
										
										
											2013-11-04 13:18:19 -08:00
										 |  |  | import re | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-25 15:32:06 +01:00
										 |  |  | import asyncio | 
					
						
							| 
									
										
										
										
											2022-09-22 12:34:45 -04:00
										 |  |  | import collections | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-04 13:18:19 -08:00
										 |  |  | STR_RGX_REPR = ( | 
					
						
							|  |  |  |     r'^<(?P<class>.*?) object at (?P<address>.*?)' | 
					
						
							|  |  |  |     r'\[(?P<extras>' | 
					
						
							| 
									
										
										
										
											2022-03-25 23:01:21 +01:00
										 |  |  |     r'(set|unset|locked|unlocked|filling|draining|resetting|broken)' | 
					
						
							|  |  |  |     r'(, value:\d)?' | 
					
						
							|  |  |  |     r'(, waiters:\d+)?' | 
					
						
							|  |  |  |     r'(, waiters:\d+\/\d+)?' # barrier | 
					
						
							| 
									
										
										
										
											2013-11-04 13:18:19 -08:00
										 |  |  |     r')\]>\Z' | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | RGX_REPR = re.compile(STR_RGX_REPR) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 20:34:09 -07:00
										 |  |  | def tearDownModule(): | 
					
						
							|  |  |  |     asyncio.set_event_loop_policy(None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  | class LockTests(unittest.IsolatedAsyncioTestCase): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_repr(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         lock = asyncio.Lock() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertTrue(repr(lock).endswith('[unlocked]>')) | 
					
						
							| 
									
										
										
										
											2013-11-04 13:18:19 -08:00
										 |  |  |         self.assertTrue(RGX_REPR.match(repr(lock))) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await lock.acquire() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertTrue(repr(lock).endswith('[locked]>')) | 
					
						
							| 
									
										
										
										
											2013-11-04 13:18:19 -08:00
										 |  |  |         self.assertTrue(RGX_REPR.match(repr(lock))) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_lock(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         lock = asyncio.Lock() | 
					
						
							| 
									
										
										
										
											2019-09-10 07:55:07 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-01 13:12:52 +02:00
										 |  |  |         with self.assertRaisesRegex( | 
					
						
							|  |  |  |             TypeError, | 
					
						
							| 
									
										
										
										
											2021-07-01 16:13:59 +03:00
										 |  |  |             "object Lock can't be used in 'await' expression" | 
					
						
							| 
									
										
										
										
											2020-02-01 13:12:52 +02:00
										 |  |  |         ): | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |             await lock | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.assertFalse(lock.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_lock_doesnt_accept_loop_parameter(self): | 
					
						
							| 
									
										
										
										
											2020-11-25 13:50:44 +02:00
										 |  |  |         primitives_cls = [ | 
					
						
							|  |  |  |             asyncio.Lock, | 
					
						
							|  |  |  |             asyncio.Condition, | 
					
						
							|  |  |  |             asyncio.Event, | 
					
						
							|  |  |  |             asyncio.Semaphore, | 
					
						
							|  |  |  |             asyncio.BoundedSemaphore, | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         loop = asyncio.get_running_loop() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-25 13:50:44 +02:00
										 |  |  |         for cls in primitives_cls: | 
					
						
							|  |  |  |             with self.assertRaisesRegex( | 
					
						
							|  |  |  |                 TypeError, | 
					
						
							| 
									
										
										
										
											2022-02-21 13:25:52 +02:00
										 |  |  |                 rf"{cls.__name__}\.__init__\(\) got an unexpected " | 
					
						
							|  |  |  |                 rf"keyword argument 'loop'" | 
					
						
							| 
									
										
										
										
											2020-11-25 13:50:44 +02:00
										 |  |  |             ): | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |                 cls(loop=loop) | 
					
						
							| 
									
										
										
										
											2020-11-25 13:50:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_lock_by_with_statement(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         primitives = [ | 
					
						
							|  |  |  |             asyncio.Lock(), | 
					
						
							|  |  |  |             asyncio.Condition(), | 
					
						
							|  |  |  |             asyncio.Semaphore(), | 
					
						
							|  |  |  |             asyncio.BoundedSemaphore(), | 
					
						
							|  |  |  |         ] | 
					
						
							| 
									
										
										
										
											2019-09-10 07:55:07 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         for lock in primitives: | 
					
						
							| 
									
										
										
										
											2021-07-01 16:13:59 +03:00
										 |  |  |             await asyncio.sleep(0.01) | 
					
						
							|  |  |  |             self.assertFalse(lock.locked()) | 
					
						
							|  |  |  |             with self.assertRaisesRegex( | 
					
						
							|  |  |  |                 TypeError, | 
					
						
							|  |  |  |                 r"object \w+ can't be used in 'await' expression" | 
					
						
							|  |  |  |             ): | 
					
						
							|  |  |  |                 with await lock: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  |             self.assertFalse(lock.locked()) | 
					
						
							| 
									
										
										
										
											2017-12-09 20:00:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_acquire(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         lock = asyncio.Lock() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         result = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         self.assertTrue(await lock.acquire()) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c1(result): | 
					
						
							|  |  |  |             if await lock.acquire(): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |                 result.append(1) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c2(result): | 
					
						
							|  |  |  |             if await lock.acquire(): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |                 result.append(2) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c3(result): | 
					
						
							|  |  |  |             if await lock.acquire(): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |                 result.append(3) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         t1 = asyncio.create_task(c1(result)) | 
					
						
							|  |  |  |         t2 = asyncio.create_task(c2(result)) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([], result) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         lock.release() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([1], result) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([1], result) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         t3 = asyncio.create_task(c3(result)) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         lock.release() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([1, 2], result) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         lock.release() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([1, 2, 3], result) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(t1.done()) | 
					
						
							|  |  |  |         self.assertTrue(t1.result()) | 
					
						
							|  |  |  |         self.assertTrue(t2.done()) | 
					
						
							|  |  |  |         self.assertTrue(t2.result()) | 
					
						
							|  |  |  |         self.assertTrue(t3.done()) | 
					
						
							|  |  |  |         self.assertTrue(t3.result()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_acquire_cancel(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         lock = asyncio.Lock() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         self.assertTrue(await lock.acquire()) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         task = asyncio.create_task(lock.acquire()) | 
					
						
							|  |  |  |         asyncio.get_running_loop().call_soon(task.cancel) | 
					
						
							|  |  |  |         with self.assertRaises(asyncio.CancelledError): | 
					
						
							|  |  |  |             await task | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertFalse(lock._waiters) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_cancel_race(self): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         # Several tasks: | 
					
						
							|  |  |  |         # - A acquires the lock | 
					
						
							| 
									
										
										
										
											2016-09-07 12:03:06 +00:00
										 |  |  |         # - B is blocked in acquire() | 
					
						
							|  |  |  |         # - C is blocked in acquire() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         # | 
					
						
							|  |  |  |         # Now, concurrently: | 
					
						
							|  |  |  |         # - B is cancelled | 
					
						
							|  |  |  |         # - A releases the lock | 
					
						
							|  |  |  |         # | 
					
						
							|  |  |  |         # If B's waiter is marked cancelled but not yet removed from | 
					
						
							|  |  |  |         # _waiters, A's release() call will crash when trying to set | 
					
						
							|  |  |  |         # B's waiter; instead, it should move on to C's waiter. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Setup: A has the lock, b and c are waiting. | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         lock = asyncio.Lock() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def lockit(name, blocker): | 
					
						
							|  |  |  |             await lock.acquire() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 if blocker is not None: | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |                     await blocker | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |             finally: | 
					
						
							|  |  |  |                 lock.release() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         fa = asyncio.get_running_loop().create_future() | 
					
						
							|  |  |  |         ta = asyncio.create_task(lockit('A', fa)) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertTrue(lock.locked()) | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         tb = asyncio.create_task(lockit('B', None)) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual(len(lock._waiters), 1) | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         tc = asyncio.create_task(lockit('C', None)) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual(len(lock._waiters), 2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Create the race and check. | 
					
						
							|  |  |  |         # Without the fix this failed at the last assert. | 
					
						
							|  |  |  |         fa.set_result(None) | 
					
						
							|  |  |  |         tb.cancel() | 
					
						
							|  |  |  |         self.assertTrue(lock._waiters[0].cancelled()) | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertFalse(lock.locked()) | 
					
						
							|  |  |  |         self.assertTrue(ta.done()) | 
					
						
							|  |  |  |         self.assertTrue(tb.cancelled()) | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await tc | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_cancel_release_race(self): | 
					
						
							| 
									
										
										
										
											2018-02-03 00:04:00 +02:00
										 |  |  |         # Issue 32734 | 
					
						
							|  |  |  |         # Acquire 4 locks, cancel second, release first | 
					
						
							|  |  |  |         # and 2 locks are taken at once. | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         loop = asyncio.get_running_loop() | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         lock = asyncio.Lock() | 
					
						
							| 
									
										
										
										
											2018-02-03 00:04:00 +02:00
										 |  |  |         lock_count = 0 | 
					
						
							|  |  |  |         call_count = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def lockit(): | 
					
						
							|  |  |  |             nonlocal lock_count | 
					
						
							|  |  |  |             nonlocal call_count | 
					
						
							|  |  |  |             call_count += 1 | 
					
						
							|  |  |  |             await lock.acquire() | 
					
						
							|  |  |  |             lock_count += 1 | 
					
						
							| 
									
										
										
										
											2018-02-14 11:18:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-03 00:04:00 +02:00
										 |  |  |         def trigger(): | 
					
						
							|  |  |  |             t1.cancel() | 
					
						
							|  |  |  |             lock.release() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await lock.acquire() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t1 = asyncio.create_task(lockit()) | 
					
						
							|  |  |  |         t2 = asyncio.create_task(lockit()) | 
					
						
							|  |  |  |         t3 = asyncio.create_task(lockit()) | 
					
						
							| 
									
										
										
										
											2018-02-03 00:04:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         # Start scheduled tasks | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2018-02-03 00:04:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         loop.call_soon(trigger) | 
					
						
							|  |  |  |         with self.assertRaises(asyncio.CancelledError): | 
					
						
							|  |  |  |             # Wait for cancellation | 
					
						
							|  |  |  |             await t1 | 
					
						
							| 
									
										
										
										
											2018-02-03 00:04:00 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Make sure only one lock was taken | 
					
						
							|  |  |  |         self.assertEqual(lock_count, 1) | 
					
						
							|  |  |  |         # While 3 calls were made to lockit() | 
					
						
							|  |  |  |         self.assertEqual(call_count, 3) | 
					
						
							|  |  |  |         self.assertTrue(t1.cancelled() and t2.done()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Cleanup the task that is stuck on acquire. | 
					
						
							|  |  |  |         t3.cancel() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2018-02-03 00:04:00 +02:00
										 |  |  |         self.assertTrue(t3.cancelled()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_finished_waiter_cancelled(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         lock = asyncio.Lock() | 
					
						
							| 
									
										
										
										
											2017-06-09 22:17:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await lock.acquire() | 
					
						
							| 
									
										
										
										
											2017-06-09 22:17:40 +02:00
										 |  |  |         self.assertTrue(lock.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         tb = asyncio.create_task(lock.acquire()) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2017-06-09 22:17:40 +02:00
										 |  |  |         self.assertEqual(len(lock._waiters), 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Create a second waiter, wake up the first, and cancel it. | 
					
						
							|  |  |  |         # Without the fix, the second was not woken up. | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         tc = asyncio.create_task(lock.acquire()) | 
					
						
							| 
									
										
										
										
											2017-06-09 22:17:40 +02:00
										 |  |  |         tb.cancel() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         lock.release() | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2017-06-09 22:17:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(lock.locked()) | 
					
						
							|  |  |  |         self.assertTrue(tb.cancelled()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         # Cleanup | 
					
						
							|  |  |  |         await tc | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_release_not_acquired(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         lock = asyncio.Lock() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.assertRaises(RuntimeError, lock.release) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_release_no_waiters(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         lock = asyncio.Lock() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await lock.acquire() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertTrue(lock.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         lock.release() | 
					
						
							|  |  |  |         self.assertFalse(lock.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_context_manager(self): | 
					
						
							|  |  |  |         lock = asyncio.Lock() | 
					
						
							|  |  |  |         self.assertFalse(lock.locked()) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         async with lock: | 
					
						
							|  |  |  |             self.assertTrue(lock.locked()) | 
					
						
							| 
									
										
										
										
											2014-01-25 16:51:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         self.assertFalse(lock.locked()) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  | class EventTests(unittest.IsolatedAsyncioTestCase): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_repr(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         ev = asyncio.Event() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertTrue(repr(ev).endswith('[unset]>')) | 
					
						
							| 
									
										
										
										
											2013-11-04 13:18:19 -08:00
										 |  |  |         match = RGX_REPR.match(repr(ev)) | 
					
						
							|  |  |  |         self.assertEqual(match.group('extras'), 'unset') | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         ev.set() | 
					
						
							|  |  |  |         self.assertTrue(repr(ev).endswith('[set]>')) | 
					
						
							| 
									
										
										
										
											2013-11-04 13:18:19 -08:00
										 |  |  |         self.assertTrue(RGX_REPR.match(repr(ev))) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 10:25:02 +01:00
										 |  |  |         ev._waiters.append(mock.Mock()) | 
					
						
							| 
									
										
										
										
											2013-11-04 13:18:19 -08:00
										 |  |  |         self.assertTrue('waiters:1' in repr(ev)) | 
					
						
							|  |  |  |         self.assertTrue(RGX_REPR.match(repr(ev))) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_wait(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         ev = asyncio.Event() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertFalse(ev.is_set()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c1(result): | 
					
						
							|  |  |  |             if await ev.wait(): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |                 result.append(1) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c2(result): | 
					
						
							|  |  |  |             if await ev.wait(): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |                 result.append(2) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c3(result): | 
					
						
							|  |  |  |             if await ev.wait(): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |                 result.append(3) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         t1 = asyncio.create_task(c1(result)) | 
					
						
							|  |  |  |         t2 = asyncio.create_task(c2(result)) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([], result) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         t3 = asyncio.create_task(c3(result)) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         ev.set() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([3, 1, 2], result) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(t1.done()) | 
					
						
							|  |  |  |         self.assertIsNone(t1.result()) | 
					
						
							|  |  |  |         self.assertTrue(t2.done()) | 
					
						
							|  |  |  |         self.assertIsNone(t2.result()) | 
					
						
							|  |  |  |         self.assertTrue(t3.done()) | 
					
						
							|  |  |  |         self.assertIsNone(t3.result()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_wait_on_set(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         ev = asyncio.Event() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         ev.set() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         res = await ev.wait() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertTrue(res) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_wait_cancel(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         ev = asyncio.Event() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         wait = asyncio.create_task(ev.wait()) | 
					
						
							|  |  |  |         asyncio.get_running_loop().call_soon(wait.cancel) | 
					
						
							|  |  |  |         with self.assertRaises(asyncio.CancelledError): | 
					
						
							|  |  |  |             await wait | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertFalse(ev._waiters) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_clear(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         ev = asyncio.Event() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertFalse(ev.is_set()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ev.set() | 
					
						
							|  |  |  |         self.assertTrue(ev.is_set()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ev.clear() | 
					
						
							|  |  |  |         self.assertFalse(ev.is_set()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_clear_with_waiters(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         ev = asyncio.Event() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         result = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c1(result): | 
					
						
							|  |  |  |             if await ev.wait(): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |                 result.append(1) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         t = asyncio.create_task(c1(result)) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([], result) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ev.set() | 
					
						
							|  |  |  |         ev.clear() | 
					
						
							|  |  |  |         self.assertFalse(ev.is_set()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ev.set() | 
					
						
							|  |  |  |         ev.set() | 
					
						
							|  |  |  |         self.assertEqual(1, len(ev._waiters)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([1], result) | 
					
						
							|  |  |  |         self.assertEqual(0, len(ev._waiters)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(t.done()) | 
					
						
							|  |  |  |         self.assertTrue(t.result()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  | class ConditionTests(unittest.IsolatedAsyncioTestCase): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_wait(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         cond = asyncio.Condition() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         result = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c1(result): | 
					
						
							|  |  |  |             await cond.acquire() | 
					
						
							|  |  |  |             if await cond.wait(): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |                 result.append(1) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c2(result): | 
					
						
							|  |  |  |             await cond.acquire() | 
					
						
							|  |  |  |             if await cond.wait(): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |                 result.append(2) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c3(result): | 
					
						
							|  |  |  |             await cond.acquire() | 
					
						
							|  |  |  |             if await cond.wait(): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |                 result.append(3) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         t1 = asyncio.create_task(c1(result)) | 
					
						
							|  |  |  |         t2 = asyncio.create_task(c2(result)) | 
					
						
							|  |  |  |         t3 = asyncio.create_task(c3(result)) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([], result) | 
					
						
							|  |  |  |         self.assertFalse(cond.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         self.assertTrue(await cond.acquire()) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         cond.notify() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([], result) | 
					
						
							|  |  |  |         self.assertTrue(cond.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cond.release() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([1], result) | 
					
						
							|  |  |  |         self.assertTrue(cond.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cond.notify(2) | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([1], result) | 
					
						
							|  |  |  |         self.assertTrue(cond.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cond.release() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([1, 2], result) | 
					
						
							|  |  |  |         self.assertTrue(cond.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cond.release() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([1, 2, 3], result) | 
					
						
							|  |  |  |         self.assertTrue(cond.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(t1.done()) | 
					
						
							|  |  |  |         self.assertTrue(t1.result()) | 
					
						
							|  |  |  |         self.assertTrue(t2.done()) | 
					
						
							|  |  |  |         self.assertTrue(t2.result()) | 
					
						
							|  |  |  |         self.assertTrue(t3.done()) | 
					
						
							|  |  |  |         self.assertTrue(t3.result()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_wait_cancel(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         cond = asyncio.Condition() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await cond.acquire() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         wait = asyncio.create_task(cond.wait()) | 
					
						
							|  |  |  |         asyncio.get_running_loop().call_soon(wait.cancel) | 
					
						
							|  |  |  |         with self.assertRaises(asyncio.CancelledError): | 
					
						
							|  |  |  |             await wait | 
					
						
							| 
									
										
										
										
											2013-11-04 13:18:19 -08:00
										 |  |  |         self.assertFalse(cond._waiters) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertTrue(cond.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_wait_cancel_contested(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         cond = asyncio.Condition() | 
					
						
							| 
									
										
										
										
											2016-06-11 12:00:07 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await cond.acquire() | 
					
						
							| 
									
										
										
										
											2016-06-11 12:00:07 -04:00
										 |  |  |         self.assertTrue(cond.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         wait_task = asyncio.create_task(cond.wait()) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2016-06-11 12:00:07 -04:00
										 |  |  |         self.assertFalse(cond.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Notify, but contest the lock before cancelling | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await cond.acquire() | 
					
						
							| 
									
										
										
										
											2016-06-11 12:00:07 -04:00
										 |  |  |         self.assertTrue(cond.locked()) | 
					
						
							|  |  |  |         cond.notify() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         asyncio.get_running_loop().call_soon(wait_task.cancel) | 
					
						
							|  |  |  |         asyncio.get_running_loop().call_soon(cond.release) | 
					
						
							| 
									
										
										
										
											2016-06-11 12:00:07 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |             await wait_task | 
					
						
							| 
									
										
										
										
											2016-06-11 12:00:07 -04:00
										 |  |  |         except asyncio.CancelledError: | 
					
						
							|  |  |  |             # Should not happen, since no cancellation points | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(cond.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_wait_cancel_after_notify(self): | 
					
						
							| 
									
										
										
										
											2018-02-14 11:18:11 +02:00
										 |  |  |         # See bpo-32841 | 
					
						
							|  |  |  |         waited = False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         cond = asyncio.Condition() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-14 11:18:11 +02:00
										 |  |  |         async def wait_on_cond(): | 
					
						
							|  |  |  |             nonlocal waited | 
					
						
							|  |  |  |             async with cond: | 
					
						
							|  |  |  |                 waited = True  # Make sure this area was reached | 
					
						
							|  |  |  |                 await cond.wait() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         waiter = asyncio.create_task(wait_on_cond()) | 
					
						
							|  |  |  |         await asyncio.sleep(0)  # Start waiting | 
					
						
							| 
									
										
										
										
											2018-02-14 11:18:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await cond.acquire() | 
					
						
							| 
									
										
										
										
											2018-02-14 11:18:11 +02:00
										 |  |  |         cond.notify() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0)  # Get to acquire() | 
					
						
							| 
									
										
										
										
											2018-02-14 11:18:11 +02:00
										 |  |  |         waiter.cancel() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0)  # Activate cancellation | 
					
						
							| 
									
										
										
										
											2018-02-14 11:18:11 +02:00
										 |  |  |         cond.release() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0)  # Cancellation should occur | 
					
						
							| 
									
										
										
										
											2018-02-14 11:18:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(waiter.cancelled()) | 
					
						
							|  |  |  |         self.assertTrue(waited) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_wait_unacquired(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         cond = asyncio.Condition() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         with self.assertRaises(RuntimeError): | 
					
						
							|  |  |  |             await cond.wait() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_wait_for(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         cond = asyncio.Condition() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         presult = False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def predicate(): | 
					
						
							|  |  |  |             return presult | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c1(result): | 
					
						
							|  |  |  |             await cond.acquire() | 
					
						
							|  |  |  |             if await cond.wait_for(predicate): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |                 result.append(1) | 
					
						
							|  |  |  |                 cond.release() | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         t = asyncio.create_task(c1(result)) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([], result) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await cond.acquire() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         cond.notify() | 
					
						
							|  |  |  |         cond.release() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([], result) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         presult = True | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await cond.acquire() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         cond.notify() | 
					
						
							|  |  |  |         cond.release() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([1], result) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(t.done()) | 
					
						
							|  |  |  |         self.assertTrue(t.result()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_wait_for_unacquired(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         cond = asyncio.Condition() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # predicate can return true immediately | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         res = await cond.wait_for(lambda: [1, 2, 3]) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([1, 2, 3], res) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         with self.assertRaises(RuntimeError): | 
					
						
							|  |  |  |             await cond.wait_for(lambda: False) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_notify(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         cond = asyncio.Condition() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         result = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c1(result): | 
					
						
							|  |  |  |             await cond.acquire() | 
					
						
							|  |  |  |             if await cond.wait(): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |                 result.append(1) | 
					
						
							|  |  |  |                 cond.release() | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c2(result): | 
					
						
							|  |  |  |             await cond.acquire() | 
					
						
							|  |  |  |             if await cond.wait(): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |                 result.append(2) | 
					
						
							|  |  |  |                 cond.release() | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c3(result): | 
					
						
							|  |  |  |             await cond.acquire() | 
					
						
							|  |  |  |             if await cond.wait(): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |                 result.append(3) | 
					
						
							|  |  |  |                 cond.release() | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         t1 = asyncio.create_task(c1(result)) | 
					
						
							|  |  |  |         t2 = asyncio.create_task(c2(result)) | 
					
						
							|  |  |  |         t3 = asyncio.create_task(c3(result)) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([], result) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await cond.acquire() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         cond.notify(1) | 
					
						
							|  |  |  |         cond.release() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([1], result) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await cond.acquire() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         cond.notify(1) | 
					
						
							|  |  |  |         cond.notify(2048) | 
					
						
							|  |  |  |         cond.release() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([1, 2, 3], result) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(t1.done()) | 
					
						
							|  |  |  |         self.assertTrue(t1.result()) | 
					
						
							|  |  |  |         self.assertTrue(t2.done()) | 
					
						
							|  |  |  |         self.assertTrue(t2.result()) | 
					
						
							|  |  |  |         self.assertTrue(t3.done()) | 
					
						
							|  |  |  |         self.assertTrue(t3.result()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_notify_all(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         cond = asyncio.Condition() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         result = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c1(result): | 
					
						
							|  |  |  |             await cond.acquire() | 
					
						
							|  |  |  |             if await cond.wait(): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |                 result.append(1) | 
					
						
							|  |  |  |                 cond.release() | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c2(result): | 
					
						
							|  |  |  |             await cond.acquire() | 
					
						
							|  |  |  |             if await cond.wait(): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |                 result.append(2) | 
					
						
							|  |  |  |                 cond.release() | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         t1 = asyncio.create_task(c1(result)) | 
					
						
							|  |  |  |         t2 = asyncio.create_task(c2(result)) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([], result) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await cond.acquire() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         cond.notify_all() | 
					
						
							|  |  |  |         cond.release() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([1, 2], result) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(t1.done()) | 
					
						
							|  |  |  |         self.assertTrue(t1.result()) | 
					
						
							|  |  |  |         self.assertTrue(t2.done()) | 
					
						
							|  |  |  |         self.assertTrue(t2.result()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_notify_unacquired(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         cond = asyncio.Condition() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertRaises(RuntimeError, cond.notify) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_notify_all_unacquired(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         cond = asyncio.Condition() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertRaises(RuntimeError, cond.notify_all) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_repr(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         cond = asyncio.Condition() | 
					
						
							| 
									
										
										
										
											2013-11-04 13:18:19 -08:00
										 |  |  |         self.assertTrue('unlocked' in repr(cond)) | 
					
						
							|  |  |  |         self.assertTrue(RGX_REPR.match(repr(cond))) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await cond.acquire() | 
					
						
							| 
									
										
										
										
											2013-11-04 13:18:19 -08:00
										 |  |  |         self.assertTrue('locked' in repr(cond)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 10:25:02 +01:00
										 |  |  |         cond._waiters.append(mock.Mock()) | 
					
						
							| 
									
										
										
										
											2013-11-04 13:18:19 -08:00
										 |  |  |         self.assertTrue('waiters:1' in repr(cond)) | 
					
						
							|  |  |  |         self.assertTrue(RGX_REPR.match(repr(cond))) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 10:25:02 +01:00
										 |  |  |         cond._waiters.append(mock.Mock()) | 
					
						
							| 
									
										
										
										
											2013-11-04 13:18:19 -08:00
										 |  |  |         self.assertTrue('waiters:2' in repr(cond)) | 
					
						
							|  |  |  |         self.assertTrue(RGX_REPR.match(repr(cond))) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_context_manager(self): | 
					
						
							|  |  |  |         cond = asyncio.Condition() | 
					
						
							|  |  |  |         self.assertFalse(cond.locked()) | 
					
						
							|  |  |  |         async with cond: | 
					
						
							|  |  |  |             self.assertTrue(cond.locked()) | 
					
						
							|  |  |  |         self.assertFalse(cond.locked()) | 
					
						
							| 
									
										
										
										
											2014-01-25 16:51:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_explicit_lock(self): | 
					
						
							| 
									
										
										
										
											2021-10-11 01:01:41 +09:00
										 |  |  |         async def f(lock=None, cond=None): | 
					
						
							|  |  |  |             if lock is None: | 
					
						
							|  |  |  |                 lock = asyncio.Lock() | 
					
						
							|  |  |  |             if cond is None: | 
					
						
							|  |  |  |                 cond = asyncio.Condition(lock) | 
					
						
							|  |  |  |             self.assertIs(cond._lock, lock) | 
					
						
							|  |  |  |             self.assertFalse(lock.locked()) | 
					
						
							|  |  |  |             self.assertFalse(cond.locked()) | 
					
						
							|  |  |  |             async with cond: | 
					
						
							|  |  |  |                 self.assertTrue(lock.locked()) | 
					
						
							|  |  |  |                 self.assertTrue(cond.locked()) | 
					
						
							|  |  |  |             self.assertFalse(lock.locked()) | 
					
						
							|  |  |  |             self.assertFalse(cond.locked()) | 
					
						
							|  |  |  |             async with lock: | 
					
						
							|  |  |  |                 self.assertTrue(lock.locked()) | 
					
						
							|  |  |  |                 self.assertTrue(cond.locked()) | 
					
						
							|  |  |  |             self.assertFalse(lock.locked()) | 
					
						
							|  |  |  |             self.assertFalse(cond.locked()) | 
					
						
							| 
									
										
										
										
											2014-07-26 17:54:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-11 01:01:41 +09:00
										 |  |  |         # All should work in the same way. | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await f() | 
					
						
							|  |  |  |         await f(asyncio.Lock()) | 
					
						
							| 
									
										
										
										
											2021-10-11 01:01:41 +09:00
										 |  |  |         lock = asyncio.Lock() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await f(lock, asyncio.Condition(lock)) | 
					
						
							| 
									
										
										
										
											2014-07-26 17:54:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_ambiguous_loops(self): | 
					
						
							| 
									
										
										
										
											2021-10-11 01:01:41 +09:00
										 |  |  |         loop = asyncio.new_event_loop() | 
					
						
							| 
									
										
										
										
											2014-07-29 12:58:23 +02:00
										 |  |  |         self.addCleanup(loop.close) | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-11 01:01:41 +09:00
										 |  |  |         async def wrong_loop_in_lock(): | 
					
						
							|  |  |  |             with self.assertRaises(TypeError): | 
					
						
							|  |  |  |                 asyncio.Lock(loop=loop)  # actively disallowed since 3.10 | 
					
						
							|  |  |  |             lock = asyncio.Lock() | 
					
						
							|  |  |  |             lock._loop = loop  # use private API for testing | 
					
						
							|  |  |  |             async with lock: | 
					
						
							|  |  |  |                 # acquired immediately via the fast-path | 
					
						
							|  |  |  |                 # without interaction with any event loop. | 
					
						
							|  |  |  |                 cond = asyncio.Condition(lock) | 
					
						
							|  |  |  |                 # cond.acquire() will trigger waiting on the lock | 
					
						
							|  |  |  |                 # and it will discover the event loop mismatch. | 
					
						
							|  |  |  |                 with self.assertRaisesRegex( | 
					
						
							|  |  |  |                     RuntimeError, | 
					
						
							|  |  |  |                     "is bound to a different event loop", | 
					
						
							|  |  |  |                 ): | 
					
						
							|  |  |  |                     await cond.acquire() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def wrong_loop_in_cond(): | 
					
						
							|  |  |  |             # Same analogy here with the condition's loop. | 
					
						
							|  |  |  |             lock = asyncio.Lock() | 
					
						
							|  |  |  |             async with lock: | 
					
						
							|  |  |  |                 with self.assertRaises(TypeError): | 
					
						
							|  |  |  |                     asyncio.Condition(lock, loop=loop) | 
					
						
							|  |  |  |                 cond = asyncio.Condition(lock) | 
					
						
							|  |  |  |                 cond._loop = loop | 
					
						
							|  |  |  |                 with self.assertRaisesRegex( | 
					
						
							|  |  |  |                     RuntimeError, | 
					
						
							|  |  |  |                     "is bound to a different event loop", | 
					
						
							|  |  |  |                 ): | 
					
						
							|  |  |  |                     await cond.wait() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await wrong_loop_in_lock() | 
					
						
							|  |  |  |         await wrong_loop_in_cond() | 
					
						
							| 
									
										
										
										
											2018-05-29 17:31:01 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_timeout_in_block(self): | 
					
						
							|  |  |  |         condition = asyncio.Condition() | 
					
						
							|  |  |  |         async with condition: | 
					
						
							|  |  |  |             with self.assertRaises(asyncio.TimeoutError): | 
					
						
							|  |  |  |                 await asyncio.wait_for(condition.wait(), timeout=0.5) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-08 19:57:48 +00:00
										 |  |  |     async def test_cancelled_error_wakeup(self): | 
					
						
							|  |  |  |         # Test that a cancelled error, received when awaiting wakeup, | 
					
						
							|  |  |  |         # will be re-raised un-modified. | 
					
						
							|  |  |  |         wake = False | 
					
						
							|  |  |  |         raised = None | 
					
						
							|  |  |  |         cond = asyncio.Condition() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def func(): | 
					
						
							|  |  |  |             nonlocal raised | 
					
						
							|  |  |  |             async with cond: | 
					
						
							|  |  |  |                 with self.assertRaises(asyncio.CancelledError) as err: | 
					
						
							|  |  |  |                     await cond.wait_for(lambda: wake) | 
					
						
							|  |  |  |                 raised = err.exception | 
					
						
							|  |  |  |                 raise raised | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         task = asyncio.create_task(func()) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  |         # Task is waiting on the condition, cancel it there. | 
					
						
							|  |  |  |         task.cancel(msg="foo") | 
					
						
							|  |  |  |         with self.assertRaises(asyncio.CancelledError) as err: | 
					
						
							|  |  |  |             await task | 
					
						
							|  |  |  |         self.assertEqual(err.exception.args, ("foo",)) | 
					
						
							|  |  |  |         # We should have got the _same_ exception instance as the one | 
					
						
							|  |  |  |         # originally raised. | 
					
						
							|  |  |  |         self.assertIs(err.exception, raised) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_cancelled_error_re_aquire(self): | 
					
						
							|  |  |  |         # Test that a cancelled error, received when re-aquiring lock, | 
					
						
							|  |  |  |         # will be re-raised un-modified. | 
					
						
							|  |  |  |         wake = False | 
					
						
							|  |  |  |         raised = None | 
					
						
							|  |  |  |         cond = asyncio.Condition() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def func(): | 
					
						
							|  |  |  |             nonlocal raised | 
					
						
							|  |  |  |             async with cond: | 
					
						
							|  |  |  |                 with self.assertRaises(asyncio.CancelledError) as err: | 
					
						
							|  |  |  |                     await cond.wait_for(lambda: wake) | 
					
						
							|  |  |  |                 raised = err.exception | 
					
						
							|  |  |  |                 raise raised | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         task = asyncio.create_task(func()) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  |         # Task is waiting on the condition | 
					
						
							|  |  |  |         await cond.acquire() | 
					
						
							|  |  |  |         wake = True | 
					
						
							|  |  |  |         cond.notify() | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  |         # Task is now trying to re-acquire the lock, cancel it there. | 
					
						
							|  |  |  |         task.cancel(msg="foo") | 
					
						
							|  |  |  |         cond.release() | 
					
						
							|  |  |  |         with self.assertRaises(asyncio.CancelledError) as err: | 
					
						
							|  |  |  |             await task | 
					
						
							|  |  |  |         self.assertEqual(err.exception.args, ("foo",)) | 
					
						
							|  |  |  |         # We should have got the _same_ exception instance as the one | 
					
						
							|  |  |  |         # originally raised. | 
					
						
							|  |  |  |         self.assertIs(err.exception, raised) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-03 16:19:37 +00:00
										 |  |  |     async def test_cancelled_wakeup(self): | 
					
						
							|  |  |  |         # Test that a task cancelled at the "same" time as it is woken | 
					
						
							|  |  |  |         # up as part of a Condition.notify() does not result in a lost wakeup. | 
					
						
							|  |  |  |         # This test simulates a cancel while the target task is awaiting initial | 
					
						
							|  |  |  |         # wakeup on the wakeup queue. | 
					
						
							|  |  |  |         condition = asyncio.Condition() | 
					
						
							|  |  |  |         state = 0 | 
					
						
							|  |  |  |         async def consumer(): | 
					
						
							|  |  |  |             nonlocal state | 
					
						
							|  |  |  |             async with condition: | 
					
						
							|  |  |  |                 while True: | 
					
						
							|  |  |  |                     await condition.wait_for(lambda: state != 0) | 
					
						
							|  |  |  |                     if state < 0: | 
					
						
							|  |  |  |                         return | 
					
						
							|  |  |  |                     state -= 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # create two consumers | 
					
						
							|  |  |  |         c = [asyncio.create_task(consumer()) for _ in range(2)] | 
					
						
							|  |  |  |         # wait for them to settle | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  |         async with condition: | 
					
						
							|  |  |  |             # produce one item and wake up one | 
					
						
							|  |  |  |             state += 1 | 
					
						
							|  |  |  |             condition.notify(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # Cancel it while it is awaiting to be run. | 
					
						
							|  |  |  |             # This cancellation could come from the outside | 
					
						
							|  |  |  |             c[0].cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # now wait for the item to be consumed | 
					
						
							|  |  |  |             # if it doesn't means that our "notify" didn"t take hold. | 
					
						
							|  |  |  |             # because it raced with a cancel() | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 async with asyncio.timeout(0.01): | 
					
						
							|  |  |  |                     await condition.wait_for(lambda: state == 0) | 
					
						
							|  |  |  |             except TimeoutError: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |             self.assertEqual(state, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # clean up | 
					
						
							|  |  |  |             state = -1 | 
					
						
							|  |  |  |             condition.notify_all() | 
					
						
							|  |  |  |         await c[1] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_cancelled_wakeup_relock(self): | 
					
						
							|  |  |  |         # Test that a task cancelled at the "same" time as it is woken | 
					
						
							|  |  |  |         # up as part of a Condition.notify() does not result in a lost wakeup. | 
					
						
							|  |  |  |         # This test simulates a cancel while the target task is acquiring the lock | 
					
						
							|  |  |  |         # again. | 
					
						
							|  |  |  |         condition = asyncio.Condition() | 
					
						
							|  |  |  |         state = 0 | 
					
						
							|  |  |  |         async def consumer(): | 
					
						
							|  |  |  |             nonlocal state | 
					
						
							|  |  |  |             async with condition: | 
					
						
							|  |  |  |                 while True: | 
					
						
							|  |  |  |                     await condition.wait_for(lambda: state != 0) | 
					
						
							|  |  |  |                     if state < 0: | 
					
						
							|  |  |  |                         return | 
					
						
							|  |  |  |                     state -= 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # create two consumers | 
					
						
							|  |  |  |         c = [asyncio.create_task(consumer()) for _ in range(2)] | 
					
						
							|  |  |  |         # wait for them to settle | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  |         async with condition: | 
					
						
							|  |  |  |             # produce one item and wake up one | 
					
						
							|  |  |  |             state += 1 | 
					
						
							|  |  |  |             condition.notify(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # now we sleep for a bit.  This allows the target task to wake up and | 
					
						
							|  |  |  |             # settle on re-aquiring the lock | 
					
						
							|  |  |  |             await asyncio.sleep(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # Cancel it while awaiting the lock | 
					
						
							|  |  |  |             # This cancel could come the outside. | 
					
						
							|  |  |  |             c[0].cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # now wait for the item to be consumed | 
					
						
							|  |  |  |             # if it doesn't means that our "notify" didn"t take hold. | 
					
						
							|  |  |  |             # because it raced with a cancel() | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 async with asyncio.timeout(0.01): | 
					
						
							|  |  |  |                     await condition.wait_for(lambda: state == 0) | 
					
						
							|  |  |  |             except TimeoutError: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |             self.assertEqual(state, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # clean up | 
					
						
							|  |  |  |             state = -1 | 
					
						
							|  |  |  |             condition.notify_all() | 
					
						
							|  |  |  |         await c[1] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  | class SemaphoreTests(unittest.IsolatedAsyncioTestCase): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-21 11:07:45 -08:00
										 |  |  |     def test_initial_value_zero(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         sem = asyncio.Semaphore(0) | 
					
						
							| 
									
										
										
										
											2013-11-21 11:07:45 -08:00
										 |  |  |         self.assertTrue(sem.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_repr(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         sem = asyncio.Semaphore() | 
					
						
							| 
									
										
										
										
											2017-12-10 18:36:12 -05:00
										 |  |  |         self.assertTrue(repr(sem).endswith('[unlocked, value:1]>')) | 
					
						
							| 
									
										
										
										
											2013-11-04 13:18:19 -08:00
										 |  |  |         self.assertTrue(RGX_REPR.match(repr(sem))) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await sem.acquire() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertTrue(repr(sem).endswith('[locked]>')) | 
					
						
							| 
									
										
										
										
											2013-11-04 13:18:19 -08:00
										 |  |  |         self.assertTrue('waiters' not in repr(sem)) | 
					
						
							|  |  |  |         self.assertTrue(RGX_REPR.match(repr(sem))) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-22 12:34:45 -04:00
										 |  |  |         if sem._waiters is None: | 
					
						
							|  |  |  |             sem._waiters = collections.deque() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 10:25:02 +01:00
										 |  |  |         sem._waiters.append(mock.Mock()) | 
					
						
							| 
									
										
										
										
											2013-11-04 13:18:19 -08:00
										 |  |  |         self.assertTrue('waiters:1' in repr(sem)) | 
					
						
							|  |  |  |         self.assertTrue(RGX_REPR.match(repr(sem))) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-26 10:25:02 +01:00
										 |  |  |         sem._waiters.append(mock.Mock()) | 
					
						
							| 
									
										
										
										
											2013-11-04 13:18:19 -08:00
										 |  |  |         self.assertTrue('waiters:2' in repr(sem)) | 
					
						
							|  |  |  |         self.assertTrue(RGX_REPR.match(repr(sem))) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_semaphore(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         sem = asyncio.Semaphore() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual(1, sem._value) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-01 13:12:52 +02:00
										 |  |  |         with self.assertRaisesRegex( | 
					
						
							|  |  |  |             TypeError, | 
					
						
							| 
									
										
										
										
											2021-07-01 16:13:59 +03:00
										 |  |  |             "object Semaphore can't be used in 'await' expression", | 
					
						
							| 
									
										
										
										
											2020-02-01 13:12:52 +02:00
										 |  |  |         ): | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |             await sem | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.assertFalse(sem.locked()) | 
					
						
							|  |  |  |         self.assertEqual(1, sem._value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_semaphore_value(self): | 
					
						
							| 
									
										
										
										
											2014-01-25 15:32:06 +01:00
										 |  |  |         self.assertRaises(ValueError, asyncio.Semaphore, -1) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_acquire(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         sem = asyncio.Semaphore(3) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         result = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         self.assertTrue(await sem.acquire()) | 
					
						
							|  |  |  |         self.assertTrue(await sem.acquire()) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertFalse(sem.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c1(result): | 
					
						
							|  |  |  |             await sem.acquire() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |             result.append(1) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c2(result): | 
					
						
							|  |  |  |             await sem.acquire() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |             result.append(2) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c3(result): | 
					
						
							|  |  |  |             await sem.acquire() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |             result.append(3) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         async def c4(result): | 
					
						
							|  |  |  |             await sem.acquire() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |             result.append(4) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         t1 = asyncio.create_task(c1(result)) | 
					
						
							|  |  |  |         t2 = asyncio.create_task(c2(result)) | 
					
						
							|  |  |  |         t3 = asyncio.create_task(c3(result)) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual([1], result) | 
					
						
							|  |  |  |         self.assertTrue(sem.locked()) | 
					
						
							|  |  |  |         self.assertEqual(2, len(sem._waiters)) | 
					
						
							|  |  |  |         self.assertEqual(0, sem._value) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         t4 = asyncio.create_task(c4(result)) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         sem.release() | 
					
						
							|  |  |  |         sem.release() | 
					
						
							| 
									
										
										
										
											2022-09-26 19:38:00 -04:00
										 |  |  |         self.assertEqual(0, sem._value) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertEqual(0, sem._value) | 
					
						
							| 
									
										
										
										
											2015-09-29 11:54:45 -07:00
										 |  |  |         self.assertEqual(3, len(result)) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertTrue(sem.locked()) | 
					
						
							|  |  |  |         self.assertEqual(1, len(sem._waiters)) | 
					
						
							|  |  |  |         self.assertEqual(0, sem._value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(t1.done()) | 
					
						
							|  |  |  |         self.assertTrue(t1.result()) | 
					
						
							| 
									
										
										
										
											2015-09-29 11:54:45 -07:00
										 |  |  |         race_tasks = [t2, t3, t4] | 
					
						
							|  |  |  |         done_tasks = [t for t in race_tasks if t.done() and t.result()] | 
					
						
							| 
									
										
										
										
											2022-06-05 21:19:18 -04:00
										 |  |  |         self.assertEqual(2, len(done_tasks)) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # cleanup locked semaphore | 
					
						
							|  |  |  |         sem.release() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.gather(*race_tasks) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_acquire_cancel(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         sem = asyncio.Semaphore() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await sem.acquire() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         acquire = asyncio.create_task(sem.acquire()) | 
					
						
							|  |  |  |         asyncio.get_running_loop().call_soon(acquire.cancel) | 
					
						
							|  |  |  |         with self.assertRaises(asyncio.CancelledError): | 
					
						
							|  |  |  |             await acquire | 
					
						
							| 
									
										
										
										
											2015-09-29 11:54:45 -07:00
										 |  |  |         self.assertTrue((not sem._waiters) or | 
					
						
							|  |  |  |                         all(waiter.done() for waiter in sem._waiters)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_acquire_cancel_before_awoken(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         sem = asyncio.Semaphore(value=0) | 
					
						
							| 
									
										
										
										
											2015-09-29 11:54:45 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         t1 = asyncio.create_task(sem.acquire()) | 
					
						
							|  |  |  |         t2 = asyncio.create_task(sem.acquire()) | 
					
						
							|  |  |  |         t3 = asyncio.create_task(sem.acquire()) | 
					
						
							|  |  |  |         t4 = asyncio.create_task(sem.acquire()) | 
					
						
							| 
									
										
										
										
											2015-09-29 11:54:45 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2015-09-29 11:54:45 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         t1.cancel() | 
					
						
							|  |  |  |         t2.cancel() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         sem.release() | 
					
						
							| 
									
										
										
										
											2015-09-29 11:54:45 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-22 12:34:45 -04:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2015-09-29 11:54:45 -07:00
										 |  |  |         num_done = sum(t.done() for t in [t3, t4]) | 
					
						
							|  |  |  |         self.assertEqual(num_done, 1) | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         self.assertTrue(t3.done()) | 
					
						
							|  |  |  |         self.assertFalse(t4.done()) | 
					
						
							| 
									
										
										
										
											2015-09-29 11:54:45 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         t3.cancel() | 
					
						
							|  |  |  |         t4.cancel() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2015-09-29 11:54:45 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_acquire_hang(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         sem = asyncio.Semaphore(value=0) | 
					
						
							| 
									
										
										
										
											2015-09-29 11:54:45 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         t1 = asyncio.create_task(sem.acquire()) | 
					
						
							|  |  |  |         t2 = asyncio.create_task(sem.acquire()) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2015-09-29 11:54:45 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         t1.cancel() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         sem.release() | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2022-09-22 12:34:45 -04:00
										 |  |  |         await asyncio.sleep(0) | 
					
						
							| 
									
										
										
										
											2015-09-29 11:54:45 -07:00
										 |  |  |         self.assertTrue(sem.locked()) | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         self.assertTrue(t2.done()) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-22 12:34:45 -04:00
										 |  |  |     async def test_acquire_no_hang(self): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         sem = asyncio.Semaphore(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def c1(): | 
					
						
							|  |  |  |             async with sem: | 
					
						
							|  |  |  |                 await asyncio.sleep(0) | 
					
						
							|  |  |  |             t2.cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def c2(): | 
					
						
							|  |  |  |             async with sem: | 
					
						
							|  |  |  |                 self.assertFalse(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t1 = asyncio.create_task(c1()) | 
					
						
							|  |  |  |         t2 = asyncio.create_task(c2()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         r1, r2 = await asyncio.gather(t1, t2, return_exceptions=True) | 
					
						
							|  |  |  |         self.assertTrue(r1 is None) | 
					
						
							|  |  |  |         self.assertTrue(isinstance(r2, asyncio.CancelledError)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await asyncio.wait_for(sem.acquire(), timeout=1.0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     def test_release_not_acquired(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         sem = asyncio.BoundedSemaphore() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.assertRaises(ValueError, sem.release) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |     async def test_release_no_waiters(self): | 
					
						
							| 
									
										
										
										
											2020-11-24 20:08:54 +02:00
										 |  |  |         sem = asyncio.Semaphore() | 
					
						
							| 
									
										
										
										
											2021-12-19 16:35:56 +02:00
										 |  |  |         await sem.acquire() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.assertTrue(sem.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         sem.release() | 
					
						
							|  |  |  |         self.assertFalse(sem.locked()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:02:51 +02:00
										 |  |  |     async def test_acquire_fifo_order(self): | 
					
						
							|  |  |  |         sem = asyncio.Semaphore(1) | 
					
						
							|  |  |  |         result = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def coro(tag): | 
					
						
							|  |  |  |             await sem.acquire() | 
					
						
							|  |  |  |             result.append(f'{tag}_1') | 
					
						
							|  |  |  |             await asyncio.sleep(0.01) | 
					
						
							|  |  |  |             sem.release() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             await sem.acquire() | 
					
						
							|  |  |  |             result.append(f'{tag}_2') | 
					
						
							|  |  |  |             await asyncio.sleep(0.01) | 
					
						
							|  |  |  |             sem.release() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async with asyncio.TaskGroup() as tg: | 
					
						
							|  |  |  |             tg.create_task(coro('c1')) | 
					
						
							|  |  |  |             tg.create_task(coro('c2')) | 
					
						
							|  |  |  |             tg.create_task(coro('c3')) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             ['c1_1', 'c2_1', 'c3_1', 'c1_2', 'c2_2', 'c3_2'], | 
					
						
							|  |  |  |             result | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-22 12:34:45 -04:00
										 |  |  |     async def test_acquire_fifo_order_2(self): | 
					
						
							|  |  |  |         sem = asyncio.Semaphore(1) | 
					
						
							|  |  |  |         result = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def c1(result): | 
					
						
							|  |  |  |             await sem.acquire() | 
					
						
							|  |  |  |             result.append(1) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def c2(result): | 
					
						
							|  |  |  |             await sem.acquire() | 
					
						
							|  |  |  |             result.append(2) | 
					
						
							|  |  |  |             sem.release() | 
					
						
							|  |  |  |             await sem.acquire() | 
					
						
							|  |  |  |             result.append(4) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def c3(result): | 
					
						
							|  |  |  |             await sem.acquire() | 
					
						
							|  |  |  |             result.append(3) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t1 = asyncio.create_task(c1(result)) | 
					
						
							|  |  |  |         t2 = asyncio.create_task(c2(result)) | 
					
						
							|  |  |  |         t3 = asyncio.create_task(c3(result)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         sem.release() | 
					
						
							|  |  |  |         sem.release() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         tasks = [t1, t2, t3] | 
					
						
							|  |  |  |         await asyncio.gather(*tasks) | 
					
						
							|  |  |  |         self.assertEqual([1, 2, 3, 4], result) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_acquire_fifo_order_3(self): | 
					
						
							|  |  |  |         sem = asyncio.Semaphore(0) | 
					
						
							|  |  |  |         result = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def c1(result): | 
					
						
							|  |  |  |             await sem.acquire() | 
					
						
							|  |  |  |             result.append(1) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def c2(result): | 
					
						
							|  |  |  |             await sem.acquire() | 
					
						
							|  |  |  |             result.append(2) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def c3(result): | 
					
						
							|  |  |  |             await sem.acquire() | 
					
						
							|  |  |  |             result.append(3) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t1 = asyncio.create_task(c1(result)) | 
					
						
							|  |  |  |         t2 = asyncio.create_task(c2(result)) | 
					
						
							|  |  |  |         t3 = asyncio.create_task(c3(result)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t1.cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         sem.release() | 
					
						
							|  |  |  |         sem.release() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         tasks = [t1, t2, t3] | 
					
						
							|  |  |  |         await asyncio.gather(*tasks, return_exceptions=True) | 
					
						
							|  |  |  |         self.assertEqual([2, 3], result) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-08 19:57:48 +00:00
										 |  |  |     async def test_acquire_fifo_order_4(self): | 
					
						
							|  |  |  |         # Test that a successfule `acquire()` will wake up multiple Tasks | 
					
						
							|  |  |  |         # that were waiting in the Semaphore queue due to FIFO rules. | 
					
						
							|  |  |  |         sem = asyncio.Semaphore(0) | 
					
						
							|  |  |  |         result = [] | 
					
						
							|  |  |  |         count = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def c1(result): | 
					
						
							|  |  |  |             # First task immediatlly waits for semaphore.  It will be awoken by c2. | 
					
						
							|  |  |  |             self.assertEqual(sem._value, 0) | 
					
						
							|  |  |  |             await sem.acquire() | 
					
						
							|  |  |  |             # We should have woken up all waiting tasks now. | 
					
						
							|  |  |  |             self.assertEqual(sem._value, 0) | 
					
						
							|  |  |  |             # Create a fourth task.  It should run after c3, not c2. | 
					
						
							|  |  |  |             nonlocal t4 | 
					
						
							|  |  |  |             t4 = asyncio.create_task(c4(result)) | 
					
						
							|  |  |  |             result.append(1) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def c2(result): | 
					
						
							|  |  |  |             # The second task begins by releasing semaphore three times, | 
					
						
							|  |  |  |             # for c1, c2, and c3. | 
					
						
							|  |  |  |             sem.release() | 
					
						
							|  |  |  |             sem.release() | 
					
						
							|  |  |  |             sem.release() | 
					
						
							|  |  |  |             self.assertEqual(sem._value, 2) | 
					
						
							|  |  |  |             # It is locked, because c1 hasn't woken up yet. | 
					
						
							|  |  |  |             self.assertTrue(sem.locked()) | 
					
						
							|  |  |  |             await sem.acquire() | 
					
						
							|  |  |  |             result.append(2) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def c3(result): | 
					
						
							|  |  |  |             await sem.acquire() | 
					
						
							|  |  |  |             self.assertTrue(sem.locked()) | 
					
						
							|  |  |  |             result.append(3) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def c4(result): | 
					
						
							|  |  |  |             result.append(4) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t1 = asyncio.create_task(c1(result)) | 
					
						
							|  |  |  |         t2 = asyncio.create_task(c2(result)) | 
					
						
							|  |  |  |         t3 = asyncio.create_task(c3(result)) | 
					
						
							|  |  |  |         t4 = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  |         # Three tasks are in the queue, the first hasn't woken up yet. | 
					
						
							|  |  |  |         self.assertEqual(sem._value, 2) | 
					
						
							|  |  |  |         self.assertEqual(len(sem._waiters), 3) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         tasks = [t1, t2, t3, t4] | 
					
						
							|  |  |  |         await asyncio.gather(*tasks) | 
					
						
							|  |  |  |         self.assertEqual([1, 2, 3, 4], result) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-25 23:01:21 +01:00
										 |  |  | class BarrierTests(unittest.IsolatedAsyncioTestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def asyncSetUp(self): | 
					
						
							|  |  |  |         await super().asyncSetUp() | 
					
						
							|  |  |  |         self.N = 5 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def make_tasks(self, n, coro): | 
					
						
							|  |  |  |         tasks = [asyncio.create_task(coro()) for _ in range(n)] | 
					
						
							|  |  |  |         return tasks | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def gather_tasks(self, n, coro): | 
					
						
							|  |  |  |         tasks = self.make_tasks(n, coro) | 
					
						
							|  |  |  |         res = await asyncio.gather(*tasks) | 
					
						
							|  |  |  |         return res, tasks | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_barrier(self): | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(self.N) | 
					
						
							|  |  |  |         self.assertIn("filling", repr(barrier)) | 
					
						
							|  |  |  |         with self.assertRaisesRegex( | 
					
						
							|  |  |  |             TypeError, | 
					
						
							|  |  |  |             "object Barrier can't be used in 'await' expression", | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             await barrier | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertIn("filling", repr(barrier)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_repr(self): | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(self.N) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(RGX_REPR.match(repr(barrier))) | 
					
						
							|  |  |  |         self.assertIn("filling", repr(barrier)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         waiters = [] | 
					
						
							|  |  |  |         async def wait(barrier): | 
					
						
							|  |  |  |             await barrier.wait() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         incr = 2 | 
					
						
							|  |  |  |         for i in range(incr): | 
					
						
							|  |  |  |             waiters.append(asyncio.create_task(wait(barrier))) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(RGX_REPR.match(repr(barrier))) | 
					
						
							|  |  |  |         self.assertTrue(f"waiters:{incr}/{self.N}" in repr(barrier)) | 
					
						
							|  |  |  |         self.assertIn("filling", repr(barrier)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # create missing waiters | 
					
						
							|  |  |  |         for i in range(barrier.parties - barrier.n_waiting): | 
					
						
							|  |  |  |             waiters.append(asyncio.create_task(wait(barrier))) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(RGX_REPR.match(repr(barrier))) | 
					
						
							|  |  |  |         self.assertIn("draining", repr(barrier)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # add a part of waiters | 
					
						
							|  |  |  |         for i in range(incr): | 
					
						
							|  |  |  |             waiters.append(asyncio.create_task(wait(barrier))) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  |         # and reset | 
					
						
							|  |  |  |         await barrier.reset() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(RGX_REPR.match(repr(barrier))) | 
					
						
							|  |  |  |         self.assertIn("resetting", repr(barrier)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # add a part of waiters again | 
					
						
							|  |  |  |         for i in range(incr): | 
					
						
							|  |  |  |             waiters.append(asyncio.create_task(wait(barrier))) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  |         # and abort | 
					
						
							|  |  |  |         await barrier.abort() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(RGX_REPR.match(repr(barrier))) | 
					
						
							|  |  |  |         self.assertIn("broken", repr(barrier)) | 
					
						
							|  |  |  |         self.assertTrue(barrier.broken) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # suppress unhandled exceptions | 
					
						
							|  |  |  |         await asyncio.gather(*waiters, return_exceptions=True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_barrier_parties(self): | 
					
						
							|  |  |  |         self.assertRaises(ValueError, lambda: asyncio.Barrier(0)) | 
					
						
							|  |  |  |         self.assertRaises(ValueError, lambda: asyncio.Barrier(-4)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertIsInstance(asyncio.Barrier(self.N), asyncio.Barrier) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_context_manager(self): | 
					
						
							|  |  |  |         self.N = 3 | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(self.N) | 
					
						
							|  |  |  |         results = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def coro(): | 
					
						
							|  |  |  |             async with barrier as i: | 
					
						
							|  |  |  |                 results.append(i) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await self.gather_tasks(self.N, coro) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertListEqual(sorted(results), list(range(self.N))) | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  |         self.assertFalse(barrier.broken) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_filling_one_task(self): | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def f(): | 
					
						
							|  |  |  |             async with barrier as i: | 
					
						
							|  |  |  |                 return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ret = await f() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(ret) | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  |         self.assertFalse(barrier.broken) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_filling_one_task_twice(self): | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t1 = asyncio.create_task(barrier.wait()) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t2 = asyncio.create_task(barrier.wait()) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(t1.result(), t2.result()) | 
					
						
							|  |  |  |         self.assertEqual(t1.done(), t2.done()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  |         self.assertFalse(barrier.broken) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_filling_task_by_task(self): | 
					
						
							|  |  |  |         self.N = 3 | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(self.N) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t1 = asyncio.create_task(barrier.wait()) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 1) | 
					
						
							|  |  |  |         self.assertIn("filling", repr(barrier)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t2 = asyncio.create_task(barrier.wait()) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 2) | 
					
						
							|  |  |  |         self.assertIn("filling", repr(barrier)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t3 = asyncio.create_task(barrier.wait()) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await asyncio.wait([t1, t2, t3]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  |         self.assertFalse(barrier.broken) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_filling_tasks_wait_twice(self): | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(self.N) | 
					
						
							|  |  |  |         results = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def coro(): | 
					
						
							|  |  |  |             async with barrier: | 
					
						
							|  |  |  |                 results.append(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 async with barrier: | 
					
						
							|  |  |  |                     results.append(False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await self.gather_tasks(self.N, coro) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(len(results), self.N*2) | 
					
						
							|  |  |  |         self.assertEqual(results.count(True), self.N) | 
					
						
							|  |  |  |         self.assertEqual(results.count(False), self.N) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  |         self.assertFalse(barrier.broken) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_filling_tasks_check_return_value(self): | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(self.N) | 
					
						
							|  |  |  |         results1 = [] | 
					
						
							|  |  |  |         results2 = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def coro(): | 
					
						
							|  |  |  |             async with barrier: | 
					
						
							|  |  |  |                 results1.append(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 async with barrier as i: | 
					
						
							|  |  |  |                     results2.append(True) | 
					
						
							|  |  |  |                     return i | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         res, _ = await self.gather_tasks(self.N, coro) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(len(results1), self.N) | 
					
						
							|  |  |  |         self.assertTrue(all(results1)) | 
					
						
							|  |  |  |         self.assertEqual(len(results2), self.N) | 
					
						
							|  |  |  |         self.assertTrue(all(results2)) | 
					
						
							|  |  |  |         self.assertListEqual(sorted(res), list(range(self.N))) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  |         self.assertFalse(barrier.broken) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_draining_state(self): | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(self.N) | 
					
						
							|  |  |  |         results = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def coro(): | 
					
						
							|  |  |  |             async with barrier: | 
					
						
							|  |  |  |                 # barrier state change to filling for the last task release | 
					
						
							|  |  |  |                 results.append("draining" in repr(barrier)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await self.gather_tasks(self.N, coro) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(len(results), self.N) | 
					
						
							|  |  |  |         self.assertEqual(results[-1], False) | 
					
						
							|  |  |  |         self.assertTrue(all(results[:self.N-1])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  |         self.assertFalse(barrier.broken) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_blocking_tasks_while_draining(self): | 
					
						
							|  |  |  |         rewait = 2 | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(self.N) | 
					
						
							|  |  |  |         barrier_nowaiting = asyncio.Barrier(self.N - rewait) | 
					
						
							|  |  |  |         results = [] | 
					
						
							|  |  |  |         rewait_n = rewait | 
					
						
							|  |  |  |         counter = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def coro(): | 
					
						
							|  |  |  |             nonlocal rewait_n | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # first time waiting | 
					
						
							|  |  |  |             await barrier.wait() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # after wainting once for all tasks | 
					
						
							|  |  |  |             if rewait_n > 0: | 
					
						
							|  |  |  |                 rewait_n -= 1 | 
					
						
							|  |  |  |                 # wait again only for rewait tasks | 
					
						
							|  |  |  |                 await barrier.wait() | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 # wait for end of draining state` | 
					
						
							|  |  |  |                 await barrier_nowaiting.wait() | 
					
						
							|  |  |  |                 # wait for other waiting tasks | 
					
						
							|  |  |  |                 await barrier.wait() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # a success means that barrier_nowaiting | 
					
						
							|  |  |  |         # was waited for exactly N-rewait=3 times | 
					
						
							|  |  |  |         await self.gather_tasks(self.N, coro) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_filling_tasks_cancel_one(self): | 
					
						
							|  |  |  |         self.N = 3 | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(self.N) | 
					
						
							|  |  |  |         results = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def coro(): | 
					
						
							|  |  |  |             await barrier.wait() | 
					
						
							|  |  |  |             results.append(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t1 = asyncio.create_task(coro()) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t2 = asyncio.create_task(coro()) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t1.cancel() | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 1) | 
					
						
							|  |  |  |         with self.assertRaises(asyncio.CancelledError): | 
					
						
							|  |  |  |             await t1 | 
					
						
							|  |  |  |         self.assertTrue(t1.cancelled()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t3 = asyncio.create_task(coro()) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t4 = asyncio.create_task(coro()) | 
					
						
							|  |  |  |         await asyncio.gather(t2, t3, t4) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(len(results), self.N) | 
					
						
							|  |  |  |         self.assertTrue(all(results)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  |         self.assertFalse(barrier.broken) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_reset_barrier(self): | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         asyncio.create_task(barrier.reset()) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  |         self.assertFalse(barrier.broken) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_reset_barrier_while_tasks_waiting(self): | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(self.N) | 
					
						
							|  |  |  |         results = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def coro(): | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 await barrier.wait() | 
					
						
							|  |  |  |             except asyncio.BrokenBarrierError: | 
					
						
							|  |  |  |                 results.append(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def coro_reset(): | 
					
						
							|  |  |  |             await barrier.reset() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # N-1 tasks waiting on barrier with N parties | 
					
						
							|  |  |  |         tasks  = self.make_tasks(self.N-1, coro) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # reset the barrier | 
					
						
							|  |  |  |         asyncio.create_task(coro_reset()) | 
					
						
							|  |  |  |         await asyncio.gather(*tasks) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(len(results), self.N-1) | 
					
						
							|  |  |  |         self.assertTrue(all(results)) | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  |         self.assertNotIn("resetting", repr(barrier)) | 
					
						
							|  |  |  |         self.assertFalse(barrier.broken) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_reset_barrier_when_tasks_half_draining(self): | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(self.N) | 
					
						
							|  |  |  |         results1 = [] | 
					
						
							|  |  |  |         rest_of_tasks = self.N//2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def coro(): | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 await barrier.wait() | 
					
						
							|  |  |  |             except asyncio.BrokenBarrierError: | 
					
						
							|  |  |  |                 # catch here waiting tasks | 
					
						
							|  |  |  |                 results1.append(True) | 
					
						
							|  |  |  |             else: | 
					
						
							| 
									
										
										
										
											2022-05-25 18:34:14 +03:00
										 |  |  |                 # here drained task outside the barrier | 
					
						
							| 
									
										
										
										
											2022-03-25 23:01:21 +01:00
										 |  |  |                 if rest_of_tasks == barrier._count: | 
					
						
							|  |  |  |                     # tasks outside the barrier | 
					
						
							|  |  |  |                     await barrier.reset() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await self.gather_tasks(self.N, coro) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(results1, [True]*rest_of_tasks) | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  |         self.assertNotIn("resetting", repr(barrier)) | 
					
						
							|  |  |  |         self.assertFalse(barrier.broken) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_reset_barrier_when_tasks_half_draining_half_blocking(self): | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(self.N) | 
					
						
							|  |  |  |         results1 = [] | 
					
						
							|  |  |  |         results2 = [] | 
					
						
							|  |  |  |         blocking_tasks = self.N//2 | 
					
						
							|  |  |  |         count = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def coro(): | 
					
						
							|  |  |  |             nonlocal count | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 await barrier.wait() | 
					
						
							|  |  |  |             except asyncio.BrokenBarrierError: | 
					
						
							|  |  |  |                 # here catch still waiting tasks | 
					
						
							|  |  |  |                 results1.append(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # so now waiting again to reach nb_parties | 
					
						
							|  |  |  |                 await barrier.wait() | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 count += 1 | 
					
						
							|  |  |  |                 if count > blocking_tasks: | 
					
						
							|  |  |  |                     # reset now: raise asyncio.BrokenBarrierError for waiting tasks | 
					
						
							|  |  |  |                     await barrier.reset() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     # so now waiting again to reach nb_parties | 
					
						
							|  |  |  |                     await barrier.wait() | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     try: | 
					
						
							|  |  |  |                         await barrier.wait() | 
					
						
							|  |  |  |                     except asyncio.BrokenBarrierError: | 
					
						
							|  |  |  |                         # here no catch - blocked tasks go to wait | 
					
						
							|  |  |  |                         results2.append(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await self.gather_tasks(self.N, coro) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(results1, [True]*blocking_tasks) | 
					
						
							|  |  |  |         self.assertEqual(results2, []) | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  |         self.assertNotIn("resetting", repr(barrier)) | 
					
						
							|  |  |  |         self.assertFalse(barrier.broken) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_reset_barrier_while_tasks_waiting_and_waiting_again(self): | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(self.N) | 
					
						
							|  |  |  |         results1 = [] | 
					
						
							|  |  |  |         results2 = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def coro1(): | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 await barrier.wait() | 
					
						
							|  |  |  |             except asyncio.BrokenBarrierError: | 
					
						
							|  |  |  |                 results1.append(True) | 
					
						
							|  |  |  |             finally: | 
					
						
							|  |  |  |                 await barrier.wait() | 
					
						
							|  |  |  |                 results2.append(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def coro2(): | 
					
						
							|  |  |  |             async with barrier: | 
					
						
							|  |  |  |                 results2.append(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         tasks = self.make_tasks(self.N-1, coro1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # reset barrier, N-1 waiting tasks raise an BrokenBarrierError | 
					
						
							|  |  |  |         asyncio.create_task(barrier.reset()) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # complete waiting tasks in the `finally` | 
					
						
							|  |  |  |         asyncio.create_task(coro2()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await asyncio.gather(*tasks) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertFalse(barrier.broken) | 
					
						
							|  |  |  |         self.assertEqual(len(results1), self.N-1) | 
					
						
							|  |  |  |         self.assertTrue(all(results1)) | 
					
						
							|  |  |  |         self.assertEqual(len(results2), self.N) | 
					
						
							|  |  |  |         self.assertTrue(all(results2)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_reset_barrier_while_tasks_draining(self): | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(self.N) | 
					
						
							|  |  |  |         results1 = [] | 
					
						
							|  |  |  |         results2 = [] | 
					
						
							|  |  |  |         results3 = [] | 
					
						
							|  |  |  |         count = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def coro(): | 
					
						
							|  |  |  |             nonlocal count | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             i = await barrier.wait() | 
					
						
							|  |  |  |             count += 1 | 
					
						
							|  |  |  |             if count == self.N: | 
					
						
							|  |  |  |                 # last task exited from barrier | 
					
						
							|  |  |  |                 await barrier.reset() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-25 18:34:14 +03:00
										 |  |  |                 # wait here to reach the `parties` | 
					
						
							| 
									
										
										
										
											2022-03-25 23:01:21 +01:00
										 |  |  |                 await barrier.wait() | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     # second waiting | 
					
						
							|  |  |  |                     await barrier.wait() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     # N-1 tasks here | 
					
						
							|  |  |  |                     results1.append(True) | 
					
						
							|  |  |  |                 except Exception as e: | 
					
						
							|  |  |  |                     # never goes here | 
					
						
							|  |  |  |                     results2.append(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # Now, pass the barrier again | 
					
						
							|  |  |  |             # last wait, must be completed | 
					
						
							|  |  |  |             k = await barrier.wait() | 
					
						
							|  |  |  |             results3.append(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await self.gather_tasks(self.N, coro) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertFalse(barrier.broken) | 
					
						
							|  |  |  |         self.assertTrue(all(results1)) | 
					
						
							|  |  |  |         self.assertEqual(len(results1), self.N-1) | 
					
						
							|  |  |  |         self.assertEqual(len(results2), 0) | 
					
						
							|  |  |  |         self.assertEqual(len(results3), self.N) | 
					
						
							|  |  |  |         self.assertTrue(all(results3)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_abort_barrier(self): | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         asyncio.create_task(barrier.abort()) | 
					
						
							|  |  |  |         await asyncio.sleep(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  |         self.assertTrue(barrier.broken) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_abort_barrier_when_tasks_half_draining_half_blocking(self): | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(self.N) | 
					
						
							|  |  |  |         results1 = [] | 
					
						
							|  |  |  |         results2 = [] | 
					
						
							|  |  |  |         blocking_tasks = self.N//2 | 
					
						
							|  |  |  |         count = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def coro(): | 
					
						
							|  |  |  |             nonlocal count | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 await barrier.wait() | 
					
						
							|  |  |  |             except asyncio.BrokenBarrierError: | 
					
						
							|  |  |  |                 # here catch tasks waiting to drain | 
					
						
							|  |  |  |                 results1.append(True) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 count += 1 | 
					
						
							|  |  |  |                 if count > blocking_tasks: | 
					
						
							|  |  |  |                     # abort now: raise asyncio.BrokenBarrierError for all tasks | 
					
						
							|  |  |  |                     await barrier.abort() | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     try: | 
					
						
							|  |  |  |                         await barrier.wait() | 
					
						
							|  |  |  |                     except asyncio.BrokenBarrierError: | 
					
						
							|  |  |  |                         # here catch blocked tasks (already drained) | 
					
						
							|  |  |  |                         results2.append(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await self.gather_tasks(self.N, coro) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(barrier.broken) | 
					
						
							|  |  |  |         self.assertEqual(results1, [True]*blocking_tasks) | 
					
						
							|  |  |  |         self.assertEqual(results2, [True]*(self.N-blocking_tasks-1)) | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  |         self.assertNotIn("resetting", repr(barrier)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_abort_barrier_when_exception(self): | 
					
						
							|  |  |  |         # test from threading.Barrier: see `lock_tests.test_reset` | 
					
						
							|  |  |  |         barrier = asyncio.Barrier(self.N) | 
					
						
							|  |  |  |         results1 = [] | 
					
						
							|  |  |  |         results2 = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def coro(): | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 async with barrier as i : | 
					
						
							|  |  |  |                     if i == self.N//2: | 
					
						
							|  |  |  |                         raise RuntimeError | 
					
						
							|  |  |  |                 async with barrier: | 
					
						
							|  |  |  |                     results1.append(True) | 
					
						
							|  |  |  |             except asyncio.BrokenBarrierError: | 
					
						
							|  |  |  |                 results2.append(True) | 
					
						
							|  |  |  |             except RuntimeError: | 
					
						
							|  |  |  |                 await barrier.abort() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await self.gather_tasks(self.N, coro) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertTrue(barrier.broken) | 
					
						
							|  |  |  |         self.assertEqual(len(results1), 0) | 
					
						
							|  |  |  |         self.assertEqual(len(results2), self.N-1) | 
					
						
							|  |  |  |         self.assertTrue(all(results2)) | 
					
						
							|  |  |  |         self.assertEqual(barrier.n_waiting, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async def test_abort_barrier_when_exception_then_resetting(self): | 
					
						
							|  |  |  |         # test from threading.Barrier: see `lock_tests.test_abort_and_reset`` | 
					
						
							|  |  |  |         barrier1 = asyncio.Barrier(self.N) | 
					
						
							|  |  |  |         barrier2 = asyncio.Barrier(self.N) | 
					
						
							|  |  |  |         results1 = [] | 
					
						
							|  |  |  |         results2 = [] | 
					
						
							|  |  |  |         results3 = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def coro(): | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 i = await barrier1.wait() | 
					
						
							|  |  |  |                 if i == self.N//2: | 
					
						
							|  |  |  |                     raise RuntimeError | 
					
						
							|  |  |  |                 await barrier1.wait() | 
					
						
							|  |  |  |                 results1.append(True) | 
					
						
							|  |  |  |             except asyncio.BrokenBarrierError: | 
					
						
							|  |  |  |                 results2.append(True) | 
					
						
							|  |  |  |             except RuntimeError: | 
					
						
							|  |  |  |                 await barrier1.abort() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # Synchronize and reset the barrier.  Must synchronize first so | 
					
						
							|  |  |  |             # that everyone has left it when we reset, and after so that no | 
					
						
							|  |  |  |             # one enters it before the reset. | 
					
						
							|  |  |  |             i = await barrier2.wait() | 
					
						
							|  |  |  |             if  i == self.N//2: | 
					
						
							|  |  |  |                 await barrier1.reset() | 
					
						
							|  |  |  |             await barrier2.wait() | 
					
						
							|  |  |  |             await barrier1.wait() | 
					
						
							|  |  |  |             results3.append(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await self.gather_tasks(self.N, coro) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertFalse(barrier1.broken) | 
					
						
							|  |  |  |         self.assertEqual(len(results1), 0) | 
					
						
							|  |  |  |         self.assertEqual(len(results2), self.N-1) | 
					
						
							|  |  |  |         self.assertTrue(all(results2)) | 
					
						
							|  |  |  |         self.assertEqual(len(results3), self.N) | 
					
						
							|  |  |  |         self.assertTrue(all(results3)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(barrier1.n_waiting, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     unittest.main() |