mirror of
https://github.com/python/cpython.git
synced 2025-08-30 21:48:47 +00:00
bpo-32030: Add _PyMainInterpreterConfig.pythonhome (#4513)
* Py_Main() now reads the PYTHONHOME environment variable * Add _Py_GetPythonHomeWithConfig() private function * Add _PyWarnings_InitWithConfig() * init_filters() doesn't get the current core configuration from the current interpreter or Python thread anymore. Pass explicitly the configuration to _PyWarnings_InitWithConfig(). * _Py_InitializeCore() now fails on _PyWarnings_InitWithConfig() failure. * Pass configuration as constant
This commit is contained in:
parent
e32e79f7d8
commit
1f15111a6e
8 changed files with 136 additions and 43 deletions
|
@ -12,6 +12,10 @@ PyAPI_FUNC(wchar_t *) Py_GetProgramName(void);
|
||||||
|
|
||||||
PyAPI_FUNC(void) Py_SetPythonHome(wchar_t *);
|
PyAPI_FUNC(void) Py_SetPythonHome(wchar_t *);
|
||||||
PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void);
|
PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void);
|
||||||
|
#ifdef Py_BUILD_CORE
|
||||||
|
PyAPI_FUNC(wchar_t *) _Py_GetPythonHomeWithConfig(
|
||||||
|
const _PyMainInterpreterConfig *config);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef Py_LIMITED_API
|
#ifndef Py_LIMITED_API
|
||||||
/* Only used by applications that embed the interpreter and need to
|
/* Only used by applications that embed the interpreter and need to
|
||||||
|
@ -94,7 +98,8 @@ PyAPI_FUNC(wchar_t *) Py_GetPrefix(void);
|
||||||
PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void);
|
PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void);
|
||||||
PyAPI_FUNC(wchar_t *) Py_GetPath(void);
|
PyAPI_FUNC(wchar_t *) Py_GetPath(void);
|
||||||
#ifdef Py_BUILD_CORE
|
#ifdef Py_BUILD_CORE
|
||||||
PyAPI_FUNC(wchar_t *) _Py_GetPathWithConfig(_PyMainInterpreterConfig *config);
|
PyAPI_FUNC(wchar_t *) _Py_GetPathWithConfig(
|
||||||
|
const _PyMainInterpreterConfig *config);
|
||||||
#endif
|
#endif
|
||||||
PyAPI_FUNC(void) Py_SetPath(const wchar_t *);
|
PyAPI_FUNC(void) Py_SetPath(const wchar_t *);
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
|
|
@ -61,12 +61,15 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int install_signal_handlers;
|
int install_signal_handlers;
|
||||||
wchar_t *module_search_path_env; /* PYTHONPATH environment variable */
|
wchar_t *module_search_path_env; /* PYTHONPATH environment variable */
|
||||||
|
wchar_t *pythonhome; /* PYTHONHOME environment variable,
|
||||||
|
see also Py_SetPythonHome(). */
|
||||||
} _PyMainInterpreterConfig;
|
} _PyMainInterpreterConfig;
|
||||||
|
|
||||||
#define _PyMainInterpreterConfig_INIT \
|
#define _PyMainInterpreterConfig_INIT \
|
||||||
(_PyMainInterpreterConfig){\
|
(_PyMainInterpreterConfig){\
|
||||||
.install_signal_handlers = -1, \
|
.install_signal_handlers = -1, \
|
||||||
.module_search_path_env = NULL}
|
.module_search_path_env = NULL, \
|
||||||
|
.pythonhome = NULL}
|
||||||
|
|
||||||
typedef struct _is {
|
typedef struct _is {
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,9 @@ extern "C" {
|
||||||
#ifndef Py_LIMITED_API
|
#ifndef Py_LIMITED_API
|
||||||
PyAPI_FUNC(PyObject*) _PyWarnings_Init(void);
|
PyAPI_FUNC(PyObject*) _PyWarnings_Init(void);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef Py_BUILD_CORE
|
||||||
|
PyAPI_FUNC(PyObject*) _PyWarnings_InitWithConfig(const _PyCoreConfig *config);
|
||||||
|
#endif
|
||||||
|
|
||||||
PyAPI_FUNC(int) PyErr_WarnEx(
|
PyAPI_FUNC(int) PyErr_WarnEx(
|
||||||
PyObject *category,
|
PyObject *category,
|
||||||
|
|
|
@ -456,13 +456,13 @@ search_for_exec_prefix(wchar_t *argv0_path, wchar_t *home,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
calculate_path(_PyMainInterpreterConfig *config)
|
calculate_path(const _PyMainInterpreterConfig *config)
|
||||||
{
|
{
|
||||||
extern wchar_t *Py_GetProgramName(void);
|
extern wchar_t *Py_GetProgramName(void);
|
||||||
|
|
||||||
static const wchar_t delimiter[2] = {DELIM, '\0'};
|
static const wchar_t delimiter[2] = {DELIM, '\0'};
|
||||||
static const wchar_t separator[2] = {SEP, '\0'};
|
static const wchar_t separator[2] = {SEP, '\0'};
|
||||||
wchar_t *home = Py_GetPythonHome();
|
wchar_t *home = _Py_GetPythonHomeWithConfig(config);
|
||||||
char *_path = getenv("PATH");
|
char *_path = getenv("PATH");
|
||||||
wchar_t *path_buffer = NULL;
|
wchar_t *path_buffer = NULL;
|
||||||
wchar_t *path = NULL;
|
wchar_t *path = NULL;
|
||||||
|
@ -858,7 +858,7 @@ Py_SetPath(const wchar_t *path)
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t *
|
wchar_t *
|
||||||
_Py_GetPathWithConfig(_PyMainInterpreterConfig *config)
|
_Py_GetPathWithConfig(const _PyMainInterpreterConfig *config)
|
||||||
{
|
{
|
||||||
if (!module_search_path) {
|
if (!module_search_path) {
|
||||||
calculate_path(config);
|
calculate_path(config);
|
||||||
|
|
|
@ -400,7 +400,6 @@ typedef struct {
|
||||||
_PyInitError err;
|
_PyInitError err;
|
||||||
/* PYTHONWARNINGS env var */
|
/* PYTHONWARNINGS env var */
|
||||||
_Py_OptList env_warning_options;
|
_Py_OptList env_warning_options;
|
||||||
/* PYTHONPATH env var */
|
|
||||||
int argc;
|
int argc;
|
||||||
wchar_t **argv;
|
wchar_t **argv;
|
||||||
} _PyMain;
|
} _PyMain;
|
||||||
|
@ -1368,43 +1367,94 @@ pymain_set_flags_from_env(_PyMain *pymain)
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pymain_init_pythonpath(_PyMain *pymain)
|
pymain_get_env_var_dup(_PyMain *pymain, wchar_t **dest,
|
||||||
|
wchar_t *wname, char *name)
|
||||||
{
|
{
|
||||||
if (Py_IgnoreEnvironmentFlag) {
|
if (Py_IgnoreEnvironmentFlag) {
|
||||||
|
*dest = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
wchar_t *path = _wgetenv(L"PYTHONPATH");
|
wchar_t *var = _wgetenv(wname);
|
||||||
if (!path || path[0] == '\0') {
|
if (!var || var[0] == '\0') {
|
||||||
|
*dest = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t *path2 = pymain_wstrdup(pymain, path);
|
wchar_t *copy = pymain_wstrdup(pymain, var);
|
||||||
if (path2 == NULL) {
|
if (copy == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pymain->config.module_search_path_env = path2;
|
*dest = copy;
|
||||||
#else
|
#else
|
||||||
char *path = pymain_get_env_var("PYTHONPATH");
|
char *var = getenv(name);
|
||||||
if (!path) {
|
if (!var || var[0] == '\0') {
|
||||||
|
*dest = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t len;
|
size_t len;
|
||||||
wchar_t *wpath = Py_DecodeLocale(path, &len);
|
wchar_t *wvar = Py_DecodeLocale(var, &len);
|
||||||
if (!wpath) {
|
if (!wvar) {
|
||||||
if (len == (size_t)-2) {
|
if (len == (size_t)-2) {
|
||||||
pymain->err = _Py_INIT_ERR("failed to decode PYTHONHOME");
|
/* don't set pymain->err */
|
||||||
|
return -2;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pymain->err = INIT_NO_MEMORY();
|
pymain->err = INIT_NO_MEMORY();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*dest = wvar;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
pymain_init_pythonpath(_PyMain *pymain)
|
||||||
|
{
|
||||||
|
wchar_t *path;
|
||||||
|
int res = pymain_get_env_var_dup(pymain, &path,
|
||||||
|
L"PYTHONPATH", "PYTHONPATH");
|
||||||
|
if (res < 0) {
|
||||||
|
if (res == -2) {
|
||||||
|
pymain->err = _Py_INIT_ERR("failed to decode PYTHONPATH");
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
pymain->config.module_search_path_env = wpath;
|
pymain->config.module_search_path_env = path;
|
||||||
#endif
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
pymain_init_pythonhome(_PyMain *pymain)
|
||||||
|
{
|
||||||
|
wchar_t *home;
|
||||||
|
|
||||||
|
home = Py_GetPythonHome();
|
||||||
|
if (home) {
|
||||||
|
/* Py_SetPythonHome() has been called before Py_Main(),
|
||||||
|
use its value */
|
||||||
|
pymain->config.pythonhome = pymain_wstrdup(pymain, home);
|
||||||
|
if (pymain->config.pythonhome == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int res = pymain_get_env_var_dup(pymain, &home,
|
||||||
|
L"PYTHONHOME", "PYTHONHOME");
|
||||||
|
if (res < 0) {
|
||||||
|
if (res == -2) {
|
||||||
|
pymain->err = _Py_INIT_ERR("failed to decode PYTHONHOME");
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pymain->config.pythonhome = home;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1433,6 +1483,9 @@ pymain_parse_envvars(_PyMain *pymain)
|
||||||
if (pymain_init_pythonpath(pymain) < 0) {
|
if (pymain_init_pythonpath(pymain) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (pymain_init_pythonhome(pymain) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* -X options */
|
/* -X options */
|
||||||
if (pymain_get_xoption(pymain, L"showrefcount")) {
|
if (pymain_get_xoption(pymain, L"showrefcount")) {
|
||||||
|
|
|
@ -624,12 +624,12 @@ error:
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
calculate_path(_PyMainInterpreterConfig *config)
|
calculate_path(const _PyMainInterpreterConfig *config)
|
||||||
{
|
{
|
||||||
wchar_t argv0_path[MAXPATHLEN+1];
|
wchar_t argv0_path[MAXPATHLEN+1];
|
||||||
wchar_t *buf;
|
wchar_t *buf;
|
||||||
size_t bufsz;
|
size_t bufsz;
|
||||||
wchar_t *pythonhome = Py_GetPythonHome();
|
wchar_t *pythonhome = _Py_GetPythonHomeWithConfig(config);
|
||||||
wchar_t *envpath = NULL;
|
wchar_t *envpath = NULL;
|
||||||
|
|
||||||
int skiphome, skipdefault;
|
int skiphome, skipdefault;
|
||||||
|
@ -899,7 +899,7 @@ Py_SetPath(const wchar_t *path)
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t *
|
wchar_t *
|
||||||
_Py_GetPathWithConfig(_PyMainInterpreterConfig *config)
|
_Py_GetPathWithConfig(const _PyMainInterpreterConfig *config)
|
||||||
{
|
{
|
||||||
if (!module_search_path) {
|
if (!module_search_path) {
|
||||||
calculate_path(config);
|
calculate_path(config);
|
||||||
|
|
|
@ -1185,10 +1185,9 @@ create_filter(PyObject *category, const char *action)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
init_filters(void)
|
init_filters(const _PyCoreConfig *config)
|
||||||
{
|
{
|
||||||
PyInterpreterState *interp = PyThreadState_GET()->interp;
|
int dev_mode = config->dev_mode;
|
||||||
int dev_mode = interp->core_config.dev_mode;
|
|
||||||
|
|
||||||
Py_ssize_t count = 2;
|
Py_ssize_t count = 2;
|
||||||
if (dev_mode) {
|
if (dev_mode) {
|
||||||
|
@ -1264,8 +1263,8 @@ static struct PyModuleDef warningsmodule = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
PyMODINIT_FUNC
|
PyObject*
|
||||||
_PyWarnings_Init(void)
|
_PyWarnings_InitWithConfig(const _PyCoreConfig *config)
|
||||||
{
|
{
|
||||||
PyObject *m;
|
PyObject *m;
|
||||||
|
|
||||||
|
@ -1274,7 +1273,7 @@ _PyWarnings_Init(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (_PyRuntime.warnings.filters == NULL) {
|
if (_PyRuntime.warnings.filters == NULL) {
|
||||||
_PyRuntime.warnings.filters = init_filters();
|
_PyRuntime.warnings.filters = init_filters(config);
|
||||||
if (_PyRuntime.warnings.filters == NULL)
|
if (_PyRuntime.warnings.filters == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1305,3 +1304,12 @@ _PyWarnings_Init(void)
|
||||||
_PyRuntime.warnings.filters_version = 0;
|
_PyRuntime.warnings.filters_version = 0;
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyMODINIT_FUNC
|
||||||
|
_PyWarnings_Init(void)
|
||||||
|
{
|
||||||
|
PyInterpreterState *interp = PyThreadState_GET()->interp;
|
||||||
|
const _PyCoreConfig *config = &interp->core_config;
|
||||||
|
return _PyWarnings_InitWithConfig(config);
|
||||||
|
}
|
||||||
|
|
|
@ -767,7 +767,9 @@ _Py_InitializeCore(const _PyCoreConfig *config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize _warnings. */
|
/* Initialize _warnings. */
|
||||||
_PyWarnings_Init();
|
if (_PyWarnings_InitWithConfig(&interp->core_config) == NULL) {
|
||||||
|
return _Py_INIT_ERR("can't initialize warnings");
|
||||||
|
}
|
||||||
|
|
||||||
/* This call sets up builtin and frozen import support */
|
/* This call sets up builtin and frozen import support */
|
||||||
if (!interp->core_config._disable_importlib) {
|
if (!interp->core_config._disable_importlib) {
|
||||||
|
@ -880,7 +882,7 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config->install_signal_handlers) {
|
if (interp->config.install_signal_handlers) {
|
||||||
err = initsigs(); /* Signal handling stuff, including initintr() */
|
err = initsigs(); /* Signal handling stuff, including initintr() */
|
||||||
if (_Py_INIT_FAILED(err)) {
|
if (_Py_INIT_FAILED(err)) {
|
||||||
return err;
|
return err;
|
||||||
|
@ -1468,7 +1470,6 @@ Py_GetProgramName(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static wchar_t *default_home = NULL;
|
static wchar_t *default_home = NULL;
|
||||||
static wchar_t env_home[MAXPATHLEN+1];
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Py_SetPythonHome(wchar_t *home)
|
Py_SetPythonHome(wchar_t *home)
|
||||||
|
@ -1476,21 +1477,41 @@ Py_SetPythonHome(wchar_t *home)
|
||||||
default_home = home;
|
default_home = home;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wchar_t *
|
||||||
|
_Py_GetPythonHomeWithConfig(const _PyMainInterpreterConfig *config)
|
||||||
|
{
|
||||||
|
/* Use a static buffer to avoid heap memory allocation failure.
|
||||||
|
Py_GetPythonHome() doesn't allow to report error, and the caller
|
||||||
|
doesn't release memory. */
|
||||||
|
static wchar_t buffer[MAXPATHLEN+1];
|
||||||
|
|
||||||
|
if (default_home) {
|
||||||
|
return default_home;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config) {
|
||||||
|
return config->pythonhome;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *home = Py_GETENV("PYTHONHOME");
|
||||||
|
if (!home) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size = Py_ARRAY_LENGTH(buffer);
|
||||||
|
size_t r = mbstowcs(buffer, home, size);
|
||||||
|
if (r == (size_t)-1 || r >= size) {
|
||||||
|
/* conversion failed or the static buffer is too small */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
wchar_t *
|
wchar_t *
|
||||||
Py_GetPythonHome(void)
|
Py_GetPythonHome(void)
|
||||||
{
|
{
|
||||||
wchar_t *home = default_home;
|
return _Py_GetPythonHomeWithConfig(NULL);
|
||||||
if (home == NULL && !Py_IgnoreEnvironmentFlag) {
|
|
||||||
char* chome = Py_GETENV("PYTHONHOME");
|
|
||||||
if (chome) {
|
|
||||||
size_t size = Py_ARRAY_LENGTH(env_home);
|
|
||||||
size_t r = mbstowcs(env_home, chome, size);
|
|
||||||
if (r != (size_t)-1 && r < size)
|
|
||||||
home = env_home;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return home;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add the __main__ module */
|
/* Add the __main__ module */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue