Skip to content

Commit 6fd4c8e

Browse files
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.
1 parent 7b2064b commit 6fd4c8e

24 files changed

+114
-248
lines changed

Include/cpython/import.h

+3
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,6 @@ struct _frozen {
4040
collection of frozen modules: */
4141

4242
PyAPI_DATA(const struct _frozen *) PyImport_FrozenModules;
43+
44+
PyAPI_DATA(PyObject *) _PyImport_GetModuleAttr(PyObject *, PyObject *);
45+
PyAPI_DATA(PyObject *) _PyImport_GetModuleAttrString(const char *, const char *);

Include/internal/pycore_global_strings.h

-4
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,6 @@ struct _Py_global_strings {
226226
STRUCT_FOR_ID(_showwarnmsg)
227227
STRUCT_FOR_ID(_shutdown)
228228
STRUCT_FOR_ID(_slotnames)
229-
STRUCT_FOR_ID(_strptime_time)
230229
STRUCT_FOR_ID(_uninitialized_submodules)
231230
STRUCT_FOR_ID(_warn_unawaited_coroutine)
232231
STRUCT_FOR_ID(_xoptions)
@@ -252,7 +251,6 @@ struct _Py_global_strings {
252251
STRUCT_FOR_ID(difference_update)
253252
STRUCT_FOR_ID(dispatch_table)
254253
STRUCT_FOR_ID(displayhook)
255-
STRUCT_FOR_ID(enable)
256254
STRUCT_FOR_ID(encode)
257255
STRUCT_FOR_ID(encoding)
258256
STRUCT_FOR_ID(end_lineno)
@@ -311,7 +309,6 @@ struct _Py_global_strings {
311309
STRUCT_FOR_ID(opcode)
312310
STRUCT_FOR_ID(open)
313311
STRUCT_FOR_ID(parent)
314-
STRUCT_FOR_ID(partial)
315312
STRUCT_FOR_ID(path)
316313
STRUCT_FOR_ID(peek)
317314
STRUCT_FOR_ID(persistent_id)
@@ -357,7 +354,6 @@ struct _Py_global_strings {
357354
STRUCT_FOR_ID(warnoptions)
358355
STRUCT_FOR_ID(writable)
359356
STRUCT_FOR_ID(write)
360-
STRUCT_FOR_ID(zipimporter)
361357
} identifiers;
362358
struct {
363359
PyASCIIObject _ascii;

Include/internal/pycore_runtime_init.h

-4
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,6 @@ extern "C" {
848848
INIT_ID(_showwarnmsg), \
849849
INIT_ID(_shutdown), \
850850
INIT_ID(_slotnames), \
851-
INIT_ID(_strptime_time), \
852851
INIT_ID(_uninitialized_submodules), \
853852
INIT_ID(_warn_unawaited_coroutine), \
854853
INIT_ID(_xoptions), \
@@ -874,7 +873,6 @@ extern "C" {
874873
INIT_ID(difference_update), \
875874
INIT_ID(dispatch_table), \
876875
INIT_ID(displayhook), \
877-
INIT_ID(enable), \
878876
INIT_ID(encode), \
879877
INIT_ID(encoding), \
880878
INIT_ID(end_lineno), \
@@ -933,7 +931,6 @@ extern "C" {
933931
INIT_ID(opcode), \
934932
INIT_ID(open), \
935933
INIT_ID(parent), \
936-
INIT_ID(partial), \
937934
INIT_ID(path), \
938935
INIT_ID(peek), \
939936
INIT_ID(persistent_id), \
@@ -979,7 +976,6 @@ extern "C" {
979976
INIT_ID(warnoptions), \
980977
INIT_ID(writable), \
981978
INIT_ID(write), \
982-
INIT_ID(zipimporter), \
983979
}, \
984980
.ascii = { \
985981
_PyASCIIObject_INIT("\x00"), \

Modules/_ctypes/callbacks.c

+3-10
Original file line numberDiff line numberDiff line change
@@ -472,24 +472,17 @@ static void LoadPython(void)
472472

473473
long Call_GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
474474
{
475-
PyObject *mod, *func, *result;
475+
PyObject *func, *result;
476476
long retval;
477477
static PyObject *context;
478478

479479
if (context == NULL)
480480
context = PyUnicode_InternFromString("_ctypes.DllGetClassObject");
481481

482-
mod = PyImport_ImportModule("ctypes");
483-
if (!mod) {
484-
PyErr_WriteUnraisable(context ? context : Py_None);
485-
/* There has been a warning before about this already */
486-
return E_FAIL;
487-
}
488-
489-
func = PyObject_GetAttrString(mod, "DllGetClassObject");
490-
Py_DECREF(mod);
482+
func = _PyImport_GetModuleAttrString("ctypes", "DllGetClassObject");
491483
if (!func) {
492484
PyErr_WriteUnraisable(context ? context : Py_None);
485+
/* There has been a warning before about this already */
493486
return E_FAIL;
494487
}
495488

Modules/_datetimemodule.c

+11-23
Original file line numberDiff line numberDiff line change
@@ -1718,17 +1718,17 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
17181718
goto Done;
17191719
{
17201720
PyObject *format;
1721-
PyObject *time = PyImport_ImportModule("time");
1721+
PyObject *strftime = _PyImport_GetModuleAttrString("time", "strftime");
17221722

1723-
if (time == NULL)
1723+
if (strftime == NULL)
17241724
goto Done;
17251725
format = PyUnicode_FromString(PyBytes_AS_STRING(newfmt));
17261726
if (format != NULL) {
1727-
result = _PyObject_CallMethodIdObjArgs(time, &PyId_strftime,
1727+
result = PyObject_CallFunctionObjArgs(strftime,
17281728
format, timetuple, NULL);
17291729
Py_DECREF(format);
17301730
}
1731-
Py_DECREF(time);
1731+
Py_DECREF(strftime);
17321732
}
17331733
Done:
17341734
Py_XDECREF(freplacement);
@@ -1748,12 +1748,10 @@ static PyObject *
17481748
time_time(void)
17491749
{
17501750
PyObject *result = NULL;
1751-
PyObject *time = PyImport_ImportModule("time");
1751+
PyObject *time = _PyImport_GetModuleAttrString("time", "time");
17521752

17531753
if (time != NULL) {
1754-
_Py_IDENTIFIER(time);
1755-
1756-
result = _PyObject_CallMethodIdNoArgs(time, &PyId_time);
1754+
result = PyObject_CallNoArgs(time);
17571755
Py_DECREF(time);
17581756
}
17591757
return result;
@@ -1765,31 +1763,21 @@ time_time(void)
17651763
static PyObject *
17661764
build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag)
17671765
{
1768-
PyObject *time;
1766+
PyObject *struct_time;
17691767
PyObject *result;
1770-
_Py_IDENTIFIER(struct_time);
1771-
PyObject *args;
17721768

1773-
1774-
time = PyImport_ImportModule("time");
1775-
if (time == NULL) {
1769+
struct_time = _PyImport_GetModuleAttrString("time", "struct_time");
1770+
if (struct_time == NULL) {
17761771
return NULL;
17771772
}
17781773

1779-
args = Py_BuildValue("iiiiiiiii",
1774+
result = PyObject_CallFunction(struct_time, "((iiiiiiiii))",
17801775
y, m, d,
17811776
hh, mm, ss,
17821777
weekday(y, m, d),
17831778
days_before_month(y, m) + d,
17841779
dstflag);
1785-
if (args == NULL) {
1786-
Py_DECREF(time);
1787-
return NULL;
1788-
}
1789-
1790-
result = _PyObject_CallMethodIdOneArg(time, &PyId_struct_time, args);
1791-
Py_DECREF(time);
1792-
Py_DECREF(args);
1780+
Py_DECREF(struct_time);
17931781
return result;
17941782
}
17951783

Modules/_elementtree.c

+2-6
Original file line numberDiff line numberDiff line change
@@ -4370,7 +4370,7 @@ static struct PyModuleDef elementtreemodule = {
43704370
PyMODINIT_FUNC
43714371
PyInit__elementtree(void)
43724372
{
4373-
PyObject *m, *temp;
4373+
PyObject *m;
43744374
elementtreestate *st;
43754375

43764376
m = PyState_FindModule(&elementtreemodule);
@@ -4394,11 +4394,7 @@ PyInit__elementtree(void)
43944394
return NULL;
43954395
st = get_elementtree_state(m);
43964396

4397-
if (!(temp = PyImport_ImportModule("copy")))
4398-
return NULL;
4399-
st->deepcopy_obj = PyObject_GetAttrString(temp, "deepcopy");
4400-
Py_XDECREF(temp);
4401-
4397+
st->deepcopy_obj = _PyImport_GetModuleAttrString("copy", "deepcopy");
44024398
if (st->deepcopy_obj == NULL) {
44034399
return NULL;
44044400
}

Modules/_operator.c

+1-6
Original file line numberDiff line numberDiff line change
@@ -1752,16 +1752,11 @@ methodcaller_reduce(methodcallerobject *mc, PyObject *Py_UNUSED(ignored))
17521752
return Py_BuildValue("ON", Py_TYPE(mc), newargs);
17531753
}
17541754
else {
1755-
PyObject *functools;
17561755
PyObject *partial;
17571756
PyObject *constructor;
17581757
PyObject *newargs[2];
17591758

1760-
functools = PyImport_ImportModule("functools");
1761-
if (!functools)
1762-
return NULL;
1763-
partial = PyObject_GetAttr(functools, &_Py_ID(partial));
1764-
Py_DECREF(functools);
1759+
partial = _PyImport_GetModuleAttrString("functools", "partial");
17651760
if (!partial)
17661761
return NULL;
17671762

Modules/_pickle.c

+2-14
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,6 @@ _Pickle_InitState(PickleState *st)
232232
{
233233
PyObject *copyreg = NULL;
234234
PyObject *compat_pickle = NULL;
235-
PyObject *codecs = NULL;
236-
PyObject *functools = NULL;
237235

238236
st->getattr = _PyEval_GetBuiltin(&_Py_ID(getattr));
239237
if (st->getattr == NULL)
@@ -329,10 +327,7 @@ _Pickle_InitState(PickleState *st)
329327
}
330328
Py_CLEAR(compat_pickle);
331329

332-
codecs = PyImport_ImportModule("codecs");
333-
if (codecs == NULL)
334-
goto error;
335-
st->codecs_encode = PyObject_GetAttrString(codecs, "encode");
330+
st->codecs_encode = _PyImport_GetModuleAttrString("codecs", "encode");
336331
if (st->codecs_encode == NULL) {
337332
goto error;
338333
}
@@ -342,23 +337,16 @@ _Pickle_InitState(PickleState *st)
342337
Py_TYPE(st->codecs_encode)->tp_name);
343338
goto error;
344339
}
345-
Py_CLEAR(codecs);
346340

347-
functools = PyImport_ImportModule("functools");
348-
if (!functools)
349-
goto error;
350-
st->partial = PyObject_GetAttrString(functools, "partial");
341+
st->partial = _PyImport_GetModuleAttrString("functools", "partial");
351342
if (!st->partial)
352343
goto error;
353-
Py_CLEAR(functools);
354344

355345
return 0;
356346

357347
error:
358348
Py_CLEAR(copyreg);
359349
Py_CLEAR(compat_pickle);
360-
Py_CLEAR(codecs);
361-
Py_CLEAR(functools);
362350
_Pickle_ClearState(st);
363351
return -1;
364352
}

Modules/_sqlite/connection.c

+6-28
Original file line numberDiff line numberDiff line change
@@ -1841,43 +1841,21 @@ static PyObject *
18411841
pysqlite_connection_iterdump_impl(pysqlite_Connection *self)
18421842
/*[clinic end generated code: output=586997aaf9808768 input=1911ca756066da89]*/
18431843
{
1844-
PyObject* retval = NULL;
1845-
PyObject* module = NULL;
1846-
PyObject* module_dict;
1847-
PyObject* pyfn_iterdump;
1848-
18491844
if (!pysqlite_check_connection(self)) {
1850-
goto finally;
1851-
}
1852-
1853-
module = PyImport_ImportModule(MODULE_NAME ".dump");
1854-
if (!module) {
1855-
goto finally;
1856-
}
1857-
1858-
module_dict = PyModule_GetDict(module);
1859-
if (!module_dict) {
1860-
goto finally;
1845+
return NULL;
18611846
}
18621847

1863-
PyObject *meth = PyUnicode_InternFromString("_iterdump");
1864-
if (meth == NULL) {
1865-
goto finally;
1866-
}
1867-
pyfn_iterdump = PyDict_GetItemWithError(module_dict, meth);
1868-
Py_DECREF(meth);
1869-
if (!pyfn_iterdump) {
1848+
PyObject *iterdump = _PyImport_GetModuleAttrString(MODULE_NAME ".dump", "_iterdump");
1849+
if (!iterdump) {
18701850
if (!PyErr_Occurred()) {
18711851
PyErr_SetString(self->OperationalError,
18721852
"Failed to obtain _iterdump() reference");
18731853
}
1874-
goto finally;
1854+
return NULL;
18751855
}
18761856

1877-
retval = PyObject_CallOneArg(pyfn_iterdump, (PyObject *)self);
1878-
1879-
finally:
1880-
Py_XDECREF(module);
1857+
PyObject *retval = PyObject_CallOneArg(iterdump, (PyObject *)self);
1858+
Py_DECREF(iterdump);
18811859
return retval;
18821860
}
18831861

Modules/_sqlite/module.c

+1-7
Original file line numberDiff line numberDiff line change
@@ -227,14 +227,8 @@ static int converters_init(PyObject* module)
227227
static int
228228
load_functools_lru_cache(PyObject *module)
229229
{
230-
PyObject *functools = PyImport_ImportModule("functools");
231-
if (functools == NULL) {
232-
return -1;
233-
}
234-
235230
pysqlite_state *state = pysqlite_get_state(module);
236-
state->lru_cache = PyObject_GetAttrString(functools, "lru_cache");
237-
Py_DECREF(functools);
231+
state->lru_cache = _PyImport_GetModuleAttrString("functools", "lru_cache");
238232
if (state->lru_cache == NULL) {
239233
return -1;
240234
}

Modules/_sre/sre.c

+1-11
Original file line numberDiff line numberDiff line change
@@ -771,22 +771,12 @@ _sre_SRE_Pattern_search_impl(PatternObject *self, PyTypeObject *cls,
771771
static PyObject*
772772
call(const char* module, const char* function, PyObject* args)
773773
{
774-
PyObject* name;
775-
PyObject* mod;
776774
PyObject* func;
777775
PyObject* result;
778776

779777
if (!args)
780778
return NULL;
781-
name = PyUnicode_FromString(module);
782-
if (!name)
783-
return NULL;
784-
mod = PyImport_Import(name);
785-
Py_DECREF(name);
786-
if (!mod)
787-
return NULL;
788-
func = PyObject_GetAttrString(mod, function);
789-
Py_DECREF(mod);
779+
func = _PyImport_GetModuleAttrString(module, function);
790780
if (!func)
791781
return NULL;
792782
result = PyObject_CallObject(func, args);

0 commit comments

Comments
 (0)