Skip to content

Commit fed02e1

Browse files
authored
bpo-36763: Remove _PyCoreConfig.program (GH-13373)
Use _PyCoreConfig.program_name instead.
1 parent 245f528 commit fed02e1

File tree

5 files changed

+27
-59
lines changed

5 files changed

+27
-59
lines changed

Include/cpython/coreconfig.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -218,11 +218,15 @@ typedef struct {
218218
always exists and is never empty. */
219219
_PyWstrList argv;
220220

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() */
221+
/* Program name:
222+
223+
- If Py_SetProgramName() was called, use its value.
224+
- On macOS, use PYTHONEXECUTABLE environment variable if set.
225+
- If WITH_NEXT_FRAMEWORK macro is defined, use __PYVENV_LAUNCHER__
226+
environment variable is set.
227+
- Use argv[0] if available and non-empty.
228+
- Use "python" on Windows, or "python3 on other platforms. */
229+
wchar_t *program_name;
226230

227231
_PyWstrList xoptions; /* Command line -X options */
228232
_PyWstrList warnoptions; /* Warnings options */

Lib/test/test_embed.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
306306
'program_name': GET_DEFAULT_CONFIG,
307307
'parse_argv': 1,
308308
'argv': [""],
309-
'program': '',
310309

311310
'xoptions': [],
312311
'warnoptions': [],
@@ -586,7 +585,6 @@ def test_init_from_config(self):
586585
'pycache_prefix': 'conf_pycache_prefix',
587586
'program_name': './conf_program_name',
588587
'argv': ['-c', 'arg2'],
589-
'program': 'conf_program',
590588
'xoptions': ['core_xoption1=3', 'core_xoption2=', 'core_xoption3'],
591589
'warnoptions': ['error::ResourceWarning', 'default::BytesWarning'],
592590
'run_command': 'pass\n',
@@ -704,7 +702,6 @@ def test_init_run_main(self):
704702
'print(json.dumps(_testinternalcapi.get_configs()))')
705703
core_config = {
706704
'argv': ['-c', 'arg2'],
707-
'program': 'python3',
708705
'program_name': './python3',
709706
'run_command': code + '\n',
710707
}
@@ -716,7 +713,6 @@ def test_init_main(self):
716713
'print(json.dumps(_testinternalcapi.get_configs()))')
717714
core_config = {
718715
'argv': ['-c', 'arg2'],
719-
'program': 'python3',
720716
'program_name': './python3',
721717
'run_command': code + '\n',
722718
'_init_main': 0,
@@ -728,7 +724,6 @@ def test_init_dont_parse_argv(self):
728724
core_config = {
729725
'argv': ['-v', '-c', 'arg1', '-W', 'arg2'],
730726
'parse_argv': 0,
731-
'program': 'program',
732727
}
733728
self.check_config("init_dont_parse_argv", core_config, {})
734729

Modules/main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ pymain_run_file(_PyCoreConfig *config, PyCompilerFlags *cf)
283283
else
284284
cfilename = "<unprintable file name>";
285285
fprintf(stderr, "%ls: can't open file '%s': [Errno %d] %s\n",
286-
config->program, cfilename, err, strerror(err));
286+
config->program_name, cfilename, err, strerror(err));
287287
PyMem_RawFree(cfilename_buffer);
288288
return 2;
289289
}
@@ -303,7 +303,7 @@ pymain_run_file(_PyCoreConfig *config, PyCompilerFlags *cf)
303303
if (_Py_fstat_noraise(fileno(fp), &sb) == 0 && S_ISDIR(sb.st_mode)) {
304304
fprintf(stderr,
305305
"%ls: '%ls' is a directory, cannot continue\n",
306-
config->program, filename);
306+
config->program_name, filename);
307307
fclose(fp);
308308
return 1;
309309
}

Programs/_testembed.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -433,8 +433,6 @@ static int test_init_from_config(void)
433433
config.argv.length = Py_ARRAY_LENGTH(argv);
434434
config.argv.items = argv;
435435

436-
config.program = L"conf_program";
437-
438436
static wchar_t* xoptions[3] = {
439437
L"core_xoption1=3",
440438
L"core_xoption2=",
@@ -532,7 +530,6 @@ static int test_init_dont_parse_argv(void)
532530
L"arg2",
533531
};
534532

535-
config.program = L"program";
536533
config.program_name = L"./_testembed";
537534

538535
config.argv.length = Py_ARRAY_LENGTH(argv);

Python/coreconfig.c

Lines changed: 16 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,6 @@ _PyCoreConfig_Clear(_PyCoreConfig *config)
492492
CLEAR(config->module_search_path_env);
493493
CLEAR(config->home);
494494
CLEAR(config->program_name);
495-
CLEAR(config->program);
496495

497496
_PyWstrList_Clear(&config->argv);
498497
_PyWstrList_Clear(&config->warnoptions);
@@ -626,7 +625,6 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
626625
COPY_WSTR_ATTR(module_search_path_env);
627626
COPY_WSTR_ATTR(home);
628627
COPY_WSTR_ATTR(program_name);
629-
COPY_WSTR_ATTR(program);
630628

631629
COPY_ATTR(parse_argv);
632630
COPY_WSTRLIST(argv);
@@ -732,7 +730,6 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config)
732730
SET_ITEM_WSTR(program_name);
733731
SET_ITEM_INT(parse_argv);
734732
SET_ITEM_WSTRLIST(argv);
735-
SET_ITEM_WSTR(program);
736733
SET_ITEM_WSTRLIST(xoptions);
737734
SET_ITEM_WSTRLIST(warnoptions);
738735
SET_ITEM_WSTR(module_search_path_env);
@@ -918,7 +915,6 @@ static _PyInitError
918915
config_init_program_name(_PyCoreConfig *config)
919916
{
920917
_PyInitError err;
921-
assert(config->program_name == NULL);
922918

923919
/* If Py_SetProgramName() was called, use its value */
924920
const wchar_t *program_name = _Py_path_config.program_name;
@@ -967,16 +963,17 @@ config_init_program_name(_PyCoreConfig *config)
967963
#endif /* WITH_NEXT_FRAMEWORK */
968964
#endif /* __APPLE__ */
969965

970-
/* Use argv[0] by default, if available */
971-
if (config->program != NULL) {
972-
err = _PyCoreConfig_SetString(&config->program_name, config->program);
973-
if (_Py_INIT_FAILED(err)) {
974-
return err;
966+
/* Use argv[0] if available and non-empty */
967+
const _PyWstrList *argv = &config->argv;
968+
if (argv->length >= 1 && argv->items[0][0] != L'\0') {
969+
config->program_name = _PyMem_RawWcsdup(argv->items[0]);
970+
if (config->program_name == NULL) {
971+
return _Py_INIT_NO_MEMORY();
975972
}
976973
return _Py_INIT_OK();
977974
}
978975

979-
/* Last fall back: hardcoded string */
976+
/* Last fall back: hardcoded name */
980977
#ifdef MS_WINDOWS
981978
const wchar_t *default_program_name = L"python";
982979
#else
@@ -1518,13 +1515,6 @@ config_read(_PyCoreConfig *config)
15181515
}
15191516
}
15201517

1521-
if (config->program_name == NULL) {
1522-
err = config_init_program_name(config);
1523-
if (_Py_INIT_FAILED(err)) {
1524-
return err;
1525-
}
1526-
}
1527-
15281518
if (config->executable == NULL) {
15291519
err = config_init_executable(config);
15301520
if (_Py_INIT_FAILED(err)) {
@@ -1678,6 +1668,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyWstrList *warnoptions,
16781668
_PyInitError err;
16791669
const _PyWstrList *argv = &config->argv;
16801670
int print_version = 0;
1671+
const wchar_t* program = config->program_name;
16811672

16821673
_PyOS_ResetGetOpt();
16831674
do {
@@ -1734,7 +1725,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyWstrList *warnoptions,
17341725
} else {
17351726
fprintf(stderr, "--check-hash-based-pycs must be one of "
17361727
"'default', 'always', or 'never'\n");
1737-
config_usage(1, config->program);
1728+
config_usage(1, program);
17381729
return _Py_INIT_EXIT(2);
17391730
}
17401731
break;
@@ -1794,7 +1785,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyWstrList *warnoptions,
17941785

17951786
case 'h':
17961787
case '?':
1797-
config_usage(0, config->program);
1788+
config_usage(0, program);
17981789
return _Py_INIT_EXIT(0);
17991790

18001791
case 'V':
@@ -1819,7 +1810,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyWstrList *warnoptions,
18191810

18201811
default:
18211812
/* unknown argument: parsing failed */
1822-
config_usage(1, config->program);
1813+
config_usage(1, program);
18231814
return _Py_INIT_EXIT(2);
18241815
}
18251816
} while (1);
@@ -1892,26 +1883,6 @@ config_init_env_warnoptions(const _PyCoreConfig *config, _PyWstrList *warnoption
18921883
}
18931884

18941885

1895-
static _PyInitError
1896-
config_init_program(_PyCoreConfig *config)
1897-
{
1898-
const _PyWstrList *argv = &config->argv;
1899-
wchar_t *program;
1900-
if (argv->length >= 1) {
1901-
program = argv->items[0];
1902-
}
1903-
else {
1904-
program = L"";
1905-
}
1906-
config->program = _PyMem_RawWcsdup(program);
1907-
if (config->program == NULL) {
1908-
return _Py_INIT_NO_MEMORY();
1909-
}
1910-
1911-
return _Py_INIT_OK();
1912-
}
1913-
1914-
19151886
static int
19161887
config_add_warnoption(_PyCoreConfig *config, const wchar_t *option)
19171888
{
@@ -2084,10 +2055,10 @@ config_read_cmdline(_PyCoreConfig *config)
20842055
config->parse_argv = 1;
20852056
}
20862057

2087-
if (config->program == NULL) {
2088-
err = config_init_program(config);
2058+
if (config->program_name == NULL) {
2059+
err = config_init_program_name(config);
20892060
if (_Py_INIT_FAILED(err)) {
2090-
goto done;
2061+
return err;
20912062
}
20922063
}
20932064

@@ -2218,6 +2189,8 @@ _PyCoreConfig_Read(_PyCoreConfig *config)
22182189
goto done;
22192190
}
22202191

2192+
/* precmdline.argv is a copy of config.argv which is modified
2193+
by config_read_cmdline() */
22212194
const _PyWstrList *argv = &precmdline.argv;
22222195
if (_Py_SetArgcArgv(argv->length, argv->items) < 0) {
22232196
err = _Py_INIT_NO_MEMORY();
@@ -2246,7 +2219,6 @@ _PyCoreConfig_Read(_PyCoreConfig *config)
22462219
assert(config->configure_c_stdio >= 0);
22472220
assert(config->buffered_stdio >= 0);
22482221
assert(config->program_name != NULL);
2249-
assert(config->program != NULL);
22502222
assert(_PyWstrList_CheckConsistency(&config->argv));
22512223
/* sys.argv must be non-empty: empty argv is replaced with [''] */
22522224
assert(config->argv.length >= 1);

0 commit comments

Comments
 (0)