Skip to content

Commit

Permalink
gh-93741: Add private C API _PyImport_GetModuleAttrString() (GH-93742)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
serhiy-storchaka authored Jun 14, 2022
1 parent 7b2064b commit 6fd4c8e
Show file tree
Hide file tree
Showing 24 changed files with 114 additions and 248 deletions.
3 changes: 3 additions & 0 deletions Include/cpython/import.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
4 changes: 0 additions & 4 deletions Include/internal/pycore_global_strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 0 additions & 4 deletions Include/internal/pycore_runtime_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -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), \
Expand All @@ -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), \
Expand Down Expand Up @@ -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), \
Expand Down Expand Up @@ -979,7 +976,6 @@ extern "C" {
INIT_ID(warnoptions), \
INIT_ID(writable), \
INIT_ID(write), \
INIT_ID(zipimporter), \
}, \
.ascii = { \
_PyASCIIObject_INIT("\x00"), \
Expand Down
13 changes: 3 additions & 10 deletions Modules/_ctypes/callbacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
34 changes: 11 additions & 23 deletions Modules/_datetimemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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;
}

Expand Down
8 changes: 2 additions & 6 deletions Modules/_elementtree.c
Original file line number Diff line number Diff line change
Expand Up @@ -4370,7 +4370,7 @@ static struct PyModuleDef elementtreemodule = {
PyMODINIT_FUNC
PyInit__elementtree(void)
{
PyObject *m, *temp;
PyObject *m;
elementtreestate *st;

m = PyState_FindModule(&elementtreemodule);
Expand All @@ -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;
}
Expand Down
7 changes: 1 addition & 6 deletions Modules/_operator.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
16 changes: 2 additions & 14 deletions Modules/_pickle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down
34 changes: 6 additions & 28 deletions Modules/_sqlite/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
8 changes: 1 addition & 7 deletions Modules/_sqlite/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
12 changes: 1 addition & 11 deletions Modules/_sre/sre.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 6fd4c8e

Please sign in to comment.