Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Lib/asyncio/futures.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,10 @@ def cancel(self):
if self._state != _PENDING:
return False
self._state = _CANCELLED
self._schedule_callbacks()
self.__schedule_callbacks()
return True

def _schedule_callbacks(self):
def __schedule_callbacks(self):
"""Internal: Ask the event loop to call all callbacks.

The callbacks are scheduled to be called as soon as possible. Also
Expand Down Expand Up @@ -234,7 +234,7 @@ def set_result(self, result):
raise InvalidStateError('{}: {!r}'.format(self._state, self))
self._result = result
self._state = _FINISHED
self._schedule_callbacks()
self.__schedule_callbacks()

def set_exception(self, exception):
"""Mark the future done and set an exception.
Expand All @@ -251,7 +251,7 @@ def set_exception(self, exception):
"and cannot be raised into a Future")
self._exception = exception
self._state = _FINISHED
self._schedule_callbacks()
self.__schedule_callbacks()
self.__log_traceback = True

def __await__(self):
Expand Down
28 changes: 14 additions & 14 deletions Lib/asyncio/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def __init__(self, coro, *, loop=None):
self._coro = coro
self._context = contextvars.copy_context()

self._loop.call_soon(self._step, context=self._context)
self._loop.call_soon(self.__step, context=self._context)
_register_task(self)

def __del__(self):
Expand Down Expand Up @@ -185,11 +185,11 @@ def cancel(self):
# catches and ignores the cancellation so we may have
# to cancel it again later.
return True
# It must be the case that self._step is already scheduled.
# It must be the case that self.__step is already scheduled.
self._must_cancel = True
return True

def _step(self, exc=None):
def __step(self, exc=None):
if self.done():
raise futures.InvalidStateError(
f'_step(): already done: {self!r}, {exc!r}')
Expand Down Expand Up @@ -232,17 +232,17 @@ def _step(self, exc=None):
f'Task {self!r} got Future '
f'{result!r} attached to a different loop')
self._loop.call_soon(
self._step, new_exc, context=self._context)
self.__step, new_exc, context=self._context)
elif blocking:
if result is self:
new_exc = RuntimeError(
f'Task cannot await on itself: {self!r}')
self._loop.call_soon(
self._step, new_exc, context=self._context)
self.__step, new_exc, context=self._context)
else:
result._asyncio_future_blocking = False
result.add_done_callback(
self._wakeup, context=self._context)
self.__wakeup, context=self._context)
self._fut_waiter = result
if self._must_cancel:
if self._fut_waiter.cancel():
Expand All @@ -252,41 +252,41 @@ def _step(self, exc=None):
f'yield was used instead of yield from '
f'in task {self!r} with {result!r}')
self._loop.call_soon(
self._step, new_exc, context=self._context)
self.__step, new_exc, context=self._context)

elif result is None:
# Bare yield relinquishes control for one event loop iteration.
self._loop.call_soon(self._step, context=self._context)
self._loop.call_soon(self.__step, context=self._context)
elif inspect.isgenerator(result):
# Yielding a generator is just wrong.
new_exc = RuntimeError(
f'yield was used instead of yield from for '
f'generator in task {self!r} with {result}')
self._loop.call_soon(
self._step, new_exc, context=self._context)
self.__step, new_exc, context=self._context)
else:
# Yielding something else is an error.
new_exc = RuntimeError(f'Task got bad yield: {result!r}')
self._loop.call_soon(
self._step, new_exc, context=self._context)
self.__step, new_exc, context=self._context)
finally:
_leave_task(self._loop, self)
self = None # Needed to break cycles when an exception occurs.

def _wakeup(self, future):
def __wakeup(self, future):
try:
future.result()
except Exception as exc:
# This may also be a cancellation.
self._step(exc)
self.__step(exc)
else:
# Don't pass the value of `future.result()` explicitly,
# as `Future.__iter__` and `Future.__await__` don't need it.
# If we call `_step(value, None)` instead of `_step()`,
# Python eval loop would use `.send(value)` method call,
# instead of `__next__()`, which is slower for futures
# that return non-generator iterators from their `__iter__`.
self._step()
self.__step()
self = None # Needed to break cycles when an exception occurs.


Expand Down Expand Up @@ -513,7 +513,7 @@ def __sleep0():

This is a private helper for 'asyncio.sleep()', used
when the 'delay' is set to 0. It uses a bare 'yield'
expression (which Task._step knows how to handle)
expression (which Task.__step knows how to handle)
instead of creating a Future object.
"""
yield
Expand Down
4 changes: 0 additions & 4 deletions Lib/test/test_asyncio/test_futures.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,6 @@ def test_uninitialized(self):
with self.assertRaises((RuntimeError, AttributeError)):
fut.remove_done_callback(lambda f: None)

fut = self.cls.__new__(self.cls, loop=self.loop)
with self.assertRaises((RuntimeError, AttributeError)):
fut._schedule_callbacks()

fut = self.cls.__new__(self.cls, loop=self.loop)
try:
repr(fut)
Expand Down
28 changes: 3 additions & 25 deletions Lib/test/test_asyncio/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -1401,17 +1401,6 @@ def wait_for_future():
self.assertTrue(t.done())
self.assertIsNone(t.result())

def test_step_with_baseexception(self):
@asyncio.coroutine
def notmutch():
raise BaseException()

task = self.new_task(self.loop, notmutch())
self.assertRaises(BaseException, task._step)

self.assertTrue(task.done())
self.assertIsInstance(task.exception(), BaseException)

def test_baseexception_during_cancel(self):

def gen():
Expand Down Expand Up @@ -2275,22 +2264,12 @@ def __init__(self, *args, **kwargs):
self.calls = collections.defaultdict(lambda: 0)
super().__init__(*args, **kwargs)

def _schedule_callbacks(self):
self.calls['_schedule_callbacks'] += 1
return super()._schedule_callbacks()

def add_done_callback(self, *args, **kwargs):
self.calls['add_done_callback'] += 1
return super().add_done_callback(*args, **kwargs)

class Task(CommonFuture, BaseTask):
def _step(self, *args):
self.calls['_step'] += 1
return super()._step(*args)

def _wakeup(self, *args):
self.calls['_wakeup'] += 1
return super()._wakeup(*args)
pass

class Future(CommonFuture, BaseFuture):
pass
Expand All @@ -2310,12 +2289,11 @@ async def func():

self.assertEqual(
dict(task.calls),
{'_step': 2, '_wakeup': 1, 'add_done_callback': 1,
'_schedule_callbacks': 1})
{'add_done_callback': 1})

self.assertEqual(
dict(fut.calls),
{'add_done_callback': 1, '_schedule_callbacks': 1})
{'add_done_callback': 1})

# Add patched Task & Future back to the test case
cls.Task = Task
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Make Task._step, Task._wakeup and Future._schedule_callbacks methods
private.
Loading