summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorShantanu <12621235+hauntsaninja@users.noreply.github.com>2023-12-21 21:24:10 (GMT)
committerGitHub <noreply@github.com>2023-12-21 21:24:10 (GMT)
commit61e818409567ce452af60605937cdedf582f6293 (patch)
tree7ebe7cb8d398d3f8f5a645b4a47da7471036aefe /Objects
parent2d91409c690b113493e3e81efc880301d2949f5f (diff)
downloadcpython-61e818409567ce452af60605937cdedf582f6293.zip
cpython-61e818409567ce452af60605937cdedf582f6293.tar.gz
cpython-61e818409567ce452af60605937cdedf582f6293.tar.bz2
gh-95754: Better AttributeError on partially initialised module (#112577)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Diffstat (limited to 'Objects')
-rw-r--r--Objects/moduleobject.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c
index e2741fe..3a1c516 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -788,7 +788,7 @@ PyObject*
_Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress)
{
// When suppress=1, this function suppresses AttributeError.
- PyObject *attr, *mod_name, *getattr;
+ PyObject *attr, *mod_name, *getattr, *origin;
attr = _PyObject_GenericGetAttrWithDict((PyObject *)m, name, NULL, suppress);
if (attr) {
return attr;
@@ -831,11 +831,31 @@ _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress)
if (suppress != 1) {
int rc = _PyModuleSpec_IsInitializing(spec);
if (rc > 0) {
- PyErr_Format(PyExc_AttributeError,
+ int valid_spec = PyObject_GetOptionalAttr(spec, &_Py_ID(origin), &origin);
+ if (valid_spec == -1) {
+ Py_XDECREF(spec);
+ Py_DECREF(mod_name);
+ return NULL;
+ }
+ if (valid_spec == 1 && !PyUnicode_Check(origin)) {
+ valid_spec = 0;
+ Py_DECREF(origin);
+ }
+ if (valid_spec == 1) {
+ PyErr_Format(PyExc_AttributeError,
+ "partially initialized "
+ "module '%U' from '%U' has no attribute '%U' "
+ "(most likely due to a circular import)",
+ mod_name, origin, name);
+ Py_DECREF(origin);
+ }
+ else {
+ PyErr_Format(PyExc_AttributeError,
"partially initialized "
"module '%U' has no attribute '%U' "
"(most likely due to a circular import)",
mod_name, name);
+ }
}
else if (rc == 0) {
rc = _PyModuleSpec_IsUninitializedSubmodule(spec, name);