| /* Path configuration like module_search_path (sys.path) */ |
| |
| #include "Python.h" |
| #include "osdefs.h" |
| #include "internal/pystate.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| |
| _PyPathConfig _Py_path_config = _PyPathConfig_INIT; |
| |
| |
| void |
| _PyPathConfig_Clear(_PyPathConfig *config) |
| { |
| /* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator, |
| since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be |
| called before Py_Initialize() which can changes the memory allocator. */ |
| PyMemAllocatorEx old_alloc; |
| _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |
| |
| #define CLEAR(ATTR) \ |
| do { \ |
| PyMem_RawFree(ATTR); \ |
| ATTR = NULL; \ |
| } while (0) |
| |
| CLEAR(config->prefix); |
| CLEAR(config->program_full_path); |
| #ifdef MS_WINDOWS |
| CLEAR(config->dll_path); |
| #else |
| CLEAR(config->exec_prefix); |
| #endif |
| CLEAR(config->module_search_path); |
| CLEAR(config->home); |
| CLEAR(config->program_name); |
| #undef CLEAR |
| |
| PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |
| } |
| |
| |
| /* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() |
| and Py_GetProgramFullPath() */ |
| _PyInitError |
| _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) |
| { |
| if (_Py_path_config.module_search_path) { |
| /* Already initialized */ |
| return _Py_INIT_OK(); |
| } |
| |
| _PyInitError err; |
| _PyPathConfig new_config = _PyPathConfig_INIT; |
| |
| PyMemAllocatorEx old_alloc; |
| _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |
| |
| /* Calculate program_full_path, prefix, exec_prefix (Unix) |
| or dll_path (Windows), and module_search_path */ |
| err = _PyPathConfig_Calculate(&new_config, main_config); |
| if (_Py_INIT_FAILED(err)) { |
| _PyPathConfig_Clear(&new_config); |
| goto done; |
| } |
| |
| /* Copy home and program_name from main_config */ |
| if (main_config->home != NULL) { |
| new_config.home = _PyMem_RawWcsdup(main_config->home); |
| if (new_config.home == NULL) { |
| err = _Py_INIT_NO_MEMORY(); |
| goto done; |
| } |
| } |
| else { |
| new_config.home = NULL; |
| } |
| |
| new_config.program_name = _PyMem_RawWcsdup(main_config->program_name); |
| if (new_config.program_name == NULL) { |
| err = _Py_INIT_NO_MEMORY(); |
| goto done; |
| } |
| |
| _PyPathConfig_Clear(&_Py_path_config); |
| _Py_path_config = new_config; |
| |
| err = _Py_INIT_OK(); |
| |
| done: |
| PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |
| return err; |
| } |
| |
| |
| static void |
| pathconfig_global_init(void) |
| { |
| if (_Py_path_config.module_search_path) { |
| /* Already initialized */ |
| return; |
| } |
| |
| _PyInitError err; |
| _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; |
| |
| err = _PyMainInterpreterConfig_ReadEnv(&config); |
| if (_Py_INIT_FAILED(err)) { |
| goto error; |
| } |
| |
| err = _PyMainInterpreterConfig_Read(&config); |
| if (_Py_INIT_FAILED(err)) { |
| goto error; |
| } |
| |
| err = _PyPathConfig_Init(&config); |
| if (_Py_INIT_FAILED(err)) { |
| goto error; |
| } |
| |
| _PyMainInterpreterConfig_Clear(&config); |
| return; |
| |
| error: |
| _PyMainInterpreterConfig_Clear(&config); |
| _Py_FatalInitError(err); |
| } |
| |
| |
| /* External interface */ |
| |
| void |
| Py_SetPath(const wchar_t *path) |
| { |
| if (path == NULL) { |
| _PyPathConfig_Clear(&_Py_path_config); |
| return; |
| } |
| |
| PyMemAllocatorEx old_alloc; |
| _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |
| |
| _PyPathConfig new_config; |
| new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName()); |
| new_config.prefix = _PyMem_RawWcsdup(L""); |
| #ifdef MS_WINDOWS |
| new_config.dll_path = _PyMem_RawWcsdup(L""); |
| #else |
| new_config.exec_prefix = _PyMem_RawWcsdup(L""); |
| #endif |
| new_config.module_search_path = _PyMem_RawWcsdup(path); |
| |
| /* steal the home and program_name values (to leave them unchanged) */ |
| new_config.home = _Py_path_config.home; |
| _Py_path_config.home = NULL; |
| new_config.program_name = _Py_path_config.program_name; |
| _Py_path_config.program_name = NULL; |
| |
| _PyPathConfig_Clear(&_Py_path_config); |
| _Py_path_config = new_config; |
| |
| PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |
| } |
| |
| |
| void |
| Py_SetPythonHome(const wchar_t *home) |
| { |
| if (home == NULL) { |
| return; |
| } |
| |
| PyMemAllocatorEx old_alloc; |
| _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |
| |
| PyMem_RawFree(_Py_path_config.home); |
| _Py_path_config.home = _PyMem_RawWcsdup(home); |
| |
| PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |
| |
| if (_Py_path_config.home == NULL) { |
| Py_FatalError("Py_SetPythonHome() failed: out of memory"); |
| } |
| } |
| |
| |
| void |
| Py_SetProgramName(const wchar_t *program_name) |
| { |
| if (program_name == NULL || program_name[0] == L'\0') { |
| return; |
| } |
| |
| PyMemAllocatorEx old_alloc; |
| _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |
| |
| PyMem_RawFree(_Py_path_config.program_name); |
| _Py_path_config.program_name = _PyMem_RawWcsdup(program_name); |
| |
| PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); |
| |
| if (_Py_path_config.program_name == NULL) { |
| Py_FatalError("Py_SetProgramName() failed: out of memory"); |
| } |
| } |
| |
| |
| wchar_t * |
| Py_GetPath(void) |
| { |
| pathconfig_global_init(); |
| return _Py_path_config.module_search_path; |
| } |
| |
| |
| wchar_t * |
| Py_GetPrefix(void) |
| { |
| pathconfig_global_init(); |
| return _Py_path_config.prefix; |
| } |
| |
| |
| wchar_t * |
| Py_GetExecPrefix(void) |
| { |
| #ifdef MS_WINDOWS |
| return Py_GetPrefix(); |
| #else |
| pathconfig_global_init(); |
| return _Py_path_config.exec_prefix; |
| #endif |
| } |
| |
| |
| wchar_t * |
| Py_GetProgramFullPath(void) |
| { |
| pathconfig_global_init(); |
| return _Py_path_config.program_full_path; |
| } |
| |
| |
| wchar_t* |
| Py_GetPythonHome(void) |
| { |
| pathconfig_global_init(); |
| return _Py_path_config.home; |
| } |
| |
| |
| wchar_t * |
| Py_GetProgramName(void) |
| { |
| pathconfig_global_init(); |
| return _Py_path_config.program_name; |
| } |
| |
| |
| #ifdef __cplusplus |
| } |
| #endif |