[Python-checkins] bpo-31185: Fixed miscellaneous errors in asyncio speedup module. (#3076)

Serhiy Storchaka webhook-mailer at python.org
Sun Sep 3 01:10:16 EDT 2017


https://github.com/python/cpython/commit/bca4939d806170c3ca5d05f23710d11a8f1669cf
commit: bca4939d806170c3ca5d05f23710d11a8f1669cf
branch: master
author: Serhiy Storchaka <storchaka at gmail.com>
committer: GitHub <noreply at github.com>
date: 2017-09-03T08:10:14+03:00
summary:

bpo-31185: Fixed miscellaneous errors in asyncio speedup module. (#3076)

files:
A Misc/NEWS.d/next/Library/2017-08-11-19-30-00.bpo-31185.i6TPgL.rst
M Lib/test/test_asyncio/test_futures.py
M Modules/_asynciomodule.c
M Modules/clinic/_asynciomodule.c.h

diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py
index f8f614f1c30..4320a901f49 100644
--- a/Lib/test/test_asyncio/test_futures.py
+++ b/Lib/test/test_asyncio/test_futures.py
@@ -100,8 +100,8 @@ def test_ensure_future(self):
 
 class BaseFutureTests:
 
-    def _new_future(self, loop=None):
-        raise NotImplementedError
+    def _new_future(self,  *args, **kwargs):
+        return self.cls(*args, **kwargs)
 
     def setUp(self):
         super().setUp()
@@ -147,6 +147,39 @@ def test_constructor_positional(self):
         # Make sure Future doesn't accept a positional argument
         self.assertRaises(TypeError, self._new_future, 42)
 
+    def test_uninitialized(self):
+        fut = self.cls.__new__(self.cls, loop=self.loop)
+        self.assertRaises(asyncio.InvalidStateError, fut.result)
+        fut = self.cls.__new__(self.cls, loop=self.loop)
+        self.assertRaises(asyncio.InvalidStateError, fut.exception)
+        fut = self.cls.__new__(self.cls, loop=self.loop)
+        with self.assertRaises((RuntimeError, AttributeError)):
+            fut.set_result(None)
+        fut = self.cls.__new__(self.cls, loop=self.loop)
+        with self.assertRaises((RuntimeError, AttributeError)):
+            fut.set_exception(Exception)
+        fut = self.cls.__new__(self.cls, loop=self.loop)
+        with self.assertRaises((RuntimeError, AttributeError)):
+            fut.cancel()
+        fut = self.cls.__new__(self.cls, loop=self.loop)
+        with self.assertRaises((RuntimeError, AttributeError)):
+            fut.add_done_callback(lambda f: None)
+        fut = self.cls.__new__(self.cls, loop=self.loop)
+        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)
+        except AttributeError:
+            pass
+        fut = self.cls.__new__(self.cls, loop=self.loop)
+        fut.cancelled()
+        fut.done()
+        iter(fut)
+
     def test_cancel(self):
         f = self._new_future(loop=self.loop)
         self.assertTrue(f.cancel())
@@ -501,15 +534,11 @@ def __del__(self):
 @unittest.skipUnless(hasattr(futures, '_CFuture'),
                      'requires the C _asyncio module')
 class CFutureTests(BaseFutureTests, test_utils.TestCase):
-
-    def _new_future(self,  *args, **kwargs):
-        return futures._CFuture(*args, **kwargs)
+    cls = getattr(futures, '_CFuture')
 
 
 class PyFutureTests(BaseFutureTests, test_utils.TestCase):
-
-    def _new_future(self, *args, **kwargs):
-        return futures._PyFuture(*args, **kwargs)
+    cls = futures._PyFuture
 
 
 class BaseFutureDoneCallbackTests():
diff --git a/Misc/NEWS.d/next/Library/2017-08-11-19-30-00.bpo-31185.i6TPgL.rst b/Misc/NEWS.d/next/Library/2017-08-11-19-30-00.bpo-31185.i6TPgL.rst
new file mode 100644
index 00000000000..bdaa4ea35da
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2017-08-11-19-30-00.bpo-31185.i6TPgL.rst
@@ -0,0 +1 @@
+Fixed miscellaneous errors in asyncio speedup module.
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index d4b313480e9..2c64c55e7e3 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -68,7 +68,7 @@ typedef struct {
     PyObject_HEAD
     TaskObj *sw_task;
     PyObject *sw_arg;
-} TaskSendMethWrapper;
+} TaskStepMethWrapper;
 
 typedef struct {
     PyObject_HEAD
@@ -92,11 +92,11 @@ static int
 future_schedule_callbacks(FutureObj *fut)
 {
     Py_ssize_t len;
-    PyObject* iters;
+    PyObject *callbacks;
     int i;
 
     if (fut->fut_callbacks == NULL) {
-        PyErr_SetString(PyExc_RuntimeError, "NULL callbacks");
+        PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
         return -1;
     }
 
@@ -105,42 +105,41 @@ future_schedule_callbacks(FutureObj *fut)
         return 0;
     }
 
-    iters = PyList_GetSlice(fut->fut_callbacks, 0, len);
-    if (iters == NULL) {
+    callbacks = PyList_GetSlice(fut->fut_callbacks, 0, len);
+    if (callbacks == NULL) {
         return -1;
     }
     if (PyList_SetSlice(fut->fut_callbacks, 0, len, NULL) < 0) {
-        Py_DECREF(iters);
+        Py_DECREF(callbacks);
         return -1;
     }
 
     for (i = 0; i < len; i++) {
-        PyObject *handle = NULL;
-        PyObject *cb = PyList_GET_ITEM(iters, i);
+        PyObject *handle;
+        PyObject *cb = PyList_GET_ITEM(callbacks, i);
 
         handle = _PyObject_CallMethodIdObjArgs(fut->fut_loop, &PyId_call_soon,
                                                cb, fut, NULL);
 
         if (handle == NULL) {
-            Py_DECREF(iters);
+            Py_DECREF(callbacks);
             return -1;
         }
-        else {
-            Py_DECREF(handle);
-        }
+        Py_DECREF(handle);
     }
 
-    Py_DECREF(iters);
+    Py_DECREF(callbacks);
     return 0;
 }
 
 static int
 future_init(FutureObj *fut, PyObject *loop)
 {
-    PyObject *res = NULL;
+    PyObject *res;
+    int is_true;
     _Py_IDENTIFIER(get_debug);
 
-    if (loop == NULL || loop == Py_None) {
+    if (loop == Py_None) {
         loop = _PyObject_CallNoArg(asyncio_get_event_loop);
         if (loop == NULL) {
             return -1;
@@ -149,25 +148,25 @@ future_init(FutureObj *fut, PyObject *loop)
     else {
         Py_INCREF(loop);
     }
-    Py_CLEAR(fut->fut_loop);
-    fut->fut_loop = loop;
+    Py_XSETREF(fut->fut_loop, loop);
 
     res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL);
     if (res == NULL) {
         return -1;
     }
-    if (PyObject_IsTrue(res)) {
-        Py_CLEAR(res);
-        fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack);
+    is_true = PyObject_IsTrue(res);
+    Py_DECREF(res);
+    if (is_true < 0) {
+        return -1;
+    }
+    if (is_true) {
+        Py_XSETREF(fut->fut_source_tb, _PyObject_CallNoArg(traceback_extract_stack));
         if (fut->fut_source_tb == NULL) {
             return -1;
         }
     }
-    else {
-        Py_CLEAR(res);
-    }
 
-    fut->fut_callbacks = PyList_New(0);
+    Py_XSETREF(fut->fut_callbacks, PyList_New(0));
     if (fut->fut_callbacks == NULL) {
         return -1;
     }
@@ -183,6 +182,7 @@ future_set_result(FutureObj *fut, PyObject *res)
         return NULL;
     }
 
+    assert(!fut->fut_result);
     Py_INCREF(res);
     fut->fut_result = res;
     fut->fut_state = STATE_FINISHED;
@@ -208,6 +208,11 @@ future_set_exception(FutureObj *fut, PyObject *exc)
         if (exc_val == NULL) {
             return NULL;
         }
+        if (fut->fut_state != STATE_PENDING) {
+            Py_DECREF(exc_val);
+            PyErr_SetString(asyncio_InvalidStateError, "invalid state");
+            return NULL;
+        }
     }
     else {
         exc_val = exc;
@@ -226,6 +231,7 @@ future_set_exception(FutureObj *fut, PyObject *exc)
         return NULL;
     }
 
+    assert(!fut->fut_exception);
     fut->fut_exception = exc_val;
     fut->fut_state = STATE_FINISHED;
 
@@ -240,31 +246,14 @@ future_set_exception(FutureObj *fut, PyObject *exc)
 static int
 future_get_result(FutureObj *fut, PyObject **result)
 {
-    PyObject *exc;
-
     if (fut->fut_state == STATE_CANCELLED) {
-        exc = _PyObject_CallNoArg(asyncio_CancelledError);
-        if (exc == NULL) {
-            return -1;
-        }
-        *result = exc;
-        return 1;
+        PyErr_SetNone(asyncio_CancelledError);
+        return -1;
     }
 
     if (fut->fut_state != STATE_FINISHED) {
-        PyObject *msg = PyUnicode_FromString("Result is not ready.");
-        if (msg == NULL) {
-            return -1;
-        }
-
-        exc = PyObject_CallFunctionObjArgs(asyncio_InvalidStateError, msg, NULL);
-        Py_DECREF(msg);
-        if (exc == NULL) {
-            return -1;
-        }
-
-        *result = exc;
-        return 1;
+        PyErr_SetString(asyncio_InvalidStateError, "Result is not set.");
+        return -1;
     }
 
     fut->fut_log_tb = 0;
@@ -286,15 +275,16 @@ future_add_done_callback(FutureObj *fut, PyObject *arg)
         PyObject *handle = _PyObject_CallMethodIdObjArgs(fut->fut_loop,
                                                          &PyId_call_soon,
                                                          arg, fut, NULL);
-
         if (handle == NULL) {
             return NULL;
         }
-        else {
-            Py_DECREF(handle);
-        }
+        Py_DECREF(handle);
     }
     else {
+        if (fut->fut_callbacks == NULL) {
+            PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
+            return NULL;
+        }
         int err = PyList_Append(fut->fut_callbacks, arg);
         if (err != 0) {
             return NULL;
@@ -324,7 +314,7 @@ future_cancel(FutureObj *fut)
 _asyncio.Future.__init__
 
     *
-    loop: 'O' = NULL
+    loop: object = None
 
 This class is *almost* compatible with concurrent.futures.Future.
 
@@ -342,7 +332,7 @@ This class is *almost* compatible with concurrent.futures.Future.
 
 static int
 _asyncio_Future___init___impl(FutureObj *self, PyObject *loop)
-/*[clinic end generated code: output=9ed75799eaccb5d6 input=8e1681f23605be2d]*/
+/*[clinic end generated code: output=9ed75799eaccb5d6 input=89af317082bc0bf8]*/
 
 {
     return future_init(self, loop);
@@ -420,12 +410,12 @@ _asyncio_Future_exception_impl(FutureObj *self)
 /*[clinic end generated code: output=88b20d4f855e0710 input=733547a70c841c68]*/
 {
     if (self->fut_state == STATE_CANCELLED) {
-        PyErr_SetString(asyncio_CancelledError, "");
+        PyErr_SetNone(asyncio_CancelledError);
         return NULL;
     }
 
     if (self->fut_state != STATE_FINISHED) {
-        PyErr_SetString(asyncio_InvalidStateError, "Result is not ready.");
+        PyErr_SetString(asyncio_InvalidStateError, "Exception is not set.");
         return NULL;
     }
 
@@ -441,7 +431,7 @@ _asyncio_Future_exception_impl(FutureObj *self)
 /*[clinic input]
 _asyncio.Future.set_result
 
-    res: 'O'
+    res: object
     /
 
 Mark the future done and set its result.
@@ -452,7 +442,7 @@ InvalidStateError.
 
 static PyObject *
 _asyncio_Future_set_result(FutureObj *self, PyObject *res)
-/*[clinic end generated code: output=a620abfc2796bfb6 input=8619565e0503357e]*/
+/*[clinic end generated code: output=a620abfc2796bfb6 input=5b9dc180f1baa56d]*/
 {
     return future_set_result(self, res);
 }
@@ -460,7 +450,7 @@ _asyncio_Future_set_result(FutureObj *self, PyObject *res)
 /*[clinic input]
 _asyncio.Future.set_exception
 
-    exception: 'O'
+    exception: object
     /
 
 Mark the future done and set an exception.
@@ -471,7 +461,7 @@ InvalidStateError.
 
 static PyObject *
 _asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
-/*[clinic end generated code: output=f1c1b0cd321be360 input=1377dbe15e6ea186]*/
+/*[clinic end generated code: output=f1c1b0cd321be360 input=e45b7d7aa71cc66d]*/
 {
     return future_set_exception(self, exception);
 }
@@ -479,7 +469,7 @@ _asyncio_Future_set_exception(FutureObj *self, PyObject *exception)
 /*[clinic input]
 _asyncio.Future.add_done_callback
 
-    fn: 'O'
+    fn: object
     /
 
 Add a callback to be run when the future becomes done.
@@ -491,7 +481,7 @@ scheduled with call_soon.
 
 static PyObject *
 _asyncio_Future_add_done_callback(FutureObj *self, PyObject *fn)
-/*[clinic end generated code: output=819e09629b2ec2b5 input=8cce187e32cec6a8]*/
+/*[clinic end generated code: output=819e09629b2ec2b5 input=8f818b39990b027d]*/
 {
     return future_add_done_callback(self, fn);
 }
@@ -499,7 +489,7 @@ _asyncio_Future_add_done_callback(FutureObj *self, PyObject *fn)
 /*[clinic input]
 _asyncio.Future.remove_done_callback
 
-    fn: 'O'
+    fn: object
     /
 
 Remove all instances of a callback from the "call when done" list.
@@ -509,11 +499,16 @@ Returns the number of callbacks removed.
 
 static PyObject *
 _asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
-/*[clinic end generated code: output=5ab1fb52b24ef31f input=3fedb73e1409c31c]*/
+/*[clinic end generated code: output=5ab1fb52b24ef31f input=0a43280a149d505b]*/
 {
     PyObject *newlist;
     Py_ssize_t len, i, j=0;
 
+    if (self->fut_callbacks == NULL) {
+        PyErr_SetString(PyExc_RuntimeError, "uninitialized Future object");
+        return NULL;
+    }
+
     len = PyList_GET_SIZE(self->fut_callbacks);
     if (len == 0) {
         return PyLong_FromSsize_t(0);
@@ -527,29 +522,31 @@ _asyncio_Future_remove_done_callback(FutureObj *self, PyObject *fn)
     for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) {
         int ret;
         PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i);
-
-        if ((ret = PyObject_RichCompareBool(fn, item, Py_EQ)) < 0) {
-            goto fail;
-        }
+        Py_INCREF(item);
+        ret = PyObject_RichCompareBool(fn, item, Py_EQ);
         if (ret == 0) {
             if (j < len) {
-                Py_INCREF(item);
                 PyList_SET_ITEM(newlist, j, item);
                 j++;
+                continue;
             }
-            else {
-                if (PyList_Append(newlist, item)) {
-                    goto fail;
-                }
-            }
+            ret = PyList_Append(newlist, item);
+        }
+        Py_DECREF(item);
+        if (ret < 0) {
+            goto fail;
         }
     }
 
-    if (PyList_SetSlice(newlist, j, len, NULL) < 0) {
-        goto fail;
+    if (j < len) {
+        Py_SIZE(newlist) = j;
     }
-    if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
-        goto fail;
+    j = PyList_GET_SIZE(newlist);
+    len = PyList_GET_SIZE(self->fut_callbacks);
+    if (j != len) {
+        if (PyList_SetSlice(self->fut_callbacks, 0, len, newlist) < 0) {
+            goto fail;
+        }
     }
     Py_DECREF(newlist);
     return PyLong_FromSsize_t(len - j);
@@ -730,7 +727,7 @@ FutureObj_get_state(FutureObj *fut)
     default:
         assert (0);
     }
-    Py_INCREF(ret);
+    Py_XINCREF(ret);
     return ret;
 }
 
@@ -766,25 +763,14 @@ FutureObj_repr(FutureObj *fut)
 {
     _Py_IDENTIFIER(_repr_info);
 
-    PyObject *_repr_info = _PyUnicode_FromId(&PyId__repr_info);  // borrowed
-    if (_repr_info == NULL) {
-        return NULL;
-    }
-
-    PyObject *rinfo = PyObject_CallMethodObjArgs((PyObject*)fut, _repr_info,
-                                                 NULL);
+    PyObject *rinfo = _PyObject_CallMethodIdObjArgs((PyObject*)fut,
+                                                    &PyId__repr_info,
+                                                    NULL);
     if (rinfo == NULL) {
         return NULL;
     }
 
-    PyObject *sp = PyUnicode_FromString(" ");
-    if (sp == NULL) {
-        Py_DECREF(rinfo);
-        return NULL;
-    }
-
-    PyObject *rinfo_s = PyUnicode_Join(sp, rinfo);
-    Py_DECREF(sp);
+    PyObject *rinfo_s = PyUnicode_Join(NULL, rinfo);
     Py_DECREF(rinfo);
     if (rinfo_s == NULL) {
         return NULL;
@@ -794,7 +780,7 @@ FutureObj_repr(FutureObj *fut)
     PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
                                                  "__name__");
     if (type_name != NULL) {
-        rstr = PyUnicode_FromFormat("<%S %S>", type_name, rinfo_s);
+        rstr = PyUnicode_FromFormat("<%S %U>", type_name, rinfo_s);
         Py_DECREF(type_name);
     }
     Py_DECREF(rinfo_s);
@@ -810,22 +796,21 @@ FutureObj_finalize(FutureObj *fut)
     _Py_IDENTIFIER(future);
     _Py_IDENTIFIER(source_traceback);
 
+    PyObject *error_type, *error_value, *error_traceback;
+    PyObject *context;
+    PyObject *type_name;
+    PyObject *message = NULL;
+    PyObject *func;
+
     if (!fut->fut_log_tb) {
         return;
     }
     assert(fut->fut_exception != NULL);
-    fut->fut_log_tb = 0;;
+    fut->fut_log_tb = 0;
 
-    PyObject *error_type, *error_value, *error_traceback;
     /* Save the current exception, if any. */
     PyErr_Fetch(&error_type, &error_value, &error_traceback);
 
-    PyObject *context = NULL;
-    PyObject *type_name = NULL;
-    PyObject *message = NULL;
-    PyObject *func = NULL;
-    PyObject *res = NULL;
-
     context = PyDict_New();
     if (context == NULL) {
         goto finally;
@@ -838,6 +823,7 @@ FutureObj_finalize(FutureObj *fut)
 
     message = PyUnicode_FromFormat(
         "%S exception was never retrieved", type_name);
+    Py_DECREF(type_name);
     if (message == NULL) {
         goto finally;
     }
@@ -856,18 +842,19 @@ FutureObj_finalize(FutureObj *fut)
 
     func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
     if (func != NULL) {
-        res = PyObject_CallFunctionObjArgs(func, context, NULL);
+        PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
         if (res == NULL) {
             PyErr_WriteUnraisable(func);
         }
+        else {
+            Py_DECREF(res);
+        }
+        Py_DECREF(func);
     }
 
 finally:
-    Py_CLEAR(context);
-    Py_CLEAR(type_name);
-    Py_CLEAR(message);
-    Py_CLEAR(func);
-    Py_CLEAR(res);
+    Py_XDECREF(context);
+    Py_XDECREF(message);
 
     /* Restore the saved exception. */
     PyErr_Restore(error_type, error_value, error_traceback);
@@ -1014,22 +1001,19 @@ FutureIter_iternext(futureiterobject *it)
             Py_INCREF(fut);
             return (PyObject *)fut;
         }
-        PyErr_Format(PyExc_AssertionError,
-                     "yield from wasn't used with future");
+        PyErr_SetString(PyExc_AssertionError,
+                        "yield from wasn't used with future");
         return NULL;
     }
 
+    it->future = NULL;
     res = _asyncio_Future_result_impl(fut);
     if (res != NULL) {
         /* The result of the Future is not an exception. */
-        if (_PyGen_SetStopIterationValue(res) < 0) {
-            Py_DECREF(res);
-            return NULL;
-        }
+        (void)_PyGen_SetStopIterationValue(res);
         Py_DECREF(res);
     }
 
-    it->future = NULL;
     Py_DECREF(fut);
     return NULL;
 }
@@ -1046,7 +1030,7 @@ FutureIter_send(futureiterobject *self, PyObject *unused)
 static PyObject *
 FutureIter_throw(futureiterobject *self, PyObject *args)
 {
-    PyObject *type=NULL, *val=NULL, *tb=NULL;
+    PyObject *type, *val = NULL, *tb = NULL;
     if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
         return NULL;
 
@@ -1090,7 +1074,7 @@ FutureIter_throw(futureiterobject *self, PyObject *args)
 
     PyErr_Restore(type, val, tb);
 
-    return FutureIter_iternext(self);
+    return NULL;
 
   fail:
     Py_DECREF(type);
@@ -1171,7 +1155,7 @@ static PyObject * task_step(TaskObj *, PyObject *);
 /* ----- Task._step wrapper */
 
 static int
-TaskSendMethWrapper_clear(TaskSendMethWrapper *o)
+TaskStepMethWrapper_clear(TaskStepMethWrapper *o)
 {
     Py_CLEAR(o->sw_task);
     Py_CLEAR(o->sw_arg);
@@ -1179,22 +1163,30 @@ TaskSendMethWrapper_clear(TaskSendMethWrapper *o)
 }
 
 static void
-TaskSendMethWrapper_dealloc(TaskSendMethWrapper *o)
+TaskStepMethWrapper_dealloc(TaskStepMethWrapper *o)
 {
     PyObject_GC_UnTrack(o);
-    (void)TaskSendMethWrapper_clear(o);
+    (void)TaskStepMethWrapper_clear(o);
     Py_TYPE(o)->tp_free(o);
 }
 
 static PyObject *
-TaskSendMethWrapper_call(TaskSendMethWrapper *o,
+TaskStepMethWrapper_call(TaskStepMethWrapper *o,
                          PyObject *args, PyObject *kwds)
 {
+    if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
+        PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
+        return NULL;
+    }
+    if (args != NULL && PyTuple_GET_SIZE(args) != 0) {
+        PyErr_SetString(PyExc_TypeError, "function takes no positional arguments");
+        return NULL;
+    }
     return task_call_step(o->sw_task, o->sw_arg);
 }
 
 static int
-TaskSendMethWrapper_traverse(TaskSendMethWrapper *o,
+TaskStepMethWrapper_traverse(TaskStepMethWrapper *o,
                              visitproc visit, void *arg)
 {
     Py_VISIT(o->sw_task);
@@ -1203,7 +1195,7 @@ TaskSendMethWrapper_traverse(TaskSendMethWrapper *o,
 }
 
 static PyObject *
-TaskSendMethWrapper_get___self__(TaskSendMethWrapper *o)
+TaskStepMethWrapper_get___self__(TaskStepMethWrapper *o)
 {
     if (o->sw_task) {
         Py_INCREF(o->sw_task);
@@ -1212,30 +1204,30 @@ TaskSendMethWrapper_get___self__(TaskSendMethWrapper *o)
     Py_RETURN_NONE;
 }
 
-static PyGetSetDef TaskSendMethWrapper_getsetlist[] = {
-    {"__self__", (getter)TaskSendMethWrapper_get___self__, NULL, NULL},
+static PyGetSetDef TaskStepMethWrapper_getsetlist[] = {
+    {"__self__", (getter)TaskStepMethWrapper_get___self__, NULL, NULL},
     {NULL} /* Sentinel */
 };
 
-PyTypeObject TaskSendMethWrapper_Type = {
+PyTypeObject TaskStepMethWrapper_Type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "TaskSendMethWrapper",
-    .tp_basicsize = sizeof(TaskSendMethWrapper),
+    "TaskStepMethWrapper",
+    .tp_basicsize = sizeof(TaskStepMethWrapper),
     .tp_itemsize = 0,
-    .tp_getset = TaskSendMethWrapper_getsetlist,
-    .tp_dealloc = (destructor)TaskSendMethWrapper_dealloc,
-    .tp_call = (ternaryfunc)TaskSendMethWrapper_call,
+    .tp_getset = TaskStepMethWrapper_getsetlist,
+    .tp_dealloc = (destructor)TaskStepMethWrapper_dealloc,
+    .tp_call = (ternaryfunc)TaskStepMethWrapper_call,
     .tp_getattro = PyObject_GenericGetAttr,
     .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
-    .tp_traverse = (traverseproc)TaskSendMethWrapper_traverse,
-    .tp_clear = (inquiry)TaskSendMethWrapper_clear,
+    .tp_traverse = (traverseproc)TaskStepMethWrapper_traverse,
+    .tp_clear = (inquiry)TaskStepMethWrapper_clear,
 };
 
 static PyObject *
-TaskSendMethWrapper_new(TaskObj *task, PyObject *arg)
+TaskStepMethWrapper_new(TaskObj *task, PyObject *arg)
 {
-    TaskSendMethWrapper *o;
-    o = PyObject_GC_New(TaskSendMethWrapper, &TaskSendMethWrapper_Type);
+    TaskStepMethWrapper *o;
+    o = PyObject_GC_New(TaskStepMethWrapper, &TaskStepMethWrapper_Type);
     if (o == NULL) {
         return NULL;
     }
@@ -1258,7 +1250,11 @@ TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o,
 {
     PyObject *fut;
 
-    if (!PyArg_ParseTuple(args, "O|", &fut)) {
+    if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
+        PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments");
+        return NULL;
+    }
+    if (!PyArg_ParseTuple(args, "O", &fut)) {
         return NULL;
     }
 
@@ -1322,16 +1318,16 @@ TaskWakeupMethWrapper_new(TaskObj *task)
 /*[clinic input]
 _asyncio.Task.__init__
 
-    coro: 'O'
+    coro: object
     *
-    loop: 'O' = NULL
+    loop: object = None
 
 A coroutine wrapped in a Future.
 [clinic start generated code]*/
 
 static int
 _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop)
-/*[clinic end generated code: output=9f24774c2287fc2f input=71d8d28c201a18cd]*/
+/*[clinic end generated code: output=9f24774c2287fc2f input=8d132974b049593e]*/
 {
     PyObject *res;
     _Py_IDENTIFIER(add);
@@ -1437,7 +1433,7 @@ TaskObj_get_fut_waiter(TaskObj *task)
 @classmethod
 _asyncio.Task.current_task
 
-    loop: 'O' = None
+    loop: object = None
 
 Return the currently running task in an event loop or None.
 
@@ -1448,7 +1444,7 @@ None is returned when called not in the context of a Task.
 
 static PyObject *
 _asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop)
-/*[clinic end generated code: output=99fbe7332c516e03 input=a0d6cdf2e3b243e1]*/
+/*[clinic end generated code: output=99fbe7332c516e03 input=cd14770c5b79c7eb]*/
 {
     PyObject *res;
 
@@ -1510,12 +1506,14 @@ task_all_tasks(PyObject *loop)
         Py_DECREF(task_loop);
         Py_DECREF(task);
     }
-
+    if (PyErr_Occurred()) {
+        goto fail;
+    }
     Py_DECREF(iter);
     return set;
 
 fail:
-    Py_XDECREF(set);
+    Py_DECREF(set);
     Py_XDECREF(iter);
     return NULL;
 }
@@ -1524,7 +1522,7 @@ task_all_tasks(PyObject *loop)
 @classmethod
 _asyncio.Task.all_tasks
 
-    loop: 'O' = None
+    loop: object = None
 
 Return a set of all tasks for an event loop.
 
@@ -1533,7 +1531,7 @@ By default all tasks for the current event loop are returned.
 
 static PyObject *
 _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
-/*[clinic end generated code: output=11f9b20749ccca5d input=c6f5b53bd487488f]*/
+/*[clinic end generated code: output=11f9b20749ccca5d input=497f80bc9ce726b5]*/
 {
     PyObject *res;
 
@@ -1627,7 +1625,7 @@ _asyncio_Task_cancel_impl(TaskObj *self)
 _asyncio.Task.get_stack
 
     *
-    limit: 'O' = None
+    limit: object = None
 
 Return the list of stack frames for this task's coroutine.
 
@@ -1652,7 +1650,7 @@ returned for a suspended coroutine.
 
 static PyObject *
 _asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
-/*[clinic end generated code: output=c9aeeeebd1e18118 input=b1920230a766d17a]*/
+/*[clinic end generated code: output=c9aeeeebd1e18118 input=05b323d42b809b90]*/
 {
     return PyObject_CallFunctionObjArgs(
         asyncio_task_get_stack_func, self, limit, NULL);
@@ -1662,8 +1660,8 @@ _asyncio_Task_get_stack_impl(TaskObj *self, PyObject *limit)
 _asyncio.Task.print_stack
 
     *
-    limit: 'O' = None
-    file: 'O' = None
+    limit: object = None
+    file: object = None
 
 Print the stack or traceback for this task's coroutine.
 
@@ -1677,7 +1675,7 @@ to sys.stderr.
 static PyObject *
 _asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
                                PyObject *file)
-/*[clinic end generated code: output=7339e10314cd3f4d input=19f1e99ab5400bc3]*/
+/*[clinic end generated code: output=7339e10314cd3f4d input=1a0352913b7fcd92]*/
 {
     return PyObject_CallFunctionObjArgs(
         asyncio_task_print_stack_func, self, limit, file, NULL);
@@ -1686,12 +1684,12 @@ _asyncio_Task_print_stack_impl(TaskObj *self, PyObject *limit,
 /*[clinic input]
 _asyncio.Task._step
 
-    exc: 'O' = NULL
+    exc: object = None
 [clinic start generated code]*/
 
 static PyObject *
 _asyncio_Task__step_impl(TaskObj *self, PyObject *exc)
-/*[clinic end generated code: output=7ed23f0cefd5ae42 input=ada4b2324e5370af]*/
+/*[clinic end generated code: output=7ed23f0cefd5ae42 input=1e19a985ace87ca4]*/
 {
     return task_step(self, exc == Py_None ? NULL : exc);
 }
@@ -1699,12 +1697,12 @@ _asyncio_Task__step_impl(TaskObj *self, PyObject *exc)
 /*[clinic input]
 _asyncio.Task._wakeup
 
-    fut: 'O'
+    fut: object
 [clinic start generated code]*/
 
 static PyObject *
 _asyncio_Task__wakeup_impl(TaskObj *self, PyObject *fut)
-/*[clinic end generated code: output=75cb341c760fd071 input=11ee4918a5bdbf21]*/
+/*[clinic end generated code: output=75cb341c760fd071 input=6a0616406f829a7b]*/
 {
     return task_wakeup(self, fut);
 }
@@ -1717,11 +1715,9 @@ TaskObj_finalize(TaskObj *task)
     _Py_IDENTIFIER(message);
     _Py_IDENTIFIER(source_traceback);
 
+    PyObject *context;
     PyObject *message = NULL;
-    PyObject *context = NULL;
-    PyObject *func = NULL;
-    PyObject *res = NULL;
-
+    PyObject *func;
     PyObject *error_type, *error_value, *error_traceback;
 
     if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {
@@ -1757,17 +1753,19 @@ TaskObj_finalize(TaskObj *task)
 
     func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler);
     if (func != NULL) {
-        res = PyObject_CallFunctionObjArgs(func, context, NULL);
+        PyObject *res = PyObject_CallFunctionObjArgs(func, context, NULL);
         if (res == NULL) {
             PyErr_WriteUnraisable(func);
         }
+        else {
+            Py_DECREF(res);
+        }
+        Py_DECREF(func);
     }
 
 finally:
-    Py_CLEAR(context);
-    Py_CLEAR(message);
-    Py_CLEAR(func);
-    Py_CLEAR(res);
+    Py_XDECREF(context);
+    Py_XDECREF(message);
 
     /* Restore the saved exception. */
     PyErr_Restore(error_type, error_value, error_traceback);
@@ -1879,9 +1877,6 @@ task_call_step(TaskObj *task, PyObject *arg)
     }
     else {
         /* `task` is a subclass of Task */
-        if (arg == NULL) {
-            arg = Py_None;
-        }
         return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__step,
                                              arg, NULL);
     }
@@ -1892,7 +1887,7 @@ task_call_step_soon(TaskObj *task, PyObject *arg)
 {
     PyObject *handle;
 
-    PyObject *cb = TaskSendMethWrapper_new(task, arg);
+    PyObject *cb = TaskStepMethWrapper_new(task, arg);
     if (cb == NULL) {
         return -1;
     }
@@ -1947,7 +1942,7 @@ task_step_impl(TaskObj *task, PyObject *exc)
     int res;
     int clear_exc = 0;
     PyObject *result = NULL;
-    PyObject *coro = task->task_coro;
+    PyObject *coro;
     PyObject *o;
 
     if (task->task_state != STATE_PENDING) {
@@ -1988,6 +1983,12 @@ task_step_impl(TaskObj *task, PyObject *exc)
 
     Py_CLEAR(task->task_fut_waiter);
 
+    coro = task->task_coro;
+    if (coro == NULL) {
+        PyErr_SetString(PyExc_RuntimeError, "uninitialized Task object");
+        return NULL;
+    }
+
     if (exc == NULL) {
         if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) {
             result = _PyGen_Send((PyGenObject*)coro, Py_None);
@@ -2002,7 +2003,7 @@ task_step_impl(TaskObj *task, PyObject *exc)
                                                exc, NULL);
         if (clear_exc) {
             /* We created 'exc' during this call */
-            Py_CLEAR(exc);
+            Py_DECREF(exc);
         }
     }
 
@@ -2051,13 +2052,13 @@ task_step_impl(TaskObj *task, PyObject *exc)
         o = future_set_exception((FutureObj*)task, ev);
         if (!o) {
             /* An exception in Task.set_exception() */
-            Py_XDECREF(et);
+            Py_DECREF(et);
             Py_XDECREF(tb);
             Py_XDECREF(ev);
             goto fail;
         }
         assert(o == Py_None);
-        Py_CLEAR(o);
+        Py_DECREF(o);
 
         if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
             /* We've got a BaseException; re-raise it */
@@ -2065,7 +2066,7 @@ task_step_impl(TaskObj *task, PyObject *exc)
             goto fail;
         }
 
-        Py_XDECREF(et);
+        Py_DECREF(et);
         Py_XDECREF(tb);
         Py_XDECREF(ev);
 
@@ -2137,7 +2138,7 @@ task_step_impl(TaskObj *task, PyObject *exc)
     }
     else {
         if (o == Py_None) {
-            Py_CLEAR(o);
+            Py_DECREF(o);
         }
         else {
             /* `result` is a Future-compatible object */
@@ -2145,7 +2146,7 @@ task_step_impl(TaskObj *task, PyObject *exc)
             PyObject *res;
 
             int blocking = PyObject_IsTrue(o);
-            Py_CLEAR(o);
+            Py_DECREF(o);
             if (blocking < 0) {
                 goto fail;
             }
@@ -2228,7 +2229,7 @@ task_step_impl(TaskObj *task, PyObject *exc)
         goto fail;
     }
     res = PyObject_IsTrue(o);
-    Py_CLEAR(o);
+    Py_DECREF(o);
     if (res == -1) {
         /* An exception while checking if 'val' is True */
         goto fail;
@@ -2296,14 +2297,8 @@ task_step(TaskObj *task, PyObject *exc)
         PyObject *et, *ev, *tb;
         PyErr_Fetch(&et, &ev, &tb);
         ot = _PyDict_Pop(current_tasks, task->task_loop, NULL);
-        if (ot == NULL) {
-            Py_XDECREF(et);
-            Py_XDECREF(tb);
-            Py_XDECREF(ev);
-            return NULL;
-        }
-        Py_DECREF(ot);
-        PyErr_Restore(et, ev, tb);
+        Py_XDECREF(ot);
+        _PyErr_ChainExceptions(et, ev, tb);
         return NULL;
     }
     else {
@@ -2322,17 +2317,18 @@ task_step(TaskObj *task, PyObject *exc)
 static PyObject *
 task_wakeup(TaskObj *task, PyObject *o)
 {
+    PyObject *et, *ev, *tb;
+    PyObject *result;
     assert(o);
 
     if (Future_CheckExact(o) || Task_CheckExact(o)) {
         PyObject *fut_result = NULL;
         int res = future_get_result((FutureObj*)o, &fut_result);
-        PyObject *result;
 
         switch(res) {
         case -1:
             assert(fut_result == NULL);
-            return NULL;
+            break; /* exception raised */
         case 0:
             Py_DECREF(fut_result);
             return task_call_step(task, NULL);
@@ -2343,29 +2339,32 @@ task_wakeup(TaskObj *task, PyObject *o)
             return result;
         }
     }
-
-    PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
-    if (fut_result == NULL) {
-        PyObject *et, *ev, *tb;
-        PyObject *res;
-
-        PyErr_Fetch(&et, &ev, &tb);
-        if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
-            PyErr_NormalizeException(&et, &ev, &tb);
+    else {
+        PyObject *fut_result = PyObject_CallMethod(o, "result", NULL);
+        if (fut_result != NULL) {
+            Py_DECREF(fut_result);
+            return task_call_step(task, NULL);
         }
+        /* exception raised */
+    }
 
-        res = task_call_step(task, ev);
-
-        Py_XDECREF(et);
-        Py_XDECREF(tb);
-        Py_XDECREF(ev);
-
-        return res;
+    PyErr_Fetch(&et, &ev, &tb);
+    if (!PyErr_GivenExceptionMatches(et, PyExc_Exception)) {
+        /* We've got a BaseException; re-raise it */
+        PyErr_Restore(et, ev, tb);
+        return NULL;
     }
-    else {
-        Py_DECREF(fut_result);
-        return task_call_step(task, NULL);
+    if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
+        PyErr_NormalizeException(&et, &ev, &tb);
     }
+
+    result = task_call_step(task, ev);
+
+    Py_DECREF(et);
+    Py_XDECREF(tb);
+    Py_XDECREF(ev);
+
+    return result;
 }
 
 
@@ -2398,7 +2397,7 @@ module_init(void)
     Py_CLEAR(module); \
     module = PyImport_ImportModule(NAME); \
     if (module == NULL) { \
-        return -1; \
+        goto fail; \
     }
 
 #define GET_MOD_ATTR(VAR, NAME) \
@@ -2429,7 +2428,7 @@ module_init(void)
     WITH_MOD("weakref")
     GET_MOD_ATTR(cls, "WeakSet")
     all_tasks = _PyObject_CallNoArg(cls);
-    Py_CLEAR(cls);
+    Py_DECREF(cls);
     if (all_tasks == NULL) {
         goto fail;
     }
@@ -2439,7 +2438,7 @@ module_init(void)
         goto fail;
     }
 
-    Py_CLEAR(module);
+    Py_DECREF(module);
     return 0;
 
 fail:
@@ -2478,7 +2477,7 @@ PyInit__asyncio(void)
     if (PyType_Ready(&FutureIterType) < 0) {
         return NULL;
     }
-    if (PyType_Ready(&TaskSendMethWrapper_Type) < 0) {
+    if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) {
         return NULL;
     }
     if(PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) {
diff --git a/Modules/clinic/_asynciomodule.c.h b/Modules/clinic/_asynciomodule.c.h
index 8f598edd05e..7627849bb88 100644
--- a/Modules/clinic/_asynciomodule.c.h
+++ b/Modules/clinic/_asynciomodule.c.h
@@ -28,7 +28,7 @@ _asyncio_Future___init__(PyObject *self, PyObject *args, PyObject *kwargs)
     int return_value = -1;
     static const char * const _keywords[] = {"loop", NULL};
     static _PyArg_Parser _parser = {"|$O:Future", _keywords, 0};
-    PyObject *loop = NULL;
+    PyObject *loop = Py_None;
 
     if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &loop)) {
@@ -244,7 +244,7 @@ _asyncio_Task___init__(PyObject *self, PyObject *args, PyObject *kwargs)
     static const char * const _keywords[] = {"coro", "loop", NULL};
     static _PyArg_Parser _parser = {"O|$O:Task", _keywords, 0};
     PyObject *coro;
-    PyObject *loop = NULL;
+    PyObject *loop = Py_None;
 
     if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
         &coro, &loop)) {
@@ -477,7 +477,7 @@ _asyncio_Task__step(TaskObj *self, PyObject **args, Py_ssize_t nargs, PyObject *
     PyObject *return_value = NULL;
     static const char * const _keywords[] = {"exc", NULL};
     static _PyArg_Parser _parser = {"|O:_step", _keywords, 0};
-    PyObject *exc = NULL;
+    PyObject *exc = Py_None;
 
     if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
         &exc)) {
@@ -517,4 +517,4 @@ _asyncio_Task__wakeup(TaskObj *self, PyObject **args, Py_ssize_t nargs, PyObject
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=fe651840e0466fa9 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=b92f9cd2b9fb37ef input=a9049054013a1b77]*/



More information about the Python-checkins mailing list