diff Python/ceval.c @ 15830:e00f718e4d8a legacy-trunk

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.
author Guido van Rossum <guido@python.org>
date Fri, 12 Jan 2001 16:24:03 +0000
parents faaf9f10d849
children 152814f6cd11
line wrap: on
line diff
--- a/Python/ceval.c	Fri Jan 12 16:03:05 2001 +0000
+++ b/Python/ceval.c	Fri Jan 12 16:24:03 2001 +0000
@@ -3089,48 +3089,72 @@
 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;
+	PyObject *all = PyObject_GetAttrString(v, "__all__");
+	PyObject *dict, *name, *value;
+	int skip_leading_underscores = 0;
+	int pos, err;
 
-	if (!PyModule_Check(v)) {
-		PyErr_SetString(PyExc_TypeError,
-				"import-from requires a module object");
-		return -1;
+	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 *