diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index 209e48767ccfd6..5830cc77bdd268 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -14,6 +14,9 @@ PyInitConfig C API .. versionadded:: 3.14 +.. versionchanged:: 3.15 + Added to the :ref:`limited C API `. + Python can be initialized with :c:func:`Py_InitializeFromInitConfig`. The :c:func:`Py_RunMain` function can be used to write a customized Python @@ -70,7 +73,7 @@ Mode ` enabled; return ``-1`` on error: Create Config ------------- -.. c:struct:: PyInitConfig +.. c:type:: PyInitConfig Opaque structure to configure the Python initialization. diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 4ae5e999f0bf21..d1943585d46b09 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -363,6 +363,20 @@ func,PyImport_ImportModuleLevel,3.2,, func,PyImport_ImportModuleLevelObject,3.7,, func,PyImport_ReloadModule,3.2,, func,PyIndex_Check,3.8,, +type,PyInitConfig,3.15,,opaque +func,PyInitConfig_AddModule,3.15,, +func,PyInitConfig_Create,3.15,, +func,PyInitConfig_Free,3.15,, +func,PyInitConfig_FreeStrList,3.15,, +func,PyInitConfig_GetError,3.15,, +func,PyInitConfig_GetExitCode,3.15,, +func,PyInitConfig_GetInt,3.15,, +func,PyInitConfig_GetStr,3.15,, +func,PyInitConfig_GetStrList,3.15,, +func,PyInitConfig_HasOption,3.15,, +func,PyInitConfig_SetInt,3.15,, +func,PyInitConfig_SetStr,3.15,, +func,PyInitConfig_SetStrList,3.15,, type,PyInterpreterState,3.2,,opaque func,PyInterpreterState_Clear,3.2,, func,PyInterpreterState_Delete,3.2,, @@ -936,6 +950,7 @@ func,Py_IS_TYPE,3.15,, func,Py_IncRef,3.2,, func,Py_Initialize,3.2,, func,Py_InitializeEx,3.2,, +func,Py_InitializeFromInitConfig,3.15,, func,Py_Is,3.10,, func,Py_IsFalse,3.10,, func,Py_IsFinalizing,3.13,, diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index a687ee5115be05..0b95b70ed3dd7d 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -2068,6 +2068,10 @@ Changed C APIs for ``NULL`` should be updated to call :c:macro:`PyDateTime_IMPORT` instead. (Contributed by Kumar Aditya in :gh:`141563`.) +* The :ref:`PyInitConfig API ` (:pep:`741`) is now part of + the :ref:`limited C API `. + (Contributed by in :gh:`149163`.) + Porting to Python 3.15 ---------------------- diff --git a/Include/Python.h b/Include/Python.h index d5e38b8b0201ee..6fe472168c08e3 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -112,7 +112,7 @@ __pragma(warning(disable: 4201)) #include "sliceobject.h" #include "cpython/cellobject.h" #include "iterobject.h" -#include "cpython/initconfig.h" +#include "initconfig.h" #include "pystate.h" #include "cpython/genobject.h" #include "descrobject.h" diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h index 1ccc496c63ac78..8dfa100f5d38b0 100644 --- a/Include/cpython/initconfig.h +++ b/Include/cpython/initconfig.h @@ -1,6 +1,9 @@ #ifndef Py_PYCORECONFIG_H #define Py_PYCORECONFIG_H -#ifndef Py_LIMITED_API +#ifndef Py_CPYTHON_INITCONFIG_H +# error "this header file must not be included directly" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -284,52 +287,7 @@ PyAPI_FUNC(int) PyConfig_Set(const char *name, PyObject *value); PyAPI_FUNC(void) Py_GetArgcArgv(int *argc, wchar_t ***argv); -// --- PyInitConfig --------------------------------------------------------- - -typedef struct PyInitConfig PyInitConfig; - -PyAPI_FUNC(PyInitConfig*) PyInitConfig_Create(void); -PyAPI_FUNC(void) PyInitConfig_Free(PyInitConfig *config); - -PyAPI_FUNC(int) PyInitConfig_GetError(PyInitConfig* config, - const char **err_msg); -PyAPI_FUNC(int) PyInitConfig_GetExitCode(PyInitConfig* config, - int *exitcode); - -PyAPI_FUNC(int) PyInitConfig_HasOption(PyInitConfig *config, - const char *name); -PyAPI_FUNC(int) PyInitConfig_GetInt(PyInitConfig *config, - const char *name, - int64_t *value); -PyAPI_FUNC(int) PyInitConfig_GetStr(PyInitConfig *config, - const char *name, - char **value); -PyAPI_FUNC(int) PyInitConfig_GetStrList(PyInitConfig *config, - const char *name, - size_t *length, - char ***items); -PyAPI_FUNC(void) PyInitConfig_FreeStrList(size_t length, char **items); - -PyAPI_FUNC(int) PyInitConfig_SetInt(PyInitConfig *config, - const char *name, - int64_t value); -PyAPI_FUNC(int) PyInitConfig_SetStr(PyInitConfig *config, - const char *name, - const char *value); -PyAPI_FUNC(int) PyInitConfig_SetStrList(PyInitConfig *config, - const char *name, - size_t length, - char * const *items); - -PyAPI_FUNC(int) PyInitConfig_AddModule(PyInitConfig *config, - const char *name, - PyObject* (*initfunc)(void)); - -PyAPI_FUNC(int) Py_InitializeFromInitConfig(PyInitConfig *config); - - #ifdef __cplusplus } #endif -#endif /* !Py_LIMITED_API */ #endif /* !Py_PYCORECONFIG_H */ diff --git a/Include/initconfig.h b/Include/initconfig.h new file mode 100644 index 00000000000000..12ed9cd550a0cc --- /dev/null +++ b/Include/initconfig.h @@ -0,0 +1,64 @@ +#ifndef Py_INITCONFIG_H +#define Py_INITCONFIG_H +#ifdef __cplusplus +extern "C" { +#endif + + +// --- PyInitConfig (PEP 741) ----------------------------------------------- + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030f0000 + +typedef struct PyInitConfig PyInitConfig; + +PyAPI_FUNC(PyInitConfig*) PyInitConfig_Create(void); +PyAPI_FUNC(void) PyInitConfig_Free(PyInitConfig *config); + +PyAPI_FUNC(int) PyInitConfig_GetError(PyInitConfig* config, + const char **err_msg); +PyAPI_FUNC(int) PyInitConfig_GetExitCode(PyInitConfig* config, + int *exitcode); + +PyAPI_FUNC(int) PyInitConfig_HasOption(PyInitConfig *config, + const char *name); +PyAPI_FUNC(int) PyInitConfig_GetInt(PyInitConfig *config, + const char *name, + int64_t *value); +PyAPI_FUNC(int) PyInitConfig_GetStr(PyInitConfig *config, + const char *name, + char **value); +PyAPI_FUNC(int) PyInitConfig_GetStrList(PyInitConfig *config, + const char *name, + size_t *length, + char ***items); +PyAPI_FUNC(void) PyInitConfig_FreeStrList(size_t length, char **items); + +PyAPI_FUNC(int) PyInitConfig_SetInt(PyInitConfig *config, + const char *name, + int64_t value); +PyAPI_FUNC(int) PyInitConfig_SetStr(PyInitConfig *config, + const char *name, + const char *value); +PyAPI_FUNC(int) PyInitConfig_SetStrList(PyInitConfig *config, + const char *name, + size_t length, + char * const *items); + +PyAPI_FUNC(int) PyInitConfig_AddModule(PyInitConfig *config, + const char *name, + PyObject* (*initfunc)(void)); + +PyAPI_FUNC(int) Py_InitializeFromInitConfig(PyInitConfig *config); + +#endif + +#ifndef Py_LIMITED_API +# define Py_CPYTHON_INITCONFIG_H +# include "cpython/initconfig.h" +# undef Py_CPYTHON_INITCONFIG_H +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INITCONFIG_H */ diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py index ed0868e0017fce..e931bf3d9a4e9c 100644 --- a/Lib/test/test_stable_abi_ctypes.py +++ b/Lib/test/test_stable_abi_ctypes.py @@ -365,6 +365,19 @@ def test_windows_feature_macros(self): "PyImport_ImportModuleNoBlock", "PyImport_ReloadModule", "PyIndex_Check", + "PyInitConfig_AddModule", + "PyInitConfig_Create", + "PyInitConfig_Free", + "PyInitConfig_FreeStrList", + "PyInitConfig_GetError", + "PyInitConfig_GetExitCode", + "PyInitConfig_GetInt", + "PyInitConfig_GetStr", + "PyInitConfig_GetStrList", + "PyInitConfig_HasOption", + "PyInitConfig_SetInt", + "PyInitConfig_SetStr", + "PyInitConfig_SetStrList", "PyInterpreterState_Clear", "PyInterpreterState_Delete", "PyInterpreterState_Get", @@ -918,6 +931,7 @@ def test_windows_feature_macros(self): "Py_IncRef", "Py_Initialize", "Py_InitializeEx", + "Py_InitializeFromInitConfig", "Py_Is", "Py_IsFalse", "Py_IsFinalizing", diff --git a/Misc/NEWS.d/next/C_API/2026-05-01-01-07-30.gh-issue-149163.GQFvNF.rst b/Misc/NEWS.d/next/C_API/2026-05-01-01-07-30.gh-issue-149163.GQFvNF.rst new file mode 100644 index 00000000000000..f7f4c6abe0ff87 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-05-01-01-07-30.gh-issue-149163.GQFvNF.rst @@ -0,0 +1 @@ +Added the :pep:`741` :c:type:`PyInitConfig` API to the limited C API. diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 101737a27829c9..f052d7fcef7692 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -2715,3 +2715,37 @@ # Note: The `_reserved` member of this struct is for interal use only. # (The definition of 'full-abi' was clarified when this entry was added.) struct_abi_kind = 'full-abi' + +# PEP 741: Python Configuration C API -- added to limited API. + +[struct.PyInitConfig] + added = '3.15' + struct_abi_kind = 'opaque' +[function.PyInitConfig_Create] + added = '3.15' +[function.PyInitConfig_Free] + added = '3.15' +[function.PyInitConfig_GetError] + added = '3.15' +[function.PyInitConfig_GetExitCode] + added = '3.15' +[function.PyInitConfig_HasOption] + added = '3.15' +[function.PyInitConfig_GetInt] + added = '3.15' +[function.PyInitConfig_GetStr] + added = '3.15' +[function.PyInitConfig_GetStrList] + added = '3.15' +[function.PyInitConfig_FreeStrList] + added = '3.15' +[function.PyInitConfig_SetInt] + added = '3.15' +[function.PyInitConfig_SetStr] + added = '3.15' +[function.PyInitConfig_SetStrList] + added = '3.15' +[function.PyInitConfig_AddModule] + added = '3.15' +[function.Py_InitializeFromInitConfig] + added = '3.15' diff --git a/PC/python3dll.c b/PC/python3dll.c index abbe35c342c13e..183c391d0cb1c8 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -70,6 +70,7 @@ EXPORT_FUNC(Py_GetVersion) EXPORT_FUNC(Py_IncRef) EXPORT_FUNC(Py_Initialize) EXPORT_FUNC(Py_InitializeEx) +EXPORT_FUNC(Py_InitializeFromInitConfig) EXPORT_FUNC(Py_Is) EXPORT_FUNC(Py_IS_TYPE) EXPORT_FUNC(Py_IsFalse) @@ -326,6 +327,19 @@ EXPORT_FUNC(PyImport_ImportModuleLevelObject) EXPORT_FUNC(PyImport_ImportModuleNoBlock) EXPORT_FUNC(PyImport_ReloadModule) EXPORT_FUNC(PyIndex_Check) +EXPORT_FUNC(PyInitConfig_AddModule) +EXPORT_FUNC(PyInitConfig_Create) +EXPORT_FUNC(PyInitConfig_Free) +EXPORT_FUNC(PyInitConfig_FreeStrList) +EXPORT_FUNC(PyInitConfig_GetError) +EXPORT_FUNC(PyInitConfig_GetExitCode) +EXPORT_FUNC(PyInitConfig_GetInt) +EXPORT_FUNC(PyInitConfig_GetStr) +EXPORT_FUNC(PyInitConfig_GetStrList) +EXPORT_FUNC(PyInitConfig_HasOption) +EXPORT_FUNC(PyInitConfig_SetInt) +EXPORT_FUNC(PyInitConfig_SetStr) +EXPORT_FUNC(PyInitConfig_SetStrList) EXPORT_FUNC(PyInterpreterState_Clear) EXPORT_FUNC(PyInterpreterState_Delete) EXPORT_FUNC(PyInterpreterState_Get)