You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
81 lines
2.5 KiB
81 lines
2.5 KiB
3 years ago
|
__all__ = ()
|
||
|
|
||
|
import reprlib
|
||
|
from _thread import get_ident
|
||
|
|
||
|
from . import format_helpers
|
||
|
|
||
|
# States for Future.
|
||
|
_PENDING = 'PENDING'
|
||
|
_CANCELLED = 'CANCELLED'
|
||
|
_FINISHED = 'FINISHED'
|
||
|
|
||
|
|
||
|
def isfuture(obj):
|
||
|
"""Check for a Future.
|
||
|
|
||
|
This returns True when obj is a Future instance or is advertising
|
||
|
itself as duck-type compatible by setting _asyncio_future_blocking.
|
||
|
See comment in Future for more details.
|
||
|
"""
|
||
|
return (hasattr(obj.__class__, '_asyncio_future_blocking') and
|
||
|
obj._asyncio_future_blocking is not None)
|
||
|
|
||
|
|
||
|
def _format_callbacks(cb):
|
||
|
"""helper function for Future.__repr__"""
|
||
|
size = len(cb)
|
||
|
if not size:
|
||
|
cb = ''
|
||
|
|
||
|
def format_cb(callback):
|
||
|
return format_helpers._format_callback_source(callback, ())
|
||
|
|
||
|
if size == 1:
|
||
|
cb = format_cb(cb[0][0])
|
||
|
elif size == 2:
|
||
|
cb = '{}, {}'.format(format_cb(cb[0][0]), format_cb(cb[1][0]))
|
||
|
elif size > 2:
|
||
|
cb = '{}, <{} more>, {}'.format(format_cb(cb[0][0]),
|
||
|
size - 2,
|
||
|
format_cb(cb[-1][0]))
|
||
|
return f'cb=[{cb}]'
|
||
|
|
||
|
|
||
|
# bpo-42183: _repr_running is needed for repr protection
|
||
|
# when a Future or Task result contains itself directly or indirectly.
|
||
|
# The logic is borrowed from @reprlib.recursive_repr decorator.
|
||
|
# Unfortunately, the direct decorator usage is impossible because of
|
||
|
# AttributeError: '_asyncio.Task' object has no attribute '__module__' error.
|
||
|
#
|
||
|
# After fixing this thing we can return to the decorator based approach.
|
||
|
_repr_running = set()
|
||
|
|
||
|
|
||
|
def _future_repr_info(future):
|
||
|
# (Future) -> str
|
||
|
"""helper function for Future.__repr__"""
|
||
|
info = [future._state.lower()]
|
||
|
if future._state == _FINISHED:
|
||
|
if future._exception is not None:
|
||
|
info.append(f'exception={future._exception!r}')
|
||
|
else:
|
||
|
key = id(future), get_ident()
|
||
|
if key in _repr_running:
|
||
|
result = '...'
|
||
|
else:
|
||
|
_repr_running.add(key)
|
||
|
try:
|
||
|
# use reprlib to limit the length of the output, especially
|
||
|
# for very long strings
|
||
|
result = reprlib.repr(future._result)
|
||
|
finally:
|
||
|
_repr_running.discard(key)
|
||
|
info.append(f'result={result}')
|
||
|
if future._callbacks:
|
||
|
info.append(_format_callbacks(future._callbacks))
|
||
|
if future._source_traceback:
|
||
|
frame = future._source_traceback[-1]
|
||
|
info.append(f'created at {frame[0]}:{frame[1]}')
|
||
|
return info
|