diff options
-rw-r--r-- | Python/ceval.c | 84 |
1 files changed, 54 insertions, 30 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 347a541..ed201b3 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3089,48 +3089,72 @@ cmp_outcome(int op, register PyObject *v, register PyObject *w) static PyObject * import_from(PyObject *v, PyObject *name) { - PyObject *w, *x; - if (!PyModule_Check(v)) { - PyErr_SetString(PyExc_TypeError, - "import-from requires a module object"); - return NULL; - } - w = PyModule_GetDict(v); /* TDB: can this not fail ? */ - x = PyDict_GetItem(w, name); - if (x == NULL) { + PyObject *x; + + x = PyObject_GetAttr(v, name); + if (x == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) { PyErr_Format(PyExc_ImportError, "cannot import name %.230s", PyString_AsString(name)); - } else - Py_INCREF(x); + } return x; } - + static int import_all_from(PyObject *locals, PyObject *v) { - int pos = 0, err; - PyObject *name, *value; - PyObject *w; - - if (!PyModule_Check(v)) { - PyErr_SetString(PyExc_TypeError, - "import-from requires a module object"); - return -1; + PyObject *all = PyObject_GetAttrString(v, "__all__"); + PyObject *dict, *name, *value; + int skip_leading_underscores = 0; + int pos, err; + + if (all == NULL) { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) + return -1; /* Unexpected error */ + PyErr_Clear(); + dict = PyObject_GetAttrString(v, "__dict__"); + if (dict == NULL) { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) + return -1; + PyErr_SetString(PyExc_ImportError, + "from-import-* object has no __dict__ and no __all__"); + return -1; + } + all = PyMapping_Keys(dict); + Py_DECREF(dict); + if (all == NULL) + return -1; + skip_leading_underscores = 1; } - w = PyModule_GetDict(v); /* TBD: can this not fail ? */ - while (PyDict_Next(w, &pos, &name, &value)) { - if (!PyString_Check(name) || - PyString_AsString(name)[0] == '_') - continue; - Py_INCREF(value); - err = PyDict_SetItem(locals, name, value); - Py_DECREF(value); + 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; + } + if (skip_leading_underscores && + PyString_Check(name) && + PyString_AS_STRING(name)[0] == '_') + { + Py_DECREF(name); + continue; + } + value = PyObject_GetAttr(v, name); + if (value == NULL) + err = -1; + else + err = PyDict_SetItem(locals, name, value); + Py_DECREF(name); + Py_XDECREF(value); if (err != 0) - return -1; + break; } - return 0; + Py_DECREF(all); + return err; } static PyObject * |