Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Include/pylifecycle.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ PyAPI_FUNC(wchar_t *) Py_GetProgramName(void);

PyAPI_FUNC(void) Py_SetPythonHome(wchar_t *);
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
/* Only used by applications that embed the interpreter and need to
Expand Down Expand Up @@ -94,7 +98,8 @@ PyAPI_FUNC(wchar_t *) Py_GetPrefix(void);
PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void);
PyAPI_FUNC(wchar_t *) Py_GetPath(void);
#ifdef Py_BUILD_CORE
PyAPI_FUNC(wchar_t *) _Py_GetPathWithConfig(_PyMainInterpreterConfig *config);
PyAPI_FUNC(wchar_t *) _Py_GetPathWithConfig(
const _PyMainInterpreterConfig *config);
#endif
PyAPI_FUNC(void) Py_SetPath(const wchar_t *);
#ifdef MS_WINDOWS
Expand Down
5 changes: 4 additions & 1 deletion Include/pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,15 @@ typedef struct {
typedef struct {
int install_signal_handlers;
wchar_t *module_search_path_env; /* PYTHONPATH environment variable */
wchar_t *pythonhome; /* PYTHONHOME environment variable,
see also Py_SetPythonHome(). */
} _PyMainInterpreterConfig;

#define _PyMainInterpreterConfig_INIT \
(_PyMainInterpreterConfig){\
.install_signal_handlers = -1, \
.module_search_path_env = NULL}
.module_search_path_env = NULL, \
.pythonhome = NULL}

typedef struct _is {

Expand Down
3 changes: 3 additions & 0 deletions Include/warnings.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ extern "C" {
#ifndef Py_LIMITED_API
PyAPI_FUNC(PyObject*) _PyWarnings_Init(void);
#endif
#ifdef Py_BUILD_CORE
PyAPI_FUNC(PyObject*) _PyWarnings_InitWithConfig(const _PyCoreConfig *config);
#endif

PyAPI_FUNC(int) PyErr_WarnEx(
PyObject *category,
Expand Down
6 changes: 3 additions & 3 deletions Modules/getpath.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,13 +456,13 @@ search_for_exec_prefix(wchar_t *argv0_path, wchar_t *home,
}

static void
calculate_path(_PyMainInterpreterConfig *config)
calculate_path(const _PyMainInterpreterConfig *config)
{
extern wchar_t *Py_GetProgramName(void);

static const wchar_t delimiter[2] = {DELIM, '\0'};
static const wchar_t separator[2] = {SEP, '\0'};
wchar_t *home = Py_GetPythonHome();
wchar_t *home = _Py_GetPythonHomeWithConfig(config);
char *_path = getenv("PATH");
wchar_t *path_buffer = NULL;
wchar_t *path = NULL;
Expand Down Expand Up @@ -858,7 +858,7 @@ Py_SetPath(const wchar_t *path)
}

wchar_t *
_Py_GetPathWithConfig(_PyMainInterpreterConfig *config)
_Py_GetPathWithConfig(const _PyMainInterpreterConfig *config)
{
if (!module_search_path) {
calculate_path(config);
Expand Down
81 changes: 67 additions & 14 deletions Modules/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,6 @@ typedef struct {
_PyInitError err;
/* PYTHONWARNINGS env var */
_Py_OptList env_warning_options;
/* PYTHONPATH env var */
int argc;
wchar_t **argv;
} _PyMain;
Expand Down Expand Up @@ -1368,47 +1367,98 @@ pymain_set_flags_from_env(_PyMain *pymain)


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) {
*dest = NULL;
return 0;
}

#ifdef MS_WINDOWS
wchar_t *path = _wgetenv(L"PYTHONPATH");
if (!path || path[0] == '\0') {
wchar_t *var = _wgetenv(wname);
if (!var || var[0] == '\0') {
*dest = NULL;
return 0;
}

wchar_t *path2 = pymain_wstrdup(pymain, path);
if (path2 == NULL) {
wchar_t *copy = pymain_wstrdup(pymain, var);
if (copy == NULL) {
return -1;
}

pymain->config.module_search_path_env = path2;
*dest = copy;
#else
char *path = pymain_get_env_var("PYTHONPATH");
if (!path) {
char *var = getenv(name);
if (!var || var[0] == '\0') {
*dest = NULL;
return 0;
}

size_t len;
wchar_t *wpath = Py_DecodeLocale(path, &len);
if (!wpath) {
wchar_t *wvar = Py_DecodeLocale(var, &len);
if (!wvar) {
if (len == (size_t)-2) {
pymain->err = _Py_INIT_ERR("failed to decode PYTHONHOME");
/* don't set pymain->err */
return -2;
}
else {
pymain->err = INIT_NO_MEMORY();
return -1;
}
return -1;
}
pymain->config.module_search_path_env = wpath;
*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;
}
pymain->config.module_search_path_env = path;
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;
}


static int
pymain_parse_envvars(_PyMain *pymain)
{
Expand All @@ -1433,6 +1483,9 @@ pymain_parse_envvars(_PyMain *pymain)
if (pymain_init_pythonpath(pymain) < 0) {
return -1;
}
if (pymain_init_pythonhome(pymain) < 0) {
return -1;
}

/* -X options */
if (pymain_get_xoption(pymain, L"showrefcount")) {
Expand Down
6 changes: 3 additions & 3 deletions PC/getpathp.c
Original file line number Diff line number Diff line change
Expand Up @@ -624,12 +624,12 @@ read_pth_file(const wchar_t *path, wchar_t *prefix, int *isolated, int *nosite)


static void
calculate_path(_PyMainInterpreterConfig *config)
calculate_path(const _PyMainInterpreterConfig *config)
{
wchar_t argv0_path[MAXPATHLEN+1];
wchar_t *buf;
size_t bufsz;
wchar_t *pythonhome = Py_GetPythonHome();
wchar_t *pythonhome = _Py_GetPythonHomeWithConfig(config);
wchar_t *envpath = NULL;

int skiphome, skipdefault;
Expand Down Expand Up @@ -899,7 +899,7 @@ Py_SetPath(const wchar_t *path)
}

wchar_t *
_Py_GetPathWithConfig(_PyMainInterpreterConfig *config)
_Py_GetPathWithConfig(const _PyMainInterpreterConfig *config)
{
if (!module_search_path) {
calculate_path(config);
Expand Down
20 changes: 14 additions & 6 deletions Python/_warnings.c
Original file line number Diff line number Diff line change
Expand Up @@ -1185,10 +1185,9 @@ create_filter(PyObject *category, const char *action)
}

static PyObject *
init_filters(void)
init_filters(const _PyCoreConfig *config)
{
PyInterpreterState *interp = PyThreadState_GET()->interp;
int dev_mode = interp->core_config.dev_mode;
int dev_mode = config->dev_mode;

Py_ssize_t count = 2;
if (dev_mode) {
Expand Down Expand Up @@ -1264,8 +1263,8 @@ static struct PyModuleDef warningsmodule = {
};


PyMODINIT_FUNC
_PyWarnings_Init(void)
PyObject*
_PyWarnings_InitWithConfig(const _PyCoreConfig *config)
{
PyObject *m;

Expand All @@ -1274,7 +1273,7 @@ _PyWarnings_Init(void)
return NULL;

if (_PyRuntime.warnings.filters == NULL) {
_PyRuntime.warnings.filters = init_filters();
_PyRuntime.warnings.filters = init_filters(config);
if (_PyRuntime.warnings.filters == NULL)
return NULL;
}
Expand Down Expand Up @@ -1305,3 +1304,12 @@ _PyWarnings_Init(void)
_PyRuntime.warnings.filters_version = 0;
return m;
}


PyMODINIT_FUNC
_PyWarnings_Init(void)
{
PyInterpreterState *interp = PyThreadState_GET()->interp;
const _PyCoreConfig *config = &interp->core_config;
return _PyWarnings_InitWithConfig(config);
}
49 changes: 35 additions & 14 deletions Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -767,7 +767,9 @@ _Py_InitializeCore(const _PyCoreConfig *config)
}

/* 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 */
if (!interp->core_config._disable_importlib) {
Expand Down Expand Up @@ -880,7 +882,7 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config)
return err;
}

if (config->install_signal_handlers) {
if (interp->config.install_signal_handlers) {
err = initsigs(); /* Signal handling stuff, including initintr() */
if (_Py_INIT_FAILED(err)) {
return err;
Expand Down Expand Up @@ -1468,7 +1470,6 @@ Py_GetProgramName(void)
}

static wchar_t *default_home = NULL;
static wchar_t env_home[MAXPATHLEN+1];

void
Py_SetPythonHome(wchar_t *home)
Expand All @@ -1477,20 +1478,40 @@ Py_SetPythonHome(wchar_t *home)
}

wchar_t *
Py_GetPythonHome(void)
_Py_GetPythonHomeWithConfig(const _PyMainInterpreterConfig *config)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I actually like this API design, but since it's an internal API, I don't have any obviously better ideas, and we expect further refactoring of this code in the future, I'm also not going to quibble over it.

{
wchar_t *home = default_home;
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;
}
/* 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;
}
return home;

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 *
Py_GetPythonHome(void)
{
return _Py_GetPythonHomeWithConfig(NULL);
}

/* Add the __main__ module */
Expand Down