Commit 0ea395ae authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

bpo-32030: Add Python/pathconfig.c (#4668)

* Factorize code from PC/getpathp.c and Modules/getpath.c to remove
  duplicated code
* rename pathconfig_clear() to _PyPathConfig_Clear()
* Inline _PyPathConfig_Fini() in pymain_impl() and then remove it,
  since it's a oneliner
parent ebac19da
...@@ -52,6 +52,10 @@ typedef struct { ...@@ -52,6 +52,10 @@ typedef struct {
#define _PyPathConfig_INIT {.module_search_path = NULL} #define _PyPathConfig_INIT {.module_search_path = NULL}
PyAPI_DATA(_PyPathConfig) _Py_path_config;
PyAPI_FUNC(void) _PyPathConfig_Clear(_PyPathConfig *config);
/* Full Python runtime state */ /* Full Python runtime state */
......
...@@ -105,7 +105,6 @@ PyAPI_FUNC(wchar_t *) Py_GetPath(void); ...@@ -105,7 +105,6 @@ PyAPI_FUNC(wchar_t *) Py_GetPath(void);
#ifdef Py_BUILD_CORE #ifdef Py_BUILD_CORE
PyAPI_FUNC(_PyInitError) _PyPathConfig_Init( PyAPI_FUNC(_PyInitError) _PyPathConfig_Init(
const _PyMainInterpreterConfig *main_config); const _PyMainInterpreterConfig *main_config);
PyAPI_FUNC(void) _PyPathConfig_Fini(void);
#endif #endif
PyAPI_FUNC(void) Py_SetPath(const wchar_t *); PyAPI_FUNC(void) Py_SetPath(const wchar_t *);
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
......
...@@ -337,8 +337,9 @@ PYTHON_OBJS= \ ...@@ -337,8 +337,9 @@ PYTHON_OBJS= \
Python/importdl.o \ Python/importdl.o \
Python/marshal.o \ Python/marshal.o \
Python/modsupport.o \ Python/modsupport.o \
Python/mystrtoul.o \
Python/mysnprintf.o \ Python/mysnprintf.o \
Python/mystrtoul.o \
Python/pathconfig.o \
Python/peephole.o \ Python/peephole.o \
Python/pyarena.o \ Python/pyarena.o \
Python/pyctype.o \ Python/pyctype.o \
......
...@@ -132,7 +132,6 @@ typedef struct { ...@@ -132,7 +132,6 @@ typedef struct {
static const wchar_t delimiter[2] = {DELIM, '\0'}; static const wchar_t delimiter[2] = {DELIM, '\0'};
static const wchar_t separator[2] = {SEP, '\0'}; static const wchar_t separator[2] = {SEP, '\0'};
static _PyPathConfig _Py_path_config = _PyPathConfig_INIT;
/* Get file status. Encode the path to the locale encoding. */ /* Get file status. Encode the path to the locale encoding. */
...@@ -1009,23 +1008,6 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, ...@@ -1009,23 +1008,6 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config,
} }
static void
pathconfig_clear(_PyPathConfig *config)
{
#define CLEAR(ATTR) \
do { \
PyMem_RawFree(ATTR); \
ATTR = NULL; \
} while (0)
CLEAR(config->prefix);
CLEAR(config->exec_prefix);
CLEAR(config->program_full_path);
CLEAR(config->module_search_path);
#undef CLEAR
}
/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() /* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix()
and Py_GetProgramFullPath() */ and Py_GetProgramFullPath() */
_PyInitError _PyInitError
...@@ -1049,7 +1031,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) ...@@ -1049,7 +1031,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config)
err = calculate_path_impl(main_config, &calculate, &new_path_config); err = calculate_path_impl(main_config, &calculate, &new_path_config);
if (_Py_INIT_FAILED(err)) { if (_Py_INIT_FAILED(err)) {
pathconfig_clear(&new_path_config); _PyPathConfig_Clear(&new_path_config);
goto done; goto done;
} }
...@@ -1061,100 +1043,6 @@ done: ...@@ -1061,100 +1043,6 @@ done:
return err; 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);
}
void
_PyPathConfig_Fini(void)
{
pathconfig_clear(&_Py_path_config);
}
/* External interface */
void
Py_SetPath(const wchar_t *path)
{
if (path == NULL) {
pathconfig_clear(&_Py_path_config);
return;
}
_PyPathConfig new_config;
new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
new_config.exec_prefix = _PyMem_RawWcsdup(L"");
new_config.prefix = _PyMem_RawWcsdup(L"");
new_config.module_search_path = _PyMem_RawWcsdup(path);
pathconfig_clear(&_Py_path_config);
_Py_path_config = new_config;
}
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)
{
pathconfig_global_init();
return _Py_path_config.exec_prefix;
}
wchar_t *
Py_GetProgramFullPath(void)
{
pathconfig_global_init();
return _Py_path_config.program_full_path;
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
...@@ -1665,12 +1665,12 @@ pymain_impl(_PyMain *pymain) ...@@ -1665,12 +1665,12 @@ pymain_impl(_PyMain *pymain)
pymain->status = 120; pymain->status = 120;
} }
/* _PyPathConfig_Fini() cannot be called in Py_FinalizeEx(). /* _PyPathConfig_Clear() cannot be called in Py_FinalizeEx().
Py_Initialize() and Py_Finalize() can be called multiple times, but it Py_Initialize() and Py_Finalize() can be called multiple times, but it
must not "forget" parameters set by Py_SetProgramName(), Py_SetPath() or must not "forget" parameters set by Py_SetProgramName(), Py_SetPath() or
Py_SetPythonHome(), whereas _PyPathConfig_Fini() clear all these Py_SetPythonHome(), whereas _PyPathConfig_Clear() clear all these
parameters. */ parameters. */
_PyPathConfig_Fini(); _PyPathConfig_Clear(&_Py_path_config);
return 0; return 0;
} }
......
...@@ -130,9 +130,6 @@ typedef struct { ...@@ -130,9 +130,6 @@ typedef struct {
} PyCalculatePath; } PyCalculatePath;
static _PyPathConfig _Py_path_config = _PyPathConfig_INIT;
/* determine if "ch" is a separator character */ /* determine if "ch" is a separator character */
static int static int
is_sep(wchar_t ch) is_sep(wchar_t ch)
...@@ -1061,23 +1058,6 @@ calculate_free(PyCalculatePath *calculate) ...@@ -1061,23 +1058,6 @@ calculate_free(PyCalculatePath *calculate)
} }
static void
pathconfig_clear(_PyPathConfig *config)
{
#define CLEAR(ATTR) \
do { \
PyMem_RawFree(ATTR); \
ATTR = NULL; \
} while (0)
CLEAR(config->prefix);
CLEAR(config->program_full_path);
CLEAR(config->dll_path);
CLEAR(config->module_search_path);
#undef CLEAR
}
/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() /* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix()
and Py_GetProgramFullPath() */ and Py_GetProgramFullPath() */
_PyInitError _PyInitError
...@@ -1108,110 +1088,13 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) ...@@ -1108,110 +1088,13 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config)
done: done:
if (_Py_INIT_FAILED(err)) { if (_Py_INIT_FAILED(err)) {
pathconfig_clear(&new_path_config); _PyPathConfig_Clear(&new_path_config);
} }
calculate_free(&calculate); calculate_free(&calculate);
return err; 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);
}
void
_PyPathConfig_Fini(void)
{
pathconfig_clear(&_Py_path_config);
}
/* External interface */
void
Py_SetPath(const wchar_t *path)
{
if (_Py_path_config.module_search_path != NULL) {
pathconfig_clear(&_Py_path_config);
}
if (path == NULL) {
return;
}
_PyPathConfig new_config;
new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
new_config.prefix = _PyMem_RawWcsdup(L"");
new_config.dll_path = _PyMem_RawWcsdup(L"");
new_config.module_search_path = _PyMem_RawWcsdup(path);
pathconfig_clear(&_Py_path_config);
_Py_path_config = new_config;
}
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)
{
return Py_GetPrefix();
}
wchar_t *
Py_GetProgramFullPath(void)
{
pathconfig_global_init();
return _Py_path_config.program_full_path;
}
/* Load python3.dll before loading any extension module that might refer /* Load python3.dll before loading any extension module that might refer
to it. That way, we can be sure that always the python3.dll corresponding to it. That way, we can be sure that always the python3.dll corresponding
to this python DLL is loaded, not a python3.dll that might be on the path to this python DLL is loaded, not a python3.dll that might be on the path
......
...@@ -381,6 +381,7 @@ ...@@ -381,6 +381,7 @@
<ClCompile Include="..\Python\modsupport.c" /> <ClCompile Include="..\Python\modsupport.c" />
<ClCompile Include="..\Python\mysnprintf.c" /> <ClCompile Include="..\Python\mysnprintf.c" />
<ClCompile Include="..\Python\mystrtoul.c" /> <ClCompile Include="..\Python\mystrtoul.c" />
<ClCompile Include="..\Python\pathconfig.c" />
<ClCompile Include="..\Python\peephole.c" /> <ClCompile Include="..\Python\peephole.c" />
<ClCompile Include="..\Python\pyarena.c" /> <ClCompile Include="..\Python\pyarena.c" />
<ClCompile Include="..\Python\pyctype.c" /> <ClCompile Include="..\Python\pyctype.c" />
......
...@@ -896,6 +896,9 @@ ...@@ -896,6 +896,9 @@
<ClCompile Include="..\Python\mystrtoul.c"> <ClCompile Include="..\Python\mystrtoul.c">
<Filter>Python</Filter> <Filter>Python</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\Python\pathconfig.c">
<Filter>Python</Filter>
</ClCompile>
<ClCompile Include="..\Python\peephole.c"> <ClCompile Include="..\Python\peephole.c">
<Filter>Python</Filter> <Filter>Python</Filter>
</ClCompile> </ClCompile>
......
/* 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;
#ifdef MS_WINDOWS
static wchar_t *progname = L"python";
#else
static wchar_t *progname = L"python3";
#endif
static wchar_t *default_home = NULL;
void
_PyPathConfig_Clear(_PyPathConfig *config)
{
#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);
#undef CLEAR
}
void
Py_SetProgramName(wchar_t *pn)
{
if (pn && *pn)
progname = pn;
}
wchar_t *
Py_GetProgramName(void)
{
return progname;
}
void
Py_SetPythonHome(wchar_t *home)
{
default_home = home;
}
wchar_t*
Py_GetPythonHome(void)
{
/* Use a static buffer to avoid heap memory allocation failure.
Py_GetPythonHome() doesn't allow to report error, and the caller
doesn't release memory. */
static wchar_t buffer[MAXPATHLEN+1];
if (default_home) {
return default_home;
}
char *home = Py_GETENV("PYTHONHOME");
if (!home) {
return NULL;
}
size_t size = Py_ARRAY_LENGTH(buffer);
size_t r = mbstowcs(buffer, home, size);
if (r == (size_t)-1 || r >= size) {
/* conversion failed or the static buffer is too small */
return NULL;
}
return buffer;
}
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;
}
_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);
_PyPathConfig_Clear(&_Py_path_config);
_Py_path_config = new_config;
}
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;
}
#ifdef __cplusplus
}
#endif
...@@ -1489,61 +1489,6 @@ Py_EndInterpreter(PyThreadState *tstate) ...@@ -1489,61 +1489,6 @@ Py_EndInterpreter(PyThreadState *tstate)
PyInterpreterState_Delete(interp); PyInterpreterState_Delete(interp);
} }
#ifdef MS_WINDOWS
static wchar_t *progname = L"python";
#else
static wchar_t *progname = L"python3";
#endif
void
Py_SetProgramName(wchar_t *pn)
{
if (pn && *pn)
progname = pn;
}
wchar_t *
Py_GetProgramName(void)
{
return progname;
}
static wchar_t *default_home = NULL;
void
Py_SetPythonHome(wchar_t *home)
{
default_home = home;
}
wchar_t*
Py_GetPythonHome(void)
{
/* Use a static buffer to avoid heap memory allocation failure.
Py_GetPythonHome() doesn't allow to report error, and the caller
doesn't release memory. */
static wchar_t buffer[MAXPATHLEN+1];
if (default_home) {
return default_home;
}
char *home = Py_GETENV("PYTHONHOME");
if (!home) {
return NULL;
}
size_t size = Py_ARRAY_LENGTH(buffer);
size_t r = mbstowcs(buffer, home, size);
if (r == (size_t)-1 || r >= size) {
/* conversion failed or the static buffer is too small */
return NULL;
}
return buffer;
}
/* Add the __main__ module */ /* Add the __main__ module */
static _PyInitError static _PyInitError
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment