bpo-36301: Add _PyPreCmdline internal API (GH-12458)
_PyCoreConfig_ReadFromArgv() now reuses the code parsing command line options from preconfig.c.
This commit is contained in:
parent
abbdd1fc5c
commit
fa15376848
|
@ -9,6 +9,30 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
|
||||
/* --- _PyPreCmdline ------------------------------------------------- */
|
||||
|
||||
typedef struct {
|
||||
_PyWstrList argv;
|
||||
_PyWstrList xoptions; /* "-X value" option */
|
||||
int use_environment; /* -E option */
|
||||
int isolated; /* -I option */
|
||||
} _PyPreCmdline;
|
||||
|
||||
#define _PyPreCmdline_INIT \
|
||||
(_PyPreCmdline){ \
|
||||
.use_environment = -1, \
|
||||
.isolated = -1}
|
||||
/* Note: _PyPreCmdline_INIT sets other fields to 0/NULL */
|
||||
|
||||
PyAPI_FUNC(void) _PyPreCmdline_Clear(_PyPreCmdline *cmdline);
|
||||
PyAPI_FUNC(_PyInitError) _PyPreCmdline_Init(_PyPreCmdline *cmdline,
|
||||
const _PyArgv *args);
|
||||
PyAPI_FUNC(_PyInitError) _PyPreCmdline_Read(_PyPreCmdline *cmdline);
|
||||
PyAPI_FUNC(void) _PyPreCmdline_SetPreConfig(
|
||||
const _PyPreCmdline *cmdline,
|
||||
_PyPreConfig *config);
|
||||
|
||||
|
||||
/* --- _PyWstrList ------------------------------------------------ */
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
|
|
@ -1658,7 +1658,7 @@ fail:
|
|||
/* --- _PyCmdline ------------------------------------------------- */
|
||||
|
||||
typedef struct {
|
||||
_PyWstrList argv;
|
||||
_PyPreCmdline precmdline;
|
||||
_PyWstrList warnoptions; /* Command line -W options */
|
||||
_PyWstrList env_warnoptions; /* PYTHONWARNINGS environment variables */
|
||||
int print_help; /* -h, -? options */
|
||||
|
@ -1669,9 +1669,9 @@ typedef struct {
|
|||
static void
|
||||
cmdline_clear(_PyCmdline *cmdline)
|
||||
{
|
||||
_PyPreCmdline_Clear(&cmdline->precmdline);
|
||||
_PyWstrList_Clear(&cmdline->warnoptions);
|
||||
_PyWstrList_Clear(&cmdline->env_warnoptions);
|
||||
_PyWstrList_Clear(&cmdline->argv);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1682,10 +1682,12 @@ static _PyInitError
|
|||
config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
|
||||
int *need_usage)
|
||||
{
|
||||
const _PyWstrList *argv = &cmdline->precmdline.argv;
|
||||
|
||||
_PyOS_ResetGetOpt();
|
||||
do {
|
||||
int longindex = -1;
|
||||
int c = _PyOS_GetOpt(cmdline->argv.length, cmdline->argv.items, &longindex);
|
||||
int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
|
||||
if (c == EOF) {
|
||||
break;
|
||||
}
|
||||
|
@ -1754,6 +1756,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
|
|||
|
||||
case 'E':
|
||||
case 'I':
|
||||
case 'X':
|
||||
/* option handled by _PyPreConfig_ReadFromArgv() */
|
||||
break;
|
||||
|
||||
|
@ -1806,12 +1809,6 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
|
|||
}
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
if (_PyWstrList_Append(&config->xoptions, _PyOS_optarg) < 0) {
|
||||
return _Py_INIT_NO_MEMORY();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
config->quiet++;
|
||||
break;
|
||||
|
@ -1830,11 +1827,11 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
|
|||
} while (1);
|
||||
|
||||
if (config->run_command == NULL && config->run_module == NULL
|
||||
&& _PyOS_optind < cmdline->argv.length
|
||||
&& wcscmp(cmdline->argv.items[_PyOS_optind], L"-") != 0
|
||||
&& _PyOS_optind < argv->length
|
||||
&& wcscmp(argv->items[_PyOS_optind], L"-") != 0
|
||||
&& config->run_filename == NULL)
|
||||
{
|
||||
config->run_filename = _PyMem_RawWcsdup(cmdline->argv.items[_PyOS_optind]);
|
||||
config->run_filename = _PyMem_RawWcsdup(argv->items[_PyOS_optind]);
|
||||
if (config->run_filename == NULL) {
|
||||
return _Py_INIT_NO_MEMORY();
|
||||
}
|
||||
|
@ -1892,9 +1889,10 @@ cmdline_init_env_warnoptions(_PyCmdline *cmdline, const _PyCoreConfig *config)
|
|||
static _PyInitError
|
||||
config_init_program(_PyCoreConfig *config, const _PyCmdline *cmdline)
|
||||
{
|
||||
const _PyWstrList *argv = &cmdline->precmdline.argv;
|
||||
wchar_t *program;
|
||||
if (cmdline->argv.length >= 1) {
|
||||
program = cmdline->argv.items[0];
|
||||
if (argv->length >= 1) {
|
||||
program = argv->items[0];
|
||||
}
|
||||
else {
|
||||
program = L"";
|
||||
|
@ -1965,24 +1963,25 @@ config_init_warnoptions(_PyCoreConfig *config, const _PyCmdline *cmdline)
|
|||
static _PyInitError
|
||||
config_init_argv(_PyCoreConfig *config, const _PyCmdline *cmdline)
|
||||
{
|
||||
_PyWstrList wargv = _PyWstrList_INIT;
|
||||
const _PyWstrList *cmdline_argv = &cmdline->precmdline.argv;
|
||||
_PyWstrList config_argv = _PyWstrList_INIT;
|
||||
|
||||
/* Copy argv to be able to modify it (to force -c/-m) */
|
||||
if (cmdline->argv.length <= _PyOS_optind) {
|
||||
if (cmdline_argv->length <= _PyOS_optind) {
|
||||
/* Ensure at least one (empty) argument is seen */
|
||||
if (_PyWstrList_Append(&wargv, L"") < 0) {
|
||||
if (_PyWstrList_Append(&config_argv, L"") < 0) {
|
||||
return _Py_INIT_NO_MEMORY();
|
||||
}
|
||||
}
|
||||
else {
|
||||
_PyWstrList slice;
|
||||
slice.length = cmdline->argv.length - _PyOS_optind;
|
||||
slice.items = &cmdline->argv.items[_PyOS_optind];
|
||||
if (_PyWstrList_Copy(&wargv, &slice) < 0) {
|
||||
slice.length = cmdline_argv->length - _PyOS_optind;
|
||||
slice.items = &cmdline_argv->items[_PyOS_optind];
|
||||
if (_PyWstrList_Copy(&config_argv, &slice) < 0) {
|
||||
return _Py_INIT_NO_MEMORY();
|
||||
}
|
||||
}
|
||||
assert(wargv.length >= 1);
|
||||
assert(config_argv.length >= 1);
|
||||
|
||||
wchar_t *arg0 = NULL;
|
||||
if (config->run_command != NULL) {
|
||||
|
@ -1996,16 +1995,16 @@ config_init_argv(_PyCoreConfig *config, const _PyCmdline *cmdline)
|
|||
if (arg0 != NULL) {
|
||||
arg0 = _PyMem_RawWcsdup(arg0);
|
||||
if (arg0 == NULL) {
|
||||
_PyWstrList_Clear(&wargv);
|
||||
_PyWstrList_Clear(&config_argv);
|
||||
return _Py_INIT_NO_MEMORY();
|
||||
}
|
||||
|
||||
PyMem_RawFree(wargv.items[0]);
|
||||
wargv.items[0] = arg0;
|
||||
PyMem_RawFree(config_argv.items[0]);
|
||||
config_argv.items[0] = arg0;
|
||||
}
|
||||
|
||||
_PyWstrList_Clear(&config->argv);
|
||||
config->argv = wargv;
|
||||
config->argv = config_argv;
|
||||
return _Py_INIT_OK();
|
||||
}
|
||||
|
||||
|
@ -2046,6 +2045,16 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
|
|||
}
|
||||
}
|
||||
|
||||
err = _PyPreCmdline_Read(&cmdline->precmdline);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
_PyPreCmdline_SetPreConfig(&cmdline->precmdline, &config->preconfig);
|
||||
if (_PyWstrList_Extend(&config->xoptions, &cmdline->precmdline.xoptions) < 0) {
|
||||
return _Py_INIT_NO_MEMORY();
|
||||
}
|
||||
|
||||
err = config_parse_cmdline(config, cmdline, &need_usage);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
return err;
|
||||
|
@ -2089,7 +2098,8 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
|
|||
return err;
|
||||
}
|
||||
|
||||
if (_Py_SetArgcArgv(cmdline->argv.length, cmdline->argv.items) < 0) {
|
||||
const _PyWstrList *argv = &cmdline->precmdline.argv;
|
||||
if (_Py_SetArgcArgv(argv->length, argv->items) < 0) {
|
||||
return _Py_INIT_NO_MEMORY();
|
||||
}
|
||||
return _Py_INIT_OK();
|
||||
|
@ -2107,10 +2117,9 @@ _PyCoreConfig_ReadFromArgv(_PyCoreConfig *config, const _PyArgv *args,
|
|||
{
|
||||
_PyInitError err;
|
||||
|
||||
_PyCmdline cmdline;
|
||||
memset(&cmdline, 0, sizeof(cmdline));
|
||||
_PyCmdline cmdline = {.precmdline = _PyPreCmdline_INIT};
|
||||
|
||||
err = _PyArgv_AsWstrList(args, &cmdline.argv);
|
||||
err = _PyPreCmdline_Init(&cmdline.precmdline, args);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
goto done;
|
||||
}
|
||||
|
|
|
@ -102,20 +102,21 @@ _PyArgv_AsWstrList(const _PyArgv *args, _PyWstrList *list)
|
|||
|
||||
/* --- _PyPreCmdline ------------------------------------------------- */
|
||||
|
||||
typedef struct {
|
||||
_PyWstrList argv;
|
||||
_PyWstrList xoptions; /* -X options */
|
||||
} _PyPreCmdline;
|
||||
|
||||
|
||||
static void
|
||||
precmdline_clear(_PyPreCmdline *cmdline)
|
||||
void
|
||||
_PyPreCmdline_Clear(_PyPreCmdline *cmdline)
|
||||
{
|
||||
_PyWstrList_Clear(&cmdline->argv);
|
||||
_PyWstrList_Clear(&cmdline->xoptions);
|
||||
}
|
||||
|
||||
|
||||
_PyInitError
|
||||
_PyPreCmdline_Init(_PyPreCmdline *cmdline, const _PyArgv *args)
|
||||
{
|
||||
return _PyArgv_AsWstrList(args, &cmdline->argv);
|
||||
}
|
||||
|
||||
|
||||
/* --- _PyPreConfig ----------------------------------------------- */
|
||||
|
||||
void
|
||||
|
@ -520,6 +521,21 @@ _PyPreConfig_Read(_PyPreConfig *config)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
_PyPreCmdline_SetPreConfig(const _PyPreCmdline *cmdline, _PyPreConfig *config)
|
||||
{
|
||||
#define COPY_ATTR(ATTR) \
|
||||
if (cmdline->ATTR != -1) { \
|
||||
config->ATTR = cmdline->ATTR; \
|
||||
}
|
||||
|
||||
COPY_ATTR(use_environment);
|
||||
COPY_ATTR(isolated);
|
||||
|
||||
#undef COPY_ATTR
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_PyPreConfig_AsDict(const _PyPreConfig *config, PyObject *dict)
|
||||
{
|
||||
|
@ -567,16 +583,18 @@ fail:
|
|||
|
||||
|
||||
/* Parse the command line arguments */
|
||||
static _PyInitError
|
||||
preconfig_parse_cmdline(_PyPreConfig *config, _PyPreCmdline *cmdline)
|
||||
_PyInitError
|
||||
_PyPreCmdline_Read(_PyPreCmdline *cmdline)
|
||||
{
|
||||
_PyWstrList *argv = &cmdline->argv;
|
||||
|
||||
_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->argv.length, cmdline->argv.items, &longindex);
|
||||
int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
|
||||
|
||||
if (c == EOF || c == 'c' || c == 'm') {
|
||||
break;
|
||||
|
@ -584,11 +602,11 @@ preconfig_parse_cmdline(_PyPreConfig *config, _PyPreCmdline *cmdline)
|
|||
|
||||
switch (c) {
|
||||
case 'E':
|
||||
config->use_environment = 0;
|
||||
cmdline->use_environment = 0;
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
config->isolated++;
|
||||
cmdline->isolated = 1;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
|
@ -615,19 +633,20 @@ preconfig_from_argv(_PyPreConfig *config, const _PyArgv *args)
|
|||
{
|
||||
_PyInitError err;
|
||||
|
||||
_PyPreCmdline cmdline;
|
||||
memset(&cmdline, 0, sizeof(cmdline));
|
||||
_PyPreCmdline cmdline = _PyPreCmdline_INIT;
|
||||
|
||||
err = _PyArgv_AsWstrList(args, &cmdline.argv);
|
||||
err = _PyPreCmdline_Init(&cmdline, args);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
err = preconfig_parse_cmdline(config, &cmdline);
|
||||
err = _PyPreCmdline_Read(&cmdline);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
_PyPreCmdline_SetPreConfig(&cmdline, config);
|
||||
|
||||
err = preconfig_read(config, &cmdline);
|
||||
if (_Py_INIT_FAILED(err)) {
|
||||
goto done;
|
||||
|
@ -635,7 +654,7 @@ preconfig_from_argv(_PyPreConfig *config, const _PyArgv *args)
|
|||
err = _Py_INIT_OK();
|
||||
|
||||
done:
|
||||
precmdline_clear(&cmdline);
|
||||
_PyPreCmdline_Clear(&cmdline);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue