diff options
Diffstat (limited to 'Python/import.c')
-rw-r--r-- | Python/import.c | 140 |
1 files changed, 101 insertions, 39 deletions
diff --git a/Python/import.c b/Python/import.c index 31e2401..f1d8188 100644 --- a/Python/import.c +++ b/Python/import.c @@ -541,56 +541,101 @@ PyImport_GetMagicNumber(void) dictionary is stored by calling _PyImport_FixupExtension() immediately after the module initialization function succeeds. A copy can be retrieved from there by calling - _PyImport_FindExtension(). */ + _PyImport_FindExtension(). -PyObject * -_PyImport_FixupExtension(char *name, char *filename) + Modules which do support multiple multiple initialization set + their m_size field to a non-negative number (indicating the size + of the module-specific state). They are still recorded in the + extensions dictionary, to avoid loading shared libraries twice. +*/ + +int +_PyImport_FixupExtension(PyObject *mod, char *name, char *filename) { - PyObject *modules, *mod, *dict, *copy; + PyObject *modules, *dict; + struct PyModuleDef *def; if (extensions == NULL) { extensions = PyDict_New(); if (extensions == NULL) - return NULL; + return -1; } - modules = PyImport_GetModuleDict(); - mod = PyDict_GetItemString(modules, name); if (mod == NULL || !PyModule_Check(mod)) { - PyErr_Format(PyExc_SystemError, - "_PyImport_FixupExtension: module %.200s not loaded", name); - return NULL; + PyErr_BadInternalCall(); + return -1; } - dict = PyModule_GetDict(mod); - if (dict == NULL) - return NULL; - copy = PyDict_Copy(dict); - if (copy == NULL) - return NULL; - PyDict_SetItemString(extensions, filename, copy); - Py_DECREF(copy); - return copy; + def = PyModule_GetDef(mod); + if (!def) { + PyErr_BadInternalCall(); + return -1; + } + modules = PyImport_GetModuleDict(); + if (PyDict_SetItemString(modules, name, mod) < 0) + return -1; + if (_PyState_AddModule(mod, def) < 0) { + PyDict_DelItemString(modules, name); + return -1; + } + if (def->m_size == -1) { + if (def->m_base.m_copy) { + /* Somebody already imported the module, + likely under a different name. + XXX this should really not happen. */ + Py_DECREF(def->m_base.m_copy); + def->m_base.m_copy = NULL; + } + dict = PyModule_GetDict(mod); + if (dict == NULL) + return -1; + def->m_base.m_copy = PyDict_Copy(dict); + if (def->m_base.m_copy == NULL) + return -1; + } + PyDict_SetItemString(extensions, filename, (PyObject*)def); + return 0; } PyObject * _PyImport_FindExtension(char *name, char *filename) { - PyObject *dict, *mod, *mdict; + PyObject *mod, *mdict; + PyModuleDef* def; if (extensions == NULL) return NULL; - dict = PyDict_GetItemString(extensions, filename); - if (dict == NULL) - return NULL; - mod = PyImport_AddModule(name); - if (mod == NULL) + def = (PyModuleDef*)PyDict_GetItemString(extensions, filename); + if (def == NULL) return NULL; - mdict = PyModule_GetDict(mod); - if (mdict == NULL) - return NULL; - if (PyDict_Update(mdict, dict)) + if (def->m_size == -1) { + /* Module does not support repeated initialization */ + if (def->m_base.m_copy == NULL) + return NULL; + mod = PyImport_AddModule(name); + if (mod == NULL) + return NULL; + Py_INCREF(mod); + mdict = PyModule_GetDict(mod); + if (mdict == NULL) + return NULL; + if (PyDict_Update(mdict, def->m_base.m_copy)) + return NULL; + } + else { + if (def->m_base.m_init == NULL) + return NULL; + mod = def->m_base.m_init(); + if (mod == NULL) + return NULL; + PyDict_SetItemString(PyImport_GetModuleDict(), name, mod); + } + if (_PyState_AddModule(mod, def) < 0) { + PyDict_DelItemString(PyImport_GetModuleDict(), name); + Py_DECREF(mod); return NULL; + } if (Py_VerboseFlag) PySys_WriteStderr("import %s # previously loaded (%s)\n", - name, filename); + name, filename); return mod; + } @@ -1801,6 +1846,7 @@ init_builtin(char *name) return 1; for (p = PyImport_Inittab; p->name != NULL; p++) { + PyObject *mod; if (strcmp(name, p->name) == 0) { if (p->initfunc == NULL) { PyErr_Format(PyExc_ImportError, @@ -1810,11 +1856,14 @@ init_builtin(char *name) } if (Py_VerboseFlag) PySys_WriteStderr("import %s # builtin\n", name); - (*p->initfunc)(); - if (PyErr_Occurred()) + mod = (*p->initfunc)(); + if (mod == 0) return -1; - if (_PyImport_FixupExtension(name, name) == NULL) + if (_PyImport_FixupExtension(mod, name, name) < 0) return -1; + /* FixupExtension has put the module into sys.modules, + so we can release our own reference. */ + Py_DECREF(mod); return 1; } } @@ -3200,17 +3249,27 @@ PyTypeObject PyNullImporter_Type = { PyType_GenericNew /* tp_new */ }; +static struct PyModuleDef impmodule = { + PyModuleDef_HEAD_INIT, + "imp", + doc_imp, + 0, + imp_methods, + NULL, + NULL, + NULL, + NULL +}; PyMODINIT_FUNC -initimp(void) +PyInit_imp(void) { PyObject *m, *d; if (PyType_Ready(&PyNullImporter_Type) < 0) - goto failure; + return NULL; - m = Py_InitModule4("imp", imp_methods, doc_imp, - NULL, PYTHON_API_VERSION); + m = PyModule_Create(&impmodule); if (m == NULL) goto failure; d = PyModule_GetDict(m); @@ -3230,8 +3289,11 @@ initimp(void) Py_INCREF(&PyNullImporter_Type); PyModule_AddObject(m, "NullImporter", (PyObject *)&PyNullImporter_Type); + return m; failure: - ; + Py_XDECREF(m); + return NULL; + } @@ -3275,7 +3337,7 @@ PyImport_ExtendInittab(struct _inittab *newtab) /* Shorthand to add a single entry given a name and a function */ int -PyImport_AppendInittab(char *name, void (*initfunc)(void)) +PyImport_AppendInittab(char *name, PyObject* (*initfunc)(void)) { struct _inittab newtab[2]; |