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
diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py
index 98a5308e..9afda22 100644
--- a/Lib/asyncio/futures.py
+++ b/Lib/asyncio/futures.py
@@ -115,7 +115,10 @@
 
     def get_loop(self):
         """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):
         """Cancel the future and schedule callbacks.
diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py
index 2e4583d..ee5edd5 100644
--- a/Lib/test/test_asyncio/test_futures.py
+++ b/Lib/test/test_asyncio/test_futures.py
@@ -822,5 +822,44 @@
         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__':
     unittest.main()