Skip to content

Commit 9f3dcf8

Browse files
authored
[3.8] bpo-38234: Fix PyConfig_Read() when Py_SetPath() was called (GH-16298) (GH-16313)
* bpo-38234: Remove _PyPathConfig.dll_path (GH-16307) The DLL path is not computed from any user configuration and cannot be configured by PyConfig. Instead, add a new _Py_dll_path global variable. Remove _PyConfig_SetPathConfig(): replaced with _PyPathConfig_Init(). Py_Initialize() now longer sets the "global path configuration", but only initialize _Py_dll_path. (cherry picked from commit c422167) * bpo-38234: Fix PyConfig_Read() when Py_SetPath() was called (GH-16298) * If Py_SetPath() has been called, _PyConfig_InitPathConfig() now uses its value. * Py_Initialize() now longer copies path configuration from PyConfig to the global path configuration (_Py_path_config). (cherry picked from commit e267793)
1 parent 245d439 commit 9f3dcf8

File tree

7 files changed

+110
-104
lines changed

7 files changed

+110
-104
lines changed

Include/internal/pycore_initconfig.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,6 @@ extern PyStatus _PyConfig_Copy(
149149
PyConfig *config,
150150
const PyConfig *config2);
151151
extern PyStatus _PyConfig_InitPathConfig(PyConfig *config);
152-
extern PyStatus _PyConfig_SetPathConfig(
153-
const PyConfig *config);
154152
extern void _PyConfig_Write(const PyConfig *config,
155153
_PyRuntimeState *runtime);
156154
extern PyStatus _PyConfig_SetPyArgv(

Include/internal/pycore_pathconfig.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@ typedef struct _PyPathConfig {
1313
wchar_t *program_full_path;
1414
wchar_t *prefix;
1515
wchar_t *exec_prefix;
16-
#ifdef MS_WINDOWS
17-
wchar_t *dll_path;
18-
#endif
19-
/* Set by Py_SetPath(), or computed by _PyPathConfig_Init() */
16+
/* Set by Py_SetPath(), or computed by _PyConfig_InitPathConfig() */
2017
wchar_t *module_search_path;
2118
/* Python program name */
2219
wchar_t *program_name;
@@ -38,6 +35,9 @@ typedef struct _PyPathConfig {
3835
/* Note: _PyPathConfig_INIT sets other fields to 0/NULL */
3936

4037
PyAPI_DATA(_PyPathConfig) _Py_path_config;
38+
#ifdef MS_WINDOWS
39+
PyAPI_DATA(wchar_t*) _Py_dll_path;
40+
#endif
4141

4242
extern void _PyPathConfig_ClearGlobal(void);
4343
extern PyStatus _PyPathConfig_SetGlobal(
@@ -59,6 +59,8 @@ extern int _Py_FindEnvConfigValue(
5959
extern wchar_t* _Py_GetDLLPath(void);
6060
#endif
6161

62+
extern PyStatus _PyPathConfig_Init(void);
63+
6264
#ifdef __cplusplus
6365
}
6466
#endif
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Python ignored path passed to :c:func:`Py_SetPath`, fix Python
2+
initialization to use the specified path.

Modules/getpath.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,10 +1213,12 @@ calculate_path_impl(const PyConfig *config,
12131213
"Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
12141214
}
12151215

1216-
status = calculate_module_search_path(config, calculate,
1217-
prefix, exec_prefix, pathconfig);
1218-
if (_PyStatus_EXCEPTION(status)) {
1219-
return status;
1216+
if (pathconfig->module_search_path == NULL) {
1217+
status = calculate_module_search_path(config, calculate,
1218+
prefix, exec_prefix, pathconfig);
1219+
if (_PyStatus_EXCEPTION(status)) {
1220+
return status;
1221+
}
12201222
}
12211223

12221224
status = calculate_reduce_prefix(calculate, prefix, Py_ARRAY_LENGTH(prefix));

PC/getpathp.c

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ typedef struct {
128128

129129
wchar_t argv0_path[MAXPATHLEN+1];
130130
wchar_t zip_path[MAXPATHLEN+1];
131+
132+
wchar_t *dll_path;
131133
} PyCalculatePath;
132134

133135

@@ -666,28 +668,36 @@ read_pth_file(_PyPathConfig *pathconfig, wchar_t *prefix, const wchar_t *path)
666668
}
667669

668670

669-
static void
671+
static PyStatus
670672
calculate_init(PyCalculatePath *calculate,
671673
const PyConfig *config)
672674
{
673675
calculate->home = config->home;
674676
calculate->path_env = _wgetenv(L"PATH");
677+
678+
calculate->dll_path = _Py_GetDLLPath();
679+
if (calculate->dll_path == NULL) {
680+
return _PyStatus_NO_MEMORY();
681+
}
682+
683+
return _PyStatus_OK();
675684
}
676685

677686

678687
static int
679-
get_pth_filename(wchar_t *spbuffer, _PyPathConfig *pathconfig)
688+
get_pth_filename(PyCalculatePath *calculate, wchar_t *filename,
689+
const _PyPathConfig *pathconfig)
680690
{
681-
if (pathconfig->dll_path[0]) {
682-
if (!change_ext(spbuffer, pathconfig->dll_path, L"._pth") &&
683-
exists(spbuffer))
691+
if (calculate->dll_path[0]) {
692+
if (!change_ext(filename, calculate->dll_path, L"._pth") &&
693+
exists(filename))
684694
{
685695
return 1;
686696
}
687697
}
688698
if (pathconfig->program_full_path[0]) {
689-
if (!change_ext(spbuffer, pathconfig->program_full_path, L"._pth") &&
690-
exists(spbuffer))
699+
if (!change_ext(filename, pathconfig->program_full_path, L"._pth") &&
700+
exists(filename))
691701
{
692702
return 1;
693703
}
@@ -697,15 +707,16 @@ get_pth_filename(wchar_t *spbuffer, _PyPathConfig *pathconfig)
697707

698708

699709
static int
700-
calculate_pth_file(_PyPathConfig *pathconfig, wchar_t *prefix)
710+
calculate_pth_file(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
711+
wchar_t *prefix)
701712
{
702-
wchar_t spbuffer[MAXPATHLEN+1];
713+
wchar_t filename[MAXPATHLEN+1];
703714

704-
if (!get_pth_filename(spbuffer, pathconfig)) {
715+
if (!get_pth_filename(calculate, filename, pathconfig)) {
705716
return 0;
706717
}
707718

708-
return read_pth_file(pathconfig, prefix, spbuffer);
719+
return read_pth_file(pathconfig, prefix, filename);
709720
}
710721

711722

@@ -966,13 +977,6 @@ calculate_path_impl(const PyConfig *config,
966977
{
967978
PyStatus status;
968979

969-
assert(pathconfig->dll_path == NULL);
970-
971-
pathconfig->dll_path = _Py_GetDLLPath();
972-
if (pathconfig->dll_path == NULL) {
973-
return _PyStatus_NO_MEMORY();
974-
}
975-
976980
status = get_program_full_path(config, calculate, pathconfig);
977981
if (_PyStatus_EXCEPTION(status)) {
978982
return status;
@@ -986,22 +990,25 @@ calculate_path_impl(const PyConfig *config,
986990
memset(prefix, 0, sizeof(prefix));
987991

988992
/* Search for a sys.path file */
989-
if (calculate_pth_file(pathconfig, prefix)) {
993+
if (calculate_pth_file(calculate, pathconfig, prefix)) {
990994
goto done;
991995
}
992996

993997
calculate_pyvenv_file(calculate);
994998

995999
/* Calculate zip archive path from DLL or exe path */
9961000
change_ext(calculate->zip_path,
997-
pathconfig->dll_path[0] ? pathconfig->dll_path : pathconfig->program_full_path,
1001+
calculate->dll_path[0] ? calculate->dll_path : pathconfig->program_full_path,
9981002
L".zip");
9991003

10001004
calculate_home_prefix(calculate, prefix);
10011005

1002-
status = calculate_module_search_path(config, calculate, pathconfig, prefix);
1003-
if (_PyStatus_EXCEPTION(status)) {
1004-
return status;
1006+
if (pathconfig->module_search_path == NULL) {
1007+
status = calculate_module_search_path(config, calculate,
1008+
pathconfig, prefix);
1009+
if (_PyStatus_EXCEPTION(status)) {
1010+
return status;
1011+
}
10051012
}
10061013

10071014
done:
@@ -1023,23 +1030,23 @@ calculate_free(PyCalculatePath *calculate)
10231030
{
10241031
PyMem_RawFree(calculate->machine_path);
10251032
PyMem_RawFree(calculate->user_path);
1033+
PyMem_RawFree(calculate->dll_path);
10261034
}
10271035

10281036

10291037
PyStatus
10301038
_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config)
10311039
{
1040+
PyStatus status;
10321041
PyCalculatePath calculate;
10331042
memset(&calculate, 0, sizeof(calculate));
10341043

1035-
calculate_init(&calculate, config);
1036-
1037-
PyStatus status = calculate_path_impl(config, &calculate, pathconfig);
1044+
status = calculate_init(&calculate, config);
10381045
if (_PyStatus_EXCEPTION(status)) {
10391046
goto done;
10401047
}
10411048

1042-
status = _PyStatus_OK();
1049+
status = calculate_path_impl(config, &calculate, pathconfig);
10431050

10441051
done:
10451052
calculate_free(&calculate);
@@ -1067,7 +1074,12 @@ _Py_CheckPython3(void)
10671074

10681075
/* If there is a python3.dll next to the python3y.dll,
10691076
assume this is a build tree; use that DLL */
1070-
wcscpy(py3path, _Py_path_config.dll_path);
1077+
if (_Py_dll_path != NULL) {
1078+
wcscpy(py3path, _Py_dll_path);
1079+
}
1080+
else {
1081+
wcscpy(py3path, L"");
1082+
}
10711083
s = wcsrchr(py3path, L'\\');
10721084
if (!s) {
10731085
s = py3path;

0 commit comments

Comments
 (0)