Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-32030: Add _PyCoreConfig_Copy() #4874

Merged
merged 1 commit into from
Dec 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
bpo-32030: Add _PyCoreConfig_Copy()
Each interpreter now has its core_config and main_config copy:

* Add _PyCoreConfig_Copy() and _PyMainInterpreterConfig_Copy()
* Move _PyCoreConfig_Read(), _PyCoreConfig_Clear() and
  _PyMainInterpreterConfig_Clear() from Python/pylifecycle.c to
  Modules/main.c
* Fix _Py_InitializeEx_Private(): call _PyCoreConfig_ReadEnv() before
  _Py_InitializeCore()
  • Loading branch information
vstinner committed Dec 15, 2017
commit 47ee76f75f523f40b21f931226fd5f652a012242
6 changes: 6 additions & 0 deletions Include/pylifecycle.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,15 @@ PyAPI_FUNC(int) _Py_IsCoreInitialized(void);
PyAPI_FUNC(_PyInitError) _PyCoreConfig_ReadEnv(_PyCoreConfig *);
PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *);
PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *);
PyAPI_FUNC(int) _PyCoreConfig_Copy(
_PyCoreConfig *config,
const _PyCoreConfig *config2);

PyAPI_FUNC(_PyInitError) _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *, _PyCoreConfig *);
PyAPI_FUNC(void) _PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *);
PyAPI_FUNC(int) _PyMainInterpreterConfig_Copy(
_PyMainInterpreterConfig *config,
const _PyMainInterpreterConfig *config2);

PyAPI_FUNC(_PyInitError) _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *);
#endif
Expand Down
148 changes: 148 additions & 0 deletions Modules/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1914,6 +1914,154 @@ pymain_parse_cmdline_envvars(_PyMain *pymain)
}


/* Read configuration settings from standard locations
*
* This function doesn't make any changes to the interpreter state - it
* merely populates any missing configuration settings. This allows an
* embedding application to completely override a config option by
* setting it before calling this function, or else modify the default
* setting before passing the fully populated config to Py_EndInitialization.
*
* More advanced selective initialization tricks are possible by calling
* this function multiple times with various preconfigured settings.
*/

_PyInitError
_PyCoreConfig_Read(_PyCoreConfig *config)
{
if (config->program_name == NULL) {
#ifdef MS_WINDOWS
const wchar_t *program_name = L"python";
#else
const wchar_t *program_name = L"python3";
#endif
config->program_name = _PyMem_RawWcsdup(program_name);
if (config->program_name == NULL) {
return _Py_INIT_NO_MEMORY();
}
}

return _Py_INIT_OK();
}


void
_PyCoreConfig_Clear(_PyCoreConfig *config)
{
#define CLEAR(ATTR) \
do { \
PyMem_RawFree(ATTR); \
ATTR = NULL; \
} while (0)

CLEAR(config->module_search_path_env);
CLEAR(config->home);
CLEAR(config->program_name);
#undef CLEAR
}


int
_PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
{
_PyCoreConfig_Clear(config);

#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
COPY_ATTR(ignore_environment);
COPY_ATTR(use_hash_seed);
COPY_ATTR(hash_seed);
COPY_ATTR(_disable_importlib);
COPY_ATTR(allocator);
COPY_ATTR(dev_mode);
COPY_ATTR(faulthandler);
COPY_ATTR(tracemalloc);
COPY_ATTR(import_time);
COPY_ATTR(show_ref_count);
COPY_ATTR(show_alloc_count);
COPY_ATTR(dump_refs);
COPY_ATTR(malloc_stats);
COPY_ATTR(utf8_mode);
#undef COPY_ATTR

#define COPY_STR_ATTR(ATTR) \
do { \
if (config2->ATTR != NULL) { \
config->ATTR = _PyMem_RawWcsdup(config2->ATTR); \
if (config->ATTR == NULL) { \
return -1; \
} \
} \
} while (0)

COPY_STR_ATTR(module_search_path_env);
COPY_STR_ATTR(home);
COPY_STR_ATTR(program_name);
#undef COPY_STR_ATTR
return 0;
}


void
_PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config)
{
Py_CLEAR(config->argv);
Py_CLEAR(config->module_search_path);
Py_CLEAR(config->warnoptions);
Py_CLEAR(config->xoptions);
}


static PyObject*
config_copy_attr(PyObject *obj)
{
if (PyUnicode_Check(obj)) {
Py_INCREF(obj);
return obj;
}
else if (PyList_Check(obj)) {
return PyList_GetSlice(obj, 0, Py_SIZE(obj));
}
else if (PyDict_Check(obj)) {
/* The dict type is used for xoptions. Make the assumption that keys
and values are immutables */
return PyDict_Copy(obj);
}
else {
PyErr_Format(PyExc_TypeError,
"cannot copy config attribute of type %.200s",
Py_TYPE(obj)->tp_name);
return NULL;
}
}


int
_PyMainInterpreterConfig_Copy(_PyMainInterpreterConfig *config,
const _PyMainInterpreterConfig *config2)
{
_PyMainInterpreterConfig_Clear(config);

#define COPY_ATTR(ATTR) \
do { \
if (config2->ATTR != NULL) { \
config->ATTR = config_copy_attr(config2->ATTR); \
if (config->ATTR == NULL) { \
return -1; \
} \
} \
} while (0)

COPY_ATTR(argv);
COPY_ATTR(module_search_path);
COPY_ATTR(warnoptions);
COPY_ATTR(xoptions);
#undef COPY_ATTR
return 0;
}




static PyObject *
config_create_path_list(const wchar_t *path, wchar_t delim)
{
Expand Down
Loading