]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Two changes to from...import:
authorGuido van Rossum <guido@python.org>
Fri, 12 Jan 2001 16:24:03 +0000 (16:24 +0000)
committerGuido van Rossum <guido@python.org>
Fri, 12 Jan 2001 16:24:03 +0000 (16:24 +0000)
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.

Python/ceval.c

index 347a5411f9368f4c8e8b7cc9fea474c8a42d9736..ed201b390fcd6b0a5bcdbcc35337faafbedd32e8 100644 (file)
@@ -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 *