]> granicus.if.org Git - python/commitdiff
asyncio: Pass cancellation from wrapping Future to wrapped Future. By Saúl Ibarra...
authorGuido van Rossum <guido@dropbox.com>
Fri, 22 Nov 2013 19:47:22 +0000 (11:47 -0800)
committerGuido van Rossum <guido@dropbox.com>
Fri, 22 Nov 2013 19:47:22 +0000 (11:47 -0800)
Doc/library/asyncio.rst [new file with mode: 0644]
Doc/library/concurrency.rst
Lib/asyncio/futures.py
Lib/test/test_asyncio/test_futures.py

diff --git a/Doc/library/asyncio.rst b/Doc/library/asyncio.rst
new file mode 100644 (file)
index 0000000..0decdc7
--- /dev/null
@@ -0,0 +1,20 @@
+:mod:`asyncio` -- Asynchronous I/O, event loop, coroutines and tasks
+====================================================================
+
+.. module:: asyncio
+   :synopsis: Asynchronous I/O, event loop, coroutines and tasks.
+
+.. versionadded:: 3.4
+
+
+Introduction
+------------
+
+This package includes a pluggable event loop, transport and protocol
+abstractions similar to those in Twisted, and a higher-level scheduler
+for coroutines and tasks based on ``yield from`` (:PEP:`380`).
+
+Full documentation is not yet ready; we hope to have it written
+before Python 3.4 leaves beta.  Until then, the best reference is
+:PEP:`3156`.  For a motivational primer on transports and protocols,
+see :PEP:`3153`.
index 2d691073bb60bb29457f3affd662a4a596e10f29..e016694c77b10001762624169a5511134db60451 100644 (file)
@@ -22,6 +22,7 @@ multitasking). Here's an overview:
    queue.rst
    select.rst
    selectors.rst
+   asyncio.rst
 
 
 The following are support modules for some of the above services:
index db278386ea06e2ed74c1f8df2254dae9a3fff2b5..dd3e718d9a501ebb23156451173a80f442335d7d 100644 (file)
@@ -301,6 +301,8 @@ class Future:
         The other Future may be a concurrent.futures.Future.
         """
         assert other.done()
+        if self.cancelled():
+            return
         assert not self.done()
         if other.cancelled():
             self.cancel()
@@ -324,14 +326,17 @@ def wrap_future(fut, *, loop=None):
     """Wrap concurrent.futures.Future object."""
     if isinstance(fut, Future):
         return fut
-
     assert isinstance(fut, concurrent.futures.Future), \
         'concurrent.futures.Future is expected, got {!r}'.format(fut)
-
     if loop is None:
         loop = events.get_event_loop()
-
     new_future = Future(loop=loop)
+
+    def _check_cancel_other(f):
+        if f.cancelled():
+            fut.cancel()
+
+    new_future.add_done_callback(_check_cancel_other)
     fut.add_done_callback(
         lambda future: loop.call_soon_threadsafe(
             new_future._copy_state, fut))
index ccea2ffded2b8f7ebe85f036752d7eb5d7a5c516..e35fcf0708559457b2856553e4f1e8e921be68f2 100644 (file)
@@ -241,6 +241,24 @@ class FutureTests(unittest.TestCase):
         f2 = futures.wrap_future(f1)
         self.assertIs(m_events.get_event_loop.return_value, f2._loop)
 
+    def test_wrap_future_cancel(self):
+        f1 = concurrent.futures.Future()
+        f2 = futures.wrap_future(f1, loop=self.loop)
+        f2.cancel()
+        test_utils.run_briefly(self.loop)
+        self.assertTrue(f1.cancelled())
+        self.assertTrue(f2.cancelled())
+
+    def test_wrap_future_cancel2(self):
+        f1 = concurrent.futures.Future()
+        f2 = futures.wrap_future(f1, loop=self.loop)
+        f1.set_result(42)
+        f2.cancel()
+        test_utils.run_briefly(self.loop)
+        self.assertFalse(f1.cancelled())
+        self.assertEqual(f1.result(), 42)
+        self.assertTrue(f2.cancelled())
+
 
 class FutureDoneCallbackTests(unittest.TestCase):