diff options
author | Ethan Furman <ethan@stoneleaf.us> | 2014-04-24 21:47:47 (GMT) |
---|---|---|
committer | Ethan Furman <ethan@stoneleaf.us> | 2014-04-24 21:47:47 (GMT) |
commit | 7b9ff0e6da5371214b29053cdb96218e0d2eb655 (patch) | |
tree | da11b0d718916d64a256d36fcc41287aca922e28 /Objects/moduleobject.c | |
parent | 7101cb07ef8cb9e63b99b0e1c8200f355841772c (diff) | |
download | cpython-7b9ff0e6da5371214b29053cdb96218e0d2eb655.zip cpython-7b9ff0e6da5371214b29053cdb96218e0d2eb655.tar.gz cpython-7b9ff0e6da5371214b29053cdb96218e0d2eb655.tar.bz2 |
Issue8297: module attribute lookup failures now include module name in error message.
Diffstat (limited to 'Objects/moduleobject.c')
-rw-r--r-- | Objects/moduleobject.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index f509932..522ee5e 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -411,6 +411,31 @@ module_repr(PyModuleObject *m) return PyObject_CallMethod(interp->importlib, "_module_repr", "O", m); } +static PyObject* +module_getattr(PyObject *m, PyObject *name) +{ + PyModuleObject *module; + PyObject *attr, *mod_name; + attr = PyObject_GenericGetAttr(m, name); + if (attr != NULL) + return attr; + PyErr_Clear(); + module = (PyModuleObject*)m; + if (module->md_dict != NULL) { + mod_name = PyDict_GetItemString(module->md_dict, "__name__"); + if (mod_name != NULL) { + PyErr_Format(PyExc_AttributeError, + "module '%U' has no attribute '%U'", mod_name, name); + return NULL; + } + else if (PyErr_Occurred()) + PyErr_Clear(); + } + PyErr_Format(PyExc_AttributeError, + "module has no attribute '%U'", name); + return NULL; +} + static int module_traverse(PyModuleObject *m, visitproc visit, void *arg) { @@ -464,7 +489,6 @@ static PyMethodDef module_methods[] = { {0} }; - PyDoc_STRVAR(module_doc, "module(name[, doc])\n\ \n\ @@ -488,7 +512,7 @@ PyTypeObject PyModule_Type = { 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ + module_getattr, /* tp_getattro */ PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | |