GH-125789: fix fut._callbacks to always return a copy of callbacks (#125922)

Fix `asyncio.Future._callbacks` to always return a copy of the internal list of callbacks to avoid mutation from user code affecting the internal state.
This commit is contained in:
Kumar Aditya 2024-10-25 18:19:30 +05:30 committed by GitHub
parent ebcc578dff
commit cae853e3b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 44 additions and 28 deletions

View file

@ -697,6 +697,24 @@ class CFutureTests(BaseFutureTests, test_utils.TestCase):
with self.assertRaises(AttributeError):
del fut._log_traceback
def test_callbacks_copy(self):
# See https://github.com/python/cpython/issues/125789
# In C implementation, the `_callbacks` attribute
# always returns a new list to avoid mutations of internal state
fut = self._new_future(loop=self.loop)
f1 = lambda _: 1
f2 = lambda _: 2
fut.add_done_callback(f1)
fut.add_done_callback(f2)
callbacks = fut._callbacks
self.assertIsNot(callbacks, fut._callbacks)
fut.remove_done_callback(f1)
callbacks = fut._callbacks
self.assertIsNot(callbacks, fut._callbacks)
fut.remove_done_callback(f2)
self.assertIsNone(fut._callbacks)
@unittest.skipUnless(hasattr(futures, '_CFuture'),
'requires the C _asyncio module')