bpo-38785: Prevent asyncio from crashing (GH-17144)
if parent `__init__` is not called from a constructor of object derived from `asyncio.Future` https://bugs.python.org/issue38785
This commit is contained in:
parent
61289d4366
commit
dad6be5ffe
|
@ -115,7 +115,10 @@ class Future:
|
||||||
|
|
||||||
def get_loop(self):
|
def get_loop(self):
|
||||||
"""Return the event loop the Future is bound to."""
|
"""Return the event loop the Future is bound to."""
|
||||||
return self._loop
|
loop = self._loop
|
||||||
|
if loop is None:
|
||||||
|
raise RuntimeError("Future object is not initialized.")
|
||||||
|
return loop
|
||||||
|
|
||||||
def cancel(self):
|
def cancel(self):
|
||||||
"""Cancel the future and schedule callbacks.
|
"""Cancel the future and schedule callbacks.
|
||||||
|
|
|
@ -822,5 +822,44 @@ class PyFutureDoneCallbackTests(BaseFutureDoneCallbackTests,
|
||||||
return futures._PyFuture(loop=self.loop)
|
return futures._PyFuture(loop=self.loop)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseFutureInheritanceTests:
|
||||||
|
|
||||||
|
def _get_future_cls(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
self.loop = self.new_test_loop()
|
||||||
|
self.addCleanup(self.loop.close)
|
||||||
|
|
||||||
|
def test_inherit_without_calling_super_init(self):
|
||||||
|
# See https://bugs.python.org/issue38785 for the context
|
||||||
|
cls = self._get_future_cls()
|
||||||
|
|
||||||
|
class MyFut(cls):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
# don't call super().__init__()
|
||||||
|
pass
|
||||||
|
|
||||||
|
fut = MyFut(loop=self.loop)
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
RuntimeError,
|
||||||
|
"Future object is not initialized."
|
||||||
|
):
|
||||||
|
fut.get_loop()
|
||||||
|
|
||||||
|
|
||||||
|
class PyFutureInheritanceTests(BaseFutureInheritanceTests,
|
||||||
|
test_utils.TestCase):
|
||||||
|
def _get_future_cls(self):
|
||||||
|
return futures._PyFuture
|
||||||
|
|
||||||
|
|
||||||
|
class CFutureInheritanceTests(BaseFutureInheritanceTests,
|
||||||
|
test_utils.TestCase):
|
||||||
|
def _get_future_cls(self):
|
||||||
|
return futures._CFuture
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Prevent asyncio from crashing if parent ``__init__`` is not called from a
|
||||||
|
constructor of object derived from ``asyncio.Future``.
|
|
@ -1091,6 +1091,7 @@ static PyObject *
|
||||||
_asyncio_Future_get_loop_impl(FutureObj *self)
|
_asyncio_Future_get_loop_impl(FutureObj *self)
|
||||||
/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
|
/*[clinic end generated code: output=119b6ea0c9816c3f input=cba48c2136c79d1f]*/
|
||||||
{
|
{
|
||||||
|
ENSURE_FUTURE_ALIVE(self)
|
||||||
Py_INCREF(self->fut_loop);
|
Py_INCREF(self->fut_loop);
|
||||||
return self->fut_loop;
|
return self->fut_loop;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue