bpo-38234: Py_Initialize() sets global path configuration (GH-16421)

* Py_InitializeFromConfig() now writes PyConfig path configuration to
  the global path configuration (_Py_path_config).
* Add test_embed.test_get_pathconfig().
* Fix typo in _PyWideStringList_Join().
This commit is contained in:
Victor Stinner 2019-09-26 15:51:50 +02:00 committed by GitHub
parent 3d984a1fd0
commit 12f2f177fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 11 deletions

View File

@ -66,7 +66,7 @@ extern int _Py_FindEnvConfigValue(
extern wchar_t* _Py_GetDLLPath(void); extern wchar_t* _Py_GetDLLPath(void);
#endif #endif
extern PyStatus _PyPathConfig_Init(void); extern PyStatus _PyConfig_WritePathConfig(const PyConfig *config);
extern void _Py_DumpPathConfig(PyThreadState *tstate); extern void _Py_DumpPathConfig(PyThreadState *tstate);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1230,6 +1230,44 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
api=API_COMPAT, env=env, api=API_COMPAT, env=env,
ignore_stderr=True, cwd=tmpdir) ignore_stderr=True, cwd=tmpdir)
def test_global_pathconfig(self):
# Test C API functions getting the path configuration:
#
# - Py_GetExecPrefix()
# - Py_GetPath()
# - Py_GetPrefix()
# - Py_GetProgramFullPath()
# - Py_GetProgramName()
# - Py_GetPythonHome()
#
# The global path configuration (_Py_path_config) must be a copy
# of the path configuration of PyInterpreter.config (PyConfig).
ctypes = support.import_module('ctypes')
_testinternalcapi = support.import_module('_testinternalcapi')
def get_func(name):
func = getattr(ctypes.pythonapi, name)
func.argtypes = ()
func.restype = ctypes.c_wchar_p
return func
Py_GetPath = get_func('Py_GetPath')
Py_GetPrefix = get_func('Py_GetPrefix')
Py_GetExecPrefix = get_func('Py_GetExecPrefix')
Py_GetProgramName = get_func('Py_GetProgramName')
Py_GetProgramFullPath = get_func('Py_GetProgramFullPath')
Py_GetPythonHome = get_func('Py_GetPythonHome')
config = _testinternalcapi.get_configs()['config']
self.assertEqual(Py_GetPath().split(os.path.pathsep),
config['module_search_paths'])
self.assertEqual(Py_GetPrefix(), config['prefix'])
self.assertEqual(Py_GetExecPrefix(), config['exec_prefix'])
self.assertEqual(Py_GetProgramName(), config['program_name'])
self.assertEqual(Py_GetProgramFullPath(), config['executable'])
self.assertEqual(Py_GetPythonHome(), config['home'])
class AuditingTests(EmbeddingTestsMixin, unittest.TestCase): class AuditingTests(EmbeddingTestsMixin, unittest.TestCase):
def test_open_code_hook(self): def test_open_code_hook(self):

View File

@ -133,7 +133,7 @@ _PyWideStringList_Join(const PyWideStringList *list, wchar_t sep)
for (Py_ssize_t i=0; i < list->length; i++) { for (Py_ssize_t i=0; i < list->length; i++) {
wchar_t *path = list->items[i]; wchar_t *path = list->items[i];
if (i != 0) { if (i != 0) {
*str++ = SEP; *str++ = sep;
} }
len = wcslen(path); len = wcslen(path);
memcpy(str, path, len * sizeof(wchar_t)); memcpy(str, path, len * sizeof(wchar_t));
@ -145,11 +145,11 @@ _PyWideStringList_Join(const PyWideStringList *list, wchar_t sep)
} }
/* Initialize _Py_dll_path on Windows. Do nothing on other platforms. */
PyStatus
_PyPathConfig_Init(void)
{
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
/* Initialize _Py_dll_path on Windows. Do nothing on other platforms. */
static PyStatus
_PyPathConfig_InitDLLPath(void)
{
if (_Py_dll_path == NULL) { if (_Py_dll_path == NULL) {
/* Already set: nothing to do */ /* Already set: nothing to do */
return _PyStatus_OK(); return _PyStatus_OK();
@ -165,9 +165,9 @@ _PyPathConfig_Init(void)
if (_Py_dll_path == NULL) { if (_Py_dll_path == NULL) {
return _PyStatus_NO_MEMORY(); return _PyStatus_NO_MEMORY();
} }
#endif
return _PyStatus_OK(); return _PyStatus_OK();
} }
#endif
static PyStatus static PyStatus
@ -217,6 +217,20 @@ done:
} }
PyStatus
_PyConfig_WritePathConfig(const PyConfig *config)
{
#ifdef MS_WINDOWS
PyStatus status = _PyPathConfig_InitDLLPath();
if (_PyStatus_EXCEPTION(status)) {
return status;
}
#endif
return pathconfig_set_from_config(&_Py_path_config, config);
}
static PyStatus static PyStatus
config_init_module_search_paths(PyConfig *config, _PyPathConfig *pathconfig) config_init_module_search_paths(PyConfig *config, _PyPathConfig *pathconfig)
{ {
@ -441,11 +455,12 @@ pathconfig_global_init(void)
{ {
PyStatus status; PyStatus status;
/* Initialize _Py_dll_path if needed */ #ifdef MS_WINDOWS
status = _PyPathConfig_Init(); status = _PyPathConfig_InitDLLPath();
if (_PyStatus_EXCEPTION(status)) { if (_PyStatus_EXCEPTION(status)) {
Py_ExitStatusException(status); Py_ExitStatusException(status);
} }
#endif
if (_Py_path_config.module_search_path == NULL) { if (_Py_path_config.module_search_path == NULL) {
status = pathconfig_global_read(&_Py_path_config); status = pathconfig_global_read(&_Py_path_config);

View File

@ -475,7 +475,7 @@ pyinit_core_reconfigure(_PyRuntimeState *runtime,
config = &interp->config; config = &interp->config;
if (config->_install_importlib) { if (config->_install_importlib) {
status = _PyPathConfig_Init(); status = _PyConfig_WritePathConfig(config);
if (_PyStatus_EXCEPTION(status)) { if (_PyStatus_EXCEPTION(status)) {
return status; return status;
} }
@ -646,7 +646,7 @@ pycore_init_import_warnings(PyThreadState *tstate, PyObject *sysmod)
} }
if (config->_install_importlib) { if (config->_install_importlib) {
status = _PyPathConfig_Init(); status = _PyConfig_WritePathConfig(config);
if (_PyStatus_EXCEPTION(status)) { if (_PyStatus_EXCEPTION(status)) {
return status; return status;
} }