Skip to content

bpo-32030: _PyPathConfig_Init() sets home and program_name #4673

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 2, 2017
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
5 changes: 2 additions & 3 deletions Doc/c-api/init.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ The following functions can be safely called before Python is initialized:
* :c:func:`Py_GetCompiler`
* :c:func:`Py_GetCopyright`
* :c:func:`Py_GetPlatform`
* :c:func:`Py_GetProgramName`
* :c:func:`Py_GetVersion`

* Utilities:
Expand All @@ -59,8 +58,8 @@ The following functions can be safely called before Python is initialized:
The following functions **should not be called** before
:c:func:`Py_Initialize`: :c:func:`Py_EncodeLocale`, :c:func:`Py_GetPath`,
:c:func:`Py_GetPrefix`, :c:func:`Py_GetExecPrefix`,
:c:func:`Py_GetProgramFullPath`, :c:func:`Py_GetPythonHome` and
:c:func:`PyEval_InitThreads`.
:c:func:`Py_GetProgramFullPath`, :c:func:`Py_GetPythonHome`,
:c:func:`Py_GetProgramName` and :c:func:`PyEval_InitThreads`.


.. _global-conf-vars:
Expand Down
25 changes: 24 additions & 1 deletion Include/internal/pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,35 @@ typedef struct {
#endif
/* Set by Py_SetPath(), or computed by _PyPathConfig_Init() */
wchar_t *module_search_path;
/* Python program name */
wchar_t *program_name;
/* Set by Py_SetPythonHome() or PYTHONHOME environment variable */
wchar_t *home;
} _PyPathConfig;

#define _PyPathConfig_INIT {.module_search_path = NULL}
#ifdef MS_WINDOWS
#define _PyPathConfig_INIT \
{.program_full_path = NULL, \
.prefix = NULL, \
.dll_path = NULL, \
.module_search_path = NULL, \
.program_name = NULL, \
.home = NULL}
#else
#define _PyPathConfig_INIT \
{.program_full_path = NULL, \
.prefix = NULL, \
.exec_prefix = NULL, \
.module_search_path = NULL, \
.program_name = NULL, \
.home = NULL}
#endif

PyAPI_DATA(_PyPathConfig) _Py_path_config;

PyAPI_FUNC(_PyInitError) _PyPathConfig_Calculate(
_PyPathConfig *config,
const _PyMainInterpreterConfig *main_config);
PyAPI_FUNC(void) _PyPathConfig_Clear(_PyPathConfig *config);


Expand Down
3 changes: 2 additions & 1 deletion Include/pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ typedef struct {
(_PyMainInterpreterConfig){\
.install_signal_handlers = -1, \
.module_search_path_env = NULL, \
.home = NULL}
.home = NULL, \
.program_name = NULL}

typedef struct _is {

Expand Down
17 changes: 3 additions & 14 deletions Modules/getpath.c
Original file line number Diff line number Diff line change
Expand Up @@ -1008,16 +1008,10 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config,
}


/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix()
and Py_GetProgramFullPath() */
_PyInitError
_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config)
_PyPathConfig_Calculate(_PyPathConfig *config,
const _PyMainInterpreterConfig *main_config)
{
if (_Py_path_config.module_search_path) {
/* Already initialized */
return _Py_INIT_OK();
}

PyCalculatePath calculate;
memset(&calculate, 0, sizeof(calculate));

Expand All @@ -1026,16 +1020,11 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config)
goto done;
}

_PyPathConfig new_path_config;
memset(&new_path_config, 0, sizeof(new_path_config));

err = calculate_path_impl(main_config, &calculate, &new_path_config);
err = calculate_path_impl(main_config, &calculate, config);
if (_Py_INIT_FAILED(err)) {
_PyPathConfig_Clear(&new_path_config);
goto done;
}

_Py_path_config = new_path_config;
err = _Py_INIT_OK();

done:
Expand Down
38 changes: 21 additions & 17 deletions Modules/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,16 @@ static _PyInitError
config_get_program_name(_PyMainInterpreterConfig *config)
{
assert(config->program_name == NULL);

/* If Py_SetProgramName() was called, use its value */
wchar_t *program_name = _Py_path_config.program_name;
if (program_name != NULL) {
config->program_name = _PyMem_RawWcsdup(program_name);
if (config->program_name == NULL) {
return _Py_INIT_NO_MEMORY();
}
}

#ifdef __APPLE__
char *p;
/* On MacOS X, when the Python interpreter is embedded in an
Expand Down Expand Up @@ -914,6 +924,7 @@ config_get_program_name(_PyMainInterpreterConfig *config)
}
#endif /* WITH_NEXT_FRAMEWORK */
#endif /* __APPLE__ */

return _Py_INIT_OK();
}

Expand Down Expand Up @@ -948,13 +959,6 @@ pymain_init_main_interpreter(_PyMain *pymain)
{
_PyInitError err;

/* TODO: Print any exceptions raised by these operations */
err = _PyMainInterpreterConfig_Read(&pymain->config);
if (_Py_INIT_FAILED(err)) {
pymain->err = err;
return -1;
}

err = _Py_InitializeMainInterpreter(&pymain->config);
if (_Py_INIT_FAILED(err)) {
pymain->err = err;
Expand Down Expand Up @@ -1412,14 +1416,13 @@ config_init_pythonpath(_PyMainInterpreterConfig *config)


static _PyInitError
config_init_pythonhome(_PyMainInterpreterConfig *config)
config_init_home(_PyMainInterpreterConfig *config)
{
wchar_t *home;

home = Py_GetPythonHome();
/* If Py_SetPythonHome() was called, use its value */
home = _Py_path_config.home;
if (home) {
/* Py_SetPythonHome() has been called before Py_Main(),
use its value */
config->home = _PyMem_RawWcsdup(home);
if (config->home == NULL) {
return _Py_INIT_NO_MEMORY();
Expand All @@ -1439,7 +1442,7 @@ config_init_pythonhome(_PyMainInterpreterConfig *config)
_PyInitError
_PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *config)
{
_PyInitError err = config_init_pythonhome(config);
_PyInitError err = config_init_home(config);
if (_Py_INIT_FAILED(err)) {
return err;
}
Expand Down Expand Up @@ -1543,6 +1546,12 @@ pymain_parse_cmdline_envvars_impl(_PyMain *pymain)
return -1;
}

_PyInitError err = _PyMainInterpreterConfig_Read(&pymain->config);
if (_Py_INIT_FAILED(err)) {
pymain->err = err;
return -1;
}

return 0;
}

Expand All @@ -1566,11 +1575,6 @@ pymain_init_python(_PyMain *pymain)
{
pymain_init_stdio(pymain);

Py_SetProgramName(pymain->config.program_name);
/* Don't free program_name here: the argument to Py_SetProgramName
must remain valid until Py_FinalizeEx is called. The string is freed
by pymain_free(). */

pymain->err = _Py_InitializeCore(&pymain->core_config);
if (_Py_INIT_FAILED(pymain->err)) {
return -1;
Expand Down
21 changes: 3 additions & 18 deletions PC/getpathp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1058,38 +1058,23 @@ calculate_free(PyCalculatePath *calculate)
}


/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix()
and Py_GetProgramFullPath() */
_PyInitError
_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config)
_PyPathConfig_Calculate(_PyPathConfig *config,
const _PyMainInterpreterConfig *main_config)
{
if (_Py_path_config.module_search_path) {
/* Already initialized */
return _Py_INIT_OK();
}

_PyInitError err;

PyCalculatePath calculate;
memset(&calculate, 0, sizeof(calculate));

calculate_init(&calculate, main_config);

_PyPathConfig new_path_config;
memset(&new_path_config, 0, sizeof(new_path_config));

err = calculate_path_impl(main_config, &calculate, &new_path_config);
_PyInitError err = calculate_path_impl(main_config, &calculate, config);
if (_Py_INIT_FAILED(err)) {
goto done;
}

_Py_path_config = new_path_config;
err = _Py_INIT_OK();

done:
if (_Py_INIT_FAILED(err)) {
_PyPathConfig_Clear(&new_path_config);
}
calculate_free(&calculate);
return err;
}
Expand Down
Loading