summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/internal/pycore_coreconfig.h10
-rw-r--r--Include/internal/pycore_getopt.h3
-rw-r--r--Modules/main.c40
-rw-r--r--Python/coreconfig.c95
-rw-r--r--Python/getopt.c15
-rw-r--r--Python/pathconfig.c2
-rw-r--r--Python/preconfig.c94
-rw-r--r--Python/pylifecycle.c2
8 files changed, 209 insertions, 52 deletions
diff --git a/Include/internal/pycore_coreconfig.h b/Include/internal/pycore_coreconfig.h
index 6469fca..5135969 100644
--- a/Include/internal/pycore_coreconfig.h
+++ b/Include/internal/pycore_coreconfig.h
@@ -44,12 +44,13 @@ PyAPI_FUNC(void) _PyPreConfig_SetGlobalConfig(const _PyPreConfig *config);
PyAPI_FUNC(_PyInitError) _PyPreConfig_Read(_PyPreConfig *config);
PyAPI_FUNC(int) _PyPreConfig_AsDict(const _PyPreConfig *config,
PyObject *dict);
-
+PyAPI_FUNC(_PyInitError) _PyPreConfig_ReadFromArgv(_PyPreConfig *config,
+ const _PyArgv *args);
+PyAPI_FUNC(void) _PyPreConfig_Write(const _PyPreConfig *config);
/* --- _PyCoreConfig ---------------------------------------------- */
-PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config);
PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *);
PyAPI_FUNC(int) _PyCoreConfig_Copy(
_PyCoreConfig *config,
@@ -67,8 +68,11 @@ PyAPI_FUNC(int) _PyCoreConfig_GetEnvDup(
wchar_t **dest,
wchar_t *wname,
char *name);
+PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config,
+ const _PyPreConfig *preconfig);
PyAPI_FUNC(_PyInitError) _PyCoreConfig_ReadFromArgv(_PyCoreConfig *config,
- const _PyArgv *args);
+ const _PyArgv *args,
+ const _PyPreConfig *preconfig);
PyAPI_FUNC(void) _PyCoreConfig_Write(const _PyCoreConfig *config);
#ifdef __cplusplus
diff --git a/Include/internal/pycore_getopt.h b/Include/internal/pycore_getopt.h
index e6f4654..1d30f5b 100644
--- a/Include/internal/pycore_getopt.h
+++ b/Include/internal/pycore_getopt.h
@@ -17,7 +17,6 @@ typedef struct {
int val;
} _PyOS_LongOption;
-extern int _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring,
- const _PyOS_LongOption *longopts, int *longindex);
+extern int _PyOS_GetOpt(int argc, wchar_t **argv, int *longindex);
#endif /* !Py_INTERNAL_PYGETOPT_H */
diff --git a/Modules/main.c b/Modules/main.c
index ff2e2f0..34032ad 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -286,20 +286,32 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *main_config,
/* --- pymain_init() ---------------------------------------------- */
-static void
-config_clear(_PyCoreConfig *config)
+static _PyInitError
+preconfig_read_write(_PyPreConfig *config, const _PyArgv *args)
{
+ _PyInitError err;
+
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
- _PyCoreConfig_Clear(config);
+ _PyPreConfig_GetGlobalConfig(config);
+
+ err = _PyPreConfig_ReadFromArgv(config, args);
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
+
+ if (_Py_INIT_FAILED(err)) {
+ return err;
+ }
+
+ _PyPreConfig_Write(config);
+ return _Py_INIT_OK();
}
static _PyInitError
-config_read_write(_PyCoreConfig *config, const _PyArgv *args)
+config_read_write(_PyCoreConfig *config, const _PyArgv *args,
+ const _PyPreConfig *preconfig)
{
_PyInitError err;
@@ -308,7 +320,7 @@ config_read_write(_PyCoreConfig *config, const _PyArgv *args)
_PyCoreConfig_GetGlobalConfig(config);
- err = _PyCoreConfig_ReadFromArgv(config, args);
+ err = _PyCoreConfig_ReadFromArgv(config, args, preconfig);
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
@@ -344,6 +356,7 @@ static _PyInitError
pymain_init(const _PyArgv *args, PyInterpreterState **interp_p)
{
_PyInitError err;
+ PyMemAllocatorEx old_alloc;
err = _PyRuntime_Initialize();
if (_Py_INIT_FAILED(err)) {
@@ -359,10 +372,18 @@ pymain_init(const _PyArgv *args, PyInterpreterState **interp_p)
fedisableexcept(FE_OVERFLOW);
#endif
+ _PyPreConfig local_preconfig = _PyPreConfig_INIT;
+ _PyPreConfig *preconfig = &local_preconfig;
+
_PyCoreConfig local_config = _PyCoreConfig_INIT;
_PyCoreConfig *config = &local_config;
- err = config_read_write(config, args);
+ err = preconfig_read_write(preconfig, args);
+ if (_Py_INIT_FAILED(err)) {
+ goto done;
+ }
+
+ err = config_read_write(config, args, preconfig);
if (_Py_INIT_FAILED(err)) {
goto done;
}
@@ -382,7 +403,12 @@ pymain_init(const _PyArgv *args, PyInterpreterState **interp_p)
err = _Py_INIT_OK();
done:
- config_clear(config);
+ _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
+
+ _PyPreConfig_Clear(preconfig);
+ _PyCoreConfig_Clear(config);
+
+ PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
return err;
}
diff --git a/Python/coreconfig.c b/Python/coreconfig.c
index 3486da4..a6aa89b 100644
--- a/Python/coreconfig.c
+++ b/Python/coreconfig.c
@@ -23,13 +23,6 @@
/* --- Command line options --------------------------------------- */
-#define PROGRAM_OPTS L"bBc:dEhiIJm:OqRsStuvVW:xX:?"
-
-static const _PyOS_LongOption longoptions[] = {
- {L"check-hash-based-pycs", 1, 0},
- {NULL, 0, 0},
-};
-
/* Short usage message (with %s for argv0) */
static const char usage_line[] =
"usage: %ls [option] ... [-c cmd | -m mod | file | -] [arg] ...\n";
@@ -1483,28 +1476,61 @@ config_init_fs_encoding(_PyCoreConfig *config)
}
-/* Read configuration settings from standard locations
- *
- * This function doesn't make any changes to the interpreter state - it
- * merely populates any missing configuration settings. This allows an
- * embedding application to completely override a config option by
- * setting it before calling this function, or else modify the default
- * setting before passing the fully populated config to Py_EndInitialization.
- *
- * More advanced selective initialization tricks are possible by calling
- * this function multiple times with various preconfigured settings.
- */
+static _PyInitError
+_PyCoreConfig_ReadPreConfig(_PyCoreConfig *config)
+{
+ _PyInitError err;
+ _PyPreConfig local_preconfig = _PyPreConfig_INIT;
+ _PyPreConfig_GetGlobalConfig(&local_preconfig);
+
+ if (_PyPreConfig_Copy(&local_preconfig, &config->preconfig) < 0) {
+ err = _Py_INIT_NO_MEMORY();
+ goto done;
+ }
+
+ err = _PyPreConfig_Read(&local_preconfig);
+ if (_Py_INIT_FAILED(err)) {
+ goto done;
+ }
+
+ if (_PyPreConfig_Copy(&config->preconfig, &local_preconfig) < 0) {
+ err = _Py_INIT_NO_MEMORY();
+ goto done;
+ }
+ err = _Py_INIT_OK();
+
+done:
+ _PyPreConfig_Clear(&local_preconfig);
+ return err;
+}
+
+
+/* Read the configuration into _PyCoreConfig and initialize the LC_CTYPE
+ locale: enable UTF-8 mode (PEP 540) and/or coerce the C locale (PEP 538).
+ Read the configuration from:
+
+ * Environment variables
+ * Py_xxx global configuration variables
+
+ See _PyCoreConfig_ReadFromArgv() to parse also command line arguments. */
_PyInitError
-_PyCoreConfig_Read(_PyCoreConfig *config)
+_PyCoreConfig_Read(_PyCoreConfig *config, const _PyPreConfig *preconfig)
{
_PyInitError err;
_PyCoreConfig_GetGlobalConfig(config);
- err = _PyPreConfig_Read(&config->preconfig);
- if (_Py_INIT_FAILED(err)) {
- return err;
+ if (preconfig != NULL) {
+ if (_PyPreConfig_Copy(&config->preconfig, preconfig) < 0) {
+ return _Py_INIT_NO_MEMORY();
+ }
+ }
+ else {
+ err = _PyCoreConfig_ReadPreConfig(config);
+ if (_Py_INIT_FAILED(err)) {
+ return err;
+ }
}
assert(config->preconfig.use_environment >= 0);
@@ -1851,8 +1877,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
_PyOS_ResetGetOpt();
do {
int longindex = -1;
- int c = _PyOS_GetOpt(cmdline->args->argc, cmdline->argv, PROGRAM_OPTS,
- longoptions, &longindex);
+ int c = _PyOS_GetOpt(cmdline->args->argc, cmdline->argv, &longindex);
if (c == EOF) {
break;
}
@@ -1915,8 +1940,9 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
config->interactive++;
break;
+ case 'E':
case 'I':
- config->preconfig.isolated++;
+ /* option handled by _PyPreConfig_ReadFromArgv() */
break;
/* case 'J': reserved for Jython */
@@ -1937,10 +1963,6 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
config->site_import = 0;
break;
- case 'E':
- config->preconfig.use_environment = 0;
- break;
-
case 't':
/* ignored for backwards compatibility */
break;
@@ -2235,7 +2257,8 @@ config_usage(int error, const wchar_t* program)
/* Parse command line options and environment variables. */
static _PyInitError
-config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline)
+config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
+ const _PyPreConfig *preconfig)
{
int need_usage = 0;
_PyInitError err;
@@ -2271,7 +2294,7 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline)
return err;
}
- err = _PyCoreConfig_Read(config);
+ err = _PyCoreConfig_Read(config, preconfig);
if (_Py_INIT_FAILED(err)) {
return err;
}
@@ -2296,7 +2319,8 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline)
static _PyInitError
-config_read_from_argv_impl(_PyCoreConfig *config, const _PyArgv *args)
+config_read_from_argv_impl(_PyCoreConfig *config, const _PyArgv *args,
+ const _PyPreConfig *preconfig)
{
_PyInitError err;
@@ -2309,7 +2333,7 @@ config_read_from_argv_impl(_PyCoreConfig *config, const _PyArgv *args)
goto done;
}
- err = config_from_cmdline(config, &cmdline);
+ err = config_from_cmdline(config, &cmdline, preconfig);
if (_Py_INIT_FAILED(err)) {
goto done;
}
@@ -2330,7 +2354,8 @@ done:
* Environment variables
* Py_xxx global configuration variables */
_PyInitError
-_PyCoreConfig_ReadFromArgv(_PyCoreConfig *config, const _PyArgv *args)
+_PyCoreConfig_ReadFromArgv(_PyCoreConfig *config, const _PyArgv *args,
+ const _PyPreConfig *preconfig)
{
_PyInitError err;
int init_utf8_mode = Py_UTF8Mode;
@@ -2381,7 +2406,7 @@ _PyCoreConfig_ReadFromArgv(_PyCoreConfig *config, const _PyArgv *args)
Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding;
#endif
- err = config_read_from_argv_impl(config, args);
+ err = config_read_from_argv_impl(config, args, preconfig);
if (_Py_INIT_FAILED(err)) {
goto done;
}
diff --git a/Python/getopt.c b/Python/getopt.c
index c165a94..1dc8720 100644
--- a/Python/getopt.c
+++ b/Python/getopt.c
@@ -43,6 +43,16 @@ wchar_t *_PyOS_optarg = NULL; /* optional argument */
static wchar_t *opt_ptr = L"";
+/* Python command line short and long options */
+
+#define SHORT_OPTS L"bBc:dEhiIJm:OqRsStuvVW:xX:?"
+
+static const _PyOS_LongOption longopts[] = {
+ {L"check-hash-based-pycs", 1, 0},
+ {NULL, 0, 0},
+};
+
+
void _PyOS_ResetGetOpt(void)
{
_PyOS_opterr = 1;
@@ -51,8 +61,7 @@ void _PyOS_ResetGetOpt(void)
opt_ptr = L"";
}
-int _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring,
- const _PyOS_LongOption *longopts, int *longindex)
+int _PyOS_GetOpt(int argc, wchar_t **argv, int *longindex)
{
wchar_t *ptr;
wchar_t option;
@@ -128,7 +137,7 @@ int _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring,
return '_';
}
- if ((ptr = wcschr(optstring, option)) == NULL) {
+ if ((ptr = wcschr(SHORT_OPTS, option)) == NULL) {
if (_PyOS_opterr)
fprintf(stderr, "Unknown option: -%c\n", (char)option);
return '_';
diff --git a/Python/pathconfig.c b/Python/pathconfig.c
index 41fc9e2..14dbba7 100644
--- a/Python/pathconfig.c
+++ b/Python/pathconfig.c
@@ -393,7 +393,7 @@ pathconfig_global_init(void)
_PyInitError err;
_PyCoreConfig config = _PyCoreConfig_INIT;
- err = _PyCoreConfig_Read(&config);
+ err = _PyCoreConfig_Read(&config, NULL);
if (_Py_INIT_FAILED(err)) {
goto error;
}
diff --git a/Python/preconfig.c b/Python/preconfig.c
index bb1e830..af70f38 100644
--- a/Python/preconfig.c
+++ b/Python/preconfig.c
@@ -1,5 +1,6 @@
#include "Python.h"
#include "pycore_coreconfig.h"
+#include "pycore_getopt.h"
#define DECODE_LOCALE_ERR(NAME, LEN) \
@@ -92,6 +93,25 @@ _PyArgv_Decode(const _PyArgv *args, wchar_t*** argv_p)
}
+/* --- _PyPreCmdline ------------------------------------------------- */
+
+typedef struct {
+ const _PyArgv *args;
+ int argc;
+ wchar_t **argv;
+} _PyPreCmdline;
+
+
+static void
+precmdline_clear(_PyPreCmdline *cmdline)
+{
+ if (cmdline->args->use_bytes_argv && cmdline->argv != NULL) {
+ _Py_wstrlist_clear(cmdline->args->argc, cmdline->argv);
+ }
+ cmdline->argv = NULL;
+}
+
+
/* --- _PyPreConfig ----------------------------------------------- */
void
@@ -169,6 +189,7 @@ _PyPreConfig_Read(_PyPreConfig *config)
config->use_environment = 0;
}
+ assert(config->isolated >= 0);
assert(config->use_environment >= 0);
return _Py_INIT_OK();
@@ -203,3 +224,76 @@ fail:
#undef SET_ITEM
#undef SET_ITEM_INT
}
+
+
+/* Parse the command line arguments */
+static _PyInitError
+preconfig_parse_cmdline(_PyPreConfig *config, _PyPreCmdline *cmdline)
+{
+ _PyOS_ResetGetOpt();
+ /* Don't log parsing errors into stderr here: _PyCoreConfig_ReadFromArgv()
+ is responsible for that */
+ _PyOS_opterr = 0;
+ do {
+ int longindex = -1;
+ int c = _PyOS_GetOpt(cmdline->args->argc, cmdline->argv, &longindex);
+
+ if (c == EOF || c == 'c' || c == 'm') {
+ break;
+ }
+
+ switch (c) {
+ case 'E':
+ config->use_environment = 0;
+ break;
+
+ case 'I':
+ config->isolated++;
+ break;
+
+ default:
+ /* ignore other argument:
+ handled by _PyCoreConfig_ReadFromArgv() */
+ break;
+ }
+ } while (1);
+
+ return _Py_INIT_OK();
+}
+
+
+_PyInitError
+_PyPreConfig_ReadFromArgv(_PyPreConfig *config, const _PyArgv *args)
+{
+ _PyInitError err;
+
+ _PyPreCmdline cmdline;
+ memset(&cmdline, 0, sizeof(cmdline));
+ cmdline.args = args;
+
+ err = _PyArgv_Decode(cmdline.args, &cmdline.argv);
+ if (_Py_INIT_FAILED(err)) {
+ goto done;
+ }
+
+ err = preconfig_parse_cmdline(config, &cmdline);
+ if (_Py_INIT_FAILED(err)) {
+ goto done;
+ }
+
+ err = _PyPreConfig_Read(config);
+ if (_Py_INIT_FAILED(err)) {
+ goto done;
+ }
+ err = _Py_INIT_OK();
+
+done:
+ precmdline_clear(&cmdline);
+ return err;
+}
+
+
+void
+_PyPreConfig_Write(const _PyPreConfig *config)
+{
+}
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index a5cfc07..7cf4a6d 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -763,7 +763,7 @@ _Py_InitializeCore(PyInterpreterState **interp_p,
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (_PyCoreConfig_Copy(&config, src_config) >= 0) {
- err = _PyCoreConfig_Read(&config);
+ err = _PyCoreConfig_Read(&config, NULL);
}
else {
err = _Py_INIT_ERR("failed to copy core config");