diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index 68a88275004..8e531cf68ba 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -44,6 +44,8 @@ PyAPI_FUNC(void) Py_SetPythonHome(const wchar_t *); PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void); #ifndef Py_LIMITED_API +PyAPI_FUNC(void) _Py_SetProgramFullPath(const wchar_t *); + /* Only used by applications that embed the interpreter and need to * override the standard encoding determination mechanism */ diff --git a/Misc/NEWS.d/next/C API/2018-10-13-16-30-54.bpo-34725.j52rIS.rst b/Misc/NEWS.d/next/C API/2018-10-13-16-30-54.bpo-34725.j52rIS.rst new file mode 100644 index 00000000000..b5bc1bf0c72 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2018-10-13-16-30-54.bpo-34725.j52rIS.rst @@ -0,0 +1 @@ +Adds _Py_SetProgramFullPath so embedders may override sys.executable diff --git a/Modules/main.c b/Modules/main.c index f0f7fe55a41..6dbe6a30786 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -1206,6 +1206,25 @@ config_init_program_name(_PyCoreConfig *config) } +static _PyInitError +config_init_executable(_PyCoreConfig *config) +{ + assert(config->executable == NULL); + + /* If Py_SetProgramFullPath() was called, use its value */ + const wchar_t *program_full_path = _Py_path_config.program_full_path; + if (program_full_path != NULL) { + config->executable = _PyMem_RawWcsdup(program_full_path); + if (config->executable == NULL) { + return _Py_INIT_NO_MEMORY(); + } + return _Py_INIT_OK(); + } + + return _Py_INIT_OK(); +} + + static void pymain_header(_PyMain *pymain) { @@ -2350,6 +2369,13 @@ _PyCoreConfig_Read(_PyCoreConfig *config) } } + if (config->executable == NULL) { + err = config_init_executable(config); + if (_Py_INIT_FAILED(err)) { + return err; + } + } + if (config->utf8_mode < 0 || config->coerce_c_locale < 0) { config_init_locale(config); } diff --git a/Python/pathconfig.c b/Python/pathconfig.c index 07aa01c0304..aacc5f5a5f0 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -205,6 +205,27 @@ Py_SetProgramName(const wchar_t *program_name) } +void +_Py_SetProgramFullPath(const wchar_t *program_full_path) +{ + if (program_full_path == NULL || program_full_path[0] == L'\0') { + return; + } + + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + PyMem_RawFree(_Py_path_config.program_full_path); + _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path); + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + if (_Py_path_config.program_full_path == NULL) { + Py_FatalError("Py_SetProgramFullPath() failed: out of memory"); + } +} + + wchar_t * Py_GetPath(void) {