mirror of https://github.com/python/cpython
Rename Future._blocking to _asyncio_future_blocking.
This is now an official "protected" API that can be used to write classes that are duck-type-compatible with Future without subclassing it. (For that purpose I also changed isinstance(result, Future) to check for this attribute instead.) Hopefully Amber Brown can use this to make Twisted.Deferred compatible with asyncio.Future. Tests and docs are TBD. (Also there are more isinstance() checks to fix.)
This commit is contained in:
commit
7719d46431
|
@ -134,7 +134,15 @@ class Future:
|
||||||
_loop = None
|
_loop = None
|
||||||
_source_traceback = None
|
_source_traceback = None
|
||||||
|
|
||||||
_blocking = False # proper use of future (yield vs yield from)
|
# This field is used for a dual purpose:
|
||||||
|
# - Its presence is a marker to declare that a class implements
|
||||||
|
# the Future protocol (i.e. is intended to be duck-type compatible).
|
||||||
|
# The value must also be not-None, to enable a subclass to declare
|
||||||
|
# that it is not compatible by setting this to None.
|
||||||
|
# - It is set by __iter__() below so that Task._step() can tell
|
||||||
|
# the difference between `yield from Future()` (correct) vs.
|
||||||
|
# `yield Future()` (incorrect).
|
||||||
|
_asyncio_future_blocking = False
|
||||||
|
|
||||||
_log_traceback = False # Used for Python 3.4 and later
|
_log_traceback = False # Used for Python 3.4 and later
|
||||||
_tb_logger = None # Used for Python 3.3 only
|
_tb_logger = None # Used for Python 3.3 only
|
||||||
|
@ -357,7 +365,7 @@ class Future:
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
if not self.done():
|
if not self.done():
|
||||||
self._blocking = True
|
self._asyncio_future_blocking = True
|
||||||
yield self # This tells Task to wait for completion.
|
yield self # This tells Task to wait for completion.
|
||||||
assert self.done(), "yield from wasn't used with future"
|
assert self.done(), "yield from wasn't used with future"
|
||||||
return self.result() # May raise too.
|
return self.result() # May raise too.
|
||||||
|
|
|
@ -249,7 +249,8 @@ class Task(futures.Future):
|
||||||
self.set_exception(exc)
|
self.set_exception(exc)
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
if isinstance(result, futures.Future):
|
blocking = getattr(result, '_asyncio_future_blocking', None)
|
||||||
|
if blocking is not None:
|
||||||
# Yielded Future must come from Future.__iter__().
|
# Yielded Future must come from Future.__iter__().
|
||||||
if result._loop is not self._loop:
|
if result._loop is not self._loop:
|
||||||
self._loop.call_soon(
|
self._loop.call_soon(
|
||||||
|
@ -257,8 +258,8 @@ class Task(futures.Future):
|
||||||
RuntimeError(
|
RuntimeError(
|
||||||
'Task {!r} got Future {!r} attached to a '
|
'Task {!r} got Future {!r} attached to a '
|
||||||
'different loop'.format(self, result)))
|
'different loop'.format(self, result)))
|
||||||
elif result._blocking:
|
elif blocking:
|
||||||
result._blocking = False
|
result._asyncio_future_blocking = False
|
||||||
result.add_done_callback(self._wakeup)
|
result.add_done_callback(self._wakeup)
|
||||||
self._fut_waiter = result
|
self._fut_waiter = result
|
||||||
if self._must_cancel:
|
if self._must_cancel:
|
||||||
|
|
Loading…
Reference in New Issue