Skip to content

Commit 41264f1

Browse files
authored
bpo-32030: Add _PyMainInterpreterConfig.executable (#4876)
* Add new fields to _PyMainInterpreterConfig: * executable * prefix * base_prefix * exec_prefix * base_exec_prefix * _PySys_EndInit() now sets sys attributes from _PyMainInterpreterConfig
1 parent da27341 commit 41264f1

File tree

5 files changed

+92
-69
lines changed

5 files changed

+92
-69
lines changed

Include/pylifecycle.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ PyAPI_FUNC(const char *) _Py_gitversion(void);
135135
#ifndef Py_LIMITED_API
136136
PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void);
137137
PyAPI_FUNC(_PyInitError) _PySys_BeginInit(PyObject **sysmod);
138-
PyAPI_FUNC(int) _PySys_EndInit(PyObject *sysdict);
138+
PyAPI_FUNC(int) _PySys_EndInit(PyObject *sysdict, _PyMainInterpreterConfig *config);
139139
PyAPI_FUNC(_PyInitError) _PyImport_Init(PyInterpreterState *interp);
140140
PyAPI_FUNC(void) _PyExc_Init(PyObject * bltinmod);
141141
PyAPI_FUNC(_PyInitError) _PyImportHooks_Init(void);

Include/pystate.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,18 @@ typedef struct {
5252
/* Placeholders while working on the new configuration API
5353
*
5454
* See PEP 432 for final anticipated contents
55-
*
56-
* For the moment, just handle the args to _Py_InitializeEx
5755
*/
5856
typedef struct {
5957
int install_signal_handlers;
60-
PyObject *argv; /* sys.argv list, can be NULL */
61-
PyObject *module_search_path; /* sys.path list */
62-
PyObject *warnoptions; /* sys.warnoptions list, can be NULL */
63-
PyObject *xoptions; /* sys._xoptions dict, can be NULL */
58+
PyObject *argv; /* sys.argv list, can be NULL */
59+
PyObject *executable; /* sys.executable str */
60+
PyObject *prefix; /* sys.prefix str */
61+
PyObject *base_prefix; /* sys.base_prefix str, can be NULL */
62+
PyObject *exec_prefix; /* sys.exec_prefix str */
63+
PyObject *base_exec_prefix; /* sys.base_exec_prefix str, can be NULL */
64+
PyObject *warnoptions; /* sys.warnoptions list, can be NULL */
65+
PyObject *xoptions; /* sys._xoptions dict, can be NULL */
66+
PyObject *module_search_path; /* sys.path list */
6467
} _PyMainInterpreterConfig;
6568

6669
#define _PyMainInterpreterConfig_INIT \

Modules/main.c

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2005,9 +2005,14 @@ void
20052005
_PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config)
20062006
{
20072007
Py_CLEAR(config->argv);
2008-
Py_CLEAR(config->module_search_path);
2008+
Py_CLEAR(config->executable);
2009+
Py_CLEAR(config->prefix);
2010+
Py_CLEAR(config->base_prefix);
2011+
Py_CLEAR(config->exec_prefix);
2012+
Py_CLEAR(config->base_exec_prefix);
20092013
Py_CLEAR(config->warnoptions);
20102014
Py_CLEAR(config->xoptions);
2015+
Py_CLEAR(config->module_search_path);
20112016
}
20122017

20132018

@@ -2052,9 +2057,14 @@ _PyMainInterpreterConfig_Copy(_PyMainInterpreterConfig *config,
20522057
} while (0)
20532058

20542059
COPY_ATTR(argv);
2055-
COPY_ATTR(module_search_path);
2060+
COPY_ATTR(executable);
2061+
COPY_ATTR(prefix);
2062+
COPY_ATTR(base_prefix);
2063+
COPY_ATTR(exec_prefix);
2064+
COPY_ATTR(base_exec_prefix);
20562065
COPY_ATTR(warnoptions);
20572066
COPY_ATTR(xoptions);
2067+
COPY_ATTR(module_search_path);
20582068
#undef COPY_ATTR
20592069
return 0;
20602070
}
@@ -2099,39 +2109,60 @@ config_create_path_list(const wchar_t *path, wchar_t delim)
20992109
}
21002110

21012111

2102-
static _PyInitError
2103-
config_init_module_search_path(_PyMainInterpreterConfig *config, _PyCoreConfig *core_config)
2112+
_PyInitError
2113+
_PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config, _PyCoreConfig *core_config)
21042114
{
21052115
_PyInitError err = _PyPathConfig_Init(core_config);
21062116
if (_Py_INIT_FAILED(err)) {
21072117
return err;
21082118
}
2109-
wchar_t *sys_path = Py_GetPath();
21102119

2111-
config->module_search_path = config_create_path_list(sys_path, DELIM);
2112-
if (config->module_search_path == NULL) {
2113-
return _Py_INIT_NO_MEMORY();
2114-
}
2115-
return _Py_INIT_OK();
2116-
}
2117-
2118-
2119-
_PyInitError
2120-
_PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config, _PyCoreConfig *core_config)
2121-
{
21222120
/* Signal handlers are installed by default */
21232121
if (config->install_signal_handlers < 0) {
21242122
config->install_signal_handlers = 1;
21252123
}
21262124

21272125
if (config->module_search_path == NULL &&
21282126
!core_config->_disable_importlib)
2127+
21292128
{
2130-
_PyInitError err = config_init_module_search_path(config, core_config);
2131-
if (_Py_INIT_FAILED(err)) {
2132-
return err;
2129+
wchar_t *sys_path = Py_GetPath();
2130+
config->module_search_path = config_create_path_list(sys_path, DELIM);
2131+
if (config->module_search_path == NULL) {
2132+
return _Py_INIT_NO_MEMORY();
21332133
}
21342134
}
2135+
2136+
if (config->executable == NULL) {
2137+
config->executable = PyUnicode_FromWideChar(Py_GetProgramFullPath(), -1);
2138+
if (config->executable == NULL) {
2139+
return _Py_INIT_NO_MEMORY();
2140+
}
2141+
}
2142+
2143+
if (config->prefix == NULL) {
2144+
config->prefix = PyUnicode_FromWideChar(Py_GetPrefix(), -1);
2145+
if (config->prefix == NULL) {
2146+
return _Py_INIT_NO_MEMORY();
2147+
}
2148+
}
2149+
2150+
if (config->exec_prefix == NULL) {
2151+
config->exec_prefix = PyUnicode_FromWideChar(Py_GetExecPrefix(), -1);
2152+
if (config->exec_prefix == NULL) {
2153+
return _Py_INIT_NO_MEMORY();
2154+
}
2155+
}
2156+
2157+
if (config->base_prefix == NULL) {
2158+
Py_INCREF(config->prefix);
2159+
config->base_prefix = config->prefix;
2160+
}
2161+
2162+
if (config->base_exec_prefix == NULL) {
2163+
Py_INCREF(config->exec_prefix);
2164+
config->base_exec_prefix = config->exec_prefix;
2165+
}
21352166
return _Py_INIT_OK();
21362167
}
21372168

Python/pylifecycle.c

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -830,28 +830,7 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config)
830830
return _Py_INIT_ERR("can't initialize time");
831831
}
832832

833-
/* Set sys attributes */
834-
assert(interp->config.module_search_path != NULL);
835-
if (PySys_SetObject("path", interp->config.module_search_path) != 0) {
836-
return _Py_INIT_ERR("can't assign sys.path");
837-
}
838-
if (interp->config.argv != NULL) {
839-
if (PySys_SetObject("argv", interp->config.argv) != 0) {
840-
return _Py_INIT_ERR("can't assign sys.argv");
841-
}
842-
}
843-
if (interp->config.warnoptions != NULL) {
844-
if (PySys_SetObject("warnoptions", interp->config.warnoptions)) {
845-
return _Py_INIT_ERR("can't assign sys.warnoptions");
846-
}
847-
}
848-
if (interp->config.xoptions != NULL) {
849-
if (PySys_SetObject("_xoptions", interp->config.xoptions)) {
850-
return _Py_INIT_ERR("can't assign sys._xoptions");
851-
}
852-
}
853-
854-
if (_PySys_EndInit(interp->sysdict) < 0) {
833+
if (_PySys_EndInit(interp->sysdict, &interp->config) < 0) {
855834
return _Py_INIT_ERR("can't finish initializing sys");
856835
}
857836

@@ -1314,12 +1293,6 @@ new_interpreter(PyThreadState **tstate_p)
13141293
return _Py_INIT_ERR("failed to copy main interpreter config");
13151294
}
13161295

1317-
err = _PyPathConfig_Init(&interp->core_config);
1318-
if (_Py_INIT_FAILED(err)) {
1319-
return err;
1320-
}
1321-
wchar_t *sys_path = Py_GetPath();
1322-
13231296
/* XXX The following is lax in error checking */
13241297
PyObject *modules = PyDict_New();
13251298
if (modules == NULL) {
@@ -1334,8 +1307,7 @@ new_interpreter(PyThreadState **tstate_p)
13341307
goto handle_error;
13351308
Py_INCREF(interp->sysdict);
13361309
PyDict_SetItemString(interp->sysdict, "modules", modules);
1337-
PySys_SetPath(sys_path);
1338-
_PySys_EndInit(interp->sysdict);
1310+
_PySys_EndInit(interp->sysdict, &interp->config);
13391311
}
13401312

13411313
bimod = _PyImport_FindBuiltin("builtins", modules);

Python/sysmodule.c

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2212,7 +2212,6 @@ _PySys_BeginInit(PyObject **sysmod)
22122212
}
22132213

22142214
#undef SET_SYS_FROM_STRING
2215-
#undef SET_SYS_FROM_STRING_BORROW
22162215

22172216
/* Updating the sys namespace, returning integer error codes */
22182217
#define SET_SYS_FROM_STRING_INT_RESULT(key, value) \
@@ -2228,10 +2227,35 @@ _PySys_BeginInit(PyObject **sysmod)
22282227
} while (0)
22292228

22302229
int
2231-
_PySys_EndInit(PyObject *sysdict)
2230+
_PySys_EndInit(PyObject *sysdict, _PyMainInterpreterConfig *config)
22322231
{
22332232
int res;
22342233

2234+
/* _PyMainInterpreterConfig_Read() must set all these variables */
2235+
assert(config->module_search_path != NULL);
2236+
assert(config->executable != NULL);
2237+
assert(config->prefix != NULL);
2238+
assert(config->base_prefix != NULL);
2239+
assert(config->exec_prefix != NULL);
2240+
assert(config->base_exec_prefix != NULL);
2241+
2242+
SET_SYS_FROM_STRING_BORROW("path", config->module_search_path);
2243+
SET_SYS_FROM_STRING_BORROW("executable", config->executable);
2244+
SET_SYS_FROM_STRING_BORROW("prefix", config->prefix);
2245+
SET_SYS_FROM_STRING_BORROW("base_prefix", config->base_prefix);
2246+
SET_SYS_FROM_STRING_BORROW("exec_prefix", config->exec_prefix);
2247+
SET_SYS_FROM_STRING_BORROW("base_exec_prefix", config->base_exec_prefix);
2248+
2249+
if (config->argv != NULL) {
2250+
SET_SYS_FROM_STRING_BORROW("argv", config->argv);
2251+
}
2252+
if (config->warnoptions != NULL) {
2253+
SET_SYS_FROM_STRING_BORROW("warnoptions", config->warnoptions);
2254+
}
2255+
if (config->xoptions != NULL) {
2256+
SET_SYS_FROM_STRING_BORROW("_xoptions", config->xoptions);
2257+
}
2258+
22352259
/* Set flags to their final values */
22362260
SET_SYS_FROM_STRING_INT_RESULT("flags", make_flags());
22372261
/* prevent user from creating new instances */
@@ -2247,17 +2271,6 @@ _PySys_EndInit(PyObject *sysdict)
22472271

22482272
SET_SYS_FROM_STRING_INT_RESULT("dont_write_bytecode",
22492273
PyBool_FromLong(Py_DontWriteBytecodeFlag));
2250-
SET_SYS_FROM_STRING_INT_RESULT("executable",
2251-
PyUnicode_FromWideChar(
2252-
Py_GetProgramFullPath(), -1));
2253-
SET_SYS_FROM_STRING_INT_RESULT("prefix",
2254-
PyUnicode_FromWideChar(Py_GetPrefix(), -1));
2255-
SET_SYS_FROM_STRING_INT_RESULT("exec_prefix",
2256-
PyUnicode_FromWideChar(Py_GetExecPrefix(), -1));
2257-
SET_SYS_FROM_STRING_INT_RESULT("base_prefix",
2258-
PyUnicode_FromWideChar(Py_GetPrefix(), -1));
2259-
SET_SYS_FROM_STRING_INT_RESULT("base_exec_prefix",
2260-
PyUnicode_FromWideChar(Py_GetExecPrefix(), -1));
22612274

22622275
if (get_warnoptions() == NULL)
22632276
return -1;
@@ -2268,8 +2281,12 @@ _PySys_EndInit(PyObject *sysdict)
22682281
if (PyErr_Occurred())
22692282
return -1;
22702283
return 0;
2284+
2285+
err_occurred:
2286+
return -1;
22712287
}
22722288

2289+
#undef SET_SYS_FROM_STRING_BORROW
22732290
#undef SET_SYS_FROM_STRING_INT_RESULT
22742291

22752292
static PyObject *

0 commit comments

Comments
 (0)