Skip to content

bpo-36142: Add _PyPreConfig_ReadFromArgv() #12173

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions Include/internal/pycore_coreconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand Down
3 changes: 1 addition & 2 deletions Include/internal/pycore_getopt.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
40 changes: 33 additions & 7 deletions Modules/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);

Expand Down Expand Up @@ -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)) {
Expand All @@ -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;
}
Expand All @@ -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;
}

Expand Down
95 changes: 60 additions & 35 deletions Python/coreconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 */
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;

Expand All @@ -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;
}
Expand All @@ -2330,7 +2354,8 @@ config_read_from_argv_impl(_PyCoreConfig *config, const _PyArgv *args)
* 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;
Expand Down Expand Up @@ -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;
}
Expand Down
15 changes: 12 additions & 3 deletions Python/getopt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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 '_';
Expand Down
2 changes: 1 addition & 1 deletion Python/pathconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Loading