| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 68b34a7 commit ae239f6
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -207,31 +207,25 @@ typedef struct { | |||
| 207 | 207 | wchar_t *filesystem_errors; | |
| 208 | 208 | ||
| 209 | 209 | wchar_t *pycache_prefix; /* PYTHONPYCACHEPREFIX, -X pycache_prefix=PATH */ | |
| 210 | - wchar_t *program_name; /* Program name, see also Py_GetProgramName() */ | ||
| 211 | - _PyWstrList argv; /* Command line arguments */ | ||
| 212 | - wchar_t *program; /* argv[0] or "" */ | ||
| 213 | - _PyWstrList xoptions; /* Command line -X options */ | ||
| 214 | - _PyWstrList warnoptions; /* Warnings options */ | ||
| 210 | + int parse_argv; /* Parse argv command line arguments? */ | ||
| 215 | 211 | ||
| 216 | - /* Path configuration inputs */ | ||
| 217 | - wchar_t *module_search_path_env; /* PYTHONPATH environment variable */ | ||
| 218 | - wchar_t *home; /* PYTHONHOME environment variable, | ||
| 219 | - see also Py_SetPythonHome(). */ | ||
| 212 | + /* Command line arguments (sys.argv). | ||
| 220 | 213 | ||
| 221 | - /* Path configuration outputs */ | ||
| 222 | - int use_module_search_paths; /* If non-zero, use module_search_paths */ | ||
| 223 | - _PyWstrList module_search_paths; /* sys.path paths. Computed if | ||
| 224 | - use_module_search_paths is equal | ||
| 225 | - to zero. */ | ||
| 214 | + By default, Python command line arguments are parsed and then stripped | ||
| 215 | + from argv. Set parse_argv to 0 to avoid that. | ||
| 226 | 216 | ||
| 227 | - wchar_t *executable; /* sys.executable */ | ||
| 228 | - wchar_t *prefix; /* sys.prefix */ | ||
| 229 | - wchar_t *base_prefix; /* sys.base_prefix */ | ||
| 230 | - wchar_t *exec_prefix; /* sys.exec_prefix */ | ||
| 231 | - wchar_t *base_exec_prefix; /* sys.base_exec_prefix */ | ||
| 232 | - #ifdef MS_WINDOWS | ||
| 233 | - wchar_t *dll_path; /* Windows DLL path */ | ||
| 234 | - #endif | ||
| 217 | + If argv is empty, an empty string is added to ensure that sys.argv | ||
| 218 | + always exists and is never empty. */ | ||
| 219 | + _PyWstrList argv; | ||
| 220 | + | ||
| 221 | + /* Program: argv[0] or "". | ||
| 222 | + Used to display Python usage if parsing command line arguments fails. | ||
| 223 | + Used to initialize the default value of program_name */ | ||
| 224 | + wchar_t *program; | ||
| 225 | + wchar_t *program_name; /* Program name, see also Py_GetProgramName() */ | ||
| 226 | + | ||
| 227 | + _PyWstrList xoptions; /* Command line -X options */ | ||
| 228 | + _PyWstrList warnoptions; /* Warnings options */ | ||
| 235 | 229 | ||
| 236 | 230 | /* If equal to zero, disable the import of the module site and the | |
| 237 | 231 | site-dependent manipulations of sys.path that it entails. Also disable | |
@@ -350,6 +344,28 @@ typedef struct { | |||
| 350 | 344 | int legacy_windows_stdio; | |
| 351 | 345 | #endif | |
| 352 | 346 | ||
| 347 | + /* --- Path configuration inputs ------------ */ | ||
| 348 | + | ||
| 349 | + wchar_t *module_search_path_env; /* PYTHONPATH environment variable */ | ||
| 350 | + wchar_t *home; /* PYTHONHOME environment variable, | ||
| 351 | + see also Py_SetPythonHome(). */ | ||
| 352 | + | ||
| 353 | + /* --- Path configuration outputs ----------- */ | ||
| 354 | + | ||
| 355 | + int use_module_search_paths; /* If non-zero, use module_search_paths */ | ||
| 356 | + _PyWstrList module_search_paths; /* sys.path paths. Computed if | ||
| 357 | + use_module_search_paths is equal | ||
| 358 | + to zero. */ | ||
| 359 | + | ||
| 360 | + wchar_t *executable; /* sys.executable */ | ||
| 361 | + wchar_t *prefix; /* sys.prefix */ | ||
| 362 | + wchar_t *base_prefix; /* sys.base_prefix */ | ||
| 363 | + wchar_t *exec_prefix; /* sys.exec_prefix */ | ||
| 364 | + wchar_t *base_exec_prefix; /* sys.base_exec_prefix */ | ||
| 365 | + #ifdef MS_WINDOWS | ||
| 366 | + wchar_t *dll_path; /* Windows DLL path */ | ||
| 367 | + #endif | ||
| 368 | + | ||
| 353 | 369 | /* --- Parameter only used by Py_Main() ---------- */ | |
| 354 | 370 | ||
| 355 | 371 | /* Skip the first line of the source ('run_filename' parameter), allowing use of non-Unix forms of | |
@@ -408,6 +424,7 @@ typedef struct { | |||
| 408 | 424 | .faulthandler = -1, \ | |
| 409 | 425 | .tracemalloc = -1, \ | |
| 410 | 426 | .use_module_search_paths = 0, \ | |
| 427 | + .parse_argv = 1, \ | ||
| 411 | 428 | .site_import = -1, \ | |
| 412 | 429 | .bytes_warning = -1, \ | |
| 413 | 430 | .inspect = -1, \ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -304,6 +304,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): | |||
| 304 | 304 | ||
| 305 | 305 | 'pycache_prefix': None, | |
| 306 | 306 | 'program_name': GET_DEFAULT_CONFIG, | |
| 307 | + 'parse_argv': 1, | ||
| 307 | 308 | 'argv': [""], | |
| 308 | 309 | 'program': '', | |
| 309 | 310 | ||
@@ -700,6 +701,14 @@ def test_run_main_config(self): | |||
| 700 | 701 | } | |
| 701 | 702 | self.check_config("run_main_config", core_config, preconfig) | |
| 702 | 703 | ||
| 704 | + def test_init_dont_parse_argv(self): | ||
| 705 | + core_config = { | ||
| 706 | + 'argv': ['-v', '-c', 'arg1', '-W', 'arg2'], | ||
| 707 | + 'parse_argv': 0, | ||
| 708 | + 'program': 'program', | ||
| 709 | + } | ||
| 710 | + self.check_config("init_dont_parse_argv", core_config, {}) | ||
| 711 | + | ||
| 703 | 712 | ||
| 704 | 713 | if __name__ == "__main__": | |
| 705 | 714 | unittest.main() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -574,13 +574,13 @@ _Py_RunMain(void) | |||
| 574 | 574 | int exitcode = 0; | |
| 575 | 575 | ||
| 576 | 576 | pymain_run_python(&exitcode); | |
| 577 | + | ||
| 577 | 578 | if (Py_FinalizeEx() < 0) { | |
| 578 | 579 | /* Value unlikely to be confused with a non-error exit status or | |
| 579 | 580 | other special meaning */ | |
| 580 | 581 | exitcode = 120; | |
| 581 | 582 | } | |
| 582 | 583 | ||
| 583 | - done: | ||
| 584 | 584 | pymain_free(); | |
| 585 | 585 | ||
| 586 | 586 | if (_Py_UnhandledKeyboardInterrupt) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -511,6 +511,37 @@ static int test_init_from_config(void) | |||
| 511 | 511 | } | |
| 512 | 512 | ||
| 513 | 513 | ||
| 514 | + static int test_init_dont_parse_argv(void) | ||
| 515 | + { | ||
| 516 | + _PyInitError err; | ||
| 517 | + | ||
| 518 | + _PyCoreConfig config = _PyCoreConfig_INIT; | ||
| 519 | + | ||
| 520 | + static wchar_t* argv[] = { | ||
| 521 | + L"-v", | ||
| 522 | + L"-c", | ||
| 523 | + L"arg1", | ||
| 524 | + L"-W", | ||
| 525 | + L"arg2", | ||
| 526 | + }; | ||
| 527 | + | ||
| 528 | + config.program = L"program"; | ||
| 529 | + config.program_name = L"./_testembed"; | ||
| 530 | + | ||
| 531 | + config.argv.length = Py_ARRAY_LENGTH(argv); | ||
| 532 | + config.argv.items = argv; | ||
| 533 | + config.parse_argv = 0; | ||
| 534 | + | ||
| 535 | + err = _Py_InitializeFromConfig(&config); | ||
| 536 | + if (_Py_INIT_FAILED(err)) { | ||
| 537 | + _Py_ExitInitError(err); | ||
| 538 | + } | ||
| 539 | + dump_config(); | ||
| 540 | + Py_Finalize(); | ||
| 541 | + return 0; | ||
| 542 | + } | ||
| 543 | + | ||
| 544 | + | ||
| 514 | 545 | static void test_init_env_putenvs(void) | |
| 515 | 546 | { | |
| 516 | 547 | putenv("PYTHONHASHSEED=42"); | |
@@ -797,6 +828,7 @@ static struct TestCase TestCases[] = { | |||
| 797 | 828 | { "init_default_config", test_init_default_config }, | |
| 798 | 829 | { "init_global_config", test_init_global_config }, | |
| 799 | 830 | { "init_from_config", test_init_from_config }, | |
| 831 | + { "init_dont_parse_argv", test_init_dont_parse_argv }, | ||
| 800 | 832 | { "init_env", test_init_env }, | |
| 801 | 833 | { "init_env_dev_mode", test_init_env_dev_mode }, | |
| 802 | 834 | { "init_env_dev_mode_alloc", test_init_env_dev_mode_alloc }, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -628,6 +628,7 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) | |||
| 628 | 628 | COPY_WSTR_ATTR(program_name); | |
| 629 | 629 | COPY_WSTR_ATTR(program); | |
| 630 | 630 | ||
| 631 | + COPY_ATTR(parse_argv); | ||
| 631 | 632 | COPY_WSTRLIST(argv); | |
| 632 | 633 | COPY_WSTRLIST(warnoptions); | |
| 633 | 634 | COPY_WSTRLIST(xoptions); | |
@@ -727,6 +728,7 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config) | |||
| 727 | 728 | SET_ITEM_WSTR(filesystem_errors); | |
| 728 | 729 | SET_ITEM_WSTR(pycache_prefix); | |
| 729 | 730 | SET_ITEM_WSTR(program_name); | |
| 731 | + SET_ITEM_INT(parse_argv); | ||
| 730 | 732 | SET_ITEM_WSTRLIST(argv); | |
| 731 | 733 | SET_ITEM_WSTR(program); | |
| 732 | 734 | SET_ITEM_WSTRLIST(xoptions); | |
@@ -1490,6 +1492,8 @@ config_read(_PyCoreConfig *config, _PyPreCmdline *cmdline) | |||
| 1490 | 1492 | } | |
| 1491 | 1493 | ||
| 1492 | 1494 | if (config->isolated > 0) { | |
| 1495 | + /* _PyPreCmdline_Read() sets use_environment to 0 if isolated is set, | ||
| 1496 | + _PyPreCmdline_SetCoreConfig() overrides config->use_environment. */ | ||
| 1493 | 1497 | config->user_site_directory = 0; | |
| 1494 | 1498 | } | |
| 1495 | 1499 | ||
@@ -1660,7 +1664,7 @@ config_usage(int error, const wchar_t* program) | |||
| 1660 | 1664 | /* Parse the command line arguments */ | |
| 1661 | 1665 | static _PyInitError | |
| 1662 | 1666 | config_parse_cmdline(_PyCoreConfig *config, _PyPreCmdline *precmdline, | |
| 1663 | - _PyWstrList *warnoptions) | ||
| 1667 | + _PyWstrList *warnoptions, int *opt_index) | ||
| 1664 | 1668 | { | |
| 1665 | 1669 | _PyInitError err; | |
| 1666 | 1670 | const _PyWstrList *argv = &precmdline->argv; | |
@@ -1833,8 +1837,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyPreCmdline *precmdline, | |||
| 1833 | 1837 | _PyOS_optind--; | |
| 1834 | 1838 | } | |
| 1835 | 1839 | ||
| 1836 | - /* -c and -m options are exclusive */ | ||
| 1837 | - assert(!(config->run_command != NULL && config->run_module != NULL)); | ||
| 1840 | + *opt_index = _PyOS_optind; | ||
| 1838 | 1841 | ||
| 1839 | 1842 | return _Py_INIT_OK(); | |
| 1840 | 1843 | } | |
@@ -1978,22 +1981,23 @@ config_init_warnoptions(_PyCoreConfig *config, | |||
| 1978 | 1981 | ||
| 1979 | 1982 | ||
| 1980 | 1983 | static _PyInitError | |
| 1981 | - config_init_argv(_PyCoreConfig *config, const _PyPreCmdline *cmdline) | ||
| 1984 | + config_update_argv(_PyCoreConfig *config, const _PyPreCmdline *cmdline, | ||
| 1985 | + int opt_index) | ||
| 1982 | 1986 | { | |
| 1983 | 1987 | const _PyWstrList *cmdline_argv = &cmdline->argv; | |
| 1984 | 1988 | _PyWstrList config_argv = _PyWstrList_INIT; | |
| 1985 | 1989 | ||
| 1986 | 1990 | /* Copy argv to be able to modify it (to force -c/-m) */ | |
| 1987 | - if (cmdline_argv->length <= _PyOS_optind) { | ||
| 1991 | + if (cmdline_argv->length <= opt_index) { | ||
| 1988 | 1992 | /* Ensure at least one (empty) argument is seen */ | |
| 1989 | 1993 | if (_PyWstrList_Append(&config_argv, L"") < 0) { | |
| 1990 | 1994 | return _Py_INIT_NO_MEMORY(); | |
| 1991 | 1995 | } | |
| 1992 | 1996 | } | |
| 1993 | 1997 | else { | |
| 1994 | 1998 | _PyWstrList slice; | |
| 1995 | - slice.length = cmdline_argv->length - _PyOS_optind; | ||
| 1996 | - slice.items = &cmdline_argv->items[_PyOS_optind]; | ||
| 1999 | + slice.length = cmdline_argv->length - opt_index; | ||
| 2000 | + slice.items = &cmdline_argv->items[opt_index]; | ||
| 1997 | 2001 | if (_PyWstrList_Copy(&config_argv, &slice) < 0) { | |
| 1998 | 2002 | return _Py_INIT_NO_MEMORY(); | |
| 1999 | 2003 | } | |
@@ -2058,14 +2062,22 @@ config_read_cmdline(_PyCoreConfig *config, _PyPreCmdline *precmdline) | |||
| 2058 | 2062 | _PyWstrList cmdline_warnoptions = _PyWstrList_INIT; | |
| 2059 | 2063 | _PyWstrList env_warnoptions = _PyWstrList_INIT; | |
| 2060 | 2064 | ||
| 2061 | - err = config_parse_cmdline(config, precmdline, &cmdline_warnoptions); | ||
| 2062 | - if (_Py_INIT_FAILED(err)) { | ||
| 2063 | - goto done; | ||
| 2065 | + if (config->parse_argv < 0) { | ||
| 2066 | + config->parse_argv = 1; | ||
| 2064 | 2067 | } | |
| 2065 | 2068 | ||
| 2066 | - err = config_init_argv(config, precmdline); | ||
| 2067 | - if (_Py_INIT_FAILED(err)) { | ||
| 2068 | - goto done; | ||
| 2069 | + if (config->parse_argv) { | ||
| 2070 | + int opt_index; | ||
| 2071 | + err = config_parse_cmdline(config, precmdline, &cmdline_warnoptions, | ||
| 2072 | + &opt_index); | ||
| 2073 | + if (_Py_INIT_FAILED(err)) { | ||
| 2074 | + goto done; | ||
| 2075 | + } | ||
| 2076 | + | ||
| 2077 | + err = config_update_argv(config, precmdline, opt_index); | ||
| 2078 | + if (_Py_INIT_FAILED(err)) { | ||
| 2079 | + goto done; | ||
| 2080 | + } | ||
| 2069 | 2081 | } | |
| 2070 | 2082 | ||
| 2071 | 2083 | err = config_read(config, precmdline); | |
@@ -2212,6 +2224,7 @@ _PyCoreConfig_Read(_PyCoreConfig *config) | |||
| 2212 | 2224 | assert(config->verbose >= 0); | |
| 2213 | 2225 | assert(config->quiet >= 0); | |
| 2214 | 2226 | assert(config->user_site_directory >= 0); | |
| 2227 | + assert(config->parse_argv >= 0); | ||
| 2215 | 2228 | assert(config->buffered_stdio >= 0); | |
| 2216 | 2229 | assert(config->program_name != NULL); | |
| 2217 | 2230 | assert(config->program != NULL); | |
@@ -2236,6 +2249,8 @@ _PyCoreConfig_Read(_PyCoreConfig *config) | |||
| 2236 | 2249 | #ifdef MS_WINDOWS | |
| 2237 | 2250 | assert(config->legacy_windows_stdio >= 0); | |
| 2238 | 2251 | #endif | |
| 2252 | + /* -c and -m options are exclusive */ | ||
| 2253 | + assert(!(config->run_command != NULL && config->run_module != NULL)); | ||
| 2239 | 2254 | assert(config->check_hash_pycs_mode != NULL); | |
| 2240 | 2255 | assert(config->_install_importlib >= 0); | |
| 2241 | 2256 | assert(config->_frozen >= 0); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments