Skip to content

Commit 5865fa5

Browse files
pythongh-117953: Add Internal struct _Py_ext_module_loader_info (pythongh-118194)
This helps with a later change that splits up _PyImport_LoadDynamicModuleWithSpec().
1 parent 9b280ab commit 5865fa5

File tree

3 files changed

+180
-94
lines changed

3 files changed

+180
-94
lines changed

Include/internal/pycore_importdl.h

+29-1
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,38 @@ extern "C" {
1414

1515
extern const char *_PyImport_DynLoadFiletab[];
1616

17-
extern PyObject *_PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *);
1817

1918
typedef PyObject *(*PyModInitFunction)(void);
2019

20+
struct _Py_ext_module_loader_info {
21+
PyObject *filename;
22+
#ifndef MS_WINDOWS
23+
PyObject *filename_encoded;
24+
#endif
25+
PyObject *name;
26+
PyObject *name_encoded;
27+
/* path is always a borrowed ref of name or filename,
28+
* depending on if it's builtin or not. */
29+
PyObject *path;
30+
const char *hook_prefix;
31+
const char *newcontext;
32+
};
33+
extern void _Py_ext_module_loader_info_clear(
34+
struct _Py_ext_module_loader_info *info);
35+
extern int _Py_ext_module_loader_info_init(
36+
struct _Py_ext_module_loader_info *info,
37+
PyObject *name,
38+
PyObject *filename);
39+
extern int _Py_ext_module_loader_info_init_from_spec(
40+
struct _Py_ext_module_loader_info *info,
41+
PyObject *spec);
42+
43+
extern PyObject *_PyImport_LoadDynamicModuleWithSpec(
44+
struct _Py_ext_module_loader_info *info,
45+
PyObject *spec,
46+
FILE *fp);
47+
48+
2149
/* Max length of module suffix searched for -- accommodates "module.slb" */
2250
#define MAXSUFFIXSIZE 12
2351

Python/import.c

+54-40
Original file line numberDiff line numberDiff line change
@@ -1328,19 +1328,19 @@ _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name,
13281328

13291329

13301330
static PyObject *
1331-
import_find_extension(PyThreadState *tstate, PyObject *name,
1332-
PyObject *path)
1331+
import_find_extension(PyThreadState *tstate,
1332+
struct _Py_ext_module_loader_info *info)
13331333
{
13341334
/* Only single-phase init modules will be in the cache. */
1335-
PyModuleDef *def = _extensions_cache_get(path, name);
1335+
PyModuleDef *def = _extensions_cache_get(info->path, info->name);
13361336
if (def == NULL) {
13371337
return NULL;
13381338
}
13391339

13401340
/* It may have been successfully imported previously
13411341
in an interpreter that allows legacy modules
13421342
but is not allowed in the current interpreter. */
1343-
const char *name_buf = PyUnicode_AsUTF8(name);
1343+
const char *name_buf = PyUnicode_AsUTF8(info->name);
13441344
assert(name_buf != NULL);
13451345
if (_PyImport_CheckSubinterpIncompatibleExtensionAllowed(name_buf) < 0) {
13461346
return NULL;
@@ -1355,12 +1355,13 @@ import_find_extension(PyThreadState *tstate, PyObject *name,
13551355
if (m_copy == NULL) {
13561356
/* It might be a core module (e.g. sys & builtins),
13571357
for which we don't set m_copy. */
1358-
m_copy = get_core_module_dict(tstate->interp, name, path);
1358+
m_copy = get_core_module_dict(
1359+
tstate->interp, info->name, info->path);
13591360
if (m_copy == NULL) {
13601361
return NULL;
13611362
}
13621363
}
1363-
mod = import_add_module(tstate, name);
1364+
mod = import_add_module(tstate, info->name);
13641365
if (mod == NULL) {
13651366
return NULL;
13661367
}
@@ -1378,23 +1379,24 @@ import_find_extension(PyThreadState *tstate, PyObject *name,
13781379
if (def->m_base.m_init == NULL)
13791380
return NULL;
13801381
mod = def->m_base.m_init();
1381-
if (mod == NULL)
1382+
if (mod == NULL) {
13821383
return NULL;
1383-
if (PyObject_SetItem(modules, name, mod) == -1) {
1384+
}
1385+
if (PyObject_SetItem(modules, info->name, mod) == -1) {
13841386
Py_DECREF(mod);
13851387
return NULL;
13861388
}
13871389
}
13881390
if (_modules_by_index_set(tstate->interp, def, mod) < 0) {
1389-
PyMapping_DelItem(modules, name);
1391+
PyMapping_DelItem(modules, info->name);
13901392
Py_DECREF(mod);
13911393
return NULL;
13921394
}
13931395

13941396
int verbose = _PyInterpreterState_GetConfig(tstate->interp)->verbose;
13951397
if (verbose) {
13961398
PySys_FormatStderr("import %U # previously loaded (%R)\n",
1397-
name, path);
1399+
info->name, info->path);
13981400
}
13991401
return mod;
14001402
}
@@ -1505,44 +1507,56 @@ static PyObject*
15051507
create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)
15061508
{
15071509
PyModuleDef *def = NULL;
1508-
PyObject *mod = import_find_extension(tstate, name, name);
1510+
1511+
struct _Py_ext_module_loader_info info;
1512+
if (_Py_ext_module_loader_info_init(&info, name, NULL) < 0) {
1513+
return NULL;
1514+
}
1515+
1516+
PyObject *mod = import_find_extension(tstate, &info);
15091517
if (mod || _PyErr_Occurred(tstate)) {
1510-
return mod;
1518+
goto finally;
15111519
}
15121520

15131521
struct _inittab *found = NULL;
15141522
for (struct _inittab *p = INITTAB; p->name != NULL; p++) {
1515-
if (_PyUnicode_EqualToASCIIString(name, p->name)) {
1523+
if (_PyUnicode_EqualToASCIIString(info.name, p->name)) {
15161524
found = p;
15171525
}
15181526
}
15191527
if (found == NULL) {
15201528
// not found
1521-
Py_RETURN_NONE;
1529+
mod = Py_NewRef(Py_None);
1530+
goto finally;
15221531
}
15231532

15241533
PyModInitFunction p0 = (PyModInitFunction)found->initfunc;
15251534
if (p0 == NULL) {
15261535
/* Cannot re-init internal module ("sys" or "builtins") */
1527-
assert(is_core_module(tstate->interp, name, name));
1528-
return import_add_module(tstate, name);
1536+
assert(is_core_module(tstate->interp, info.name, info.path));
1537+
mod = import_add_module(tstate, info.name);
1538+
goto finally;
15291539
}
15301540

15311541
mod = p0();
15321542
if (mod == NULL) {
1533-
return NULL;
1543+
goto finally;
15341544
}
15351545

15361546
if (PyObject_TypeCheck(mod, &PyModuleDef_Type)) {
15371547
def = (PyModuleDef*)mod;
15381548
assert(!is_singlephase(def));
1539-
return PyModule_FromDefAndSpec(def, spec);
1549+
mod = PyModule_FromDefAndSpec(def, spec);
1550+
if (mod == NULL) {
1551+
goto finally;
1552+
}
15401553
}
15411554
else {
15421555
assert(PyModule_Check(mod));
15431556
def = PyModule_GetDef(mod);
15441557
if (def == NULL) {
1545-
return NULL;
1558+
Py_CLEAR(mod);
1559+
goto finally;
15461560
}
15471561
assert(is_singlephase(def));
15481562

@@ -1553,22 +1567,29 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)
15531567
// gh-88216: Extensions and def->m_base.m_copy can be updated
15541568
// when the extension module doesn't support sub-interpreters.
15551569
if (def->m_size == -1
1556-
&& !is_core_module(tstate->interp, name, name))
1570+
&& !is_core_module(tstate->interp, info.name, info.path))
15571571
{
15581572
singlephase.m_dict = PyModule_GetDict(mod);
15591573
assert(singlephase.m_dict != NULL);
15601574
}
15611575
if (update_global_state_for_extension(
1562-
tstate, name, name, def, &singlephase) < 0)
1576+
tstate, info.name, info.path, def, &singlephase) < 0)
15631577
{
1564-
return NULL;
1578+
Py_CLEAR(mod);
1579+
goto finally;
15651580
}
15661581
PyObject *modules = get_modules_dict(tstate, true);
1567-
if (finish_singlephase_extension(tstate, mod, def, name, modules) < 0) {
1568-
return NULL;
1582+
if (finish_singlephase_extension(
1583+
tstate, mod, def, info.name, modules) < 0)
1584+
{
1585+
Py_CLEAR(mod);
1586+
goto finally;
15691587
}
1570-
return mod;
15711588
}
1589+
1590+
finally:
1591+
_Py_ext_module_loader_info_clear(&info);
1592+
return mod;
15721593
}
15731594

15741595

@@ -3878,28 +3899,22 @@ static PyObject *
38783899
_imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file)
38793900
/*[clinic end generated code: output=83249b827a4fde77 input=c31b954f4cf4e09d]*/
38803901
{
3881-
PyObject *mod, *name, *filename;
3902+
PyObject *mod = NULL;
38823903
FILE *fp;
38833904

3884-
name = PyObject_GetAttrString(spec, "name");
3885-
if (name == NULL) {
3886-
return NULL;
3887-
}
3888-
3889-
filename = PyObject_GetAttrString(spec, "origin");
3890-
if (filename == NULL) {
3891-
Py_DECREF(name);
3905+
struct _Py_ext_module_loader_info info;
3906+
if (_Py_ext_module_loader_info_init_from_spec(&info, spec) < 0) {
38923907
return NULL;
38933908
}
38943909

38953910
PyThreadState *tstate = _PyThreadState_GET();
3896-
mod = import_find_extension(tstate, name, filename);
3911+
mod = import_find_extension(tstate, &info);
38973912
if (mod != NULL || _PyErr_Occurred(tstate)) {
38983913
assert(mod == NULL || !_PyErr_Occurred(tstate));
38993914
goto finally;
39003915
}
39013916

3902-
if (PySys_Audit("import", "OOOOO", name, filename,
3917+
if (PySys_Audit("import", "OOOOO", info.name, info.filename,
39033918
Py_None, Py_None, Py_None) < 0)
39043919
{
39053920
goto finally;
@@ -3911,7 +3926,7 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file)
39113926
* _PyImport_GetModInitFunc(), but it isn't clear if the intervening
39123927
* code relies on fp still being open. */
39133928
if (file != NULL) {
3914-
fp = _Py_fopen_obj(filename, "r");
3929+
fp = _Py_fopen_obj(info.filename, "r");
39153930
if (fp == NULL) {
39163931
goto finally;
39173932
}
@@ -3920,16 +3935,15 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file)
39203935
fp = NULL;
39213936
}
39223937

3923-
mod = _PyImport_LoadDynamicModuleWithSpec(spec, fp);
3938+
mod = _PyImport_LoadDynamicModuleWithSpec(&info, spec, fp);
39243939

39253940
// XXX Shouldn't this happen in the error cases too.
39263941
if (fp) {
39273942
fclose(fp);
39283943
}
39293944

39303945
finally:
3931-
Py_DECREF(name);
3932-
Py_DECREF(filename);
3946+
_Py_ext_module_loader_info_clear(&info);
39333947
return mod;
39343948
}
39353949

0 commit comments

Comments
 (0)