bpo-32030: Add _PyCoreConfig.module_search_path_env (#4504)

Changes:

* Py_Main() initializes _PyCoreConfig.module_search_path_env from
  the PYTHONPATH environment variable.
* PyInterpreterState_New() now initializes core_config and config
  fields
* Compute sys.path a little bit ealier in
  _Py_InitializeMainInterpreter() and new_interpreter()
* Add _Py_GetPathWithConfig() private function.
This commit is contained in:
Victor Stinner 2017-11-23 00:12:09 +01:00 committed by GitHub
parent 82656276ca
commit d434110974
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 189 additions and 86 deletions

View file

@ -456,14 +456,12 @@ search_for_exec_prefix(wchar_t *argv0_path, wchar_t *home,
}
static void
calculate_path(void)
calculate_path(_PyCoreConfig *core_config)
{
extern wchar_t *Py_GetProgramName(void);
static const wchar_t delimiter[2] = {DELIM, '\0'};
static const wchar_t separator[2] = {SEP, '\0'};
char *_rtpypath = Py_GETENV("PYTHONPATH"); /* XXX use wide version on Windows */
wchar_t *rtpypath = NULL;
wchar_t *home = Py_GetPythonHome();
char *_path = getenv("PATH");
wchar_t *path_buffer = NULL;
@ -707,11 +705,22 @@ calculate_path(void)
*/
bufsz = 0;
if (_rtpypath && _rtpypath[0] != '\0') {
size_t rtpypath_len;
rtpypath = Py_DecodeLocale(_rtpypath, &rtpypath_len);
if (rtpypath != NULL)
bufsz += rtpypath_len + 1;
wchar_t *env_path = NULL;
if (core_config) {
if (core_config->module_search_path_env) {
bufsz += wcslen(core_config->module_search_path_env) + 1;
}
}
else {
char *env_pathb = Py_GETENV("PYTHONPATH");
if (env_pathb && env_pathb[0] != '\0') {
size_t env_path_len;
env_path = Py_DecodeLocale(env_pathb, &env_path_len);
/* FIXME: handle decoding and memory error */
if (env_path != NULL) {
bufsz += env_path_len + 1;
}
}
}
defpath = _pythonpath;
@ -742,12 +751,20 @@ calculate_path(void)
}
/* Run-time value of $PYTHONPATH goes first */
if (rtpypath) {
wcscpy(buf, rtpypath);
wcscat(buf, delimiter);
buf[0] = '\0';
if (core_config) {
if (core_config->module_search_path_env) {
wcscpy(buf, core_config->module_search_path_env);
wcscat(buf, delimiter);
}
}
else
buf[0] = '\0';
else {
if (env_path) {
wcscpy(buf, env_path);
wcscat(buf, delimiter);
}
}
PyMem_RawFree(env_path);
/* Next is the default zip path */
wcscat(buf, zip_path);
@ -818,7 +835,6 @@ calculate_path(void)
PyMem_RawFree(_prefix);
PyMem_RawFree(_exec_prefix);
PyMem_RawFree(lib_python);
PyMem_RawFree(rtpypath);
}
@ -841,11 +857,20 @@ Py_SetPath(const wchar_t *path)
}
}
wchar_t *
_Py_GetPathWithConfig(_PyCoreConfig *core_config)
{
if (!module_search_path) {
calculate_path(core_config);
}
return module_search_path;
}
wchar_t *
Py_GetPath(void)
{
if (!module_search_path)
calculate_path();
calculate_path(NULL);
return module_search_path;
}
@ -853,7 +878,7 @@ wchar_t *
Py_GetPrefix(void)
{
if (!module_search_path)
calculate_path();
calculate_path(NULL);
return prefix;
}
@ -861,7 +886,7 @@ wchar_t *
Py_GetExecPrefix(void)
{
if (!module_search_path)
calculate_path();
calculate_path(NULL);
return exec_prefix;
}
@ -869,7 +894,7 @@ wchar_t *
Py_GetProgramFullPath(void)
{
if (!module_search_path)
calculate_path();
calculate_path(NULL);
return progpath;
}

View file

@ -399,6 +399,7 @@ typedef struct {
_PyInitError err;
/* PYTHONWARNINGS env var */
_Py_OptList env_warning_options;
/* PYTHONPATH env var */
int argc;
wchar_t **argv;
} _PyMain;
@ -441,6 +442,8 @@ pymain_free_impl(_PyMain *pymain)
Py_CLEAR(pymain->main_importer_path);
PyMem_RawFree(pymain->program_name);
PyMem_RawFree(pymain->core_config.module_search_path_env);
#ifdef __INSURE__
/* Insure++ is a memory analysis tool that aids in discovering
* memory leaks and other memory problems. On Python exit, the
@ -502,15 +505,22 @@ error:
static wchar_t*
pymain_strdup(_PyMain *pymain, wchar_t *str)
pymain_wstrdup(_PyMain *pymain, wchar_t *str)
{
size_t len = wcslen(str) + 1; /* +1 for NUL character */
wchar_t *str2 = PyMem_RawMalloc(sizeof(wchar_t) * len);
if (len > (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
pymain->err = INIT_NO_MEMORY();
return NULL;
}
size_t size = len * sizeof(wchar_t);
wchar_t *str2 = PyMem_RawMalloc(size);
if (str2 == NULL) {
pymain->err = INIT_NO_MEMORY();
return NULL;
}
memcpy(str2, str, len * sizeof(wchar_t));
memcpy(str2, str, size);
return str2;
}
@ -518,7 +528,7 @@ pymain_strdup(_PyMain *pymain, wchar_t *str)
static int
pymain_optlist_append(_PyMain *pymain, _Py_OptList *list, wchar_t *str)
{
wchar_t *str2 = pymain_strdup(pymain, str);
wchar_t *str2 = pymain_wstrdup(pymain, str);
if (str2 == NULL) {
return -1;
}
@ -762,14 +772,12 @@ pymain_warnings_envvar(_PyMain *pymain)
wchar_t *wp;
if ((wp = _wgetenv(L"PYTHONWARNINGS")) && *wp != L'\0') {
wchar_t *buf, *warning, *context = NULL;
wchar_t *warning, *context = NULL;
buf = (wchar_t *)PyMem_RawMalloc((wcslen(wp) + 1) * sizeof(wchar_t));
wchar_t *buf = pymain_wstrdup(pymain, wp);
if (buf == NULL) {
pymain->err = INIT_NO_MEMORY();
return -1;
}
wcscpy(buf, wp);
for (warning = wcstok_s(buf, L",", &context);
warning != NULL;
warning = wcstok_s(NULL, L",", &context)) {
@ -805,12 +813,11 @@ pymain_warnings_envvar(_PyMain *pymain)
if (len == (size_t)-2) {
pymain->err = _Py_INIT_ERR("failed to decode "
"PYTHONWARNINGS");
return -1;
}
else {
pymain->err = INIT_NO_MEMORY();
return -1;
}
return -1;
}
if (pymain_optlist_append(pymain, &pymain->env_warning_options,
warning) < 0) {
@ -929,7 +936,7 @@ pymain_get_program_name(_PyMain *pymain)
if (pymain->program_name == NULL) {
/* Use argv[0] by default */
pymain->program_name = pymain_strdup(pymain, pymain->argv[0]);
pymain->program_name = pymain_wstrdup(pymain, pymain->argv[0]);
if (pymain->program_name == NULL) {
return -1;
}
@ -1362,6 +1369,48 @@ pymain_set_flags_from_env(_PyMain *pymain)
}
static int
pymain_init_pythonpath(_PyMain *pymain)
{
if (Py_IgnoreEnvironmentFlag) {
return 0;
}
#ifdef MS_WINDOWS
wchar_t *path = _wgetenv(L"PYTHONPATH");
if (!path || path[0] == '\0') {
return 0;
}
wchar_t *path2 = pymain_wstrdup(pymain, path);
if (path2 == NULL) {
return -1;
}
pymain->core_config.module_search_path_env = path2;
#else
char *path = pymain_get_env_var("PYTHONPATH");
if (!path) {
return 0;
}
size_t len;
wchar_t *wpath = Py_DecodeLocale(path, &len);
if (!wpath) {
if (len == (size_t)-2) {
pymain->err = _Py_INIT_ERR("failed to decode PYTHONHOME");
}
else {
pymain->err = INIT_NO_MEMORY();
}
return -1;
}
pymain->core_config.module_search_path_env = wpath;
#endif
return 0;
}
static int
pymain_parse_envvars(_PyMain *pymain)
{
@ -1383,6 +1432,9 @@ pymain_parse_envvars(_PyMain *pymain)
return -1;
}
core_config->allocator = Py_GETENV("PYTHONMALLOC");
if (pymain_init_pythonpath(pymain) < 0) {
return -1;
}
/* -X options */
if (pymain_get_xoption(pymain, L"showrefcount")) {