mirror of https://github.com/python/cpython
gh-107954, PEP 741: Add PyInitConfig_AddModule() function (#123668)
This commit is contained in:
parent
7d2c2f24da
commit
0d6b6e34a2
|
@ -1744,6 +1744,26 @@ only implemented when ``Py_InitializeFromInitConfig()`` is called, not by the
|
||||||
* Set an error in *config* and return ``-1`` on error.
|
* Set an error in *config* and return ``-1`` on error.
|
||||||
|
|
||||||
|
|
||||||
|
Module
|
||||||
|
------
|
||||||
|
|
||||||
|
.. c:function:: int PyInitConfig_AddModule(PyInitConfig *config, const char *name, PyObject* (*initfunc)(void))
|
||||||
|
|
||||||
|
Add a built-in extension module to the table of built-in modules.
|
||||||
|
|
||||||
|
The new module can be imported by the name *name*, and uses the function
|
||||||
|
*initfunc* as the initialization function called on the first attempted
|
||||||
|
import.
|
||||||
|
|
||||||
|
* Return ``0`` on success.
|
||||||
|
* Set an error in *config* and return ``-1`` on error.
|
||||||
|
|
||||||
|
If Python is initialized multiple times, ``PyInitConfig_AddModule()`` must
|
||||||
|
be called at each Python initialization.
|
||||||
|
|
||||||
|
Similar to the :c:func:`PyImport_AppendInittab` function.
|
||||||
|
|
||||||
|
|
||||||
Initialize Python
|
Initialize Python
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
|
|
@ -524,6 +524,7 @@ New Features
|
||||||
* :c:func:`PyInitConfig_SetInt`
|
* :c:func:`PyInitConfig_SetInt`
|
||||||
* :c:func:`PyInitConfig_SetStr`
|
* :c:func:`PyInitConfig_SetStr`
|
||||||
* :c:func:`PyInitConfig_SetStrList`
|
* :c:func:`PyInitConfig_SetStrList`
|
||||||
|
* :c:func:`PyInitConfig_AddModule`
|
||||||
* :c:func:`Py_InitializeFromInitConfig`
|
* :c:func:`Py_InitializeFromInitConfig`
|
||||||
|
|
||||||
(Contributed by Victor Stinner in :gh:`107954`.)
|
(Contributed by Victor Stinner in :gh:`107954`.)
|
||||||
|
|
|
@ -313,6 +313,10 @@ PyAPI_FUNC(int) PyInitConfig_SetStrList(PyInitConfig *config,
|
||||||
size_t length,
|
size_t length,
|
||||||
char * const *items);
|
char * const *items);
|
||||||
|
|
||||||
|
PyAPI_FUNC(int) PyInitConfig_AddModule(PyInitConfig *config,
|
||||||
|
const char *name,
|
||||||
|
PyObject* (*initfunc)(void));
|
||||||
|
|
||||||
PyAPI_FUNC(int) Py_InitializeFromInitConfig(PyInitConfig *config);
|
PyAPI_FUNC(int) Py_InitializeFromInitConfig(PyInitConfig *config);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1775,6 +1775,9 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
def test_initconfig_exit(self):
|
def test_initconfig_exit(self):
|
||||||
self.run_embedded_interpreter("test_initconfig_exit")
|
self.run_embedded_interpreter("test_initconfig_exit")
|
||||||
|
|
||||||
|
def test_initconfig_module(self):
|
||||||
|
self.run_embedded_interpreter("test_initconfig_module")
|
||||||
|
|
||||||
def test_get_argc_argv(self):
|
def test_get_argc_argv(self):
|
||||||
self.run_embedded_interpreter("test_get_argc_argv")
|
self.run_embedded_interpreter("test_get_argc_argv")
|
||||||
# ignore output
|
# ignore output
|
||||||
|
|
|
@ -12,6 +12,7 @@ Add functions to configure the Python initialization (:pep:`741`):
|
||||||
* :c:func:`PyInitConfig_SetInt`
|
* :c:func:`PyInitConfig_SetInt`
|
||||||
* :c:func:`PyInitConfig_SetStr`
|
* :c:func:`PyInitConfig_SetStr`
|
||||||
* :c:func:`PyInitConfig_SetStrList`
|
* :c:func:`PyInitConfig_SetStrList`
|
||||||
|
* :c:func:`PyInitConfig_AddModule`
|
||||||
* :c:func:`Py_InitializeFromInitConfig`
|
* :c:func:`Py_InitializeFromInitConfig`
|
||||||
|
|
||||||
Patch by Victor Stinner.
|
Patch by Victor Stinner.
|
||||||
|
|
|
@ -1963,6 +1963,62 @@ static int test_initconfig_exit(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyModuleDef_Slot extension_slots[] = {
|
||||||
|
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
|
||||||
|
{0, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct PyModuleDef extension_module = {
|
||||||
|
PyModuleDef_HEAD_INIT,
|
||||||
|
.m_name = "my_test_extension",
|
||||||
|
.m_size = 0,
|
||||||
|
.m_slots = extension_slots,
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyObject* init_my_test_extension(void)
|
||||||
|
{
|
||||||
|
return PyModuleDef_Init(&extension_module);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int test_initconfig_module(void)
|
||||||
|
{
|
||||||
|
PyInitConfig *config = PyInitConfig_Create();
|
||||||
|
if (config == NULL) {
|
||||||
|
printf("Init allocation error\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PyInitConfig_SetStr(config, "program_name", PROGRAM_NAME_UTF8) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PyInitConfig_AddModule(config, "my_test_extension",
|
||||||
|
init_my_test_extension) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Py_InitializeFromInitConfig(config) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
PyInitConfig_Free(config);
|
||||||
|
|
||||||
|
if (PyRun_SimpleString("import my_test_extension") < 0) {
|
||||||
|
fprintf(stderr, "unable to import my_test_extension\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_Finalize();
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const char *err_msg;
|
||||||
|
error:
|
||||||
|
(void)PyInitConfig_GetError(config, &err_msg);
|
||||||
|
printf("Python init failed: %s\n", err_msg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void configure_init_main(PyConfig *config)
|
static void configure_init_main(PyConfig *config)
|
||||||
{
|
{
|
||||||
wchar_t* argv[] = {
|
wchar_t* argv[] = {
|
||||||
|
@ -2384,6 +2440,7 @@ static struct TestCase TestCases[] = {
|
||||||
{"test_initconfig_api", test_initconfig_api},
|
{"test_initconfig_api", test_initconfig_api},
|
||||||
{"test_initconfig_get_api", test_initconfig_get_api},
|
{"test_initconfig_get_api", test_initconfig_get_api},
|
||||||
{"test_initconfig_exit", test_initconfig_exit},
|
{"test_initconfig_exit", test_initconfig_exit},
|
||||||
|
{"test_initconfig_module", test_initconfig_module},
|
||||||
{"test_run_main", test_run_main},
|
{"test_run_main", test_run_main},
|
||||||
{"test_run_main_loop", test_run_main_loop},
|
{"test_run_main_loop", test_run_main_loop},
|
||||||
{"test_get_argc_argv", test_get_argc_argv},
|
{"test_get_argc_argv", test_get_argc_argv},
|
||||||
|
|
|
@ -3423,6 +3423,8 @@ _Py_DumpPathConfig(PyThreadState *tstate)
|
||||||
struct PyInitConfig {
|
struct PyInitConfig {
|
||||||
PyPreConfig preconfig;
|
PyPreConfig preconfig;
|
||||||
PyConfig config;
|
PyConfig config;
|
||||||
|
struct _inittab *inittab;
|
||||||
|
Py_ssize_t inittab_size;
|
||||||
PyStatus status;
|
PyStatus status;
|
||||||
char *err_msg;
|
char *err_msg;
|
||||||
};
|
};
|
||||||
|
@ -3873,9 +3875,42 @@ PyInitConfig_SetStrList(PyInitConfig *config, const char *name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
PyInitConfig_AddModule(PyInitConfig *config, const char *name,
|
||||||
|
PyObject* (*initfunc)(void))
|
||||||
|
{
|
||||||
|
size_t size = sizeof(struct _inittab) * (config->inittab_size + 2);
|
||||||
|
struct _inittab *new_inittab = PyMem_RawRealloc(config->inittab, size);
|
||||||
|
if (new_inittab == NULL) {
|
||||||
|
config->status = _PyStatus_NO_MEMORY();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
config->inittab = new_inittab;
|
||||||
|
|
||||||
|
struct _inittab *entry = &config->inittab[config->inittab_size];
|
||||||
|
entry->name = name;
|
||||||
|
entry->initfunc = initfunc;
|
||||||
|
|
||||||
|
// Terminator entry
|
||||||
|
entry = &config->inittab[config->inittab_size + 1];
|
||||||
|
entry->name = NULL;
|
||||||
|
entry->initfunc = NULL;
|
||||||
|
|
||||||
|
config->inittab_size++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
Py_InitializeFromInitConfig(PyInitConfig *config)
|
Py_InitializeFromInitConfig(PyInitConfig *config)
|
||||||
{
|
{
|
||||||
|
if (config->inittab_size >= 1) {
|
||||||
|
if (PyImport_ExtendInittab(config->inittab) < 0) {
|
||||||
|
config->status = _PyStatus_NO_MEMORY();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_PyPreConfig_GetConfig(&config->preconfig, &config->config);
|
_PyPreConfig_GetConfig(&config->preconfig, &config->config);
|
||||||
|
|
||||||
config->status = Py_PreInitializeFromArgs(
|
config->status = Py_PreInitializeFromArgs(
|
||||||
|
|
Loading…
Reference in New Issue