Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 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
9 changes: 5 additions & 4 deletions Include/cpython/initconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -373,10 +373,11 @@ typedef struct {
module_search_paths_set is equal
to zero. */

wchar_t *executable; /* sys.executable */
wchar_t *prefix; /* sys.prefix */
wchar_t *base_prefix; /* sys.base_prefix */
wchar_t *exec_prefix; /* sys.exec_prefix */
wchar_t *executable; /* sys.executable */
wchar_t *base_executable; /* sys.base_executable */
Comment thread
zooba marked this conversation as resolved.
Outdated
wchar_t *prefix; /* sys.prefix */
wchar_t *base_prefix; /* sys.base_prefix */
wchar_t *exec_prefix; /* sys.exec_prefix */
wchar_t *base_exec_prefix; /* sys.base_exec_prefix */

/* --- Parameter only used by Py_Main() ---------- */
Expand Down
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;
/* Set when a venv is detected */
wchar_t *base_executable;
} _PyPathConfig;

#define _PyPathConfig_INIT \
Expand Down
11 changes: 5 additions & 6 deletions Lib/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,13 +459,12 @@ 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:
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
2 changes: 1 addition & 1 deletion Lib/venv/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ def setup_python(self, context):

for suffix in suffixes:
src = os.path.join(dirname, suffix)
if os.path.exists(src):
if os.path.lexists(src):
Comment thread
zooba marked this conversation as resolved.
copier(src, os.path.join(binpath, suffix))

if sysconfig.is_python_build(True):
Expand Down
17 changes: 14 additions & 3 deletions PC/getpathp.c
Original file line number Diff line number Diff line change
Expand Up @@ -537,14 +537,25 @@ get_program_full_path(const PyConfig *config,
wchar_t program_full_path[MAXPATHLEN+1];
memset(program_full_path, 0, sizeof(program_full_path));

if (!GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) {
/* GetModuleFileName should never fail when passed NULL */
return _PyStatus_ERR("Cannot determine program path");
}

/* The launcher may need to force the executable path to a
* different environment, so override it here. */
pyvenv_launcher = _wgetenv(L"__PYVENV_LAUNCHER__");
if (pyvenv_launcher && pyvenv_launcher[0]) {
/* If overridden, preserve the original full path */
Comment thread
zooba marked this conversation as resolved.
pathconfig->base_executable = PyMem_RawMalloc(
sizeof(wchar_t) * (MAXPATHLEN + 1));

PyStatus status = canonicalize(pathconfig->base_executable,
program_full_path);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
wcscpy_s(program_full_path, MAXPATHLEN+1, pyvenv_launcher);
} else if (!GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) {
/* GetModuleFileName should never fail when passed NULL */
return _PyStatus_ERR("Cannot determine program path");
}

pathconfig->program_full_path = PyMem_RawMalloc(
Expand Down
Loading