Kaydet (Commit) 7a465647 authored tarafından Guido van Rossum's avatar Guido van Rossum

asyncio: Pass cancellation from wrapping Future to wrapped Future. By Saúl…

asyncio: Pass cancellation from wrapping Future to wrapped Future. By Saúl Ibarra Corretgé (mostly).
üst 873d1226
: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`.
...@@ -22,6 +22,7 @@ multitasking). Here's an overview: ...@@ -22,6 +22,7 @@ multitasking). Here's an overview:
queue.rst queue.rst
select.rst select.rst
selectors.rst selectors.rst
asyncio.rst
The following are support modules for some of the above services: The following are support modules for some of the above services:
......
...@@ -301,6 +301,8 @@ class Future: ...@@ -301,6 +301,8 @@ class Future:
The other Future may be a concurrent.futures.Future. The other Future may be a concurrent.futures.Future.
""" """
assert other.done() assert other.done()
if self.cancelled():
return
assert not self.done() assert not self.done()
if other.cancelled(): if other.cancelled():
self.cancel() self.cancel()
...@@ -324,14 +326,17 @@ def wrap_future(fut, *, loop=None): ...@@ -324,14 +326,17 @@ def wrap_future(fut, *, loop=None):
"""Wrap concurrent.futures.Future object.""" """Wrap concurrent.futures.Future object."""
if isinstance(fut, Future): if isinstance(fut, Future):
return fut return fut
assert isinstance(fut, concurrent.futures.Future), \ assert isinstance(fut, concurrent.futures.Future), \
'concurrent.futures.Future is expected, got {!r}'.format(fut) 'concurrent.futures.Future is expected, got {!r}'.format(fut)
if loop is None: if loop is None:
loop = events.get_event_loop() loop = events.get_event_loop()
new_future = Future(loop=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( fut.add_done_callback(
lambda future: loop.call_soon_threadsafe( lambda future: loop.call_soon_threadsafe(
new_future._copy_state, fut)) new_future._copy_state, fut))
......
...@@ -241,6 +241,24 @@ class FutureTests(unittest.TestCase): ...@@ -241,6 +241,24 @@ class FutureTests(unittest.TestCase):
f2 = futures.wrap_future(f1) f2 = futures.wrap_future(f1)
self.assertIs(m_events.get_event_loop.return_value, f2._loop) 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): class FutureDoneCallbackTests(unittest.TestCase):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment