mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
PEP 489: Multi-phase extension module initialization
Known limitations of the current implementation: - documentation changes are incomplete - there's a reference leak I haven't tracked down yet The leak is most visible by running: ./python -m test -R3:3 test_importlib However, you can also see it by running: ./python -X showrefcount Importing the array or _testmultiphase modules, and then deleting them from both sys.modules and the local namespace shows significant increases in the total number of active references each cycle. By contrast, with _testcapi (which continues to use single-phase initialisation) the global refcounts stabilise after a couple of cycles.
This commit is contained in:
parent
ec219ba1c0
commit
d5cacbb1d9
34 changed files with 4462 additions and 3124 deletions
|
@ -97,6 +97,15 @@ exit:
|
|||
return return_value;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(_imp_create_builtin__doc__,
|
||||
"create_builtin($module, spec, /)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Create an extension module.");
|
||||
|
||||
#define _IMP_CREATE_BUILTIN_METHODDEF \
|
||||
{"create_builtin", (PyCFunction)_imp_create_builtin, METH_O, _imp_create_builtin__doc__},
|
||||
|
||||
PyDoc_STRVAR(_imp_extension_suffixes__doc__,
|
||||
"extension_suffixes($module, /)\n"
|
||||
"--\n"
|
||||
|
@ -115,32 +124,6 @@ _imp_extension_suffixes(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
|
|||
return _imp_extension_suffixes_impl(module);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(_imp_init_builtin__doc__,
|
||||
"init_builtin($module, name, /)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Initializes a built-in module.");
|
||||
|
||||
#define _IMP_INIT_BUILTIN_METHODDEF \
|
||||
{"init_builtin", (PyCFunction)_imp_init_builtin, METH_O, _imp_init_builtin__doc__},
|
||||
|
||||
static PyObject *
|
||||
_imp_init_builtin_impl(PyModuleDef *module, PyObject *name);
|
||||
|
||||
static PyObject *
|
||||
_imp_init_builtin(PyModuleDef *module, PyObject *arg)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
PyObject *name;
|
||||
|
||||
if (!PyArg_Parse(arg, "U:init_builtin", &name))
|
||||
goto exit;
|
||||
return_value = _imp_init_builtin_impl(module, name);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(_imp_init_frozen__doc__,
|
||||
"init_frozen($module, name, /)\n"
|
||||
"--\n"
|
||||
|
@ -273,31 +256,30 @@ exit:
|
|||
|
||||
#if defined(HAVE_DYNAMIC_LOADING)
|
||||
|
||||
PyDoc_STRVAR(_imp_load_dynamic__doc__,
|
||||
"load_dynamic($module, name, path, file=None, /)\n"
|
||||
PyDoc_STRVAR(_imp_create_dynamic__doc__,
|
||||
"create_dynamic($module, spec, file=None, /)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Loads an extension module.");
|
||||
"Create an extension module.");
|
||||
|
||||
#define _IMP_LOAD_DYNAMIC_METHODDEF \
|
||||
{"load_dynamic", (PyCFunction)_imp_load_dynamic, METH_VARARGS, _imp_load_dynamic__doc__},
|
||||
#define _IMP_CREATE_DYNAMIC_METHODDEF \
|
||||
{"create_dynamic", (PyCFunction)_imp_create_dynamic, METH_VARARGS, _imp_create_dynamic__doc__},
|
||||
|
||||
static PyObject *
|
||||
_imp_load_dynamic_impl(PyModuleDef *module, PyObject *name, PyObject *path,
|
||||
PyObject *file);
|
||||
_imp_create_dynamic_impl(PyModuleDef *module, PyObject *spec, PyObject *file);
|
||||
|
||||
static PyObject *
|
||||
_imp_load_dynamic(PyModuleDef *module, PyObject *args)
|
||||
_imp_create_dynamic(PyModuleDef *module, PyObject *args)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
PyObject *name;
|
||||
PyObject *path;
|
||||
PyObject *spec;
|
||||
PyObject *file = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "UO&|O:load_dynamic",
|
||||
&name, PyUnicode_FSDecoder, &path, &file))
|
||||
if (!PyArg_UnpackTuple(args, "create_dynamic",
|
||||
1, 2,
|
||||
&spec, &file))
|
||||
goto exit;
|
||||
return_value = _imp_load_dynamic_impl(module, name, path, file);
|
||||
return_value = _imp_create_dynamic_impl(module, spec, file);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
|
@ -305,7 +287,42 @@ exit:
|
|||
|
||||
#endif /* defined(HAVE_DYNAMIC_LOADING) */
|
||||
|
||||
#ifndef _IMP_LOAD_DYNAMIC_METHODDEF
|
||||
#define _IMP_LOAD_DYNAMIC_METHODDEF
|
||||
#endif /* !defined(_IMP_LOAD_DYNAMIC_METHODDEF) */
|
||||
/*[clinic end generated code: output=6d75cece35863874 input=a9049054013a1b77]*/
|
||||
#if defined(HAVE_DYNAMIC_LOADING)
|
||||
|
||||
PyDoc_STRVAR(_imp_exec_dynamic__doc__,
|
||||
"exec_dynamic($module, mod, /)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Initialize an extension module.");
|
||||
|
||||
#define _IMP_EXEC_DYNAMIC_METHODDEF \
|
||||
{"exec_dynamic", (PyCFunction)_imp_exec_dynamic, METH_O, _imp_exec_dynamic__doc__},
|
||||
|
||||
static int
|
||||
_imp_exec_dynamic_impl(PyModuleDef *module, PyObject *mod);
|
||||
|
||||
static PyObject *
|
||||
_imp_exec_dynamic(PyModuleDef *module, PyObject *mod)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
int _return_value;
|
||||
|
||||
_return_value = _imp_exec_dynamic_impl(module, mod);
|
||||
if ((_return_value == -1) && PyErr_Occurred())
|
||||
goto exit;
|
||||
return_value = PyLong_FromLong((long)_return_value);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
|
||||
#endif /* defined(HAVE_DYNAMIC_LOADING) */
|
||||
|
||||
#ifndef _IMP_CREATE_DYNAMIC_METHODDEF
|
||||
#define _IMP_CREATE_DYNAMIC_METHODDEF
|
||||
#endif /* !defined(_IMP_CREATE_DYNAMIC_METHODDEF) */
|
||||
|
||||
#ifndef _IMP_EXEC_DYNAMIC_METHODDEF
|
||||
#define _IMP_EXEC_DYNAMIC_METHODDEF
|
||||
#endif /* !defined(_IMP_EXEC_DYNAMIC_METHODDEF) */
|
||||
/*[clinic end generated code: output=0f1059766dd58f88 input=a9049054013a1b77]*/
|
||||
|
|
|
@ -154,8 +154,9 @@ aix_loaderror(const char *pathname)
|
|||
}
|
||||
|
||||
|
||||
dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname,
|
||||
const char *pathname, FILE *fp)
|
||||
dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix,
|
||||
const char *shortname,
|
||||
const char *pathname, FILE *fp)
|
||||
{
|
||||
dl_funcptr p;
|
||||
|
||||
|
|
|
@ -12,11 +12,12 @@ extern char *Py_GetProgramName(void);
|
|||
const char *_PyImport_DynLoadFiletab[] = {".o", NULL};
|
||||
|
||||
|
||||
dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname,
|
||||
const char *pathname, FILE *fp)
|
||||
dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix,
|
||||
const char *shortname,
|
||||
const char *pathname, FILE *fp)
|
||||
{
|
||||
char funcname[258];
|
||||
|
||||
PyOS_snprintf(funcname, sizeof(funcname), "PyInit_%.200s", shortname);
|
||||
PyOS_snprintf(funcname, sizeof(funcname), "%20s_%.200s", prefix, shortname);
|
||||
return dl_loadmod(Py_GetProgramName(), pathname, funcname);
|
||||
}
|
||||
|
|
|
@ -8,15 +8,16 @@
|
|||
#include "importdl.h"
|
||||
|
||||
#if defined(__hp9000s300)
|
||||
#define FUNCNAME_PATTERN "_PyInit_%.200s"
|
||||
#define FUNCNAME_PATTERN "_%20s_%.200s"
|
||||
#else
|
||||
#define FUNCNAME_PATTERN "PyInit_%.200s"
|
||||
#define FUNCNAME_PATTERN "%20s_%.200s"
|
||||
#endif
|
||||
|
||||
const char *_PyImport_DynLoadFiletab[] = {SHLIB_EXT, NULL};
|
||||
|
||||
dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname,
|
||||
const char *pathname, FILE *fp)
|
||||
dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix,
|
||||
const char *shortname,
|
||||
const char *pathname, FILE *fp)
|
||||
{
|
||||
dl_funcptr p;
|
||||
shl_t lib;
|
||||
|
@ -50,7 +51,8 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname,
|
|||
Py_DECREF(pathname_ob);
|
||||
return NULL;
|
||||
}
|
||||
PyOS_snprintf(funcname, sizeof(funcname), FUNCNAME_PATTERN, shortname);
|
||||
PyOS_snprintf(funcname, sizeof(funcname), FUNCNAME_PATTERN,
|
||||
prefix, shortname);
|
||||
if (Py_VerboseFlag)
|
||||
printf("shl_findsym %s\n", funcname);
|
||||
if (shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p) == -1) {
|
||||
|
|
|
@ -27,8 +27,9 @@ const char *_PyImport_DynLoadFiletab[] = {".so", NULL};
|
|||
#define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW| \
|
||||
NSLINKMODULE_OPTION_RETURN_ON_ERROR|NSLINKMODULE_OPTION_PRIVATE
|
||||
#endif
|
||||
dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname,
|
||||
const char *pathname, FILE *fp)
|
||||
dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix,
|
||||
const char *shortname,
|
||||
const char *pathname, FILE *fp)
|
||||
{
|
||||
dl_funcptr p = NULL;
|
||||
char funcname[258];
|
||||
|
@ -39,7 +40,7 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname,
|
|||
const char *errString;
|
||||
char errBuf[512];
|
||||
|
||||
PyOS_snprintf(funcname, sizeof(funcname), "_PyInit_%.200s", shortname);
|
||||
PyOS_snprintf(funcname, sizeof(funcname), "_%20s_%.200s", prefix, shortname);
|
||||
|
||||
#ifdef USE_DYLD_GLOBAL_NAMESPACE
|
||||
if (NSIsSymbolNameDefined(funcname)) {
|
||||
|
|
|
@ -51,8 +51,10 @@ static struct {
|
|||
static int nhandles = 0;
|
||||
|
||||
|
||||
dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname,
|
||||
const char *pathname, FILE *fp)
|
||||
dl_funcptr
|
||||
_PyImport_FindSharedFuncptr(const char *prefix,
|
||||
const char *shortname,
|
||||
const char *pathname, FILE *fp)
|
||||
{
|
||||
dl_funcptr p;
|
||||
void *handle;
|
||||
|
@ -67,7 +69,7 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname,
|
|||
}
|
||||
|
||||
PyOS_snprintf(funcname, sizeof(funcname),
|
||||
LEAD_UNDERSCORE "PyInit_%.200s", shortname);
|
||||
LEAD_UNDERSCORE "%.20s_%.200s", prefix, shortname);
|
||||
|
||||
if (fp != NULL) {
|
||||
int i;
|
||||
|
|
|
@ -186,8 +186,9 @@ static char *GetPythonImport (HINSTANCE hModule)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
dl_funcptr _PyImport_GetDynLoadWindows(const char *shortname,
|
||||
PyObject *pathname, FILE *fp)
|
||||
dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
|
||||
const char *shortname,
|
||||
PyObject *pathname, FILE *fp)
|
||||
{
|
||||
dl_funcptr p;
|
||||
char funcname[258], *import_python;
|
||||
|
@ -201,7 +202,7 @@ dl_funcptr _PyImport_GetDynLoadWindows(const char *shortname,
|
|||
if (wpathname == NULL)
|
||||
return NULL;
|
||||
|
||||
PyOS_snprintf(funcname, sizeof(funcname), "PyInit_%.200s", shortname);
|
||||
PyOS_snprintf(funcname, sizeof(funcname), "%20_%.200s", prefix, shortname);
|
||||
|
||||
{
|
||||
HINSTANCE hDLL = NULL;
|
||||
|
|
189
Python/import.c
189
Python/import.c
|
@ -1026,50 +1026,74 @@ PyImport_GetImporter(PyObject *path) {
|
|||
return importer;
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
_imp.create_builtin
|
||||
|
||||
static int init_builtin(PyObject *); /* Forward */
|
||||
spec: object
|
||||
/
|
||||
|
||||
/* Initialize a built-in module.
|
||||
Return 1 for success, 0 if the module is not found, and -1 with
|
||||
an exception set if the initialization failed. */
|
||||
Create an extension module.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static int
|
||||
init_builtin(PyObject *name)
|
||||
static PyObject *
|
||||
_imp_create_builtin(PyModuleDef *module, PyObject *spec)
|
||||
/*[clinic end generated code: output=5038f467617226bd input=37f966f890384e47]*/
|
||||
{
|
||||
struct _inittab *p;
|
||||
PyObject *name;
|
||||
char *namestr;
|
||||
PyObject *mod;
|
||||
|
||||
name = PyObject_GetAttrString(spec, "name");
|
||||
if (name == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mod = _PyImport_FindExtensionObject(name, name);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
if (mod != NULL)
|
||||
return 1;
|
||||
if (mod || PyErr_Occurred()) {
|
||||
Py_DECREF(name);
|
||||
Py_INCREF(mod);
|
||||
return mod;
|
||||
}
|
||||
|
||||
namestr = PyUnicode_AsUTF8(name);
|
||||
if (namestr == NULL) {
|
||||
Py_DECREF(name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (p = PyImport_Inittab; p->name != NULL; p++) {
|
||||
PyObject *mod;
|
||||
PyModuleDef *def;
|
||||
if (PyUnicode_CompareWithASCIIString(name, p->name) == 0) {
|
||||
if (p->initfunc == NULL) {
|
||||
PyErr_Format(PyExc_ImportError,
|
||||
"Cannot re-init internal module %R",
|
||||
name);
|
||||
return -1;
|
||||
/* Cannot re-init internal module ("sys" or "builtins") */
|
||||
mod = PyImport_AddModule(namestr);
|
||||
Py_DECREF(name);
|
||||
return mod;
|
||||
}
|
||||
mod = (*p->initfunc)();
|
||||
if (mod == 0)
|
||||
return -1;
|
||||
/* Remember pointer to module init function. */
|
||||
def = PyModule_GetDef(mod);
|
||||
def->m_base.m_init = p->initfunc;
|
||||
if (_PyImport_FixupExtensionObject(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;
|
||||
if (mod == NULL) {
|
||||
Py_DECREF(name);
|
||||
return NULL;
|
||||
}
|
||||
if (PyObject_TypeCheck(mod, &PyModuleDef_Type)) {
|
||||
Py_DECREF(name);
|
||||
return PyModule_FromDefAndSpec((PyModuleDef*)mod, spec);
|
||||
} else {
|
||||
/* Remember pointer to module init function. */
|
||||
def = PyModule_GetDef(mod);
|
||||
def->m_base.m_init = p->initfunc;
|
||||
if (_PyImport_FixupExtensionObject(mod, name, name) < 0) {
|
||||
Py_DECREF(name);
|
||||
return NULL;
|
||||
}
|
||||
Py_DECREF(name);
|
||||
return mod;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
Py_DECREF(name);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1820,34 +1844,6 @@ _imp_extension_suffixes_impl(PyModuleDef *module)
|
|||
return list;
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
_imp.init_builtin
|
||||
|
||||
name: unicode
|
||||
/
|
||||
|
||||
Initializes a built-in module.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
_imp_init_builtin_impl(PyModuleDef *module, PyObject *name)
|
||||
/*[clinic end generated code: output=1868f473685f6d67 input=f934d2231ec52a2e]*/
|
||||
{
|
||||
int ret;
|
||||
PyObject *m;
|
||||
|
||||
ret = init_builtin(name);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
if (ret == 0) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
m = PyImport_AddModuleObject(name);
|
||||
Py_XINCREF(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
_imp.init_frozen
|
||||
|
||||
|
@ -1946,40 +1942,100 @@ _imp_is_frozen_impl(PyModuleDef *module, PyObject *name)
|
|||
#ifdef HAVE_DYNAMIC_LOADING
|
||||
|
||||
/*[clinic input]
|
||||
_imp.load_dynamic
|
||||
_imp.create_dynamic
|
||||
|
||||
name: unicode
|
||||
path: fs_unicode
|
||||
spec: object
|
||||
file: object = NULL
|
||||
/
|
||||
|
||||
Loads an extension module.
|
||||
Create an extension module.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
_imp_load_dynamic_impl(PyModuleDef *module, PyObject *name, PyObject *path,
|
||||
PyObject *file)
|
||||
/*[clinic end generated code: output=e84e5f7f0f39bc54 input=af64f06e4bad3526]*/
|
||||
_imp_create_dynamic_impl(PyModuleDef *module, PyObject *spec, PyObject *file)
|
||||
/*[clinic end generated code: output=935cde5b3872d56d input=c31b954f4cf4e09d]*/
|
||||
{
|
||||
PyObject *mod;
|
||||
PyObject *mod, *name, *path;
|
||||
FILE *fp;
|
||||
|
||||
name = PyObject_GetAttrString(spec, "name");
|
||||
if (name == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path = PyObject_GetAttrString(spec, "origin");
|
||||
if (path == NULL) {
|
||||
Py_DECREF(name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mod = _PyImport_FindExtensionObject(name, path);
|
||||
if (mod != NULL) {
|
||||
Py_DECREF(name);
|
||||
Py_DECREF(path);
|
||||
Py_INCREF(mod);
|
||||
return mod;
|
||||
}
|
||||
|
||||
if (file != NULL) {
|
||||
fp = _Py_fopen_obj(path, "r");
|
||||
if (fp == NULL) {
|
||||
Py_DECREF(name);
|
||||
Py_DECREF(path);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
fp = NULL;
|
||||
mod = _PyImport_LoadDynamicModule(name, path, fp);
|
||||
|
||||
mod = _PyImport_LoadDynamicModuleWithSpec(spec, fp);
|
||||
|
||||
Py_DECREF(name);
|
||||
Py_DECREF(path);
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
return mod;
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
_imp.exec_dynamic -> int
|
||||
|
||||
mod: object
|
||||
/
|
||||
|
||||
Initialize an extension module.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static int
|
||||
_imp_exec_dynamic_impl(PyModuleDef *module, PyObject *mod)
|
||||
/*[clinic end generated code: output=4b84f1301b22d4bd input=9fdbfcb250280d3a]*/
|
||||
{
|
||||
PyModuleDef *def;
|
||||
void *state;
|
||||
|
||||
if (!PyModule_Check(mod)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
def = PyModule_GetDef(mod);
|
||||
if (def == NULL) {
|
||||
if (PyErr_Occurred()) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
state = PyModule_GetState(mod);
|
||||
if (PyErr_Occurred()) {
|
||||
return -1;
|
||||
}
|
||||
if (state) {
|
||||
/* Already initialized; skip reload */
|
||||
return 0;
|
||||
}
|
||||
return PyModule_ExecDef(mod, def);
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_DYNAMIC_LOADING */
|
||||
|
||||
/*[clinic input]
|
||||
|
@ -1998,11 +2054,12 @@ static PyMethodDef imp_methods[] = {
|
|||
_IMP_RELEASE_LOCK_METHODDEF
|
||||
_IMP_GET_FROZEN_OBJECT_METHODDEF
|
||||
_IMP_IS_FROZEN_PACKAGE_METHODDEF
|
||||
_IMP_INIT_BUILTIN_METHODDEF
|
||||
_IMP_CREATE_BUILTIN_METHODDEF
|
||||
_IMP_INIT_FROZEN_METHODDEF
|
||||
_IMP_IS_BUILTIN_METHODDEF
|
||||
_IMP_IS_FROZEN_METHODDEF
|
||||
_IMP_LOAD_DYNAMIC_METHODDEF
|
||||
_IMP_CREATE_DYNAMIC_METHODDEF
|
||||
_IMP_EXEC_DYNAMIC_METHODDEF
|
||||
_IMP__FIX_CO_FILENAME_METHODDEF
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
|
|
@ -13,87 +13,186 @@
|
|||
#include "importdl.h"
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
extern dl_funcptr _PyImport_GetDynLoadWindows(const char *shortname,
|
||||
PyObject *pathname, FILE *fp);
|
||||
extern dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
|
||||
const char *shortname,
|
||||
PyObject *pathname,
|
||||
FILE *fp);
|
||||
#else
|
||||
extern dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname,
|
||||
const char *pathname, FILE *fp);
|
||||
extern dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix,
|
||||
const char *shortname,
|
||||
const char *pathname, FILE *fp);
|
||||
#endif
|
||||
|
||||
static const char *ascii_only_prefix = "PyInit";
|
||||
static const char *nonascii_prefix = "PyInitU";
|
||||
|
||||
/* Get the variable part of a module's export symbol name.
|
||||
* Returns a bytes instance. For non-ASCII-named modules, the name is
|
||||
* encoded as per PEP 489.
|
||||
* The hook_prefix pointer is set to either ascii_only_prefix or
|
||||
* nonascii_prefix, as appropriate.
|
||||
*/
|
||||
static PyObject *
|
||||
get_encoded_name(PyObject *name, const char **hook_prefix) {
|
||||
char *buf;
|
||||
PyObject *tmp;
|
||||
PyObject *encoded = NULL;
|
||||
Py_ssize_t name_len, lastdot, i;
|
||||
|
||||
/* Get the short name (substring after last dot) */
|
||||
name_len = PyUnicode_GetLength(name);
|
||||
lastdot = PyUnicode_FindChar(name, '.', 0, name_len, -1);
|
||||
if (lastdot < -1) {
|
||||
return NULL;
|
||||
} else if (lastdot >= 0) {
|
||||
tmp = PyUnicode_Substring(name, lastdot, name_len);
|
||||
if (tmp == NULL)
|
||||
return NULL;
|
||||
name = tmp;
|
||||
/* "name" now holds a new reference to the substring */
|
||||
} else {
|
||||
Py_INCREF(name);
|
||||
}
|
||||
|
||||
/* Encode to ASCII or Punycode, as needed */
|
||||
encoded = PyUnicode_AsEncodedString(name, "ascii", NULL);
|
||||
if (encoded != NULL) {
|
||||
*hook_prefix = ascii_only_prefix;
|
||||
} else {
|
||||
if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) {
|
||||
PyErr_Clear();
|
||||
encoded = PyUnicode_AsEncodedString(name, "punycode", NULL);
|
||||
if (encoded == NULL) {
|
||||
goto error;
|
||||
}
|
||||
*hook_prefix = nonascii_prefix;
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
buf = PyBytes_AS_STRING(encoded);
|
||||
assert(Py_REFCNT(encoded) == 1);
|
||||
for (i = 0; i < PyBytes_GET_SIZE(encoded) + 1; i++) {
|
||||
if (buf[i] == '-') {
|
||||
buf[i] = '_';
|
||||
}
|
||||
}
|
||||
|
||||
Py_DECREF(name);
|
||||
return encoded;
|
||||
error:
|
||||
Py_DECREF(name);
|
||||
Py_XDECREF(encoded);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
_PyImport_LoadDynamicModule(PyObject *name, PyObject *path, FILE *fp)
|
||||
_PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp)
|
||||
{
|
||||
PyObject *m = NULL;
|
||||
#ifndef MS_WINDOWS
|
||||
PyObject *pathbytes;
|
||||
PyObject *pathbytes = NULL;
|
||||
#endif
|
||||
PyObject *nameascii;
|
||||
char *namestr, *lastdot, *shortname, *packagecontext, *oldcontext;
|
||||
dl_funcptr p0;
|
||||
PyObject* (*p)(void);
|
||||
struct PyModuleDef *def;
|
||||
PyObject *name_unicode = NULL, *name = NULL, *path = NULL, *m = NULL;
|
||||
const char *name_buf, *hook_prefix;
|
||||
char *oldcontext;
|
||||
dl_funcptr exportfunc;
|
||||
PyModuleDef *def;
|
||||
PyObject *(*p0)(void);
|
||||
|
||||
m = _PyImport_FindExtensionObject(name, path);
|
||||
if (m != NULL) {
|
||||
Py_INCREF(m);
|
||||
return m;
|
||||
name_unicode = PyObject_GetAttrString(spec, "name");
|
||||
if (name_unicode == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* name must be encodable to ASCII because dynamic module must have a
|
||||
function called "PyInit_NAME", they are written in C, and the C language
|
||||
doesn't accept non-ASCII identifiers. */
|
||||
nameascii = PyUnicode_AsEncodedString(name, "ascii", NULL);
|
||||
if (nameascii == NULL)
|
||||
return NULL;
|
||||
name = get_encoded_name(name_unicode, &hook_prefix);
|
||||
if (name == NULL) {
|
||||
goto error;
|
||||
}
|
||||
name_buf = PyBytes_AS_STRING(name);
|
||||
|
||||
namestr = PyBytes_AS_STRING(nameascii);
|
||||
if (namestr == NULL)
|
||||
path = PyObject_GetAttrString(spec, "origin");
|
||||
if (path == NULL)
|
||||
goto error;
|
||||
|
||||
lastdot = strrchr(namestr, '.');
|
||||
if (lastdot == NULL) {
|
||||
packagecontext = NULL;
|
||||
shortname = namestr;
|
||||
}
|
||||
else {
|
||||
packagecontext = namestr;
|
||||
shortname = lastdot+1;
|
||||
}
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
p0 = _PyImport_GetDynLoadWindows(shortname, path, fp);
|
||||
exportfunc = _PyImport_FindSharedFuncptrWindows(hook_prefix, name_buf,
|
||||
path, fp);
|
||||
#else
|
||||
pathbytes = PyUnicode_EncodeFSDefault(path);
|
||||
if (pathbytes == NULL)
|
||||
goto error;
|
||||
p0 = _PyImport_GetDynLoadFunc(shortname,
|
||||
PyBytes_AS_STRING(pathbytes), fp);
|
||||
exportfunc = _PyImport_FindSharedFuncptr(hook_prefix, name_buf,
|
||||
PyBytes_AS_STRING(pathbytes),
|
||||
fp);
|
||||
Py_DECREF(pathbytes);
|
||||
#endif
|
||||
p = (PyObject*(*)(void))p0;
|
||||
if (PyErr_Occurred())
|
||||
goto error;
|
||||
if (p == NULL) {
|
||||
PyObject *msg = PyUnicode_FromFormat("dynamic module does not define "
|
||||
"init function (PyInit_%s)",
|
||||
shortname);
|
||||
if (msg == NULL)
|
||||
goto error;
|
||||
PyErr_SetImportError(msg, name, path);
|
||||
Py_DECREF(msg);
|
||||
|
||||
if (exportfunc == NULL) {
|
||||
if (!PyErr_Occurred()) {
|
||||
PyObject *msg;
|
||||
msg = PyUnicode_FromFormat(
|
||||
"dynamic module does not define "
|
||||
"module export function (%s_%s)",
|
||||
hook_prefix, name_buf);
|
||||
if (msg == NULL)
|
||||
goto error;
|
||||
PyErr_SetImportError(msg, name_unicode, path);
|
||||
Py_DECREF(msg);
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
oldcontext = _Py_PackageContext;
|
||||
_Py_PackageContext = packagecontext;
|
||||
m = (*p)();
|
||||
_Py_PackageContext = oldcontext;
|
||||
if (m == NULL)
|
||||
goto error;
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
p0 = (PyObject *(*)(void))exportfunc;
|
||||
|
||||
/* Package context is needed for single-phase init */
|
||||
oldcontext = _Py_PackageContext;
|
||||
_Py_PackageContext = PyUnicode_AsUTF8(name_unicode);
|
||||
m = p0();
|
||||
_Py_PackageContext = oldcontext;
|
||||
|
||||
if (m == NULL) {
|
||||
if (!PyErr_Occurred()) {
|
||||
PyErr_Format(
|
||||
PyExc_SystemError,
|
||||
"initialization of %s failed without raising an exception",
|
||||
name_buf);
|
||||
}
|
||||
goto error;
|
||||
} else if (PyErr_Occurred()) {
|
||||
PyErr_Clear();
|
||||
PyErr_Format(
|
||||
PyExc_SystemError,
|
||||
"initialization of %s raised unreported exception",
|
||||
name_buf);
|
||||
m = NULL;
|
||||
goto error;
|
||||
}
|
||||
if (Py_TYPE(m) == NULL) {
|
||||
/* This can happen when a PyModuleDef is returned without calling
|
||||
* PyModuleDef_Init on it
|
||||
*/
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"initialization of %s raised unreported exception",
|
||||
shortname);
|
||||
"init function of %s returned uninitialized object",
|
||||
name_buf);
|
||||
m = NULL; /* prevent segfault in DECREF */
|
||||
goto error;
|
||||
}
|
||||
if (PyObject_TypeCheck(m, &PyModuleDef_Type)) {
|
||||
Py_DECREF(name_unicode);
|
||||
Py_DECREF(name);
|
||||
Py_DECREF(path);
|
||||
return PyModule_FromDefAndSpec((PyModuleDef*)m, spec);
|
||||
}
|
||||
|
||||
/* Fall back to single-phase init mechanism */
|
||||
|
||||
if (hook_prefix == nonascii_prefix) {
|
||||
/* don't allow legacy init for non-ASCII module names */
|
||||
PyErr_Format(
|
||||
PyExc_SystemError,
|
||||
"initialization of * did not return PyModuleDef",
|
||||
name_buf);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -102,10 +201,10 @@ _PyImport_LoadDynamicModule(PyObject *name, PyObject *path, FILE *fp)
|
|||
if (def == NULL) {
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"initialization of %s did not return an extension "
|
||||
"module", shortname);
|
||||
"module", name_buf);
|
||||
goto error;
|
||||
}
|
||||
def->m_base.m_init = p;
|
||||
def->m_base.m_init = p0;
|
||||
|
||||
/* Remember the filename as the __file__ attribute */
|
||||
if (PyModule_AddObject(m, "__file__", path) < 0)
|
||||
|
@ -113,13 +212,19 @@ _PyImport_LoadDynamicModule(PyObject *name, PyObject *path, FILE *fp)
|
|||
else
|
||||
Py_INCREF(path);
|
||||
|
||||
if (_PyImport_FixupExtensionObject(m, name, path) < 0)
|
||||
if (_PyImport_FixupExtensionObject(m, name_unicode, path) < 0)
|
||||
goto error;
|
||||
Py_DECREF(nameascii);
|
||||
|
||||
Py_DECREF(name_unicode);
|
||||
Py_DECREF(name);
|
||||
Py_DECREF(path);
|
||||
|
||||
return m;
|
||||
|
||||
error:
|
||||
Py_DECREF(nameascii);
|
||||
Py_DECREF(name_unicode);
|
||||
Py_XDECREF(name);
|
||||
Py_XDECREF(path);
|
||||
Py_XDECREF(m);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -8,8 +8,7 @@ extern "C" {
|
|||
|
||||
extern const char *_PyImport_DynLoadFiletab[];
|
||||
|
||||
extern PyObject *_PyImport_LoadDynamicModule(PyObject *name, PyObject *pathname,
|
||||
FILE *);
|
||||
extern PyObject *_PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *);
|
||||
|
||||
/* Max length of module suffix searched for -- accommodates "module.slb" */
|
||||
#define MAXSUFFIXSIZE 12
|
||||
|
|
1524
Python/importlib.h
1524
Python/importlib.h
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -255,6 +255,9 @@ PyState_FindModule(struct PyModuleDef* module)
|
|||
Py_ssize_t index = module->m_base.m_index;
|
||||
PyInterpreterState *state = PyThreadState_GET()->interp;
|
||||
PyObject *res;
|
||||
if (module->m_slots) {
|
||||
return NULL;
|
||||
}
|
||||
if (index == 0)
|
||||
return NULL;
|
||||
if (state->modules_by_index == NULL)
|
||||
|
@ -268,7 +271,13 @@ PyState_FindModule(struct PyModuleDef* module)
|
|||
int
|
||||
_PyState_AddModule(PyObject* module, struct PyModuleDef* def)
|
||||
{
|
||||
PyInterpreterState *state = PyThreadState_GET()->interp;
|
||||
PyInterpreterState *state;
|
||||
if (def->m_slots) {
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"PyState_AddModule called on module with slots");
|
||||
return -1;
|
||||
}
|
||||
state = PyThreadState_GET()->interp;
|
||||
if (!def)
|
||||
return -1;
|
||||
if (!state->modules_by_index) {
|
||||
|
@ -308,8 +317,14 @@ PyState_AddModule(PyObject* module, struct PyModuleDef* def)
|
|||
int
|
||||
PyState_RemoveModule(struct PyModuleDef* def)
|
||||
{
|
||||
PyInterpreterState *state;
|
||||
Py_ssize_t index = def->m_base.m_index;
|
||||
PyInterpreterState *state = PyThreadState_GET()->interp;
|
||||
if (def->m_slots) {
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"PyState_RemoveModule called on module with slots");
|
||||
return -1;
|
||||
}
|
||||
state = PyThreadState_GET()->interp;
|
||||
if (index == 0) {
|
||||
Py_FatalError("PyState_RemoveModule: Module index invalid.");
|
||||
return -1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue