Commit 18d4d8f7 authored by Guido van Rossum's avatar Guido van Rossum

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.
parent ad991775
...@@ -3089,48 +3089,72 @@ cmp_outcome(int op, register PyObject *v, register PyObject *w) ...@@ -3089,48 +3089,72 @@ cmp_outcome(int op, register PyObject *v, register PyObject *w)
static PyObject * static PyObject *
import_from(PyObject *v, PyObject *name) import_from(PyObject *v, PyObject *name)
{ {
PyObject *w, *x; PyObject *x;
if (!PyModule_Check(v)) {
PyErr_SetString(PyExc_TypeError, x = PyObject_GetAttr(v, name);
"import-from requires a module object"); if (x == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
return NULL;
}
w = PyModule_GetDict(v); /* TDB: can this not fail ? */
x = PyDict_GetItem(w, name);
if (x == NULL) {
PyErr_Format(PyExc_ImportError, PyErr_Format(PyExc_ImportError,
"cannot import name %.230s", "cannot import name %.230s",
PyString_AsString(name)); PyString_AsString(name));
} else }
Py_INCREF(x);
return x; return x;
} }
static int static int
import_all_from(PyObject *locals, PyObject *v) import_all_from(PyObject *locals, PyObject *v)
{ {
int pos = 0, err; PyObject *all = PyObject_GetAttrString(v, "__all__");
PyObject *name, *value; PyObject *dict, *name, *value;
PyObject *w; int skip_leading_underscores = 0;
int pos, err;
if (!PyModule_Check(v)) {
PyErr_SetString(PyExc_TypeError, if (all == NULL) {
"import-from requires a module object"); if (!PyErr_ExceptionMatches(PyExc_AttributeError))
return -1; 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)) { for (pos = 0, err = 0; ; pos++) {
if (!PyString_Check(name) || name = PySequence_GetItem(all, pos);
PyString_AsString(name)[0] == '_') if (name == NULL) {
continue; if (!PyErr_ExceptionMatches(PyExc_IndexError))
Py_INCREF(value); err = -1;
err = PyDict_SetItem(locals, name, value); else
Py_DECREF(value); 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) if (err != 0)
return -1; break;
} }
return 0; Py_DECREF(all);
return err;
} }
static PyObject * static PyObject *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment