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:
parent
3d984a1fd0
commit
12f2f177fc
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue