]> granicus.if.org Git - python/commitdiff
asyncio: Make Tasks check if Futures are attached to the same event loop
authorYury Selivanov <yselivanov@sprymix.com>
Fri, 11 Dec 2015 16:33:59 +0000 (11:33 -0500)
committerYury Selivanov <yselivanov@sprymix.com>
Fri, 11 Dec 2015 16:33:59 +0000 (11:33 -0500)
See https://github.com/python/asyncio/pull/303 for details

Lib/asyncio/tasks.py
Lib/test/test_asyncio/test_tasks.py

index e6389d82bdb46ea98871b95e67aeabc908d1263f..a2ab8815b66053a6467a687571705405afd24b4d 100644 (file)
@@ -251,7 +251,13 @@ class Task(futures.Future):
         else:
             if isinstance(result, futures.Future):
                 # Yielded Future must come from Future.__iter__().
-                if result._blocking:
+                if result._loop is not self._loop:
+                    self._loop.call_soon(
+                        self._step,
+                        RuntimeError(
+                            'Task {!r} got Future {!r} attached to a '
+                            'different loop'.format(self, result)))
+                elif result._blocking:
                     result._blocking = False
                     result.add_done_callback(self._wakeup)
                     self._fut_waiter = result
index 04d19ac63b2f9c660b84123c006348085ff29424..47b17d1bcb37f05be7eecfab6c7e9cfd501a43e2 100644 (file)
@@ -76,6 +76,21 @@ class TaskTests(test_utils.TestCase):
     def setUp(self):
         self.loop = self.new_test_loop()
 
+    def test_other_loop_future(self):
+        other_loop = asyncio.new_event_loop()
+        fut = asyncio.Future(loop=other_loop)
+
+        @asyncio.coroutine
+        def run(fut):
+            yield from fut
+
+        try:
+            with self.assertRaisesRegex(RuntimeError,
+                                        r'Task .* got Future .* attached'):
+                self.loop.run_until_complete(run(fut))
+        finally:
+            other_loop.close()
+
     def test_task_class(self):
         @asyncio.coroutine
         def notmuch():