mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	bpo-38234: Fix _PyConfig_InitPathConfig() (GH-16335)
* _PyConfig_InitPathConfig() now starts by copying the global path configuration, and then override values set in PyConfig. * _PyPathConfig_Calculate() implementations no longer override _PyPathConfig fields which are already computed. For example, if _PyPathConfig.prefix is not NULL, leave it unchanged. * If Py_SetPath() has been called, _PyConfig_InitPathConfig() doesn't call _PyPathConfig_Calculate() anymore. * _PyPathConfig_Calculate() no longer uses PyConfig, except to initialize PyCalculatePath structure. * pathconfig_calculate(): remove useless temporary "_PyPathConfig new_config" variable. * calculate_module_search_path(): remove hack to workaround memory allocation failure, call Py_FatalError() instead. * Fix get_program_full_path(): handle memory allocation failure.
This commit is contained in:
		
							parent
							
								
									88e6447451
								
							
						
					
					
						commit
						9c42f8cda5
					
				
					 4 changed files with 318 additions and 256 deletions
				
			
		|  | @ -1,2 +1,3 @@ | ||||||
| Python ignored path passed to :c:func:`Py_SetPath`, fix Python | Python ignored arguments passed to :c:func:`Py_SetPath`, | ||||||
| initialization to use the specified path. | :c:func:`Py_SetPythonHome` and :c:func:`Py_SetProgramName`: fix Python | ||||||
|  | initialization to use specified arguments. | ||||||
|  |  | ||||||
|  | @ -133,6 +133,9 @@ typedef struct { | ||||||
| 
 | 
 | ||||||
|     int prefix_found;         /* found platform independent libraries? */ |     int prefix_found;         /* found platform independent libraries? */ | ||||||
|     int exec_prefix_found;    /* found the platform dependent libraries? */ |     int exec_prefix_found;    /* found the platform dependent libraries? */ | ||||||
|  | 
 | ||||||
|  |     int warnings; | ||||||
|  |     const wchar_t *pythonpath_env; | ||||||
| } PyCalculatePath; | } PyCalculatePath; | ||||||
| 
 | 
 | ||||||
| static const wchar_t delimiter[2] = {DELIM, '\0'}; | static const wchar_t delimiter[2] = {DELIM, '\0'}; | ||||||
|  | @ -365,17 +368,16 @@ add_exe_suffix(wchar_t *progpath, size_t progpathlen) | ||||||
|    bytes long. |    bytes long. | ||||||
| */ | */ | ||||||
| static PyStatus | static PyStatus | ||||||
| search_for_prefix(const PyConfig *config, PyCalculatePath *calculate, | search_for_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, | ||||||
|                   wchar_t *prefix, size_t prefix_len, |                   wchar_t *prefix, size_t prefix_len, int *found) | ||||||
|                   int *found) |  | ||||||
| { | { | ||||||
|     PyStatus status; |     PyStatus status; | ||||||
|     size_t n; |     size_t n; | ||||||
|     wchar_t *vpath; |     wchar_t *vpath; | ||||||
| 
 | 
 | ||||||
|     /* If PYTHONHOME is set, we believe it unconditionally */ |     /* If PYTHONHOME is set, we believe it unconditionally */ | ||||||
|     if (config->home) { |     if (pathconfig->home) { | ||||||
|         if (safe_wcscpy(prefix, config->home, prefix_len) < 0) { |         if (safe_wcscpy(prefix, pathconfig->home, prefix_len) < 0) { | ||||||
|             return PATHLEN_ERR(); |             return PATHLEN_ERR(); | ||||||
|         } |         } | ||||||
|         wchar_t *delim = wcschr(prefix, DELIM); |         wchar_t *delim = wcschr(prefix, DELIM); | ||||||
|  | @ -482,19 +484,19 @@ search_for_prefix(const PyConfig *config, PyCalculatePath *calculate, | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static PyStatus | static PyStatus | ||||||
| calculate_prefix(const PyConfig *config, | calculate_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, | ||||||
|                  PyCalculatePath *calculate, wchar_t *prefix, size_t prefix_len) |                  wchar_t *prefix, size_t prefix_len) | ||||||
| { | { | ||||||
|     PyStatus status; |     PyStatus status; | ||||||
| 
 | 
 | ||||||
|     status = search_for_prefix(config, calculate, prefix, prefix_len, |     status = search_for_prefix(calculate, pathconfig, prefix, prefix_len, | ||||||
|                             &calculate->prefix_found); |                                &calculate->prefix_found); | ||||||
|     if (_PyStatus_EXCEPTION(status)) { |     if (_PyStatus_EXCEPTION(status)) { | ||||||
|         return status; |         return status; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!calculate->prefix_found) { |     if (!calculate->prefix_found) { | ||||||
|         if (config->pathconfig_warnings) { |         if (calculate->warnings) { | ||||||
|             fprintf(stderr, |             fprintf(stderr, | ||||||
|                 "Could not find platform independent libraries <prefix>\n"); |                 "Could not find platform independent libraries <prefix>\n"); | ||||||
|         } |         } | ||||||
|  | @ -544,8 +546,7 @@ calculate_reduce_prefix(PyCalculatePath *calculate, | ||||||
|    MAXPATHLEN bytes long. |    MAXPATHLEN bytes long. | ||||||
| */ | */ | ||||||
| static PyStatus | static PyStatus | ||||||
| search_for_exec_prefix(const PyConfig *config, | search_for_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, | ||||||
|                        PyCalculatePath *calculate, |  | ||||||
|                        wchar_t *exec_prefix, size_t exec_prefix_len, |                        wchar_t *exec_prefix, size_t exec_prefix_len, | ||||||
|                        int *found) |                        int *found) | ||||||
| { | { | ||||||
|  | @ -553,15 +554,15 @@ search_for_exec_prefix(const PyConfig *config, | ||||||
|     size_t n; |     size_t n; | ||||||
| 
 | 
 | ||||||
|     /* If PYTHONHOME is set, we believe it unconditionally */ |     /* If PYTHONHOME is set, we believe it unconditionally */ | ||||||
|     if (config->home) { |     if (pathconfig->home) { | ||||||
|         wchar_t *delim = wcschr(config->home, DELIM); |         wchar_t *delim = wcschr(pathconfig->home, DELIM); | ||||||
|         if (delim) { |         if (delim) { | ||||||
|             if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) { |             if (safe_wcscpy(exec_prefix, delim+1, exec_prefix_len) < 0) { | ||||||
|                 return PATHLEN_ERR(); |                 return PATHLEN_ERR(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             if (safe_wcscpy(exec_prefix, config->home, exec_prefix_len) < 0) { |             if (safe_wcscpy(exec_prefix, pathconfig->home, exec_prefix_len) < 0) { | ||||||
|                 return PATHLEN_ERR(); |                 return PATHLEN_ERR(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -668,21 +669,20 @@ search_for_exec_prefix(const PyConfig *config, | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static PyStatus | static PyStatus | ||||||
| calculate_exec_prefix(const PyConfig *config, | calculate_exec_prefix(PyCalculatePath *calculate, _PyPathConfig *pathconfig, | ||||||
|                       PyCalculatePath *calculate, |  | ||||||
|                       wchar_t *exec_prefix, size_t exec_prefix_len) |                       wchar_t *exec_prefix, size_t exec_prefix_len) | ||||||
| { | { | ||||||
|     PyStatus status; |     PyStatus status; | ||||||
| 
 | 
 | ||||||
|     status = search_for_exec_prefix(config, calculate, |     status = search_for_exec_prefix(calculate, pathconfig, | ||||||
|                                  exec_prefix, exec_prefix_len, |                                     exec_prefix, exec_prefix_len, | ||||||
|                                  &calculate->exec_prefix_found); |                                     &calculate->exec_prefix_found); | ||||||
|     if (_PyStatus_EXCEPTION(status)) { |     if (_PyStatus_EXCEPTION(status)) { | ||||||
|         return status; |         return status; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!calculate->exec_prefix_found) { |     if (!calculate->exec_prefix_found) { | ||||||
|         if (config->pathconfig_warnings) { |         if (calculate->warnings) { | ||||||
|             fprintf(stderr, |             fprintf(stderr, | ||||||
|                 "Could not find platform dependent libraries <exec_prefix>\n"); |                 "Could not find platform dependent libraries <exec_prefix>\n"); | ||||||
|         } |         } | ||||||
|  | @ -721,8 +721,7 @@ calculate_reduce_exec_prefix(PyCalculatePath *calculate, | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static PyStatus | static PyStatus | ||||||
| calculate_program_full_path(const PyConfig *config, | calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) | ||||||
|                             PyCalculatePath *calculate, _PyPathConfig *pathconfig) |  | ||||||
| { | { | ||||||
|     PyStatus status; |     PyStatus status; | ||||||
|     wchar_t program_full_path[MAXPATHLEN + 1]; |     wchar_t program_full_path[MAXPATHLEN + 1]; | ||||||
|  | @ -743,8 +742,8 @@ calculate_program_full_path(const PyConfig *config, | ||||||
|      * other way to find a directory to start the search from.  If |      * other way to find a directory to start the search from.  If | ||||||
|      * $PATH isn't exported, you lose. |      * $PATH isn't exported, you lose. | ||||||
|      */ |      */ | ||||||
|     if (wcschr(config->program_name, SEP)) { |     if (wcschr(pathconfig->program_name, SEP)) { | ||||||
|         if (safe_wcscpy(program_full_path, config->program_name, |         if (safe_wcscpy(program_full_path, pathconfig->program_name, | ||||||
|                         program_full_path_len) < 0) { |                         program_full_path_len) < 0) { | ||||||
|             return PATHLEN_ERR(); |             return PATHLEN_ERR(); | ||||||
|         } |         } | ||||||
|  | @ -795,8 +794,8 @@ calculate_program_full_path(const PyConfig *config, | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             status = joinpath(program_full_path, config->program_name, |             status = joinpath(program_full_path, pathconfig->program_name, | ||||||
|                             program_full_path_len); |                               program_full_path_len); | ||||||
|             if (_PyStatus_EXCEPTION(status)) { |             if (_PyStatus_EXCEPTION(status)) { | ||||||
|                 return status; |                 return status; | ||||||
|             } |             } | ||||||
|  | @ -1030,15 +1029,14 @@ calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static PyStatus | static PyStatus | ||||||
| calculate_module_search_path(const PyConfig *config, | calculate_module_search_path(PyCalculatePath *calculate, | ||||||
|                              PyCalculatePath *calculate, |                              _PyPathConfig *pathconfig, | ||||||
|                              const wchar_t *prefix, const wchar_t *exec_prefix, |                              const wchar_t *prefix, const wchar_t *exec_prefix) | ||||||
|                              _PyPathConfig *pathconfig) |  | ||||||
| { | { | ||||||
|     /* Calculate size of return buffer */ |     /* Calculate size of return buffer */ | ||||||
|     size_t bufsz = 0; |     size_t bufsz = 0; | ||||||
|     if (config->pythonpath_env != NULL) { |     if (calculate->pythonpath_env != NULL) { | ||||||
|         bufsz += wcslen(config->pythonpath_env) + 1; |         bufsz += wcslen(calculate->pythonpath_env) + 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     wchar_t *defpath = calculate->pythonpath; |     wchar_t *defpath = calculate->pythonpath; | ||||||
|  | @ -1072,8 +1070,8 @@ calculate_module_search_path(const PyConfig *config, | ||||||
|     buf[0] = '\0'; |     buf[0] = '\0'; | ||||||
| 
 | 
 | ||||||
|     /* Run-time value of $PYTHONPATH goes first */ |     /* Run-time value of $PYTHONPATH goes first */ | ||||||
|     if (config->pythonpath_env) { |     if (calculate->pythonpath_env) { | ||||||
|         wcscpy(buf, config->pythonpath_env); |         wcscpy(buf, calculate->pythonpath_env); | ||||||
|         wcscat(buf, delimiter); |         wcscat(buf, delimiter); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -1149,6 +1147,10 @@ calculate_init(PyCalculatePath *calculate, | ||||||
|     if (!calculate->lib_python) { |     if (!calculate->lib_python) { | ||||||
|         return DECODE_LOCALE_ERR("EXEC_PREFIX define", len); |         return DECODE_LOCALE_ERR("EXEC_PREFIX define", len); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     calculate->warnings = config->pathconfig_warnings; | ||||||
|  |     calculate->pythonpath_env = config->pythonpath_env; | ||||||
|  | 
 | ||||||
|     return _PyStatus_OK(); |     return _PyStatus_OK(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1165,14 +1167,15 @@ calculate_free(PyCalculatePath *calculate) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static PyStatus | static PyStatus | ||||||
| calculate_path_impl(const PyConfig *config, | calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) | ||||||
|                     PyCalculatePath *calculate, _PyPathConfig *pathconfig) |  | ||||||
| { | { | ||||||
|     PyStatus status; |     PyStatus status; | ||||||
| 
 | 
 | ||||||
|     status = calculate_program_full_path(config, calculate, pathconfig); |     if (pathconfig->program_full_path == NULL) { | ||||||
|     if (_PyStatus_EXCEPTION(status)) { |         status = calculate_program_full_path(calculate, pathconfig); | ||||||
|         return status; |         if (_PyStatus_EXCEPTION(status)) { | ||||||
|  |             return status; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     status = calculate_argv0_path(calculate, pathconfig->program_full_path); |     status = calculate_argv0_path(calculate, pathconfig->program_full_path); | ||||||
|  | @ -1187,8 +1190,8 @@ calculate_path_impl(const PyConfig *config, | ||||||
| 
 | 
 | ||||||
|     wchar_t prefix[MAXPATHLEN+1]; |     wchar_t prefix[MAXPATHLEN+1]; | ||||||
|     memset(prefix, 0, sizeof(prefix)); |     memset(prefix, 0, sizeof(prefix)); | ||||||
|     status = calculate_prefix(config, calculate, |     status = calculate_prefix(calculate, pathconfig, | ||||||
|                            prefix, Py_ARRAY_LENGTH(prefix)); |                               prefix, Py_ARRAY_LENGTH(prefix)); | ||||||
|     if (_PyStatus_EXCEPTION(status)) { |     if (_PyStatus_EXCEPTION(status)) { | ||||||
|         return status; |         return status; | ||||||
|     } |     } | ||||||
|  | @ -1200,52 +1203,65 @@ calculate_path_impl(const PyConfig *config, | ||||||
| 
 | 
 | ||||||
|     wchar_t exec_prefix[MAXPATHLEN+1]; |     wchar_t exec_prefix[MAXPATHLEN+1]; | ||||||
|     memset(exec_prefix, 0, sizeof(exec_prefix)); |     memset(exec_prefix, 0, sizeof(exec_prefix)); | ||||||
|     status = calculate_exec_prefix(config, calculate, |     status = calculate_exec_prefix(calculate, pathconfig, | ||||||
|                                 exec_prefix, Py_ARRAY_LENGTH(exec_prefix)); |                                    exec_prefix, Py_ARRAY_LENGTH(exec_prefix)); | ||||||
|     if (_PyStatus_EXCEPTION(status)) { |     if (_PyStatus_EXCEPTION(status)) { | ||||||
|         return status; |         return status; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if ((!calculate->prefix_found || !calculate->exec_prefix_found) && |     if ((!calculate->prefix_found || !calculate->exec_prefix_found) && | ||||||
|         config->pathconfig_warnings) |         calculate->warnings) | ||||||
|     { |     { | ||||||
|         fprintf(stderr, |         fprintf(stderr, | ||||||
|                 "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n"); |                 "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (pathconfig->module_search_path == NULL) { |     if (pathconfig->module_search_path == NULL) { | ||||||
|         status = calculate_module_search_path(config, calculate, |         status = calculate_module_search_path(calculate, pathconfig, | ||||||
|                                               prefix, exec_prefix, pathconfig); |                                               prefix, exec_prefix); | ||||||
|         if (_PyStatus_EXCEPTION(status)) { |         if (_PyStatus_EXCEPTION(status)) { | ||||||
|             return status; |             return status; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     status = calculate_reduce_prefix(calculate, prefix, Py_ARRAY_LENGTH(prefix)); |  | ||||||
|     if (_PyStatus_EXCEPTION(status)) { |  | ||||||
|         return status; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pathconfig->prefix = _PyMem_RawWcsdup(prefix); |  | ||||||
|     if (pathconfig->prefix == NULL) { |     if (pathconfig->prefix == NULL) { | ||||||
|         return _PyStatus_NO_MEMORY(); |         status = calculate_reduce_prefix(calculate, prefix, Py_ARRAY_LENGTH(prefix)); | ||||||
|  |         if (_PyStatus_EXCEPTION(status)) { | ||||||
|  |             return status; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         pathconfig->prefix = _PyMem_RawWcsdup(prefix); | ||||||
|  |         if (pathconfig->prefix == NULL) { | ||||||
|  |             return _PyStatus_NO_MEMORY(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     status = calculate_reduce_exec_prefix(calculate, |  | ||||||
|                                        exec_prefix, Py_ARRAY_LENGTH(exec_prefix)); |  | ||||||
|     if (_PyStatus_EXCEPTION(status)) { |  | ||||||
|         return status; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pathconfig->exec_prefix = _PyMem_RawWcsdup(exec_prefix); |  | ||||||
|     if (pathconfig->exec_prefix == NULL) { |     if (pathconfig->exec_prefix == NULL) { | ||||||
|         return _PyStatus_NO_MEMORY(); |         status = calculate_reduce_exec_prefix(calculate, | ||||||
|  |                                               exec_prefix, | ||||||
|  |                                               Py_ARRAY_LENGTH(exec_prefix)); | ||||||
|  |         if (_PyStatus_EXCEPTION(status)) { | ||||||
|  |             return status; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         pathconfig->exec_prefix = _PyMem_RawWcsdup(exec_prefix); | ||||||
|  |         if (pathconfig->exec_prefix == NULL) { | ||||||
|  |             return _PyStatus_NO_MEMORY(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return _PyStatus_OK(); |     return _PyStatus_OK(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | /* Calculate 'pathconfig' attributes:
 | ||||||
|  | 
 | ||||||
|  |    - program_full_path | ||||||
|  |    - module_search_path | ||||||
|  |    - prefix | ||||||
|  |    - exec_prefix | ||||||
|  | 
 | ||||||
|  |    If an attribute is already set (non NULL), it is left unchanged. */ | ||||||
| PyStatus | PyStatus | ||||||
| _PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config) | _PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config) | ||||||
| { | { | ||||||
|  | @ -1258,7 +1274,7 @@ _PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config) | ||||||
|         goto done; |         goto done; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     status = calculate_path_impl(config, &calculate, pathconfig); |     status = calculate_path(&calculate, pathconfig); | ||||||
|     if (_PyStatus_EXCEPTION(status)) { |     if (_PyStatus_EXCEPTION(status)) { | ||||||
|         goto done; |         goto done; | ||||||
|     } |     } | ||||||
|  |  | ||||||
							
								
								
									
										110
									
								
								PC/getpathp.c
									
										
									
									
									
								
							
							
						
						
									
										110
									
								
								PC/getpathp.c
									
										
									
									
									
								
							|  | @ -130,6 +130,8 @@ typedef struct { | ||||||
|     wchar_t zip_path[MAXPATHLEN+1]; |     wchar_t zip_path[MAXPATHLEN+1]; | ||||||
| 
 | 
 | ||||||
|     wchar_t *dll_path; |     wchar_t *dll_path; | ||||||
|  | 
 | ||||||
|  |     const wchar_t *pythonpath_env; | ||||||
| } PyCalculatePath; | } PyCalculatePath; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -322,7 +324,7 @@ gotlandmark(wchar_t *prefix, const wchar_t *landmark) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* assumes argv0_path is MAXPATHLEN+1 bytes long, already \0 term'd.
 | /* assumes argv0_path is MAXPATHLEN+1 bytes long, already \0 term'd.
 | ||||||
|    assumption provided by only caller, calculate_path_impl() */ |    assumption provided by only caller, calculate_path() */ | ||||||
| static int | static int | ||||||
| search_for_prefix(wchar_t *prefix, const wchar_t *argv0_path, const wchar_t *landmark) | search_for_prefix(wchar_t *prefix, const wchar_t *argv0_path, const wchar_t *landmark) | ||||||
| { | { | ||||||
|  | @ -534,6 +536,7 @@ _Py_GetDLLPath(void) | ||||||
| static PyStatus | static PyStatus | ||||||
| get_program_full_path(_PyPathConfig *pathconfig) | get_program_full_path(_PyPathConfig *pathconfig) | ||||||
| { | { | ||||||
|  |     PyStatus status; | ||||||
|     const wchar_t *pyvenv_launcher; |     const wchar_t *pyvenv_launcher; | ||||||
|     wchar_t program_full_path[MAXPATHLEN+1]; |     wchar_t program_full_path[MAXPATHLEN+1]; | ||||||
|     memset(program_full_path, 0, sizeof(program_full_path)); |     memset(program_full_path, 0, sizeof(program_full_path)); | ||||||
|  | @ -548,12 +551,18 @@ get_program_full_path(_PyPathConfig *pathconfig) | ||||||
|     pyvenv_launcher = _wgetenv(L"__PYVENV_LAUNCHER__"); |     pyvenv_launcher = _wgetenv(L"__PYVENV_LAUNCHER__"); | ||||||
|     if (pyvenv_launcher && pyvenv_launcher[0]) { |     if (pyvenv_launcher && pyvenv_launcher[0]) { | ||||||
|         /* If overridden, preserve the original full path */ |         /* If overridden, preserve the original full path */ | ||||||
|         pathconfig->base_executable = PyMem_RawMalloc( |         if (pathconfig->base_executable == NULL) { | ||||||
|             sizeof(wchar_t) * (MAXPATHLEN + 1)); |             pathconfig->base_executable = PyMem_RawMalloc( | ||||||
|         PyStatus status = canonicalize(pathconfig->base_executable, |                 sizeof(wchar_t) * (MAXPATHLEN + 1)); | ||||||
|                                        program_full_path); |             if (pathconfig->base_executable == NULL) { | ||||||
|         if (_PyStatus_EXCEPTION(status)) { |                 return _PyStatus_NO_MEMORY(); | ||||||
|             return status; |             } | ||||||
|  | 
 | ||||||
|  |             status = canonicalize(pathconfig->base_executable, | ||||||
|  |                                   program_full_path); | ||||||
|  |             if (_PyStatus_EXCEPTION(status)) { | ||||||
|  |                 return status; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         wcscpy_s(program_full_path, MAXPATHLEN+1, pyvenv_launcher); |         wcscpy_s(program_full_path, MAXPATHLEN+1, pyvenv_launcher); | ||||||
|  | @ -562,11 +571,20 @@ get_program_full_path(_PyPathConfig *pathconfig) | ||||||
|         _wputenv_s(L"__PYVENV_LAUNCHER__", L""); |         _wputenv_s(L"__PYVENV_LAUNCHER__", L""); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pathconfig->program_full_path = PyMem_RawMalloc( |     if (pathconfig->program_full_path == NULL) { | ||||||
|         sizeof(wchar_t) * (MAXPATHLEN + 1)); |         pathconfig->program_full_path = PyMem_RawMalloc( | ||||||
|  |             sizeof(wchar_t) * (MAXPATHLEN + 1)); | ||||||
|  |         if (pathconfig->program_full_path == NULL) { | ||||||
|  |             return _PyStatus_NO_MEMORY(); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     return canonicalize(pathconfig->program_full_path, |         status = canonicalize(pathconfig->program_full_path, | ||||||
|                         program_full_path); |                               program_full_path); | ||||||
|  |         if (_PyStatus_EXCEPTION(status)) { | ||||||
|  |             return status; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return _PyStatus_OK(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -657,7 +675,13 @@ read_pth_file(_PyPathConfig *pathconfig, wchar_t *prefix, const wchar_t *path) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fclose(sp_file); |     fclose(sp_file); | ||||||
|     pathconfig->module_search_path = buf; |     if (pathconfig->module_search_path == NULL) { | ||||||
|  |         pathconfig->module_search_path = _PyMem_RawWcsdup(buf); | ||||||
|  |         if (pathconfig->module_search_path == NULL) { | ||||||
|  |             Py_FatalError("out of memory"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     PyMem_RawFree(buf); | ||||||
|     return 1; |     return 1; | ||||||
| 
 | 
 | ||||||
| error: | error: | ||||||
|  | @ -668,8 +692,7 @@ read_pth_file(_PyPathConfig *pathconfig, wchar_t *prefix, const wchar_t *path) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static PyStatus | static PyStatus | ||||||
| calculate_init(PyCalculatePath *calculate, | calculate_init(PyCalculatePath *calculate, const PyConfig *config) | ||||||
|                const PyConfig *config) |  | ||||||
| { | { | ||||||
|     calculate->home = config->home; |     calculate->home = config->home; | ||||||
|     calculate->path_env = _wgetenv(L"PATH"); |     calculate->path_env = _wgetenv(L"PATH"); | ||||||
|  | @ -679,6 +702,8 @@ calculate_init(PyCalculatePath *calculate, | ||||||
|         return _PyStatus_NO_MEMORY(); |         return _PyStatus_NO_MEMORY(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     calculate->pythonpath_env = config->pythonpath_env; | ||||||
|  | 
 | ||||||
|     return _PyStatus_OK(); |     return _PyStatus_OK(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -785,8 +810,8 @@ calculate_home_prefix(PyCalculatePath *calculate, wchar_t *prefix) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static PyStatus | static PyStatus | ||||||
| calculate_module_search_path(const PyConfig *config, | calculate_module_search_path(PyCalculatePath *calculate, | ||||||
|                              PyCalculatePath *calculate, _PyPathConfig *pathconfig, |                              _PyPathConfig *pathconfig, | ||||||
|                              wchar_t *prefix) |                              wchar_t *prefix) | ||||||
| { | { | ||||||
|     int skiphome = calculate->home==NULL ? 0 : 1; |     int skiphome = calculate->home==NULL ? 0 : 1; | ||||||
|  | @ -796,7 +821,7 @@ calculate_module_search_path(const PyConfig *config, | ||||||
| #endif | #endif | ||||||
|     /* We only use the default relative PYTHONPATH if we haven't
 |     /* We only use the default relative PYTHONPATH if we haven't
 | ||||||
|        anything better to use! */ |        anything better to use! */ | ||||||
|     int skipdefault = (config->pythonpath_env != NULL || |     int skipdefault = (calculate->pythonpath_env != NULL || | ||||||
|                        calculate->home != NULL || |                        calculate->home != NULL || | ||||||
|                        calculate->machine_path != NULL || |                        calculate->machine_path != NULL || | ||||||
|                        calculate->user_path != NULL); |                        calculate->user_path != NULL); | ||||||
|  | @ -835,30 +860,20 @@ calculate_module_search_path(const PyConfig *config, | ||||||
|         bufsz += wcslen(calculate->machine_path) + 1; |         bufsz += wcslen(calculate->machine_path) + 1; | ||||||
|     } |     } | ||||||
|     bufsz += wcslen(calculate->zip_path) + 1; |     bufsz += wcslen(calculate->zip_path) + 1; | ||||||
|     if (config->pythonpath_env != NULL) { |     if (calculate->pythonpath_env != NULL) { | ||||||
|         bufsz += wcslen(config->pythonpath_env) + 1; |         bufsz += wcslen(calculate->pythonpath_env) + 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     wchar_t *buf, *start_buf; |     wchar_t *buf, *start_buf; | ||||||
|     buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t)); |     buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t)); | ||||||
|     if (buf == NULL) { |     if (buf == NULL) { | ||||||
|         /* We can't exit, so print a warning and limp along */ |         Py_FatalError("Can't malloc dynamic PYTHONPATH"); | ||||||
|         fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n"); |  | ||||||
|         if (config->pythonpath_env) { |  | ||||||
|             fprintf(stderr, "Using environment $PYTHONPATH.\n"); |  | ||||||
|             pathconfig->module_search_path = config->pythonpath_env; |  | ||||||
|         } |  | ||||||
|         else { |  | ||||||
|             fprintf(stderr, "Using default static path.\n"); |  | ||||||
|             pathconfig->module_search_path = PYTHONPATH; |  | ||||||
|         } |  | ||||||
|         return _PyStatus_OK(); |  | ||||||
|     } |     } | ||||||
|     start_buf = buf; |     start_buf = buf; | ||||||
| 
 | 
 | ||||||
|     if (config->pythonpath_env) { |     if (calculate->pythonpath_env) { | ||||||
|         if (wcscpy_s(buf, bufsz - (buf - start_buf), |         if (wcscpy_s(buf, bufsz - (buf - start_buf), | ||||||
|                      config->pythonpath_env)) { |                      calculate->pythonpath_env)) { | ||||||
|             return INIT_ERR_BUFFER_OVERFLOW(); |             return INIT_ERR_BUFFER_OVERFLOW(); | ||||||
|         } |         } | ||||||
|         buf = wcschr(buf, L'\0'); |         buf = wcschr(buf, L'\0'); | ||||||
|  | @ -971,8 +986,7 @@ calculate_module_search_path(const PyConfig *config, | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static PyStatus | static PyStatus | ||||||
| calculate_path_impl(const PyConfig *config, | calculate_path(PyCalculatePath *calculate, _PyPathConfig *pathconfig) | ||||||
|                     PyCalculatePath *calculate, _PyPathConfig *pathconfig) |  | ||||||
| { | { | ||||||
|     PyStatus status; |     PyStatus status; | ||||||
| 
 | 
 | ||||||
|  | @ -1003,21 +1017,24 @@ calculate_path_impl(const PyConfig *config, | ||||||
|     calculate_home_prefix(calculate, prefix); |     calculate_home_prefix(calculate, prefix); | ||||||
| 
 | 
 | ||||||
|     if (pathconfig->module_search_path == NULL) { |     if (pathconfig->module_search_path == NULL) { | ||||||
|         status = calculate_module_search_path(config, calculate, |         status = calculate_module_search_path(calculate, pathconfig, prefix); | ||||||
|                                               pathconfig, prefix); |  | ||||||
|         if (_PyStatus_EXCEPTION(status)) { |         if (_PyStatus_EXCEPTION(status)) { | ||||||
|             return status; |             return status; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| done: | done: | ||||||
|     pathconfig->prefix = _PyMem_RawWcsdup(prefix); |  | ||||||
|     if (pathconfig->prefix == NULL) { |     if (pathconfig->prefix == NULL) { | ||||||
|         return _PyStatus_NO_MEMORY(); |         pathconfig->prefix = _PyMem_RawWcsdup(prefix); | ||||||
|  |         if (pathconfig->prefix == NULL) { | ||||||
|  |             return _PyStatus_NO_MEMORY(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     pathconfig->exec_prefix = _PyMem_RawWcsdup(prefix); |  | ||||||
|     if (pathconfig->exec_prefix == NULL) { |     if (pathconfig->exec_prefix == NULL) { | ||||||
|         return _PyStatus_NO_MEMORY(); |         pathconfig->exec_prefix = _PyMem_RawWcsdup(prefix); | ||||||
|  |         if (pathconfig->exec_prefix == NULL) { | ||||||
|  |             return _PyStatus_NO_MEMORY(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return _PyStatus_OK(); |     return _PyStatus_OK(); | ||||||
|  | @ -1033,6 +1050,17 @@ calculate_free(PyCalculatePath *calculate) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | /* Calculate 'pathconfig' attributes:
 | ||||||
|  | 
 | ||||||
|  |    - base_executable | ||||||
|  |    - program_full_path | ||||||
|  |    - module_search_path | ||||||
|  |    - prefix | ||||||
|  |    - exec_prefix | ||||||
|  |    - isolated | ||||||
|  |    - site_import | ||||||
|  | 
 | ||||||
|  |    If an attribute is already set (non NULL), it is left unchanged. */ | ||||||
| PyStatus | PyStatus | ||||||
| _PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config) | _PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config) | ||||||
| { | { | ||||||
|  | @ -1045,7 +1073,7 @@ _PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config) | ||||||
|         goto done; |         goto done; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     status = calculate_path_impl(config, &calculate, pathconfig); |     status = calculate_path(&calculate, pathconfig); | ||||||
| 
 | 
 | ||||||
| done: | done: | ||||||
|     calculate_free(&calculate); |     calculate_free(&calculate); | ||||||
|  |  | ||||||
|  | @ -51,12 +51,12 @@ pathconfig_clear(_PyPathConfig *config) | ||||||
|         ATTR = NULL; \ |         ATTR = NULL; \ | ||||||
|     } while (0) |     } while (0) | ||||||
| 
 | 
 | ||||||
|     CLEAR(config->prefix); |  | ||||||
|     CLEAR(config->program_full_path); |     CLEAR(config->program_full_path); | ||||||
|  |     CLEAR(config->prefix); | ||||||
|     CLEAR(config->exec_prefix); |     CLEAR(config->exec_prefix); | ||||||
|     CLEAR(config->module_search_path); |     CLEAR(config->module_search_path); | ||||||
|     CLEAR(config->home); |  | ||||||
|     CLEAR(config->program_name); |     CLEAR(config->program_name); | ||||||
|  |     CLEAR(config->home); | ||||||
|     CLEAR(config->base_executable); |     CLEAR(config->base_executable); | ||||||
| #undef CLEAR | #undef CLEAR | ||||||
| 
 | 
 | ||||||
|  | @ -64,60 +64,31 @@ pathconfig_clear(_PyPathConfig *config) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Calculate the path configuration: initialize pathconfig from config */ |  | ||||||
| static PyStatus | static PyStatus | ||||||
| pathconfig_calculate(_PyPathConfig *pathconfig, const PyConfig *config) | pathconfig_copy(_PyPathConfig *config, const _PyPathConfig *config2) | ||||||
| { | { | ||||||
|     PyStatus status; |     pathconfig_clear(config); | ||||||
|     _PyPathConfig new_config = _PyPathConfig_INIT; |  | ||||||
| 
 | 
 | ||||||
|     PyMemAllocatorEx old_alloc; | #define COPY_ATTR(ATTR) \ | ||||||
|     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |     do { \ | ||||||
|  |         if (copy_wstr(&config->ATTR, config2->ATTR) < 0) { \ | ||||||
|  |             return _PyStatus_NO_MEMORY(); \ | ||||||
|  |         } \ | ||||||
|  |     } while (0) | ||||||
| 
 | 
 | ||||||
|     if (copy_wstr(&new_config.module_search_path, |     COPY_ATTR(program_full_path); | ||||||
|                   _Py_path_config.module_search_path) < 0) |     COPY_ATTR(prefix); | ||||||
|     { |     COPY_ATTR(exec_prefix); | ||||||
|         status = _PyStatus_NO_MEMORY(); |     COPY_ATTR(module_search_path); | ||||||
|         goto error; |     COPY_ATTR(program_name); | ||||||
|     } |     COPY_ATTR(home); | ||||||
|  |     config->isolated = config2->isolated; | ||||||
|  |     config->site_import = config2->site_import; | ||||||
|  |     COPY_ATTR(base_executable); | ||||||
| 
 | 
 | ||||||
|     /* Calculate program_full_path, prefix, exec_prefix,
 | #undef COPY_ATTR | ||||||
|        dll_path (Windows), and module_search_path */ |  | ||||||
|     status = _PyPathConfig_Calculate(&new_config, config); |  | ||||||
|     if (_PyStatus_EXCEPTION(status)) { |  | ||||||
|         goto error; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     /* Copy home and program_name from config */ |     return _PyStatus_OK(); | ||||||
|     if (copy_wstr(&new_config.home, config->home) < 0) { |  | ||||||
|         status = _PyStatus_NO_MEMORY(); |  | ||||||
|         goto error; |  | ||||||
|     } |  | ||||||
|     if (copy_wstr(&new_config.program_name, config->program_name) < 0) { |  | ||||||
|         status = _PyStatus_NO_MEMORY(); |  | ||||||
|         goto error; |  | ||||||
|     } |  | ||||||
|     if (config->base_executable) { |  | ||||||
|         PyMem_RawFree(new_config.base_executable); |  | ||||||
|         if (copy_wstr(&new_config.base_executable, |  | ||||||
|                       config->base_executable) < 0) { |  | ||||||
|             status = _PyStatus_NO_MEMORY(); |  | ||||||
|             goto error; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pathconfig_clear(pathconfig); |  | ||||||
|     *pathconfig = new_config; |  | ||||||
| 
 |  | ||||||
|     status = _PyStatus_OK(); |  | ||||||
|     goto done; |  | ||||||
| 
 |  | ||||||
| error: |  | ||||||
|     pathconfig_clear(&new_config); |  | ||||||
| 
 |  | ||||||
| done: |  | ||||||
|     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |  | ||||||
|     return status; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -168,7 +139,7 @@ _PyWideStringList_Join(const PyWideStringList *list, wchar_t sep) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Set the global path configuration from config. */ | /* Initialize _Py_dll_path on Windows. Do nothing on other platforms. */ | ||||||
| PyStatus | PyStatus | ||||||
| _PyPathConfig_Init(void) | _PyPathConfig_Init(void) | ||||||
| { | { | ||||||
|  | @ -194,47 +165,39 @@ _PyPathConfig_Init(void) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static PyStatus | static PyStatus | ||||||
| pathconfig_global_init_from_config(const PyConfig *config) | pathconfig_set_from_config(_PyPathConfig *pathconfig, const PyConfig *config) | ||||||
| { | { | ||||||
|     PyStatus status; |     PyStatus status; | ||||||
|     PyMemAllocatorEx old_alloc; |     PyMemAllocatorEx old_alloc; | ||||||
|     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); | ||||||
| 
 | 
 | ||||||
|     _PyPathConfig pathconfig = _PyPathConfig_INIT; |     if (config->module_search_paths_set) { | ||||||
| 
 |         pathconfig->module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM); | ||||||
|     pathconfig.module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM); |         if (pathconfig->module_search_path == NULL) { | ||||||
|     if (pathconfig.module_search_path == NULL) { |             goto no_memory; | ||||||
|         goto no_memory; |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (copy_wstr(&pathconfig.program_full_path, config->executable) < 0) { | #define COPY_CONFIG(PATH_ATTR, CONFIG_ATTR) \ | ||||||
|         goto no_memory; |         if (config->CONFIG_ATTR) { \ | ||||||
|     } |             if (copy_wstr(&pathconfig->PATH_ATTR, config->CONFIG_ATTR) < 0) { \ | ||||||
|     if (copy_wstr(&pathconfig.prefix, config->prefix) < 0) { |                 goto no_memory; \ | ||||||
|         goto no_memory; |             } \ | ||||||
|     } |         } | ||||||
|     if (copy_wstr(&pathconfig.exec_prefix, config->exec_prefix) < 0) { |  | ||||||
|         goto no_memory; |  | ||||||
|     } |  | ||||||
|     if (copy_wstr(&pathconfig.program_name, config->program_name) < 0) { |  | ||||||
|         goto no_memory; |  | ||||||
|     } |  | ||||||
|     if (copy_wstr(&pathconfig.home, config->home) < 0) { |  | ||||||
|         goto no_memory; |  | ||||||
|     } |  | ||||||
|     if (copy_wstr(&pathconfig.base_executable, config->base_executable) < 0) { |  | ||||||
|         goto no_memory; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     pathconfig_clear(&_Py_path_config); |     COPY_CONFIG(base_executable, base_executable); | ||||||
|     /* Steal new_config strings; don't clear new_config */ |     COPY_CONFIG(program_full_path, executable); | ||||||
|     _Py_path_config = pathconfig; |     COPY_CONFIG(prefix, prefix); | ||||||
|  |     COPY_CONFIG(exec_prefix, exec_prefix); | ||||||
|  |     COPY_CONFIG(program_name, program_name); | ||||||
|  |     COPY_CONFIG(home, home); | ||||||
|  | 
 | ||||||
|  | #undef COPY_CONFIG | ||||||
| 
 | 
 | ||||||
|     status = _PyStatus_OK(); |     status = _PyStatus_OK(); | ||||||
|     goto done; |     goto done; | ||||||
| 
 | 
 | ||||||
| no_memory: | no_memory: | ||||||
|     pathconfig_clear(&pathconfig); |  | ||||||
|     status = _PyStatus_NO_MEMORY(); |     status = _PyStatus_NO_MEMORY(); | ||||||
| 
 | 
 | ||||||
| done: | done: | ||||||
|  | @ -283,6 +246,61 @@ config_init_module_search_paths(PyConfig *config, _PyPathConfig *pathconfig) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | /* Calculate the path configuration:
 | ||||||
|  | 
 | ||||||
|  |    - exec_prefix | ||||||
|  |    - module_search_path | ||||||
|  |    - prefix | ||||||
|  |    - program_full_path | ||||||
|  | 
 | ||||||
|  |    On Windows, more fields are calculated: | ||||||
|  | 
 | ||||||
|  |    - base_executable | ||||||
|  |    - isolated | ||||||
|  |    - site_import | ||||||
|  | 
 | ||||||
|  |    On other platforms, isolated and site_import are left unchanged, and | ||||||
|  |    _PyConfig_InitPathConfig() copies executable to base_executable (if it's not | ||||||
|  |    set). | ||||||
|  | 
 | ||||||
|  |    Priority, highest to lowest: | ||||||
|  | 
 | ||||||
|  |    - PyConfig | ||||||
|  |    - _Py_path_config: set by Py_SetPath(), Py_SetPythonHome() | ||||||
|  |      and Py_SetProgramName() | ||||||
|  |    - _PyPathConfig_Calculate() | ||||||
|  | */ | ||||||
|  | static PyStatus | ||||||
|  | pathconfig_calculate(_PyPathConfig *pathconfig, const PyConfig *config) | ||||||
|  | { | ||||||
|  |     PyStatus status; | ||||||
|  | 
 | ||||||
|  |     PyMemAllocatorEx old_alloc; | ||||||
|  |     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); | ||||||
|  | 
 | ||||||
|  |     status = pathconfig_copy(pathconfig, &_Py_path_config); | ||||||
|  |     if (_PyStatus_EXCEPTION(status)) { | ||||||
|  |         goto done; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     status = pathconfig_set_from_config(pathconfig, config); | ||||||
|  |     if (_PyStatus_EXCEPTION(status)) { | ||||||
|  |         goto done; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (_Py_path_config.module_search_path == NULL) { | ||||||
|  |         status = _PyPathConfig_Calculate(pathconfig, config); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         /* Py_SetPath() has been called: avoid _PyPathConfig_Calculate() */ | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | done: | ||||||
|  |     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); | ||||||
|  |     return status; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| static PyStatus | static PyStatus | ||||||
| config_calculate_pathconfig(PyConfig *config) | config_calculate_pathconfig(PyConfig *config) | ||||||
| { | { | ||||||
|  | @ -291,42 +309,28 @@ config_calculate_pathconfig(PyConfig *config) | ||||||
| 
 | 
 | ||||||
|     status = pathconfig_calculate(&pathconfig, config); |     status = pathconfig_calculate(&pathconfig, config); | ||||||
|     if (_PyStatus_EXCEPTION(status)) { |     if (_PyStatus_EXCEPTION(status)) { | ||||||
|         goto error; |         goto done; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!config->module_search_paths_set) { |     if (!config->module_search_paths_set) { | ||||||
|         status = config_init_module_search_paths(config, &pathconfig); |         status = config_init_module_search_paths(config, &pathconfig); | ||||||
|         if (_PyStatus_EXCEPTION(status)) { |         if (_PyStatus_EXCEPTION(status)) { | ||||||
|             goto error; |             goto done; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (config->executable == NULL) { | #define COPY_ATTR(PATH_ATTR, CONFIG_ATTR) \ | ||||||
|         if (copy_wstr(&config->executable, |         if (config->CONFIG_ATTR == NULL) { \ | ||||||
|                       pathconfig.program_full_path) < 0) { |             if (copy_wstr(&config->CONFIG_ATTR, pathconfig.PATH_ATTR) < 0) { \ | ||||||
|             goto no_memory; |                 goto no_memory; \ | ||||||
|  |             } \ | ||||||
|         } |         } | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     if (config->prefix == NULL) { |     COPY_ATTR(program_full_path, executable); | ||||||
|         if (copy_wstr(&config->prefix, pathconfig.prefix) < 0) { |     COPY_ATTR(prefix, prefix); | ||||||
|             goto no_memory; |     COPY_ATTR(exec_prefix, exec_prefix); | ||||||
|         } |     COPY_ATTR(base_executable, base_executable); | ||||||
|     } | #undef COPY_ATTR | ||||||
| 
 |  | ||||||
|     if (config->exec_prefix == NULL) { |  | ||||||
|         if (copy_wstr(&config->exec_prefix, |  | ||||||
|                       pathconfig.exec_prefix) < 0) { |  | ||||||
|             goto no_memory; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (config->base_executable == NULL) { |  | ||||||
|         if (copy_wstr(&config->base_executable, |  | ||||||
|                       pathconfig.base_executable) < 0) { |  | ||||||
|             goto no_memory; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     if (pathconfig.isolated != -1) { |     if (pathconfig.isolated != -1) { | ||||||
|         config->isolated = pathconfig.isolated; |         config->isolated = pathconfig.isolated; | ||||||
|  | @ -335,13 +339,13 @@ config_calculate_pathconfig(PyConfig *config) | ||||||
|         config->site_import = pathconfig.site_import; |         config->site_import = pathconfig.site_import; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pathconfig_clear(&pathconfig); |     status = _PyStatus_OK(); | ||||||
|     return _PyStatus_OK(); |     goto done; | ||||||
| 
 | 
 | ||||||
| no_memory: | no_memory: | ||||||
|     status = _PyStatus_NO_MEMORY(); |     status = _PyStatus_NO_MEMORY(); | ||||||
| 
 | 
 | ||||||
| error: | done: | ||||||
|     pathconfig_clear(&pathconfig); |     pathconfig_clear(&pathconfig); | ||||||
|     return status; |     return status; | ||||||
| } | } | ||||||
|  | @ -386,39 +390,55 @@ _PyConfig_InitPathConfig(PyConfig *config) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | static PyStatus | ||||||
|  | pathconfig_global_read(_PyPathConfig *pathconfig) | ||||||
|  | { | ||||||
|  |     PyStatus status; | ||||||
|  |     PyConfig config; | ||||||
|  |     _PyConfig_InitCompatConfig(&config); | ||||||
|  | 
 | ||||||
|  |     /* Call _PyConfig_InitPathConfig() */ | ||||||
|  |     status = PyConfig_Read(&config); | ||||||
|  |     if (_PyStatus_EXCEPTION(status)) { | ||||||
|  |         goto done; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     status = pathconfig_set_from_config(pathconfig, &config); | ||||||
|  | 
 | ||||||
|  | done: | ||||||
|  |     PyConfig_Clear(&config); | ||||||
|  |     return status; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| static void | static void | ||||||
| pathconfig_global_init(void) | pathconfig_global_init(void) | ||||||
| { | { | ||||||
|  |     PyStatus status; | ||||||
|  | 
 | ||||||
|     /* Initialize _Py_dll_path if needed */ |     /* Initialize _Py_dll_path if needed */ | ||||||
|     PyStatus status = _PyPathConfig_Init(); |     status = _PyPathConfig_Init(); | ||||||
|     if (_PyStatus_EXCEPTION(status)) { |     if (_PyStatus_EXCEPTION(status)) { | ||||||
|         Py_ExitStatusException(status); |         Py_ExitStatusException(status); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (_Py_path_config.module_search_path != NULL) { |     if (_Py_path_config.module_search_path == NULL) { | ||||||
|         /* Already initialized */ |         status = pathconfig_global_read(&_Py_path_config); | ||||||
|         return; |         if (_PyStatus_EXCEPTION(status)) { | ||||||
|  |             Py_ExitStatusException(status); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         /* Global configuration already initialized */ | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     PyConfig config; |     assert(_Py_path_config.program_full_path != NULL); | ||||||
|     _PyConfig_InitCompatConfig(&config); |     assert(_Py_path_config.prefix != NULL); | ||||||
| 
 |     assert(_Py_path_config.exec_prefix != NULL); | ||||||
|     status = PyConfig_Read(&config); |     assert(_Py_path_config.module_search_path != NULL); | ||||||
|     if (_PyStatus_EXCEPTION(status)) { |     assert(_Py_path_config.program_name != NULL); | ||||||
|         goto error; |     /* home can be NULL */ | ||||||
|     } |     assert(_Py_path_config.base_executable != NULL); | ||||||
| 
 |  | ||||||
|     status = pathconfig_global_init_from_config(&config); |  | ||||||
|     if (_PyStatus_EXCEPTION(status)) { |  | ||||||
|         goto error; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     PyConfig_Clear(&config); |  | ||||||
|     return; |  | ||||||
| 
 |  | ||||||
| error: |  | ||||||
|     PyConfig_Clear(&config); |  | ||||||
|     Py_ExitStatusException(status); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -435,30 +455,27 @@ Py_SetPath(const wchar_t *path) | ||||||
|     PyMemAllocatorEx old_alloc; |     PyMemAllocatorEx old_alloc; | ||||||
|     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); | ||||||
| 
 | 
 | ||||||
|     _PyPathConfig new_config; |     /* Getting the program name calls pathconfig_global_init() */ | ||||||
|     new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName()); |     wchar_t *program_name = _PyMem_RawWcsdup(Py_GetProgramName()); | ||||||
|     int alloc_error = (new_config.program_full_path == NULL); |  | ||||||
|     new_config.prefix = _PyMem_RawWcsdup(L""); |  | ||||||
|     alloc_error |= (new_config.prefix == NULL); |  | ||||||
|     new_config.exec_prefix = _PyMem_RawWcsdup(L""); |  | ||||||
|     alloc_error |= (new_config.exec_prefix == NULL); |  | ||||||
|     new_config.module_search_path = _PyMem_RawWcsdup(path); |  | ||||||
|     alloc_error |= (new_config.module_search_path == NULL); |  | ||||||
| 
 | 
 | ||||||
|     /* steal the home and program_name values (to leave them unchanged) */ |     PyMem_RawFree(_Py_path_config.program_full_path); | ||||||
|     new_config.home = _Py_path_config.home; |     PyMem_RawFree(_Py_path_config.prefix); | ||||||
|     _Py_path_config.home = NULL; |     PyMem_RawFree(_Py_path_config.exec_prefix); | ||||||
|     new_config.program_name = _Py_path_config.program_name; |     PyMem_RawFree(_Py_path_config.module_search_path); | ||||||
|     _Py_path_config.program_name = NULL; |  | ||||||
|     new_config.base_executable = _Py_path_config.base_executable; |  | ||||||
|     _Py_path_config.base_executable = NULL; |  | ||||||
| 
 | 
 | ||||||
|     pathconfig_clear(&_Py_path_config); |     /* Copy program_name to program_full_path  */ | ||||||
|     _Py_path_config = new_config; |     _Py_path_config.program_full_path = program_name; | ||||||
|  |     _Py_path_config.prefix = _PyMem_RawWcsdup(L""); | ||||||
|  |     _Py_path_config.exec_prefix = _PyMem_RawWcsdup(L""); | ||||||
|  |     _Py_path_config.module_search_path = _PyMem_RawWcsdup(path); | ||||||
| 
 | 
 | ||||||
|     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); | ||||||
| 
 | 
 | ||||||
|     if (alloc_error) { |     if (_Py_path_config.program_full_path == NULL | ||||||
|  |         || _Py_path_config.prefix == NULL | ||||||
|  |         || _Py_path_config.exec_prefix == NULL | ||||||
|  |         || _Py_path_config.module_search_path == NULL) | ||||||
|  |     { | ||||||
|         Py_FatalError("Py_SetPath() failed: out of memory"); |         Py_FatalError("Py_SetPath() failed: out of memory"); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Victor Stinner
						Victor Stinner