Skip to content

Commit

Permalink
Add _PyModule_IsInitializing().
Browse files Browse the repository at this point in the history
  • Loading branch information
serhiy-storchaka committed Jul 24, 2018
1 parent b072b9b commit 770f2f5
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 42 deletions.
1 change: 1 addition & 0 deletions Include/moduleobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ PyAPI_FUNC(PyObject *) PyModule_GetFilenameObject(PyObject *);
#ifndef Py_LIMITED_API
PyAPI_FUNC(void) _PyModule_Clear(PyObject *);
PyAPI_FUNC(void) _PyModule_ClearDict(PyObject *);
PyAPI_FUNC(int) _PyModule_IsInitializing(PyObject *);
#endif
PyAPI_FUNC(struct PyModuleDef*) PyModule_GetDef(PyObject*);
PyAPI_FUNC(void*) PyModule_GetState(PyObject*);
Expand Down
46 changes: 28 additions & 18 deletions Objects/moduleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,33 @@ module_repr(PyModuleObject *m)
return PyObject_CallMethod(interp->importlib, "_module_repr", "O", m);
}

int
_PyModule_IsInitializing(PyObject *m)
{
if (PyModule_Check(m) && ((PyModuleObject *)m)->md_dict) {
_Py_IDENTIFIER(__spec__);
_Py_IDENTIFIER(_initializing);
PyObject *value = NULL;
PyObject *spec;
int initializing = 0;
spec = _PyDict_GetItemId(((PyModuleObject *)m)->md_dict, &PyId___spec__);
if (spec != NULL && spec != Py_None) {
value = _PyObject_GetAttrId(spec, &PyId__initializing);
}
if (value == NULL) {
PyErr_Clear();
}
else {
initializing = PyObject_IsTrue(value);
Py_DECREF(value);
if (initializing < 0)
PyErr_Clear();
return initializing > 0;
}
}
return 0;
}

static PyObject*
module_getattro(PyModuleObject *m, PyObject *name)
{
Expand All @@ -718,25 +745,8 @@ module_getattro(PyModuleObject *m, PyObject *name)
_Py_IDENTIFIER(__name__);
mod_name = _PyDict_GetItemId(m->md_dict, &PyId___name__);
if (mod_name && PyUnicode_Check(mod_name)) {
_Py_IDENTIFIER(__spec__);
_Py_IDENTIFIER(_initializing);
PyObject *value = NULL;
PyObject *spec;
int initializing = 0;
Py_INCREF(mod_name);
spec = _PyDict_GetItemId(m->md_dict, &PyId___spec__);
if (spec != NULL && spec != Py_None) {
value = _PyObject_GetAttrId(spec, &PyId__initializing);
}
if (value == NULL)
PyErr_Clear();
else {
initializing = PyObject_IsTrue(value);
Py_DECREF(value);
if (initializing < 0)
PyErr_Clear();
}
if (initializing > 0) {
if (_PyModule_IsInitializing((PyObject *)m)) {
PyErr_Format(PyExc_AttributeError,
"partially initialized "
"module '%U' has no attribute '%U' "
Expand Down
30 changes: 6 additions & 24 deletions Python/import.c
Original file line number Diff line number Diff line change
Expand Up @@ -1720,38 +1720,20 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,

mod = PyImport_GetModule(abs_name);
if (mod != NULL && mod != Py_None) {
_Py_IDENTIFIER(__spec__);
_Py_IDENTIFIER(_initializing);
_Py_IDENTIFIER(_lock_unlock_module);
PyObject *value = NULL;
PyObject *spec;
int initializing = 0;

/* Optimization: only call _bootstrap._lock_unlock_module() if
__spec__._initializing is true.
NOTE: because of this, initializing must be set *before*
stuffing the new module in sys.modules.
*/
spec = _PyObject_GetAttrId(mod, &PyId___spec__);
if (spec != NULL) {
value = _PyObject_GetAttrId(spec, &PyId__initializing);
Py_DECREF(spec);
}
if (value == NULL)
PyErr_Clear();
else {
initializing = PyObject_IsTrue(value);
if (_PyModule_IsInitializing(mod)) {
PyObject *value = _PyObject_CallMethodIdObjArgs(interp->importlib,
&PyId__lock_unlock_module, abs_name,
NULL);
if (value == NULL)
goto error;
Py_DECREF(value);
if (initializing == -1)
PyErr_Clear();
if (initializing > 0) {
value = _PyObject_CallMethodIdObjArgs(interp->importlib,
&PyId__lock_unlock_module, abs_name,
NULL);
if (value == NULL)
goto error;
Py_DECREF(value);
}
}
}
else {
Expand Down

0 comments on commit 770f2f5

Please sign in to comment.