bpo-36763: Implement the PEP 587 (GH-13592)

* Add a whole new documentation page:
  "Python Initialization Configuration"
* PyWideStringList_Append() return type is now PyStatus,
  instead of int
* PyInterpreterState_New() now calls PyConfig_Clear() if
  PyConfig_InitPythonConfig() fails.
* Rename files:

  * Python/coreconfig.c => Python/initconfig.c
  * Include/cpython/coreconfig.h => Include/cpython/initconfig.h
  * Include/internal/: pycore_coreconfig.h => pycore_initconfig.h

* Rename structures

  * _PyCoreConfig => PyConfig
  * _PyPreConfig => PyPreConfig
  * _PyInitError => PyStatus
  * _PyWstrList => PyWideStringList

* Rename PyConfig fields:

  * use_module_search_paths => module_search_paths_set
  * module_search_path_env => pythonpath_env

* Rename PyStatus field: _func => func
* PyInterpreterState: rename core_config field to config
* Rename macros and functions:

  * _PyCoreConfig_SetArgv() => PyConfig_SetBytesArgv()
  * _PyCoreConfig_SetWideArgv() => PyConfig_SetArgv()
  * _PyCoreConfig_DecodeLocale() => PyConfig_SetBytesString()
  * _PyInitError_Failed() => PyStatus_Exception()
  * _Py_INIT_ERROR_TYPE_xxx enums => _PyStatus_TYPE_xxx
  * _Py_UnixMain() => Py_BytesMain()
  * _Py_ExitInitError() => Py_ExitStatusException()
  * _Py_PreInitializeFromArgs() => Py_PreInitializeFromBytesArgs()
  * _Py_PreInitializeFromWideArgs() => Py_PreInitializeFromArgs()
  * _Py_PreInitialize() => Py_PreInitialize()
  * _Py_RunMain() => Py_RunMain()
  * _Py_InitializeFromConfig() => Py_InitializeFromConfig()
  * _Py_INIT_XXX() => _PyStatus_XXX()
  * _Py_INIT_FAILED() => _PyStatus_EXCEPTION()

* Rename 'err' PyStatus variables to 'status'
* Convert RUN_CODE() macro to config_run_code() static inline function
* Remove functions:

  * _Py_InitializeFromArgs()
  * _Py_InitializeFromWideArgs()
  * _PyInterpreterState_GetCoreConfig()
This commit is contained in:
Victor Stinner 2019-05-27 16:39:22 +02:00 committed by GitHub
parent 8cd5165ba0
commit 331a6a56e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
50 changed files with 3229 additions and 2165 deletions

View file

@ -1,5 +1,5 @@
#include "Python.h"
#include "pycore_coreconfig.h"
#include "pycore_initconfig.h"
#include "pycore_getopt.h"
#include "pycore_pystate.h" /* _PyRuntime_Initialize() */
#include <locale.h> /* setlocale() */
@ -7,8 +7,13 @@
#define DECODE_LOCALE_ERR(NAME, LEN) \
(((LEN) == -2) \
? _Py_INIT_ERR("cannot decode " NAME) \
: _Py_INIT_NO_MEMORY())
? _PyStatus_ERR("cannot decode " NAME) \
: _PyStatus_NO_MEMORY())
/* Forward declarations */
static void
preconfig_copy(PyPreConfig *config, const PyPreConfig *config2);
/* --- File system encoding/errors -------------------------------- */
@ -67,22 +72,22 @@ _Py_SetFileSystemEncoding(const char *encoding, const char *errors)
/* --- _PyArgv ---------------------------------------------------- */
/* Decode bytes_argv using Py_DecodeLocale() */
_PyInitError
_PyArgv_AsWstrList(const _PyArgv *args, _PyWstrList *list)
PyStatus
_PyArgv_AsWstrList(const _PyArgv *args, PyWideStringList *list)
{
_PyWstrList wargv = _PyWstrList_INIT;
PyWideStringList wargv = PyWideStringList_INIT;
if (args->use_bytes_argv) {
size_t size = sizeof(wchar_t*) * args->argc;
wargv.items = (wchar_t **)PyMem_RawMalloc(size);
if (wargv.items == NULL) {
return _Py_INIT_NO_MEMORY();
return _PyStatus_NO_MEMORY();
}
for (Py_ssize_t i = 0; i < args->argc; i++) {
size_t len;
wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len);
if (arg == NULL) {
_PyWstrList_Clear(&wargv);
_PyWideStringList_Clear(&wargv);
return DECODE_LOCALE_ERR("command line arguments",
(Py_ssize_t)len);
}
@ -90,17 +95,17 @@ _PyArgv_AsWstrList(const _PyArgv *args, _PyWstrList *list)
wargv.length++;
}
_PyWstrList_Clear(list);
_PyWideStringList_Clear(list);
*list = wargv;
}
else {
wargv.length = args->argc;
wargv.items = (wchar_t **)args->wchar_argv;
if (_PyWstrList_Copy(list, &wargv) < 0) {
return _Py_INIT_NO_MEMORY();
if (_PyWideStringList_Copy(list, &wargv) < 0) {
return _PyStatus_NO_MEMORY();
}
}
return _Py_INIT_OK();
return _PyStatus_OK();
}
@ -109,12 +114,12 @@ _PyArgv_AsWstrList(const _PyArgv *args, _PyWstrList *list)
void
_PyPreCmdline_Clear(_PyPreCmdline *cmdline)
{
_PyWstrList_Clear(&cmdline->argv);
_PyWstrList_Clear(&cmdline->xoptions);
_PyWideStringList_Clear(&cmdline->argv);
_PyWideStringList_Clear(&cmdline->xoptions);
}
_PyInitError
PyStatus
_PyPreCmdline_SetArgv(_PyPreCmdline *cmdline, const _PyArgv *args)
{
return _PyArgv_AsWstrList(args, &cmdline->argv);
@ -122,7 +127,7 @@ _PyPreCmdline_SetArgv(_PyPreCmdline *cmdline, const _PyArgv *args)
static void
_PyPreCmdline_GetPreConfig(_PyPreCmdline *cmdline, const _PyPreConfig *config)
precmdline_get_preconfig(_PyPreCmdline *cmdline, const PyPreConfig *config)
{
#define COPY_ATTR(ATTR) \
if (config->ATTR != -1) { \
@ -138,7 +143,7 @@ _PyPreCmdline_GetPreConfig(_PyPreCmdline *cmdline, const _PyPreConfig *config)
static void
_PyPreCmdline_SetPreConfig(const _PyPreCmdline *cmdline, _PyPreConfig *config)
precmdline_set_preconfig(const _PyPreCmdline *cmdline, PyPreConfig *config)
{
#define COPY_ATTR(ATTR) \
config->ATTR = cmdline->ATTR
@ -151,33 +156,34 @@ _PyPreCmdline_SetPreConfig(const _PyPreCmdline *cmdline, _PyPreConfig *config)
}
int
_PyPreCmdline_SetCoreConfig(const _PyPreCmdline *cmdline, _PyCoreConfig *config)
PyStatus
_PyPreCmdline_SetConfig(const _PyPreCmdline *cmdline, PyConfig *config)
{
#define COPY_ATTR(ATTR) \
config->ATTR = cmdline->ATTR
if (_PyWstrList_Extend(&config->xoptions, &cmdline->xoptions) < 0) {
return -1;
PyStatus status = _PyWideStringList_Extend(&config->xoptions, &cmdline->xoptions);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
COPY_ATTR(isolated);
COPY_ATTR(use_environment);
COPY_ATTR(dev_mode);
return 0;
return _PyStatus_OK();
#undef COPY_ATTR
}
/* Parse the command line arguments */
static _PyInitError
static PyStatus
precmdline_parse_cmdline(_PyPreCmdline *cmdline)
{
const _PyWstrList *argv = &cmdline->argv;
const PyWideStringList *argv = &cmdline->argv;
_PyOS_ResetGetOpt();
/* Don't log parsing errors into stderr here: _PyCoreConfig_Read()
/* Don't log parsing errors into stderr here: PyConfig_Read()
is responsible for that */
_PyOS_opterr = 0;
do {
@ -199,32 +205,34 @@ precmdline_parse_cmdline(_PyPreCmdline *cmdline)
case 'X':
{
if (_PyWstrList_Append(&cmdline->xoptions, _PyOS_optarg) < 0) {
return _Py_INIT_NO_MEMORY();
PyStatus status = PyWideStringList_Append(&cmdline->xoptions,
_PyOS_optarg);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
break;
}
default:
/* ignore other argument:
handled by _PyCoreConfig_Read() */
handled by PyConfig_Read() */
break;
}
} while (1);
return _Py_INIT_OK();
return _PyStatus_OK();
}
_PyInitError
_PyPreCmdline_Read(_PyPreCmdline *cmdline, const _PyPreConfig *preconfig)
PyStatus
_PyPreCmdline_Read(_PyPreCmdline *cmdline, const PyPreConfig *preconfig)
{
_PyPreCmdline_GetPreConfig(cmdline, preconfig);
precmdline_get_preconfig(cmdline, preconfig);
if (preconfig->parse_argv) {
_PyInitError err = precmdline_parse_cmdline(cmdline);
if (_Py_INIT_FAILED(err)) {
return err;
PyStatus status = precmdline_parse_cmdline(cmdline);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
}
@ -254,15 +262,15 @@ _PyPreCmdline_Read(_PyPreCmdline *cmdline, const _PyPreConfig *preconfig)
assert(cmdline->isolated >= 0);
assert(cmdline->dev_mode >= 0);
return _Py_INIT_OK();
return _PyStatus_OK();
}
/* --- _PyPreConfig ----------------------------------------------- */
/* --- PyPreConfig ----------------------------------------------- */
void
_PyPreConfig_InitCompatConfig(_PyPreConfig *config)
_PyPreConfig_InitCompatConfig(PyPreConfig *config)
{
memset(config, 0, sizeof(*config));
@ -291,7 +299,7 @@ _PyPreConfig_InitCompatConfig(_PyPreConfig *config)
void
_PyPreConfig_InitPythonConfig(_PyPreConfig *config)
PyPreConfig_InitPythonConfig(PyPreConfig *config)
{
_PyPreConfig_InitCompatConfig(config);
@ -312,7 +320,7 @@ _PyPreConfig_InitPythonConfig(_PyPreConfig *config)
void
_PyPreConfig_InitIsolatedConfig(_PyPreConfig *config)
PyPreConfig_InitIsolatedConfig(PyPreConfig *config)
{
_PyPreConfig_InitCompatConfig(config);
@ -329,37 +337,37 @@ _PyPreConfig_InitIsolatedConfig(_PyPreConfig *config)
void
_PyPreConfig_InitFromPreConfig(_PyPreConfig *config,
const _PyPreConfig *config2)
_PyPreConfig_InitFromPreConfig(PyPreConfig *config,
const PyPreConfig *config2)
{
_PyPreConfig_InitCompatConfig(config);
_PyPreConfig_Copy(config, config2);
PyPreConfig_InitPythonConfig(config);
preconfig_copy(config, config2);
}
void
_PyPreConfig_InitFromCoreConfig(_PyPreConfig *config,
const _PyCoreConfig *coreconfig)
_PyPreConfig_InitFromConfig(PyPreConfig *preconfig, const PyConfig *config)
{
_PyConfigInitEnum config_init = (_PyConfigInitEnum)coreconfig->_config_init;
_PyConfigInitEnum config_init = (_PyConfigInitEnum)config->_config_init;
switch (config_init) {
case _PyConfig_INIT_PYTHON:
_PyPreConfig_InitPythonConfig(config);
PyPreConfig_InitPythonConfig(preconfig);
break;
case _PyConfig_INIT_ISOLATED:
_PyPreConfig_InitIsolatedConfig(config);
PyPreConfig_InitIsolatedConfig(preconfig);
break;
case _PyConfig_INIT_COMPAT:
default:
_PyPreConfig_InitCompatConfig(config);
_PyPreConfig_InitCompatConfig(preconfig);
}
_PyPreConfig_GetCoreConfig(config, coreconfig);
_PyPreConfig_GetConfig(preconfig, config);
}
void
_PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2)
static void
preconfig_copy(PyPreConfig *config, const PyPreConfig *config2)
{
assert(config2->_config_version == _Py_CONFIG_VERSION);
#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
COPY_ATTR(_config_init);
@ -381,7 +389,7 @@ _PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2)
PyObject*
_PyPreConfig_AsDict(const _PyPreConfig *config)
_PyPreConfig_AsDict(const PyPreConfig *config)
{
PyObject *dict;
@ -427,12 +435,11 @@ fail:
void
_PyPreConfig_GetCoreConfig(_PyPreConfig *config,
const _PyCoreConfig *core_config)
_PyPreConfig_GetConfig(PyPreConfig *preconfig, const PyConfig *config)
{
#define COPY_ATTR(ATTR) \
if (core_config->ATTR != -1) { \
config->ATTR = core_config->ATTR; \
if (config->ATTR != -1) { \
preconfig->ATTR = config->ATTR; \
}
COPY_ATTR(parse_argv);
@ -445,7 +452,7 @@ _PyPreConfig_GetCoreConfig(_PyPreConfig *config,
static void
_PyPreConfig_GetGlobalConfig(_PyPreConfig *config)
preconfig_get_global_vars(PyPreConfig *config)
{
if (config->_config_init != _PyConfig_INIT_COMPAT) {
/* Python and Isolated configuration ignore global variables */
@ -476,7 +483,7 @@ _PyPreConfig_GetGlobalConfig(_PyPreConfig *config)
static void
_PyPreConfig_SetGlobalConfig(const _PyPreConfig *config)
preconfig_set_global_vars(const PyPreConfig *config)
{
#define COPY_FLAG(ATTR, VAR) \
if (config->ATTR >= 0) { \
@ -555,7 +562,7 @@ _Py_get_env_flag(int use_environment, int *flag, const char *name)
const wchar_t*
_Py_get_xoption(const _PyWstrList *xoptions, const wchar_t *name)
_Py_get_xoption(const PyWideStringList *xoptions, const wchar_t *name)
{
for (Py_ssize_t i=0; i < xoptions->length; i++) {
const wchar_t *option = xoptions->items[i];
@ -575,8 +582,8 @@ _Py_get_xoption(const _PyWstrList *xoptions, const wchar_t *name)
}
static _PyInitError
preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline)
static PyStatus
preconfig_init_utf8_mode(PyPreConfig *config, const _PyPreCmdline *cmdline)
{
#ifdef MS_WINDOWS
if (config->legacy_windows_fs_encoding) {
@ -585,7 +592,7 @@ preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline)
#endif
if (config->utf8_mode >= 0) {
return _Py_INIT_OK();
return _PyStatus_OK();
}
const wchar_t *xopt;
@ -601,13 +608,13 @@ preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline)
config->utf8_mode = 0;
}
else {
return _Py_INIT_ERR("invalid -X utf8 option value");
return _PyStatus_ERR("invalid -X utf8 option value");
}
}
else {
config->utf8_mode = 1;
}
return _Py_INIT_OK();
return _PyStatus_OK();
}
const char *opt = _Py_GetEnv(config->use_environment, "PYTHONUTF8");
@ -619,10 +626,10 @@ preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline)
config->utf8_mode = 0;
}
else {
return _Py_INIT_ERR("invalid PYTHONUTF8 environment "
return _PyStatus_ERR("invalid PYTHONUTF8 environment "
"variable value");
}
return _Py_INIT_OK();
return _PyStatus_OK();
}
@ -642,12 +649,12 @@ preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline)
if (config->utf8_mode < 0) {
config->utf8_mode = 0;
}
return _Py_INIT_OK();
return _PyStatus_OK();
}
static void
preconfig_init_coerce_c_locale(_PyPreConfig *config)
preconfig_init_coerce_c_locale(PyPreConfig *config)
{
if (!config->configure_locale) {
config->coerce_c_locale = 0;
@ -693,8 +700,8 @@ preconfig_init_coerce_c_locale(_PyPreConfig *config)
}
static _PyInitError
preconfig_init_allocator(_PyPreConfig *config)
static PyStatus
preconfig_init_allocator(PyPreConfig *config)
{
if (config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
/* bpo-34247. The PYTHONMALLOC environment variable has the priority
@ -705,7 +712,7 @@ preconfig_init_allocator(_PyPreConfig *config)
if (envvar) {
PyMemAllocatorName name;
if (_PyMem_GetAllocatorName(envvar, &name) < 0) {
return _Py_INIT_ERR("PYTHONMALLOC: unknown allocator");
return _PyStatus_ERR("PYTHONMALLOC: unknown allocator");
}
config->allocator = (int)name;
}
@ -714,21 +721,21 @@ preconfig_init_allocator(_PyPreConfig *config)
if (config->dev_mode && config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
config->allocator = PYMEM_ALLOCATOR_DEBUG;
}
return _Py_INIT_OK();
return _PyStatus_OK();
}
static _PyInitError
preconfig_read(_PyPreConfig *config, _PyPreCmdline *cmdline)
static PyStatus
preconfig_read(PyPreConfig *config, _PyPreCmdline *cmdline)
{
_PyInitError err;
PyStatus status;
err = _PyPreCmdline_Read(cmdline, config);
if (_Py_INIT_FAILED(err)) {
return err;
status = _PyPreCmdline_Read(cmdline, config);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
_PyPreCmdline_SetPreConfig(cmdline, config);
precmdline_set_preconfig(cmdline, config);
/* legacy_windows_fs_encoding, coerce_c_locale, utf8_mode */
#ifdef MS_WINDOWS
@ -739,15 +746,15 @@ preconfig_read(_PyPreConfig *config, _PyPreCmdline *cmdline)
preconfig_init_coerce_c_locale(config);
err = preconfig_init_utf8_mode(config, cmdline);
if (_Py_INIT_FAILED(err)) {
return err;
status = preconfig_init_utf8_mode(config, cmdline);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
/* allocator */
err = preconfig_init_allocator(config);
if (_Py_INIT_FAILED(err)) {
return err;
status = preconfig_init_allocator(config);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
assert(config->coerce_c_locale >= 0);
@ -760,7 +767,7 @@ preconfig_read(_PyPreConfig *config, _PyPreCmdline *cmdline)
assert(config->use_environment >= 0);
assert(config->dev_mode >= 0);
return _Py_INIT_OK();
return _PyStatus_OK();
}
@ -770,30 +777,30 @@ preconfig_read(_PyPreConfig *config, _PyPreCmdline *cmdline)
- environment variables
- Py_xxx global configuration variables
- the LC_CTYPE locale */
_PyInitError
_PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args)
PyStatus
_PyPreConfig_Read(PyPreConfig *config, const _PyArgv *args)
{
_PyInitError err;
PyStatus status;
err = _PyRuntime_Initialize();
if (_Py_INIT_FAILED(err)) {
return err;
status = _PyRuntime_Initialize();
if (_PyStatus_EXCEPTION(status)) {
return status;
}
_PyPreConfig_GetGlobalConfig(config);
preconfig_get_global_vars(config);
/* Copy LC_CTYPE locale, since it's modified later */
const char *loc = setlocale(LC_CTYPE, NULL);
if (loc == NULL) {
return _Py_INIT_ERR("failed to LC_CTYPE locale");
return _PyStatus_ERR("failed to LC_CTYPE locale");
}
char *init_ctype_locale = _PyMem_RawStrdup(loc);
if (init_ctype_locale == NULL) {
return _Py_INIT_NO_MEMORY();
return _PyStatus_NO_MEMORY();
}
/* Save the config to be able to restore it if encodings change */
_PyPreConfig save_config;
PyPreConfig save_config;
_PyPreConfig_InitFromPreConfig(&save_config, config);
/* Set LC_CTYPE to the user preferred locale */
@ -808,8 +815,8 @@ _PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args)
#endif
if (args) {
err = _PyPreCmdline_SetArgv(&cmdline, args);
if (_Py_INIT_FAILED(err)) {
status = _PyPreCmdline_SetArgv(&cmdline, args);
if (_PyStatus_EXCEPTION(status)) {
goto done;
}
}
@ -823,7 +830,7 @@ _PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args)
/* Watchdog to prevent an infinite loop */
loops++;
if (loops == 3) {
err = _Py_INIT_ERR("Encoding changed twice while "
status = _PyStatus_ERR("Encoding changed twice while "
"reading the configuration");
goto done;
}
@ -835,8 +842,8 @@ _PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args)
Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding;
#endif
err = preconfig_read(config, &cmdline);
if (_Py_INIT_FAILED(err)) {
status = preconfig_read(config, &cmdline);
if (_PyStatus_EXCEPTION(status)) {
goto done;
}
@ -877,14 +884,14 @@ _PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args)
just keep UTF-8 Mode value. */
int new_utf8_mode = config->utf8_mode;
int new_coerce_c_locale = config->coerce_c_locale;
_PyPreConfig_Copy(config, &save_config);
preconfig_copy(config, &save_config);
config->utf8_mode = new_utf8_mode;
config->coerce_c_locale = new_coerce_c_locale;
/* The encoding changed: read again the configuration
with the new encoding */
}
err = _Py_INIT_OK();
status = _PyStatus_OK();
done:
if (init_ctype_locale != NULL) {
@ -896,7 +903,7 @@ done:
Py_LegacyWindowsFSEncodingFlag = init_legacy_encoding;
#endif
_PyPreCmdline_Clear(&cmdline);
return err;
return status;
}
@ -912,26 +919,26 @@ done:
Do nothing if called after Py_Initialize(): ignore the new
pre-configuration. */
_PyInitError
_PyPreConfig_Write(const _PyPreConfig *src_config)
PyStatus
_PyPreConfig_Write(const PyPreConfig *src_config)
{
_PyPreConfig config;
PyPreConfig config;
_PyPreConfig_InitFromPreConfig(&config, src_config);
if (_PyRuntime.core_initialized) {
/* bpo-34008: Calling this functions after Py_Initialize() ignores
the new configuration. */
return _Py_INIT_OK();
return _PyStatus_OK();
}
PyMemAllocatorName name = (PyMemAllocatorName)config.allocator;
if (name != PYMEM_ALLOCATOR_NOT_SET) {
if (_PyMem_SetupAllocators(name) < 0) {
return _Py_INIT_ERR("Unknown PYTHONMALLOC allocator");
return _PyStatus_ERR("Unknown PYTHONMALLOC allocator");
}
}
_PyPreConfig_SetGlobalConfig(&config);
preconfig_set_global_vars(&config);
if (config.configure_locale) {
if (config.coerce_c_locale) {
@ -946,7 +953,7 @@ _PyPreConfig_Write(const _PyPreConfig *src_config)
}
/* Write the new pre-configuration into _PyRuntime */
_PyPreConfig_Copy(&_PyRuntime.preconfig, &config);
preconfig_copy(&_PyRuntime.preconfig, &config);
return _Py_INIT_OK();
return _PyStatus_OK();
}