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
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.
"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):
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):
# 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}')
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():
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.
# 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.
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
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)
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():
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
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
--- /dev/null
+Make Task._step, Task._wakeup and Future._schedule_callbacks methods
+private.
_Py_IDENTIFIER(get_event_loop);
_Py_IDENTIFIER(send);
_Py_IDENTIFIER(throw);
-_Py_IDENTIFIER(_step);
-_Py_IDENTIFIER(_schedule_callbacks);
-_Py_IDENTIFIER(_wakeup);
/* State of the _asyncio module */
/* Get FutureIter from Future */
static PyObject * future_new_iter(PyObject *);
-static inline int future_call_schedule_callbacks(FutureObj *);
static PyRunningLoopHolder * new_running_loop_holder(PyObject *);
fut->fut_result = res;
fut->fut_state = STATE_FINISHED;
- if (future_call_schedule_callbacks(fut) == -1) {
+ if (future_schedule_callbacks(fut) == -1) {
return NULL;
}
Py_RETURN_NONE;
fut->fut_exception = exc_val;
fut->fut_state = STATE_FINISHED;
- if (future_call_schedule_callbacks(fut) == -1) {
+ if (future_schedule_callbacks(fut) == -1) {
return NULL;
}
}
fut->fut_state = STATE_CANCELLED;
- if (future_call_schedule_callbacks(fut) == -1) {
+ if (future_schedule_callbacks(fut) == -1) {
return NULL;
}
asyncio_future_repr_info_func, self, NULL);
}
-/*[clinic input]
-_asyncio.Future._schedule_callbacks
-[clinic start generated code]*/
-
-static PyObject *
-_asyncio_Future__schedule_callbacks_impl(FutureObj *self)
-/*[clinic end generated code: output=5e8958d89ea1c5dc input=4f5f295f263f4a88]*/
-{
- ENSURE_FUTURE_ALIVE(self)
-
- int ret = future_schedule_callbacks(self);
- if (ret == -1) {
- return NULL;
- }
- Py_RETURN_NONE;
-}
-
static PyObject *
FutureObj_repr(FutureObj *fut)
{
_ASYNCIO_FUTURE_DONE_METHODDEF
_ASYNCIO_FUTURE_GET_LOOP_METHODDEF
_ASYNCIO_FUTURE__REPR_INFO_METHODDEF
- _ASYNCIO_FUTURE__SCHEDULE_CALLBACKS_METHODDEF
{NULL, NULL} /* Sentinel */
};
.tp_finalize = (destructor)FutureObj_finalize,
};
-static inline int
-future_call_schedule_callbacks(FutureObj *fut)
-{
- if (Future_CheckExact(fut) || Task_CheckExact(fut)) {
- return future_schedule_callbacks(fut);
- }
- else {
- /* `fut` is a subclass of Future */
- PyObject *ret = _PyObject_CallMethodId(
- (PyObject*)fut, &PyId__schedule_callbacks, NULL);
- if (ret == NULL) {
- return -1;
- }
-
- Py_DECREF(ret);
- return 0;
- }
-}
-
static void
FutureObj_dealloc(PyObject *self)
{
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=719dcef0fcc03b37]*/
static int task_call_step_soon(TaskObj *, PyObject *);
-static inline PyObject * task_call_wakeup(TaskObj *, PyObject *);
-static inline PyObject * task_call_step(TaskObj *, PyObject *);
static PyObject * task_wakeup(TaskObj *, PyObject *);
static PyObject * task_step(TaskObj *, PyObject *);
PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
return NULL;
}
- return task_call_step(o->sw_task, o->sw_arg);
+ return task_step(o->sw_task, o->sw_arg);
}
static int
return NULL;
}
- return task_call_wakeup(o->ww_task, fut);
+ return task_wakeup(o->ww_task, fut);
}
static int
asyncio_task_print_stack_func, self, limit, file, NULL);
}
-/*[clinic input]
-_asyncio.Task._step
-
- exc: object = None
-[clinic start generated code]*/
-
-static PyObject *
-_asyncio_Task__step_impl(TaskObj *self, PyObject *exc)
-/*[clinic end generated code: output=7ed23f0cefd5ae42 input=1e19a985ace87ca4]*/
-{
- return task_step(self, exc == Py_None ? NULL : exc);
-}
-
-/*[clinic input]
-_asyncio.Task._wakeup
-
- fut: object
-[clinic start generated code]*/
-
-static PyObject *
-_asyncio_Task__wakeup_impl(TaskObj *self, PyObject *fut)
-/*[clinic end generated code: output=75cb341c760fd071 input=6a0616406f829a7b]*/
-{
- return task_wakeup(self, fut);
-}
-
/*[clinic input]
_asyncio.Task.set_result
_ASYNCIO_TASK_CANCEL_METHODDEF
_ASYNCIO_TASK_GET_STACK_METHODDEF
_ASYNCIO_TASK_PRINT_STACK_METHODDEF
- _ASYNCIO_TASK__WAKEUP_METHODDEF
- _ASYNCIO_TASK__STEP_METHODDEF
_ASYNCIO_TASK__REPR_INFO_METHODDEF
{NULL, NULL} /* Sentinel */
};
Py_TYPE(task)->tp_free(task);
}
-static inline PyObject *
-task_call_wakeup(TaskObj *task, PyObject *fut)
-{
- if (Task_CheckExact(task)) {
- return task_wakeup(task, fut);
- }
- else {
- /* `task` is a subclass of Task */
- return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__wakeup,
- fut, NULL);
- }
-}
-
-static inline PyObject *
-task_call_step(TaskObj *task, PyObject *arg)
-{
- if (Task_CheckExact(task)) {
- return task_step(task, arg);
- }
- else {
- /* `task` is a subclass of Task */
- return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__step,
- arg, NULL);
- }
-}
-
static int
task_call_step_soon(TaskObj *task, PyObject *arg)
{
break; /* exception raised */
case 0:
Py_DECREF(fut_result);
- return task_call_step(task, NULL);
+ return task_step(task, NULL);
default:
assert(res == 1);
- result = task_call_step(task, fut_result);
+ result = task_step(task, fut_result);
Py_DECREF(fut_result);
return result;
}
PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
if (fut_result != NULL) {
Py_DECREF(fut_result);
- return task_call_step(task, NULL);
+ return task_step(task, NULL);
}
/* exception raised */
}
PyErr_NormalizeException(&et, &ev, &tb);
}
- result = task_call_step(task, ev);
+ result = task_step(task, ev);
Py_DECREF(et);
Py_XDECREF(tb);
return _asyncio_Future__repr_info_impl(self);
}
-PyDoc_STRVAR(_asyncio_Future__schedule_callbacks__doc__,
-"_schedule_callbacks($self, /)\n"
-"--\n"
-"\n");
-
-#define _ASYNCIO_FUTURE__SCHEDULE_CALLBACKS_METHODDEF \
- {"_schedule_callbacks", (PyCFunction)_asyncio_Future__schedule_callbacks, METH_NOARGS, _asyncio_Future__schedule_callbacks__doc__},
-
-static PyObject *
-_asyncio_Future__schedule_callbacks_impl(FutureObj *self);
-
-static PyObject *
-_asyncio_Future__schedule_callbacks(FutureObj *self, PyObject *Py_UNUSED(ignored))
-{
- return _asyncio_Future__schedule_callbacks_impl(self);
-}
-
PyDoc_STRVAR(_asyncio_Task___init____doc__,
"Task(coro, *, loop=None)\n"
"--\n"
return return_value;
}
-PyDoc_STRVAR(_asyncio_Task__step__doc__,
-"_step($self, /, exc=None)\n"
-"--\n"
-"\n");
-
-#define _ASYNCIO_TASK__STEP_METHODDEF \
- {"_step", (PyCFunction)_asyncio_Task__step, METH_FASTCALL|METH_KEYWORDS, _asyncio_Task__step__doc__},
-
-static PyObject *
-_asyncio_Task__step_impl(TaskObj *self, PyObject *exc);
-
-static PyObject *
-_asyncio_Task__step(TaskObj *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
-{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = {"exc", NULL};
- static _PyArg_Parser _parser = {"|O:_step", _keywords, 0};
- PyObject *exc = Py_None;
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &exc)) {
- goto exit;
- }
- return_value = _asyncio_Task__step_impl(self, exc);
-
-exit:
- return return_value;
-}
-
-PyDoc_STRVAR(_asyncio_Task__wakeup__doc__,
-"_wakeup($self, /, fut)\n"
-"--\n"
-"\n");
-
-#define _ASYNCIO_TASK__WAKEUP_METHODDEF \
- {"_wakeup", (PyCFunction)_asyncio_Task__wakeup, METH_FASTCALL|METH_KEYWORDS, _asyncio_Task__wakeup__doc__},
-
-static PyObject *
-_asyncio_Task__wakeup_impl(TaskObj *self, PyObject *fut);
-
-static PyObject *
-_asyncio_Task__wakeup(TaskObj *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
-{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = {"fut", NULL};
- static _PyArg_Parser _parser = {"O:_wakeup", _keywords, 0};
- PyObject *fut;
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &fut)) {
- goto exit;
- }
- return_value = _asyncio_Task__wakeup_impl(self, fut);
-
-exit:
- return return_value;
-}
-
PyDoc_STRVAR(_asyncio_Task_set_result__doc__,
"set_result($self, result, /)\n"
"--\n"
exit:
return return_value;
}
-/*[clinic end generated code: output=bcbaf1b2480f4aa9 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=b6148b0134e7a819 input=a9049054013a1b77]*/