Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Fix config.base_executable calculations
  • Loading branch information
zooba committed Jun 27, 2019
commit 5bf292be3abce9b89e754b49a12acd387f06d33e
2 changes: 2 additions & 0 deletions Include/internal/pycore_pathconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ typedef struct _PyPathConfig {
are ignored when their value are equal to -1 (unset). */
int isolated;
int site_import;
/* sys.base_executable if in a venv */
wchar_t *base_executable;
} _PyPathConfig;

#define _PyPathConfig_INIT \
Expand Down
13 changes: 6 additions & 7 deletions Lib/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,14 +458,13 @@ def venv(known_paths):

env = os.environ
if sys.platform == 'darwin' and '__PYVENV_LAUNCHER__' in env:
executable = sys._base_executable = os.environ['__PYVENV_LAUNCHER__']
elif sys.platform == 'win32' and '__PYVENV_LAUNCHER__' in env:
executable = sys.base_executable = os.environ['__PYVENV_LAUNCHER__']
elif sys.platform == 'win32':
executable = sys.executable
import _winapi
sys._base_executable = _winapi.GetModuleFileName(0)
# bpo-35873: Clear the environment variable to avoid it being
# inherited by child processes.
del os.environ['__PYVENV_LAUNCHER__']
if '__PYVENV_LAUNCHER__' in env:
# bpo-35873: Clear the environment variable to avoid it being
# inherited by child processes.
del os.environ['__PYVENV_LAUNCHER__']
else:
executable = sys.executable
exe_dir, _ = os.path.split(os.path.abspath(executable))
Expand Down
17 changes: 10 additions & 7 deletions Lib/test/test_embed.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'pythonpath_env': None,
'home': None,
'executable': GET_DEFAULT_CONFIG,
'base_executable': GET_DEFAULT_CONFIG,

'prefix': GET_DEFAULT_CONFIG,
'base_prefix': GET_DEFAULT_CONFIG,
Expand Down Expand Up @@ -534,14 +535,16 @@ def get_expected_config(self, expected_preconfig, expected, env, api,
if expected['stdio_errors'] is self.GET_DEFAULT_CONFIG:
expected['stdio_errors'] = 'surrogateescape'

if sys.platform == 'win32':
default_executable = self.test_exe
elif expected['program_name'] is not self.GET_DEFAULT_CONFIG:
default_executable = os.path.abspath(expected['program_name'])
else:
default_executable = os.path.join(os.getcwd(), '_testembed')
if expected['executable'] is self.GET_DEFAULT_CONFIG:
if sys.platform == 'win32':
expected['executable'] = self.test_exe
else:
if expected['program_name'] is not self.GET_DEFAULT_CONFIG:
expected['executable'] = os.path.abspath(expected['program_name'])
else:
expected['executable'] = os.path.join(os.getcwd(), '_testembed')
expected['executable'] = default_executable
if expected['base_executable'] is self.GET_DEFAULT_CONFIG:
expected['base_executable'] = default_executable
if expected['program_name'] is self.GET_DEFAULT_CONFIG:
expected['program_name'] = './_testembed'

Expand Down
12 changes: 12 additions & 0 deletions Modules/getpath.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,12 @@ typedef struct {

wchar_t *lib_python; /* "lib/pythonX.Y" */
wchar_t argv0_path[MAXPATHLEN+1];
wchar_t base_executable[MAXPATHLEN+1];
wchar_t zip_path[MAXPATHLEN+1]; /* ".../lib/pythonXY.zip" */

int prefix_found; /* found platform independent libraries? */
int exec_prefix_found; /* found the platform dependent libraries? */
int base_executable_found; /* found a base_executable path */
} PyCalculatePath;

static const wchar_t delimiter[2] = {DELIM, '\0'};
Expand Down Expand Up @@ -987,6 +989,12 @@ calculate_read_pyenv(PyCalculatePath *calculate)

/* Look for a 'home' variable and set argv0_path to it, if found */
if (_Py_FindEnvConfigValue(env_file, L"home", tmpbuffer, buflen)) {
/* preserve the previous argv0_path as sys.base_executable */
if (safe_wcscpy(calculate->base_executable, calculate->argv0_path,
Py_ARRAY_LENGTH(calculate->base_executable)) < 0) {
return PATHLEN_ERR();
}
calculate->base_executable_found = 1;
if (safe_wcscpy(calculate->argv0_path, tmpbuffer,
Py_ARRAY_LENGTH(calculate->argv0_path)) < 0) {
return PATHLEN_ERR();
Expand Down Expand Up @@ -1240,6 +1248,10 @@ calculate_path_impl(const PyConfig *config,
return _PyStatus_NO_MEMORY();
}

if (calculate->base_executable_found) {
pathconfig->base_executable = _PyMem_RawWcsdup(calculate->base_executable);
}

return _PyStatus_OK();
}

Expand Down
10 changes: 10 additions & 0 deletions PC/getpathp.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ typedef struct {

wchar_t argv0_path[MAXPATHLEN+1];
wchar_t zip_path[MAXPATHLEN+1];
wchar_t base_executable[MAXPATHLEN+1];
} PyCalculatePath;


Expand Down Expand Up @@ -729,6 +730,8 @@ calculate_pyvenv_file(PyCalculatePath *calculate)
/* Look for a 'home' variable and set argv0_path to it, if found */
wchar_t tmpbuffer[MAXPATHLEN+1];
if (_Py_FindEnvConfigValue(env_file, L"home", tmpbuffer, MAXPATHLEN)) {
/* Preserve original path as base_executable */
wcscpy_s(calculate->base_executable, MAXPATHLEN+1, calculate->argv0_path);
wcscpy_s(calculate->argv0_path, MAXPATHLEN+1, tmpbuffer);
}
fclose(env_file);
Expand Down Expand Up @@ -999,6 +1002,13 @@ calculate_path_impl(const PyConfig *config,
if (pathconfig->exec_prefix == NULL) {
return _PyStatus_NO_MEMORY();
}
if (calculate->base_executable[0]) {
pathconfig->base_executable = _PyMem_RawWcsdup(
calculate->base_executable);
if (pathconfig->base_executable == NULL) {
return _PyStatus_NO_MEMORY();
}
}

return _PyStatus_OK();
}
Expand Down
15 changes: 15 additions & 0 deletions Python/pathconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ pathconfig_clear(_PyPathConfig *config)
CLEAR(config->module_search_path);
CLEAR(config->home);
CLEAR(config->program_name);
CLEAR(config->base_executable);
#undef CLEAR

PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
Expand Down Expand Up @@ -89,6 +90,10 @@ pathconfig_calculate(_PyPathConfig *pathconfig, const PyConfig *config)
status = _PyStatus_NO_MEMORY();
goto error;
}
if (copy_wstr(&new_config.base_executable, config->base_executable) < 0) {
status = _PyStatus_NO_MEMORY();
goto error;
}

pathconfig_clear(pathconfig);
*pathconfig = new_config;
Expand Down Expand Up @@ -224,6 +229,9 @@ _PyConfig_SetPathConfig(const PyConfig *config)
if (copy_wstr(&pathconfig.home, config->home) < 0) {
goto no_memory;
}
if (copy_wstr(&pathconfig.base_executable, config->base_executable) < 0) {
goto no_memory;
}

status = _PyPathConfig_SetGlobal(&pathconfig);
if (_PyStatus_EXCEPTION(status)) {
Expand Down Expand Up @@ -321,6 +329,13 @@ config_calculate_pathconfig(PyConfig *config)
}
}

if (config->base_executable == NULL) {
if (copy_wstr(&config->base_executable,
pathconfig.base_executable) < 0) {
goto no_memory;
}
}

if (pathconfig.isolated != -1) {
config->isolated = pathconfig.isolated;
}
Expand Down