mirror of
https://github.com/python/cpython.git
synced 2025-10-06 15:11:58 +00:00
gh-101758: Clean Up Uses of Import State (gh-101919)
This change is almost entirely moving code around and hiding import state behind internal API. We introduce no changes to behavior, nor to non-internal API. (Since there was already going to be a lot of churn, I took this as an opportunity to re-organize import.c into topically-grouped sections of code.) The motivation is to simplify a number of upcoming changes. Specific changes: * move existing import-related code to import.c, wherever possible * add internal API for interacting with import state (both global and per-interpreter) * use only API outside of import.c (to limit churn there when changing the location, etc.) * consolidate the import-related state of PyInterpreterState into a single struct field (this changes layout slightly) * add macros for import state in import.c (to simplify changing the location) * group code in import.c into sections *remove _PyState_AddModule() https://github.com/python/cpython/issues/101758
This commit is contained in:
parent
c1ce0d178f
commit
b2fc549278
20 changed files with 1496 additions and 1092 deletions
151
Python/pystate.c
151
Python/pystate.c
|
@ -772,11 +772,13 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
|
|||
Py_CLEAR(interp->codec_search_path);
|
||||
Py_CLEAR(interp->codec_search_cache);
|
||||
Py_CLEAR(interp->codec_error_registry);
|
||||
Py_CLEAR(interp->modules);
|
||||
Py_CLEAR(interp->modules_by_index);
|
||||
|
||||
assert(interp->imports.modules == NULL);
|
||||
assert(interp->imports.modules_by_index == NULL);
|
||||
assert(interp->imports.importlib == NULL);
|
||||
assert(interp->imports.import_func == NULL);
|
||||
|
||||
Py_CLEAR(interp->builtins_copy);
|
||||
Py_CLEAR(interp->importlib);
|
||||
Py_CLEAR(interp->import_func);
|
||||
Py_CLEAR(interp->dict);
|
||||
#ifdef HAVE_FORK
|
||||
Py_CLEAR(interp->before_forkers);
|
||||
|
@ -836,6 +838,7 @@ PyInterpreterState_Clear(PyInterpreterState *interp)
|
|||
// garbage. It can be different than the current Python thread state
|
||||
// of 'interp'.
|
||||
PyThreadState *current_tstate = current_fast_get(interp->runtime);
|
||||
_PyImport_ClearCore(interp);
|
||||
interpreter_clear(interp, current_tstate);
|
||||
}
|
||||
|
||||
|
@ -843,6 +846,7 @@ PyInterpreterState_Clear(PyInterpreterState *interp)
|
|||
void
|
||||
_PyInterpreterState_Clear(PyThreadState *tstate)
|
||||
{
|
||||
_PyImport_ClearCore(tstate->interp);
|
||||
interpreter_clear(tstate->interp, tstate);
|
||||
}
|
||||
|
||||
|
@ -945,36 +949,6 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime)
|
|||
#endif
|
||||
|
||||
|
||||
// Used by finalize_modules()
|
||||
void
|
||||
_PyInterpreterState_ClearModules(PyInterpreterState *interp)
|
||||
{
|
||||
if (!interp->modules_by_index) {
|
||||
return;
|
||||
}
|
||||
|
||||
Py_ssize_t i;
|
||||
for (i = 0; i < PyList_GET_SIZE(interp->modules_by_index); i++) {
|
||||
PyObject *m = PyList_GET_ITEM(interp->modules_by_index, i);
|
||||
if (PyModule_Check(m)) {
|
||||
/* cleanup the saved copy of module dicts */
|
||||
PyModuleDef *md = PyModule_GetDef(m);
|
||||
if (md) {
|
||||
Py_CLEAR(md->m_base.m_copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Setting modules_by_index to NULL could be dangerous, so we
|
||||
clear the list instead. */
|
||||
if (PyList_SetSlice(interp->modules_by_index,
|
||||
0, PyList_GET_SIZE(interp->modules_by_index),
|
||||
NULL)) {
|
||||
PyErr_WriteUnraisable(interp->modules_by_index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//----------
|
||||
// accessors
|
||||
//----------
|
||||
|
@ -1058,11 +1032,12 @@ _PyInterpreterState_RequireIDRef(PyInterpreterState *interp, int required)
|
|||
PyObject *
|
||||
_PyInterpreterState_GetMainModule(PyInterpreterState *interp)
|
||||
{
|
||||
if (interp->modules == NULL) {
|
||||
PyObject *modules = _PyImport_GetModules(interp);
|
||||
if (modules == NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "interpreter not initialized");
|
||||
return NULL;
|
||||
}
|
||||
return PyMapping_GetItemString(interp->modules, "__main__");
|
||||
return PyMapping_GetItemString(modules, "__main__");
|
||||
}
|
||||
|
||||
PyObject *
|
||||
|
@ -1922,110 +1897,6 @@ done:
|
|||
}
|
||||
|
||||
|
||||
/****************/
|
||||
/* module state */
|
||||
/****************/
|
||||
|
||||
PyObject*
|
||||
PyState_FindModule(PyModuleDef* module)
|
||||
{
|
||||
Py_ssize_t index = module->m_base.m_index;
|
||||
PyInterpreterState *state = _PyInterpreterState_GET();
|
||||
PyObject *res;
|
||||
if (module->m_slots) {
|
||||
return NULL;
|
||||
}
|
||||
if (index == 0)
|
||||
return NULL;
|
||||
if (state->modules_by_index == NULL)
|
||||
return NULL;
|
||||
if (index >= PyList_GET_SIZE(state->modules_by_index))
|
||||
return NULL;
|
||||
res = PyList_GET_ITEM(state->modules_by_index, index);
|
||||
return res==Py_None ? NULL : res;
|
||||
}
|
||||
|
||||
int
|
||||
_PyState_AddModule(PyThreadState *tstate, PyObject* module, PyModuleDef* def)
|
||||
{
|
||||
if (!def) {
|
||||
assert(_PyErr_Occurred(tstate));
|
||||
return -1;
|
||||
}
|
||||
if (def->m_slots) {
|
||||
_PyErr_SetString(tstate,
|
||||
PyExc_SystemError,
|
||||
"PyState_AddModule called on module with slots");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyInterpreterState *interp = tstate->interp;
|
||||
if (!interp->modules_by_index) {
|
||||
interp->modules_by_index = PyList_New(0);
|
||||
if (!interp->modules_by_index) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
while (PyList_GET_SIZE(interp->modules_by_index) <= def->m_base.m_index) {
|
||||
if (PyList_Append(interp->modules_by_index, Py_None) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return PyList_SetItem(interp->modules_by_index,
|
||||
def->m_base.m_index, Py_NewRef(module));
|
||||
}
|
||||
|
||||
int
|
||||
PyState_AddModule(PyObject* module, PyModuleDef* def)
|
||||
{
|
||||
if (!def) {
|
||||
Py_FatalError("module definition is NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyThreadState *tstate = current_fast_get(&_PyRuntime);
|
||||
PyInterpreterState *interp = tstate->interp;
|
||||
Py_ssize_t index = def->m_base.m_index;
|
||||
if (interp->modules_by_index &&
|
||||
index < PyList_GET_SIZE(interp->modules_by_index) &&
|
||||
module == PyList_GET_ITEM(interp->modules_by_index, index))
|
||||
{
|
||||
_Py_FatalErrorFormat(__func__, "module %p already added", module);
|
||||
return -1;
|
||||
}
|
||||
return _PyState_AddModule(tstate, module, def);
|
||||
}
|
||||
|
||||
int
|
||||
PyState_RemoveModule(PyModuleDef* def)
|
||||
{
|
||||
PyThreadState *tstate = current_fast_get(&_PyRuntime);
|
||||
PyInterpreterState *interp = tstate->interp;
|
||||
|
||||
if (def->m_slots) {
|
||||
_PyErr_SetString(tstate,
|
||||
PyExc_SystemError,
|
||||
"PyState_RemoveModule called on module with slots");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Py_ssize_t index = def->m_base.m_index;
|
||||
if (index == 0) {
|
||||
Py_FatalError("invalid module index");
|
||||
}
|
||||
if (interp->modules_by_index == NULL) {
|
||||
Py_FatalError("Interpreters module-list not accessible.");
|
||||
}
|
||||
if (index > PyList_GET_SIZE(interp->modules_by_index)) {
|
||||
Py_FatalError("Module index out of bounds.");
|
||||
}
|
||||
|
||||
return PyList_SetItem(interp->modules_by_index, index, Py_NewRef(Py_None));
|
||||
}
|
||||
|
||||
|
||||
/***********************************/
|
||||
/* Python "auto thread state" API. */
|
||||
/***********************************/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue