summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2001-01-12 16:24:03 (GMT)
committerGuido van Rossum <guido@python.org>2001-01-12 16:24:03 (GMT)
commit18d4d8f71dca03a99220623d7eb4a5af733796e3 (patch)
tree767184c7d8d6fb8a11b536f706fe269985c4e259 /Python/ceval.c
parentad991775ab57fc5c4647b70d793d52ff6b0d25bf (diff)
downloadcpython-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.c84
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 *