Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f1024f7

Browse files
committed
merge
2 parents 3ceb573 + 87dc4d6 commit f1024f7

7 files changed

Lines changed: 96 additions & 19 deletions

File tree

Doc/library/queue.rst

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ the first retrieved (operating like a stack). With a priority queue,
2323
the entries are kept sorted (using the :mod:`heapq` module) and the
2424
lowest valued entry is retrieved first.
2525

26+
Internally, the module uses locks to temporarily block competing threads;
27+
however, it is not designed to handle reentrancy within a thread.
2628

2729
The :mod:`queue` module defines the following classes and exceptions:
2830

@@ -189,11 +191,6 @@ Example of how to wait for enqueued tasks to be completed::
189191
t.join()
190192

191193

192-
.. note::
193-
194-
The :mod:`queue` module is not safe for use from :mod:`signal` handlers as
195-
it uses :mod:`threading` locks.
196-
197194
.. seealso::
198195

199196
Class :class:`multiprocessing.Queue`

Lib/asyncio/base_events.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ def run_until_complete(self, future):
414414
"""
415415
self._check_closed()
416416

417-
new_task = not isinstance(future, futures.Future)
417+
new_task = not futures.isfuture(future)
418418
future = tasks.ensure_future(future, loop=self)
419419
if new_task:
420420
# An exception is raised if the future didn't complete, so there

Lib/asyncio/coroutines.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,8 @@ def coroutine(func):
204204
@functools.wraps(func)
205205
def coro(*args, **kw):
206206
res = func(*args, **kw)
207-
if isinstance(res, futures.Future) or inspect.isgenerator(res) or \
208-
isinstance(res, CoroWrapper):
207+
if (futures.isfuture(res) or inspect.isgenerator(res) or
208+
isinstance(res, CoroWrapper)):
209209
res = yield from res
210210
elif _AwaitableABC is not None:
211211
# If 'func' returns an Awaitable (new in 3.5) we

Lib/asyncio/futures.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,16 @@ def __del__(self):
110110
self.loop.call_exception_handler({'message': msg})
111111

112112

113+
def isfuture(obj):
114+
"""Check for a Future.
115+
116+
This returns True when obj is a Future instance or is advertising
117+
itself as duck-type compatible by setting _asyncio_future_blocking.
118+
See comment in Future for more details.
119+
"""
120+
return getattr(obj, '_asyncio_future_blocking', None) is not None
121+
122+
113123
class Future:
114124
"""This class is *almost* compatible with concurrent.futures.Future.
115125
@@ -423,15 +433,17 @@ def _chain_future(source, destination):
423433
If destination is cancelled, source gets cancelled too.
424434
Compatible with both asyncio.Future and concurrent.futures.Future.
425435
"""
426-
if not isinstance(source, (Future, concurrent.futures.Future)):
436+
if not isfuture(source) and not isinstance(source,
437+
concurrent.futures.Future):
427438
raise TypeError('A future is required for source argument')
428-
if not isinstance(destination, (Future, concurrent.futures.Future)):
439+
if not isfuture(destination) and not isinstance(destination,
440+
concurrent.futures.Future):
429441
raise TypeError('A future is required for destination argument')
430-
source_loop = source._loop if isinstance(source, Future) else None
431-
dest_loop = destination._loop if isinstance(destination, Future) else None
442+
source_loop = source._loop if isfuture(source) else None
443+
dest_loop = destination._loop if isfuture(destination) else None
432444

433445
def _set_state(future, other):
434-
if isinstance(future, Future):
446+
if isfuture(future):
435447
_copy_future_state(other, future)
436448
else:
437449
_set_concurrent_future_state(future, other)
@@ -455,7 +467,7 @@ def _call_set_state(source):
455467

456468
def wrap_future(future, *, loop=None):
457469
"""Wrap concurrent.futures.Future object."""
458-
if isinstance(future, Future):
470+
if isfuture(future):
459471
return future
460472
assert isinstance(future, concurrent.futures.Future), \
461473
'concurrent.futures.Future is expected, got {!r}'.format(future)

Lib/asyncio/tasks.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ def wait(fs, *, loop=None, timeout=None, return_when=ALL_COMPLETED):
333333
Note: This does not raise TimeoutError! Futures that aren't done
334334
when the timeout occurs are returned in the second set.
335335
"""
336-
if isinstance(fs, futures.Future) or coroutines.iscoroutine(fs):
336+
if futures.isfuture(fs) or coroutines.iscoroutine(fs):
337337
raise TypeError("expect a list of futures, not %s" % type(fs).__name__)
338338
if not fs:
339339
raise ValueError('Set of coroutines/Futures is empty.')
@@ -462,7 +462,7 @@ def as_completed(fs, *, loop=None, timeout=None):
462462
463463
Note: The futures 'f' are not necessarily members of fs.
464464
"""
465-
if isinstance(fs, futures.Future) or coroutines.iscoroutine(fs):
465+
if futures.isfuture(fs) or coroutines.iscoroutine(fs):
466466
raise TypeError("expect a list of futures, not %s" % type(fs).__name__)
467467
loop = loop if loop is not None else events.get_event_loop()
468468
todo = {ensure_future(f, loop=loop) for f in set(fs)}
@@ -538,7 +538,7 @@ def ensure_future(coro_or_future, *, loop=None):
538538
539539
If the argument is a Future, it is returned directly.
540540
"""
541-
if isinstance(coro_or_future, futures.Future):
541+
if futures.isfuture(coro_or_future):
542542
if loop is not None and loop is not coro_or_future._loop:
543543
raise ValueError('loop argument must agree with Future')
544544
return coro_or_future
@@ -614,7 +614,7 @@ def gather(*coros_or_futures, loop=None, return_exceptions=False):
614614

615615
arg_to_fut = {}
616616
for arg in set(coros_or_futures):
617-
if not isinstance(arg, futures.Future):
617+
if not futures.isfuture(arg):
618618
fut = ensure_future(arg, loop=loop)
619619
if loop is None:
620620
loop = fut._loop

Lib/test/test_asyncio/test_events.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ def client():
793793
loop.connect_accepted_socket(
794794
(lambda : proto), conn, ssl=server_ssl))
795795
loop.run_forever()
796-
conn.close()
796+
proto.transport.close()
797797
lsock.close()
798798

799799
thread.join(1)

Lib/test/test_asyncio/test_futures.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,74 @@ def last_cb():
2525
pass
2626

2727

28+
class DuckFuture:
29+
# Class that does not inherit from Future but aims to be duck-type
30+
# compatible with it.
31+
32+
_asyncio_future_blocking = False
33+
__cancelled = False
34+
__result = None
35+
__exception = None
36+
37+
def cancel(self):
38+
if self.done():
39+
return False
40+
self.__cancelled = True
41+
return True
42+
43+
def cancelled(self):
44+
return self.__cancelled
45+
46+
def done(self):
47+
return (self.__cancelled
48+
or self.__result is not None
49+
or self.__exception is not None)
50+
51+
def result(self):
52+
assert not self.cancelled()
53+
if self.__exception is not None:
54+
raise self.__exception
55+
return self.__result
56+
57+
def exception(self):
58+
assert not self.cancelled()
59+
return self.__exception
60+
61+
def set_result(self, result):
62+
assert not self.done()
63+
assert result is not None
64+
self.__result = result
65+
66+
def set_exception(self, exception):
67+
assert not self.done()
68+
assert exception is not None
69+
self.__exception = exception
70+
71+
def __iter__(self):
72+
if not self.done():
73+
self._asyncio_future_blocking = True
74+
yield self
75+
assert self.done()
76+
return self.result()
77+
78+
79+
class DuckTests(test_utils.TestCase):
80+
81+
def setUp(self):
82+
self.loop = self.new_test_loop()
83+
self.addCleanup(self.loop.close)
84+
85+
def test_wrap_future(self):
86+
f = DuckFuture()
87+
g = asyncio.wrap_future(f)
88+
assert g is f
89+
90+
def test_ensure_future(self):
91+
f = DuckFuture()
92+
g = asyncio.ensure_future(f)
93+
assert g is f
94+
95+
2896
class FutureTests(test_utils.TestCase):
2997

3098
def setUp(self):

0 commit comments

Comments
 (0)