bpo-32030: Add _PyMainInterpreterConfig.program_name (#4548) · pythoncapi/cpython@f04ebe2 · GitHub
Skip to content

Commit f04ebe2

Browse files
authored
bpo-32030: Add _PyMainInterpreterConfig.program_name (python#4548)
* Py_Main() now calls Py_SetProgramName() earlier to be able to get the program name in _PyMainInterpreterConfig_ReadEnv(). * Rename prog to program_name * Rename progpath to program_name
1 parent 46972b7 commit f04ebe2

5 files changed

Lines changed: 96 additions & 70 deletions

File tree

Include/pystate.h

Lines changed: 2 additions & 0 deletions

Modules/getpath.c

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ extern "C" {
112112
typedef struct {
113113
wchar_t prefix[MAXPATHLEN+1];
114114
wchar_t exec_prefix[MAXPATHLEN+1];
115-
wchar_t progpath[MAXPATHLEN+1];
115+
wchar_t program_name[MAXPATHLEN+1];
116116
wchar_t *module_search_path;
117117
} PyPathConfig;
118118

@@ -121,7 +121,7 @@ typedef struct {
121121
wchar_t *home; /* PYTHONHOME environment variable */
122122
wchar_t *module_search_path_env; /* PYTHONPATH environment variable */
123123

124-
wchar_t *prog; /* Program name */
124+
wchar_t *program_name; /* Program name */
125125
wchar_t *pythonpath; /* PYTHONPATH define */
126126
wchar_t *prefix; /* PREFIX define */
127127
wchar_t *exec_prefix; /* EXEC_PREFIX define */
@@ -602,8 +602,8 @@ calculate_progpath(PyCalculatePath *calculate, PyPathConfig *config)
602602
* other way to find a directory to start the search from. If
603603
* $PATH isn't exported, you lose.
604604
*/
605-
if (wcschr(calculate->prog, SEP)) {
606-
wcsncpy(config->progpath, calculate->prog, MAXPATHLEN);
605+
if (wcschr(calculate->program_name, SEP)) {
606+
wcsncpy(config->program_name, calculate->program_name, MAXPATHLEN);
607607
}
608608
#ifdef __APPLE__
609609
/* On Mac OS X, if a script uses an interpreter of the form
@@ -616,11 +616,13 @@ calculate_progpath(PyCalculatePath *calculate, PyPathConfig *config)
616616
* will fail if a relative path was used. but in that case,
617617
* absolutize() should help us out below
618618
*/
619-
else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) && execpath[0] == SEP) {
620-
size_t r = mbstowcs(config->progpath, execpath, MAXPATHLEN+1);
619+
else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) &&
620+
execpath[0] == SEP)
621+
{
622+
size_t r = mbstowcs(config->program_name, execpath, MAXPATHLEN+1);
621623
if (r == (size_t)-1 || r > MAXPATHLEN) {
622624
/* Could not convert execpath, or it's too long. */
623-
config->progpath[0] = '\0';
625+
config->program_name[0] = '\0';
624626
}
625627
}
626628
#endif /* __APPLE__ */
@@ -634,38 +636,38 @@ calculate_progpath(PyCalculatePath *calculate, PyPathConfig *config)
634636
if (len > MAXPATHLEN) {
635637
len = MAXPATHLEN;
636638
}
637-
wcsncpy(config->progpath, path, len);
638-
*(config->progpath + len) = '\0';
639+
wcsncpy(config->program_name, path, len);
640+
*(config->program_name + len) = '\0';
639641
}
640642
else {
641-
wcsncpy(config->progpath, path, MAXPATHLEN);
643+
wcsncpy(config->program_name, path, MAXPATHLEN);
642644
}
643645

644-
joinpath(config->progpath, calculate->prog);
645-
if (isxfile(config->progpath)) {
646+
joinpath(config->program_name, calculate->program_name);
647+
if (isxfile(config->program_name)) {
646648
break;
647649
}
648650

649651
if (!delim) {
650-
config->progpath[0] = L'\0';
652+
config->program_name[0] = L'\0';
651653
break;
652654
}
653655
path = delim + 1;
654656
}
655657
}
656658
else {
657-
config->progpath[0] = '\0';
659+
config->program_name[0] = '\0';
658660
}
659-
if (config->progpath[0] != SEP && config->progpath[0] != '\0') {
660-
absolutize(config->progpath);
661+
if (config->program_name[0] != SEP && config->program_name[0] != '\0') {
662+
absolutize(config->program_name);
661663
}
662664
}
663665

664666

665667
static void
666668
calculate_argv0_path(PyCalculatePath *calculate, PyPathConfig *config)
667669
{
668-
wcsncpy(calculate->argv0_path, config->progpath, MAXPATHLEN);
670+
wcsncpy(calculate->argv0_path, config->program_name, MAXPATHLEN);
669671
calculate->argv0_path[MAXPATHLEN] = '\0';
670672

671673
#ifdef WITH_NEXT_FRAMEWORK
@@ -700,10 +702,10 @@ calculate_argv0_path(PyCalculatePath *calculate, PyPathConfig *config)
700702
if (!ismodule(calculate->argv0_path)) {
701703
/* We are in the build directory so use the name of the
702704
executable - we know that the absolute path is passed */
703-
wcsncpy(calculate->argv0_path, config->progpath, MAXPATHLEN);
705+
wcsncpy(calculate->argv0_path, config->program_name, MAXPATHLEN);
704706
}
705707
else {
706-
/* Use the location of the library as the progpath */
708+
/* Use the location of the library as the program_name */
707709
wcsncpy(calculate->argv0_path, wbuf, MAXPATHLEN);
708710
}
709711
PyMem_RawFree(wbuf);
@@ -712,15 +714,15 @@ calculate_argv0_path(PyCalculatePath *calculate, PyPathConfig *config)
712714

713715
#if HAVE_READLINK
714716
wchar_t tmpbuffer[MAXPATHLEN+1];
715-
int linklen = _Py_wreadlink(config->progpath, tmpbuffer, MAXPATHLEN);
717+
int linklen = _Py_wreadlink(config->program_name, tmpbuffer, MAXPATHLEN);
716718
while (linklen != -1) {
717719
if (tmpbuffer[0] == SEP) {
718720
/* tmpbuffer should never be longer than MAXPATHLEN,
719721
but extra check does not hurt */
720722
wcsncpy(calculate->argv0_path, tmpbuffer, MAXPATHLEN);
721723
}
722724
else {
723-
/* Interpret relative to progpath */
725+
/* Interpret relative to program_name */
724726
reduce(calculate->argv0_path);
725727
joinpath(calculate->argv0_path, tmpbuffer);
726728
}
@@ -897,6 +899,7 @@ calculate_init(PyCalculatePath *calculate,
897899
{
898900
calculate->home = main_config->home;
899901
calculate->module_search_path_env = main_config->module_search_path_env;
902+
calculate->program_name = main_config->program_name;
900903

901904
size_t len;
902905
char *path = getenv("PATH");
@@ -907,8 +910,6 @@ calculate_init(PyCalculatePath *calculate,
907910
}
908911
}
909912

910-
calculate->prog = Py_GetProgramName();
911-
912913
calculate->pythonpath = Py_DecodeLocale(PYTHONPATH, &len);
913914
if (!calculate->pythonpath) {
914915
return DECODE_LOCALE_ERR("PYTHONPATH define", len);
@@ -950,7 +951,9 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config)
950951
calculate_zip_path(calculate, config);
951952
calculate_exec_prefix(calculate, config);
952953

953-
if ((!calculate->prefix_found || !calculate->exec_prefix_found) && !Py_FrozenFlag) {
954+
if ((!calculate->prefix_found || !calculate->exec_prefix_found) &&
955+
!Py_FrozenFlag)
956+
{
954957
fprintf(stderr,
955958
"Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
956959
}
@@ -1018,10 +1021,11 @@ Py_SetPath(const wchar_t *path)
10181021
return;
10191022
}
10201023

1021-
wchar_t *prog = Py_GetProgramName();
1022-
wcsncpy(path_config.progpath, prog, MAXPATHLEN);
1024+
wchar_t *program_name = Py_GetProgramName();
1025+
wcsncpy(path_config.program_name, program_name, MAXPATHLEN);
10231026
path_config.exec_prefix[0] = path_config.prefix[0] = L'\0';
1024-
path_config.module_search_path = PyMem_RawMalloc((wcslen(path) + 1) * sizeof(wchar_t));
1027+
size_t size = (wcslen(path) + 1) * sizeof(wchar_t);
1028+
path_config.module_search_path = PyMem_RawMalloc(size);
10251029
if (path_config.module_search_path != NULL) {
10261030
wcscpy(path_config.module_search_path, path);
10271031
}
@@ -1074,7 +1078,7 @@ Py_GetProgramFullPath(void)
10741078
if (!path_config.module_search_path) {
10751079
calculate_path(NULL);
10761080
}
1077-
return path_config.progpath;
1081+
return path_config.program_name;
10781082
}
10791083

10801084
#ifdef __cplusplus

Modules/main.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,6 +1452,13 @@ _PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *config)
14521452
return err;
14531453
}
14541454

1455+
/* FIXME: _PyMainInterpreterConfig_Read() has the same code. Remove it
1456+
here? See also pymain_get_program_name() and pymain_parse_envvars(). */
1457+
config->program_name = _PyMem_RawWcsdup(Py_GetProgramName());
1458+
if (config->program_name == NULL) {
1459+
return _Py_INIT_NO_MEMORY();
1460+
}
1461+
14551462
return _Py_INIT_OK();
14561463
}
14571464

@@ -1480,6 +1487,15 @@ pymain_parse_envvars(_PyMain *pymain)
14801487
}
14811488
core_config->allocator = Py_GETENV("PYTHONMALLOC");
14821489

1490+
/* FIXME: move pymain_get_program_name() code into
1491+
_PyMainInterpreterConfig_ReadEnv().
1492+
Problem: _PyMainInterpreterConfig_ReadEnv() doesn't have access
1493+
to argv[0]. */
1494+
Py_SetProgramName(pymain->program_name);
1495+
/* Don't free program_name here: the argument to Py_SetProgramName
1496+
must remain valid until Py_FinalizeEx is called. The string is freed
1497+
by pymain_free(). */
1498+
14831499
_PyInitError err = _PyMainInterpreterConfig_ReadEnv(&pymain->config);
14841500
if (_Py_INIT_FAILED(pymain->err)) {
14851501
pymain->err = err;
@@ -1569,11 +1585,6 @@ pymain_init_python(_PyMain *pymain)
15691585
return -1;
15701586
}
15711587

1572-
Py_SetProgramName(pymain->program_name);
1573-
/* Don't free program_name here: the argument to Py_SetProgramName
1574-
must remain valid until Py_FinalizeEx is called. The string is freed
1575-
by pymain_free(). */
1576-
15771588
if (pymain_add_xoptions(pymain)) {
15781589
return -1;
15791590
}

PC/getpathp.c

Lines changed: 28 additions & 33 deletions

0 commit comments

Comments
 (0)