diff -r ebf189626763 Python/ceval.c --- a/Python/ceval.c Mon Sep 19 22:20:19 2016 -0700 +++ b/Python/ceval.c Wed Sep 21 00:54:20 2016 +0800 @@ -5200,9 +5200,9 @@ _Py_IDENTIFIER(__all__); _Py_IDENTIFIER(__dict__); PyObject *all = _PyObject_GetAttrId(v, &PyId___all__); - PyObject *dict, *name, *value; - int skip_leading_underscores = 0; - int pos, err; + PyObject *dict, *name, *value, **items; + Py_ssize_t i, size; + int skip_leading_underscores = 0, err; if (all == NULL) { if (!PyErr_ExceptionMatches(PyExc_AttributeError)) @@ -5221,34 +5221,35 @@ if (all == NULL) return -1; skip_leading_underscores = 1; + } else if (!(PyList_CheckExact(all) || PyTuple_CheckExact(all))){ + PyObject *seq = PySequence_Fast(all, "__all__ is not iterable"); + if (seq == NULL) { + return -1; + } + Py_SETREF(all, seq); } - for (pos = 0, err = 0; ; pos++) { - name = PySequence_GetItem(all, pos); - if (name == NULL) { - if (!PyErr_ExceptionMatches(PyExc_IndexError)) - err = -1; - else - PyErr_Clear(); - break; - } + size = PySequence_Fast_GET_SIZE(all); + items = PySequence_Fast_ITEMS(all); + for (i = 0, err = 0; i < size; i++) { + name = items[i]; // borrowed if (skip_leading_underscores && PyUnicode_Check(name) && PyUnicode_READY(name) != -1 && PyUnicode_READ_CHAR(name, 0) == '_') { - Py_DECREF(name); continue; } value = PyObject_GetAttr(v, name); - if (value == NULL) + if (value == NULL) { err = -1; - else if (PyDict_CheckExact(locals)) + break; + } + if (PyDict_Check(locals)) err = PyDict_SetItem(locals, name, value); else err = PyObject_SetItem(locals, name, value); - Py_DECREF(name); - Py_XDECREF(value); + Py_DECREF(value); if (err != 0) break; }