diff options
author | Guido van Rossum <guido@python.org> | 2001-01-12 16:24:03 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2001-01-12 16:24:03 (GMT) |
commit | 18d4d8f71dca03a99220623d7eb4a5af733796e3 (patch) | |
tree | 767184c7d8d6fb8a11b536f706fe269985c4e259 /Python/ceval.c | |
parent | ad991775ab57fc5c4647b70d793d52ff6b0d25bf (diff) | |
download | cpython-18d4d8f71dca03a99220623d7eb4a5af733796e3.zip cpython-18d4d8f71dca03a99220623d7eb4a5af733796e3.tar.gz cpython-18d4d8f71dca03a99220623d7eb4a5af733796e3.tar.bz2 |
Two changes to from...import:
1) "from M import X" now works even if M is not a real module; it's
basically a getattr() operation with AttributeError exceptions
changed into ImportError.
2) "from M import *" now looks for M.__all__ to decide which names to
import; if M.__all__ doesn't exist, it uses M.__dict__.keys() but
filters out names starting with '_' as before. Whether or not
__all__ exists, there's no restriction on the type of M.
Diffstat (limited to 'Python/ceval.c')
-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 * |