Issue #25698: Importing module if the stack is too deep no longer replaces
imported module with the empty one.
diff --git a/Include/dictobject.h b/Include/dictobject.h
index ece01c6..ef524a4 100644
--- a/Include/dictobject.h
+++ b/Include/dictobject.h
@@ -108,6 +108,7 @@
PyAPI_FUNC(PyObject *) PyDict_New(void);
PyAPI_FUNC(PyObject *) PyDict_GetItem(PyObject *mp, PyObject *key);
+PyAPI_FUNC(PyObject *) _PyDict_GetItemWithError(PyObject *mp, PyObject *key);
PyAPI_FUNC(int) PyDict_SetItem(PyObject *mp, PyObject *key, PyObject *item);
PyAPI_FUNC(int) PyDict_DelItem(PyObject *mp, PyObject *key);
PyAPI_FUNC(void) PyDict_Clear(PyObject *mp);
diff --git a/Misc/NEWS b/Misc/NEWS
index a917523..659d7ca 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -50,6 +50,9 @@
Library
-------
+- Issue #25698: Importing module if the stack is too deep no longer replaces
+ imported module with the empty one.
+
- Issue #12923: Reset FancyURLopener's redirect counter even if there is an
exception. Based on patches by Brian Brazil and Daniel Rocco.
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index b281948..3e1c583 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -749,6 +749,36 @@
return ep->me_value;
}
+/* Variant of PyDict_GetItem() that doesn't suppress exceptions.
+ This returns NULL *with* an exception set if an exception occurred.
+ It returns NULL *without* an exception set if the key wasn't present.
+*/
+PyObject *
+_PyDict_GetItemWithError(PyObject *op, PyObject *key)
+{
+ long hash;
+ PyDictObject *mp = (PyDictObject *)op;
+ PyDictEntry *ep;
+ if (!PyDict_Check(op)) {
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+ if (!PyString_CheckExact(key) ||
+ (hash = ((PyStringObject *) key)->ob_shash) == -1)
+ {
+ hash = PyObject_Hash(key);
+ if (hash == -1) {
+ return NULL;
+ }
+ }
+
+ ep = (mp->ma_lookup)(mp, key, hash);
+ if (ep == NULL) {
+ return NULL;
+ }
+ return ep->me_value;
+}
+
static int
dict_set_item_by_hash_or_entry(register PyObject *op, PyObject *key,
long hash, PyDictEntry *ep, PyObject *value)
diff --git a/Python/import.c b/Python/import.c
index e47ce63..96f7d47 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -632,27 +632,45 @@
Because the former action is most common, THIS DOES NOT RETURN A
'NEW' REFERENCE! */
-PyObject *
-PyImport_AddModule(const char *name)
+static PyObject *
+_PyImport_AddModuleObject(PyObject *name)
{
PyObject *modules = PyImport_GetModuleDict();
PyObject *m;
- if ((m = PyDict_GetItemString(modules, name)) != NULL &&
- PyModule_Check(m))
+ if ((m = _PyDict_GetItemWithError(modules, name)) != NULL &&
+ PyModule_Check(m)) {
return m;
- m = PyModule_New(name);
- if (m == NULL)
+ }
+ if (PyErr_Occurred()) {
return NULL;
- if (PyDict_SetItemString(modules, name, m) != 0) {
+ }
+ m = PyModule_New(PyString_AS_STRING(name));
+ if (m == NULL) {
+ return NULL;
+ }
+ if (PyDict_SetItem(modules, name, m) != 0) {
Py_DECREF(m);
return NULL;
}
+ assert(Py_REFCNT(m) > 1);
Py_DECREF(m); /* Yes, it still exists, in modules! */
return m;
}
+PyObject *
+PyImport_AddModule(const char *name)
+{
+ PyObject *nameobj, *module;
+ nameobj = PyString_FromString(name);
+ if (nameobj == NULL)
+ return NULL;
+ module = _PyImport_AddModuleObject(nameobj);
+ Py_DECREF(nameobj);
+ return module;
+}
+
/* Remove name from sys.modules, if it's there. */
static void
remove_module(const char *name)