[Python-checkins] gh-93741: Add private C API _PyImport_GetModuleAttrString() (GH-93742)

serhiy-storchaka webhook-mailer at python.org
Tue Jun 14 00:15:35 EDT 2022


https://github.com/python/cpython/commit/6fd4c8ec7740523bb81191c013118d9d6959bc9d
commit: 6fd4c8ec7740523bb81191c013118d9d6959bc9d
branch: main
author: Serhiy Storchaka <storchaka at gmail.com>
committer: serhiy-storchaka <storchaka at gmail.com>
date: 2022-06-14T07:15:26+03:00
summary:

gh-93741: Add private C API _PyImport_GetModuleAttrString() (GH-93742)

It combines PyImport_ImportModule() and PyObject_GetAttrString()
and saves 4-6 lines of code on every use.

Add also _PyImport_GetModuleAttr() which takes Python strings as arguments.

files:
M Include/cpython/import.h
M Include/internal/pycore_global_strings.h
M Include/internal/pycore_runtime_init.h
M Modules/_ctypes/callbacks.c
M Modules/_datetimemodule.c
M Modules/_elementtree.c
M Modules/_operator.c
M Modules/_pickle.c
M Modules/_sqlite/connection.c
M Modules/_sqlite/module.c
M Modules/_sre/sre.c
M Modules/_zoneinfo.c
M Modules/arraymodule.c
M Modules/cjkcodecs/cjkcodecs.h
M Modules/faulthandler.c
M Modules/posixmodule.c
M Modules/timemodule.c
M Objects/abstract.c
M Objects/fileobject.c
M Objects/memoryobject.c
M Parser/pegen.c
M Parser/tokenizer.c
M Python/import.c
M Python/pylifecycle.c

diff --git a/Include/cpython/import.h b/Include/cpython/import.h
index ef6be689468ee..a69b4f34def34 100644
--- a/Include/cpython/import.h
+++ b/Include/cpython/import.h
@@ -40,3 +40,6 @@ struct _frozen {
    collection of frozen modules: */
 
 PyAPI_DATA(const struct _frozen *) PyImport_FrozenModules;
+
+PyAPI_DATA(PyObject *) _PyImport_GetModuleAttr(PyObject *, PyObject *);
+PyAPI_DATA(PyObject *) _PyImport_GetModuleAttrString(const char *, const char *);
diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h
index af6c5ebaaf9de..2bf16c30e1bce 100644
--- a/Include/internal/pycore_global_strings.h
+++ b/Include/internal/pycore_global_strings.h
@@ -226,7 +226,6 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(_showwarnmsg)
         STRUCT_FOR_ID(_shutdown)
         STRUCT_FOR_ID(_slotnames)
-        STRUCT_FOR_ID(_strptime_time)
         STRUCT_FOR_ID(_uninitialized_submodules)
         STRUCT_FOR_ID(_warn_unawaited_coroutine)
         STRUCT_FOR_ID(_xoptions)
@@ -252,7 +251,6 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(difference_update)
         STRUCT_FOR_ID(dispatch_table)
         STRUCT_FOR_ID(displayhook)
-        STRUCT_FOR_ID(enable)
         STRUCT_FOR_ID(encode)
         STRUCT_FOR_ID(encoding)
         STRUCT_FOR_ID(end_lineno)
@@ -311,7 +309,6 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(opcode)
         STRUCT_FOR_ID(open)
         STRUCT_FOR_ID(parent)
-        STRUCT_FOR_ID(partial)
         STRUCT_FOR_ID(path)
         STRUCT_FOR_ID(peek)
         STRUCT_FOR_ID(persistent_id)
@@ -357,7 +354,6 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(warnoptions)
         STRUCT_FOR_ID(writable)
         STRUCT_FOR_ID(write)
-        STRUCT_FOR_ID(zipimporter)
     } identifiers;
     struct {
         PyASCIIObject _ascii;
diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h
index 2420d81a8a238..b4ce4e325a4d8 100644
--- a/Include/internal/pycore_runtime_init.h
+++ b/Include/internal/pycore_runtime_init.h
@@ -848,7 +848,6 @@ extern "C" {
                 INIT_ID(_showwarnmsg), \
                 INIT_ID(_shutdown), \
                 INIT_ID(_slotnames), \
-                INIT_ID(_strptime_time), \
                 INIT_ID(_uninitialized_submodules), \
                 INIT_ID(_warn_unawaited_coroutine), \
                 INIT_ID(_xoptions), \
@@ -874,7 +873,6 @@ extern "C" {
                 INIT_ID(difference_update), \
                 INIT_ID(dispatch_table), \
                 INIT_ID(displayhook), \
-                INIT_ID(enable), \
                 INIT_ID(encode), \
                 INIT_ID(encoding), \
                 INIT_ID(end_lineno), \
@@ -933,7 +931,6 @@ extern "C" {
                 INIT_ID(opcode), \
                 INIT_ID(open), \
                 INIT_ID(parent), \
-                INIT_ID(partial), \
                 INIT_ID(path), \
                 INIT_ID(peek), \
                 INIT_ID(persistent_id), \
@@ -979,7 +976,6 @@ extern "C" {
                 INIT_ID(warnoptions), \
                 INIT_ID(writable), \
                 INIT_ID(write), \
-                INIT_ID(zipimporter), \
             }, \
             .ascii = { \
                 _PyASCIIObject_INIT("\x00"), \
diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c
index e1e0225f67b34..220b6120dac52 100644
--- a/Modules/_ctypes/callbacks.c
+++ b/Modules/_ctypes/callbacks.c
@@ -472,24 +472,17 @@ static void LoadPython(void)
 
 long Call_GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
 {
-    PyObject *mod, *func, *result;
+    PyObject *func, *result;
     long retval;
     static PyObject *context;
 
     if (context == NULL)
         context = PyUnicode_InternFromString("_ctypes.DllGetClassObject");
 
-    mod = PyImport_ImportModule("ctypes");
-    if (!mod) {
-        PyErr_WriteUnraisable(context ? context : Py_None);
-        /* There has been a warning before about this already */
-        return E_FAIL;
-    }
-
-    func = PyObject_GetAttrString(mod, "DllGetClassObject");
-    Py_DECREF(mod);
+    func = _PyImport_GetModuleAttrString("ctypes", "DllGetClassObject");
     if (!func) {
         PyErr_WriteUnraisable(context ? context : Py_None);
+        /* There has been a warning before about this already */
         return E_FAIL;
     }
 
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
index 06dff8fdd9eed..ba24e3c124846 100644
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -1718,17 +1718,17 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
         goto Done;
     {
         PyObject *format;
-        PyObject *time = PyImport_ImportModule("time");
+        PyObject *strftime = _PyImport_GetModuleAttrString("time", "strftime");
 
-        if (time == NULL)
+        if (strftime == NULL)
             goto Done;
         format = PyUnicode_FromString(PyBytes_AS_STRING(newfmt));
         if (format != NULL) {
-            result = _PyObject_CallMethodIdObjArgs(time, &PyId_strftime,
+            result = PyObject_CallFunctionObjArgs(strftime,
                                                    format, timetuple, NULL);
             Py_DECREF(format);
         }
-        Py_DECREF(time);
+        Py_DECREF(strftime);
     }
  Done:
     Py_XDECREF(freplacement);
@@ -1748,12 +1748,10 @@ static PyObject *
 time_time(void)
 {
     PyObject *result = NULL;
-    PyObject *time = PyImport_ImportModule("time");
+    PyObject *time = _PyImport_GetModuleAttrString("time", "time");
 
     if (time != NULL) {
-        _Py_IDENTIFIER(time);
-
-        result = _PyObject_CallMethodIdNoArgs(time, &PyId_time);
+        result = PyObject_CallNoArgs(time);
         Py_DECREF(time);
     }
     return result;
@@ -1765,31 +1763,21 @@ time_time(void)
 static PyObject *
 build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag)
 {
-    PyObject *time;
+    PyObject *struct_time;
     PyObject *result;
-    _Py_IDENTIFIER(struct_time);
-    PyObject *args;
 
-
-    time = PyImport_ImportModule("time");
-    if (time == NULL) {
+    struct_time = _PyImport_GetModuleAttrString("time", "struct_time");
+    if (struct_time == NULL) {
         return NULL;
     }
 
-    args = Py_BuildValue("iiiiiiiii",
+    result = PyObject_CallFunction(struct_time, "((iiiiiiiii))",
                          y, m, d,
                          hh, mm, ss,
                          weekday(y, m, d),
                          days_before_month(y, m) + d,
                          dstflag);
-    if (args == NULL) {
-        Py_DECREF(time);
-        return NULL;
-    }
-
-    result = _PyObject_CallMethodIdOneArg(time, &PyId_struct_time, args);
-    Py_DECREF(time);
-    Py_DECREF(args);
+    Py_DECREF(struct_time);
     return result;
 }
 
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index 453e57a94f2c6..87f18d6e671a6 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -4370,7 +4370,7 @@ static struct PyModuleDef elementtreemodule = {
 PyMODINIT_FUNC
 PyInit__elementtree(void)
 {
-    PyObject *m, *temp;
+    PyObject *m;
     elementtreestate *st;
 
     m = PyState_FindModule(&elementtreemodule);
@@ -4394,11 +4394,7 @@ PyInit__elementtree(void)
         return NULL;
     st = get_elementtree_state(m);
 
-    if (!(temp = PyImport_ImportModule("copy")))
-        return NULL;
-    st->deepcopy_obj = PyObject_GetAttrString(temp, "deepcopy");
-    Py_XDECREF(temp);
-
+    st->deepcopy_obj = _PyImport_GetModuleAttrString("copy", "deepcopy");
     if (st->deepcopy_obj == NULL) {
         return NULL;
     }
diff --git a/Modules/_operator.c b/Modules/_operator.c
index 1af4a4feb7728..e89451631ca1b 100644
--- a/Modules/_operator.c
+++ b/Modules/_operator.c
@@ -1752,16 +1752,11 @@ methodcaller_reduce(methodcallerobject *mc, PyObject *Py_UNUSED(ignored))
         return Py_BuildValue("ON", Py_TYPE(mc), newargs);
     }
     else {
-        PyObject *functools;
         PyObject *partial;
         PyObject *constructor;
         PyObject *newargs[2];
 
-        functools = PyImport_ImportModule("functools");
-        if (!functools)
-            return NULL;
-        partial = PyObject_GetAttr(functools, &_Py_ID(partial));
-        Py_DECREF(functools);
+        partial = _PyImport_GetModuleAttrString("functools", "partial");
         if (!partial)
             return NULL;
 
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
index 753ac2fe892a1..1c5de30b07d62 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -232,8 +232,6 @@ _Pickle_InitState(PickleState *st)
 {
     PyObject *copyreg = NULL;
     PyObject *compat_pickle = NULL;
-    PyObject *codecs = NULL;
-    PyObject *functools = NULL;
 
     st->getattr = _PyEval_GetBuiltin(&_Py_ID(getattr));
     if (st->getattr == NULL)
@@ -329,10 +327,7 @@ _Pickle_InitState(PickleState *st)
     }
     Py_CLEAR(compat_pickle);
 
-    codecs = PyImport_ImportModule("codecs");
-    if (codecs == NULL)
-        goto error;
-    st->codecs_encode = PyObject_GetAttrString(codecs, "encode");
+    st->codecs_encode = _PyImport_GetModuleAttrString("codecs", "encode");
     if (st->codecs_encode == NULL) {
         goto error;
     }
@@ -342,23 +337,16 @@ _Pickle_InitState(PickleState *st)
                      Py_TYPE(st->codecs_encode)->tp_name);
         goto error;
     }
-    Py_CLEAR(codecs);
 
-    functools = PyImport_ImportModule("functools");
-    if (!functools)
-        goto error;
-    st->partial = PyObject_GetAttrString(functools, "partial");
+    st->partial = _PyImport_GetModuleAttrString("functools", "partial");
     if (!st->partial)
         goto error;
-    Py_CLEAR(functools);
 
     return 0;
 
   error:
     Py_CLEAR(copyreg);
     Py_CLEAR(compat_pickle);
-    Py_CLEAR(codecs);
-    Py_CLEAR(functools);
     _Pickle_ClearState(st);
     return -1;
 }
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 4ac0078eb83c2..484af7a1771b0 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -1841,43 +1841,21 @@ static PyObject *
 pysqlite_connection_iterdump_impl(pysqlite_Connection *self)
 /*[clinic end generated code: output=586997aaf9808768 input=1911ca756066da89]*/
 {
-    PyObject* retval = NULL;
-    PyObject* module = NULL;
-    PyObject* module_dict;
-    PyObject* pyfn_iterdump;
-
     if (!pysqlite_check_connection(self)) {
-        goto finally;
-    }
-
-    module = PyImport_ImportModule(MODULE_NAME ".dump");
-    if (!module) {
-        goto finally;
-    }
-
-    module_dict = PyModule_GetDict(module);
-    if (!module_dict) {
-        goto finally;
+        return NULL;
     }
 
-    PyObject *meth = PyUnicode_InternFromString("_iterdump");
-    if (meth == NULL) {
-        goto finally;
-    }
-    pyfn_iterdump = PyDict_GetItemWithError(module_dict, meth);
-    Py_DECREF(meth);
-    if (!pyfn_iterdump) {
+    PyObject *iterdump = _PyImport_GetModuleAttrString(MODULE_NAME ".dump", "_iterdump");
+    if (!iterdump) {
         if (!PyErr_Occurred()) {
             PyErr_SetString(self->OperationalError,
                             "Failed to obtain _iterdump() reference");
         }
-        goto finally;
+        return NULL;
     }
 
-    retval = PyObject_CallOneArg(pyfn_iterdump, (PyObject *)self);
-
-finally:
-    Py_XDECREF(module);
+    PyObject *retval = PyObject_CallOneArg(iterdump, (PyObject *)self);
+    Py_DECREF(iterdump);
     return retval;
 }
 
diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c
index 995d0946d9414..dfb93015387b1 100644
--- a/Modules/_sqlite/module.c
+++ b/Modules/_sqlite/module.c
@@ -227,14 +227,8 @@ static int converters_init(PyObject* module)
 static int
 load_functools_lru_cache(PyObject *module)
 {
-    PyObject *functools = PyImport_ImportModule("functools");
-    if (functools == NULL) {
-        return -1;
-    }
-
     pysqlite_state *state = pysqlite_get_state(module);
-    state->lru_cache = PyObject_GetAttrString(functools, "lru_cache");
-    Py_DECREF(functools);
+    state->lru_cache = _PyImport_GetModuleAttrString("functools", "lru_cache");
     if (state->lru_cache == NULL) {
         return -1;
     }
diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c
index 491734f243849..a1da180892fb4 100644
--- a/Modules/_sre/sre.c
+++ b/Modules/_sre/sre.c
@@ -771,22 +771,12 @@ _sre_SRE_Pattern_search_impl(PatternObject *self, PyTypeObject *cls,
 static PyObject*
 call(const char* module, const char* function, PyObject* args)
 {
-    PyObject* name;
-    PyObject* mod;
     PyObject* func;
     PyObject* result;
 
     if (!args)
         return NULL;
-    name = PyUnicode_FromString(module);
-    if (!name)
-        return NULL;
-    mod = PyImport_Import(name);
-    Py_DECREF(name);
-    if (!mod)
-        return NULL;
-    func = PyObject_GetAttrString(mod, function);
-    Py_DECREF(mod);
+    func = _PyImport_GetModuleAttrString(module, function);
     if (!func)
         return NULL;
     result = PyObject_CallObject(func, args);
diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c
index 1535721b026d1..207340adec152 100644
--- a/Modules/_zoneinfo.c
+++ b/Modules/_zoneinfo.c
@@ -659,14 +659,8 @@ zoneinfo_reduce(PyObject *obj_self, PyObject *unused)
     PyZoneInfo_ZoneInfo *self = (PyZoneInfo_ZoneInfo *)obj_self;
     if (self->source == SOURCE_FILE) {
         // Objects constructed from files cannot be pickled.
-        PyObject *pickle = PyImport_ImportModule("pickle");
-        if (pickle == NULL) {
-            return NULL;
-        }
-
         PyObject *pickle_error =
-            PyObject_GetAttrString(pickle, "PicklingError");
-        Py_DECREF(pickle);
+            _PyImport_GetModuleAttrString("pickle", "PicklingError");
         if (pickle_error == NULL) {
             return NULL;
         }
@@ -2492,14 +2486,13 @@ clear_strong_cache(const PyTypeObject *const type)
 static PyObject *
 new_weak_cache(void)
 {
-    PyObject *weakref_module = PyImport_ImportModule("weakref");
-    if (weakref_module == NULL) {
+    PyObject *WeakValueDictionary =
+            _PyImport_GetModuleAttrString("weakref", "WeakValueDictionary");
+    if (WeakValueDictionary == NULL) {
         return NULL;
     }
-
-    PyObject *weak_cache =
-        PyObject_CallMethod(weakref_module, "WeakValueDictionary", "");
-    Py_DECREF(weakref_module);
+    PyObject *weak_cache = PyObject_CallNoArgs(WeakValueDictionary);
+    Py_DECREF(WeakValueDictionary);
     return weak_cache;
 }
 
@@ -2656,25 +2649,13 @@ zoneinfomodule_exec(PyObject *m)
     PyModule_AddObject(m, "ZoneInfo", (PyObject *)&PyZoneInfo_ZoneInfoType);
 
     /* Populate imports */
-    PyObject *_tzpath_module = PyImport_ImportModule("zoneinfo._tzpath");
-    if (_tzpath_module == NULL) {
-        goto error;
-    }
-
     _tzpath_find_tzfile =
-        PyObject_GetAttrString(_tzpath_module, "find_tzfile");
-    Py_DECREF(_tzpath_module);
+        _PyImport_GetModuleAttrString("zoneinfo._tzpath", "find_tzfile");
     if (_tzpath_find_tzfile == NULL) {
         goto error;
     }
 
-    PyObject *io_module = PyImport_ImportModule("io");
-    if (io_module == NULL) {
-        goto error;
-    }
-
-    io_open = PyObject_GetAttrString(io_module, "open");
-    Py_DECREF(io_module);
+    io_open = _PyImport_GetModuleAttrString("io", "open");
     if (io_open == NULL) {
         goto error;
     }
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index a04e6a4e070d9..924fbf29bfb88 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -60,7 +60,6 @@ typedef struct {
 
     PyObject *str_read;
     PyObject *str_write;
-    PyObject *str__array_reconstructor;
     PyObject *str___dict__;
     PyObject *str_iter;
 } array_state;
@@ -2199,13 +2198,8 @@ array_array___reduce_ex___impl(arrayobject *self, PyTypeObject *cls,
     assert(state != NULL);
 
     if (array_reconstructor == NULL) {
-        PyObject *array_module = PyImport_ImportModule("array");
-        if (array_module == NULL)
-            return NULL;
-        array_reconstructor = PyObject_GetAttr(
-            array_module,
-            state->str__array_reconstructor);
-        Py_DECREF(array_module);
+        array_reconstructor = _PyImport_GetModuleAttrString(
+                "array", "_array_reconstructor");
         if (array_reconstructor == NULL)
             return NULL;
     }
@@ -3029,7 +3023,6 @@ array_clear(PyObject *module)
     Py_CLEAR(state->ArrayIterType);
     Py_CLEAR(state->str_read);
     Py_CLEAR(state->str_write);
-    Py_CLEAR(state->str__array_reconstructor);
     Py_CLEAR(state->str___dict__);
     Py_CLEAR(state->str_iter);
     return 0;
@@ -3075,7 +3068,6 @@ array_modexec(PyObject *m)
     /* Add interned strings */
     ADD_INTERNED(state, read);
     ADD_INTERNED(state, write);
-    ADD_INTERNED(state, _array_reconstructor);
     ADD_INTERNED(state, __dict__);
     ADD_INTERNED(state, iter);
 
@@ -3089,13 +3081,8 @@ array_modexec(PyObject *m)
         return -1;
     }
 
-    PyObject *abc_mod = PyImport_ImportModule("collections.abc");
-    if (!abc_mod) {
-        Py_DECREF((PyObject *)state->ArrayType);
-        return -1;
-    }
-    PyObject *mutablesequence = PyObject_GetAttrString(abc_mod, "MutableSequence");
-    Py_DECREF(abc_mod);
+    PyObject *mutablesequence = _PyImport_GetModuleAttrString(
+            "collections.abc", "MutableSequence");
     if (!mutablesequence) {
         Py_DECREF((PyObject *)state->ArrayType);
         return -1;
diff --git a/Modules/cjkcodecs/cjkcodecs.h b/Modules/cjkcodecs/cjkcodecs.h
index ba8fad26055a8..d9aeec2ff40b0 100644
--- a/Modules/cjkcodecs/cjkcodecs.h
+++ b/Modules/cjkcodecs/cjkcodecs.h
@@ -245,14 +245,7 @@ static const struct dbcs_map *mapping_list;
 static PyObject *
 getmultibytecodec(void)
 {
-    PyObject *mod = PyImport_ImportModuleNoBlock("_multibytecodec");
-    if (mod == NULL) {
-        return NULL;
-    }
-
-    PyObject *cofunc = PyObject_GetAttrString(mod, "__create_codec");
-    Py_DECREF(mod);
-    return cofunc;
+    return _PyImport_GetModuleAttrString("_multibytecodec", "__create_codec");
 }
 
 static PyObject *
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
index 08c40834c45f2..d33cd58333ec1 100644
--- a/Modules/faulthandler.c
+++ b/Modules/faulthandler.c
@@ -1340,13 +1340,13 @@ PyInit_faulthandler(void)
 static int
 faulthandler_init_enable(void)
 {
-    PyObject *module = PyImport_ImportModule("faulthandler");
-    if (module == NULL) {
+    PyObject *enable = _PyImport_GetModuleAttrString("faulthandler", "enable");
+    if (enable == NULL) {
         return -1;
     }
 
-    PyObject *res = PyObject_CallMethodNoArgs(module, &_Py_ID(enable));
-    Py_DECREF(module);
+    PyObject *res = PyObject_CallNoArgs(enable);
+    Py_DECREF(enable);
     if (res == NULL) {
         return -1;
     }
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index d41e19e652714..40229bce0f403 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -8279,11 +8279,7 @@ wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
         memset(ru, 0, sizeof(*ru));
     }
 
-    PyObject *m = PyImport_ImportModule("resource");
-    if (m == NULL)
-        return NULL;
-    struct_rusage = PyObject_GetAttr(m, get_posix_state(module)->struct_rusage);
-    Py_DECREF(m);
+    struct_rusage = _PyImport_GetModuleAttrString("resource", "struct_rusage");
     if (struct_rusage == NULL)
         return NULL;
 
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 18f9ddb909c02..11c888af03e82 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -910,14 +910,9 @@ is not present, current time as returned by localtime() is used.\n\
 static PyObject *
 time_strptime(PyObject *self, PyObject *args)
 {
-    PyObject *module, *func, *result;
+    PyObject *func, *result;
 
-    module = PyImport_ImportModule("_strptime");
-    if (!module)
-        return NULL;
-
-    func = PyObject_GetAttr(module, &_Py_ID(_strptime_time));
-    Py_DECREF(module);
+    func = _PyImport_GetModuleAttrString("_strptime", "_strptime_time");
     if (!func) {
         return NULL;
     }
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 93987c201b5e2..5d50491b2dd34 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -526,18 +526,12 @@ _Py_add_one_to_index_C(int nd, Py_ssize_t *index, const Py_ssize_t *shape)
 Py_ssize_t
 PyBuffer_SizeFromFormat(const char *format)
 {
-    PyObject *structmodule = NULL;
     PyObject *calcsize = NULL;
     PyObject *res = NULL;
     PyObject *fmt = NULL;
     Py_ssize_t itemsize = -1;
 
-    structmodule = PyImport_ImportModule("struct");
-    if (structmodule == NULL) {
-        return itemsize;
-    }
-
-    calcsize = PyObject_GetAttrString(structmodule, "calcsize");
+    calcsize = _PyImport_GetModuleAttrString("struct", "calcsize");
     if (calcsize == NULL) {
         goto done;
     }
@@ -558,7 +552,6 @@ PyBuffer_SizeFromFormat(const char *format)
     }
 
 done:
-    Py_DECREF(structmodule);
     Py_XDECREF(calcsize);
     Py_XDECREF(fmt);
     Py_XDECREF(res);
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
index 8dba5b9aea6db..cbc57412134d3 100644
--- a/Objects/fileobject.c
+++ b/Objects/fileobject.c
@@ -32,16 +32,16 @@ PyObject *
 PyFile_FromFd(int fd, const char *name, const char *mode, int buffering, const char *encoding,
               const char *errors, const char *newline, int closefd)
 {
-    PyObject *io, *stream;
+    PyObject *open, *stream;
 
     /* import _io in case we are being used to open io.py */
-    io = PyImport_ImportModule("_io");
-    if (io == NULL)
+    open = _PyImport_GetModuleAttrString("_io", "open");
+    if (open == NULL)
         return NULL;
-    stream = _PyObject_CallMethod(io, &_Py_ID(open), "isisssO", fd, mode,
+    stream = PyObject_CallFunction(open, "isisssO", fd, mode,
                                   buffering, encoding, errors,
                                   newline, closefd ? Py_True : Py_False);
-    Py_DECREF(io);
+    Py_DECREF(open);
     if (stream == NULL)
         return NULL;
     /* ignore name attribute because the name attribute of _BufferedIOMixin
@@ -490,7 +490,7 @@ PyFile_SetOpenCodeHook(Py_OpenCodeHookFunction hook, void *userData) {
 PyObject *
 PyFile_OpenCodeObject(PyObject *path)
 {
-    PyObject *iomod, *f = NULL;
+    PyObject *f = NULL;
 
     if (!PyUnicode_Check(path)) {
         PyErr_Format(PyExc_TypeError, "'path' must be 'str', not '%.200s'",
@@ -502,10 +502,10 @@ PyFile_OpenCodeObject(PyObject *path)
     if (hook) {
         f = hook(path, _PyRuntime.open_code_userdata);
     } else {
-        iomod = PyImport_ImportModule("_io");
-        if (iomod) {
-            f = _PyObject_CallMethod(iomod, &_Py_ID(open), "Os", path, "rb");
-            Py_DECREF(iomod);
+        PyObject *open = _PyImport_GetModuleAttrString("_io", "open");
+        if (open) {
+            f = PyObject_CallFunction(open, "Os", path, "rb");
+            Py_DECREF(open);
         }
     }
 
diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c
index 8c26916882447..c833c0bef65f3 100644
--- a/Objects/memoryobject.c
+++ b/Objects/memoryobject.c
@@ -1950,18 +1950,12 @@ unpacker_free(struct unpacker *x)
 static struct unpacker *
 struct_get_unpacker(const char *fmt, Py_ssize_t itemsize)
 {
-    PyObject *structmodule;     /* XXX cache these two */
-    PyObject *Struct = NULL;    /* XXX in globals?     */
+    PyObject *Struct = NULL;    /* XXX cache it in globals? */
     PyObject *structobj = NULL;
     PyObject *format = NULL;
     struct unpacker *x = NULL;
 
-    structmodule = PyImport_ImportModule("struct");
-    if (structmodule == NULL)
-        return NULL;
-
-    Struct = PyObject_GetAttrString(structmodule, "Struct");
-    Py_DECREF(structmodule);
+    Struct = _PyImport_GetModuleAttrString("struct", "Struct");
     if (Struct == NULL)
         return NULL;
 
diff --git a/Parser/pegen.c b/Parser/pegen.c
index ec4fee3fc4b71..dbf105aedcf42 100644
--- a/Parser/pegen.c
+++ b/Parser/pegen.c
@@ -77,13 +77,7 @@ init_normalization(Parser *p)
     if (p->normalize) {
         return 1;
     }
-    PyObject *m = PyImport_ImportModule("unicodedata");
-    if (!m)
-    {
-        return 0;
-    }
-    p->normalize = PyObject_GetAttrString(m, "normalize");
-    Py_DECREF(m);
+    p->normalize = _PyImport_GetModuleAttrString("unicodedata", "normalize");
     if (!p->normalize)
     {
         return 0;
diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c
index d5b549c8706ce..952265eb923f9 100644
--- a/Parser/tokenizer.c
+++ b/Parser/tokenizer.c
@@ -421,7 +421,7 @@ tok_readline_recode(struct tok_state *tok) {
 static int
 fp_setreadl(struct tok_state *tok, const char* enc)
 {
-    PyObject *readline, *io, *stream;
+    PyObject *readline, *open, *stream;
     int fd;
     long pos;
 
@@ -438,13 +438,13 @@ fp_setreadl(struct tok_state *tok, const char* enc)
         return 0;
     }
 
-    io = PyImport_ImportModule("io");
-    if (io == NULL) {
+    open = _PyImport_GetModuleAttrString("io", "open");
+    if (open == NULL) {
         return 0;
     }
-    stream = _PyObject_CallMethod(io, &_Py_ID(open), "isisOOO",
+    stream = PyObject_CallFunction(open, "isisOOO",
                     fd, "r", -1, enc, Py_None, Py_None, Py_False);
-    Py_DECREF(io);
+    Py_DECREF(open);
     if (stream == NULL) {
         return 0;
     }
diff --git a/Python/import.c b/Python/import.c
index 4b6d6d16821a9..54c21fa4a56aa 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -48,7 +48,7 @@ module _imp
 PyStatus
 _PyImportZip_Init(PyThreadState *tstate)
 {
-    PyObject *path_hooks, *zipimport;
+    PyObject *path_hooks;
     int err = 0;
 
     path_hooks = PySys_GetObject("path_hooks");
@@ -63,32 +63,22 @@ _PyImportZip_Init(PyThreadState *tstate)
         PySys_WriteStderr("# installing zipimport hook\n");
     }
 
-    zipimport = PyImport_ImportModule("zipimport");
-    if (zipimport == NULL) {
-        _PyErr_Clear(tstate); /* No zip import module -- okay */
+    PyObject *zipimporter = _PyImport_GetModuleAttrString("zipimport", "zipimporter");
+    if (zipimporter == NULL) {
+        _PyErr_Clear(tstate); /* No zipimporter object -- okay */
         if (verbose) {
-            PySys_WriteStderr("# can't import zipimport\n");
+            PySys_WriteStderr("# can't import zipimport.zipimporter\n");
         }
     }
     else {
-        PyObject *zipimporter = PyObject_GetAttr(zipimport, &_Py_ID(zipimporter));
-        Py_DECREF(zipimport);
-        if (zipimporter == NULL) {
-            _PyErr_Clear(tstate); /* No zipimporter object -- okay */
-            if (verbose) {
-                PySys_WriteStderr("# can't import zipimport.zipimporter\n");
-            }
+        /* sys.path_hooks.insert(0, zipimporter) */
+        err = PyList_Insert(path_hooks, 0, zipimporter);
+        Py_DECREF(zipimporter);
+        if (err < 0) {
+            goto error;
         }
-        else {
-            /* sys.path_hooks.insert(0, zipimporter) */
-            err = PyList_Insert(path_hooks, 0, zipimporter);
-            Py_DECREF(zipimporter);
-            if (err < 0) {
-                goto error;
-            }
-            if (verbose) {
-                PySys_WriteStderr("# installed zipimport hook\n");
-            }
+        if (verbose) {
+            PySys_WriteStderr("# installed zipimport hook\n");
         }
     }
 
@@ -2632,6 +2622,37 @@ PyImport_AppendInittab(const char *name, PyObject* (*initfunc)(void))
     return PyImport_ExtendInittab(newtab);
 }
 
+
+PyObject *
+_PyImport_GetModuleAttr(PyObject *modname, PyObject *attrname)
+{
+    PyObject *mod = PyImport_Import(modname);
+    if (mod == NULL) {
+        return NULL;
+    }
+    PyObject *result = PyObject_GetAttr(mod, attrname);
+    Py_DECREF(mod);
+    return result;
+}
+
+PyObject *
+_PyImport_GetModuleAttrString(const char *modname, const char *attrname)
+{
+    PyObject *pmodname = PyUnicode_FromString(modname);
+    if (pmodname == NULL) {
+        return NULL;
+    }
+    PyObject *pattrname = PyUnicode_FromString(attrname);
+    if (pattrname == NULL) {
+        Py_DECREF(pmodname);
+        return NULL;
+    }
+    PyObject *result = _PyImport_GetModuleAttr(pmodname, pattrname);
+    Py_DECREF(pattrname);
+    Py_DECREF(pmodname);
+    return result;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 31a358fe80de2..0937cce5c38f3 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -2342,19 +2342,15 @@ create_stdio(const PyConfig *config, PyObject* io,
 static PyStatus
 init_set_builtins_open(void)
 {
-    PyObject *iomod = NULL, *wrapper;
+    PyObject *wrapper;
     PyObject *bimod = NULL;
     PyStatus res = _PyStatus_OK();
 
-    if (!(iomod = PyImport_ImportModule("io"))) {
-        goto error;
-    }
-
     if (!(bimod = PyImport_ImportModule("builtins"))) {
         goto error;
     }
 
-    if (!(wrapper = PyObject_GetAttrString(iomod, "open"))) {
+    if (!(wrapper = _PyImport_GetModuleAttrString("io", "open"))) {
         goto error;
     }
 
@@ -2371,7 +2367,6 @@ init_set_builtins_open(void)
 
 done:
     Py_XDECREF(bimod);
-    Py_XDECREF(iomod);
     return res;
 }
 



More information about the Python-checkins mailing list