bpo-32030: Add _PyCoreConfig_Copy() (#4874) · python/cpython@da27341 (original) (raw)
`@@ -1914,6 +1914,154 @@ pymain_parse_cmdline_envvars(_PyMain *pymain)
`
1914
1914
`}
`
1915
1915
``
1916
1916
``
``
1917
`+
/* Read configuration settings from standard locations
`
``
1918
`+
`
``
1919
`+
- This function doesn't make any changes to the interpreter state - it
`
``
1920
`+
- merely populates any missing configuration settings. This allows an
`
``
1921
`+
- embedding application to completely override a config option by
`
``
1922
`+
- setting it before calling this function, or else modify the default
`
``
1923
`+
- setting before passing the fully populated config to Py_EndInitialization.
`
``
1924
`+
`
``
1925
`+
- More advanced selective initialization tricks are possible by calling
`
``
1926
`+
- this function multiple times with various preconfigured settings.
`
``
1927
`+
*/
`
``
1928
+
``
1929
`+
_PyInitError
`
``
1930
`+
_PyCoreConfig_Read(_PyCoreConfig *config)
`
``
1931
`+
{
`
``
1932
`+
if (config->program_name == NULL) {
`
``
1933
`+
#ifdef MS_WINDOWS
`
``
1934
`+
const wchar_t *program_name = L"python";
`
``
1935
`+
#else
`
``
1936
`+
const wchar_t *program_name = L"python3";
`
``
1937
`+
#endif
`
``
1938
`+
config->program_name = _PyMem_RawWcsdup(program_name);
`
``
1939
`+
if (config->program_name == NULL) {
`
``
1940
`+
return _Py_INIT_NO_MEMORY();
`
``
1941
`+
}
`
``
1942
`+
}
`
``
1943
+
``
1944
`+
return _Py_INIT_OK();
`
``
1945
`+
}
`
``
1946
+
``
1947
+
``
1948
`+
void
`
``
1949
`+
_PyCoreConfig_Clear(_PyCoreConfig *config)
`
``
1950
`+
{
`
``
1951
`+
#define CLEAR(ATTR) \
`
``
1952
`+
do { \
`
``
1953
`+
PyMem_RawFree(ATTR); \
`
``
1954
`+
ATTR = NULL; \
`
``
1955
`+
} while (0)
`
``
1956
+
``
1957
`+
CLEAR(config->module_search_path_env);
`
``
1958
`+
CLEAR(config->home);
`
``
1959
`+
CLEAR(config->program_name);
`
``
1960
`+
#undef CLEAR
`
``
1961
`+
}
`
``
1962
+
``
1963
+
``
1964
`+
int
`
``
1965
`+
_PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
`
``
1966
`+
{
`
``
1967
`+
_PyCoreConfig_Clear(config);
`
``
1968
+
``
1969
`+
#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
`
``
1970
`+
COPY_ATTR(ignore_environment);
`
``
1971
`+
COPY_ATTR(use_hash_seed);
`
``
1972
`+
COPY_ATTR(hash_seed);
`
``
1973
`+
COPY_ATTR(_disable_importlib);
`
``
1974
`+
COPY_ATTR(allocator);
`
``
1975
`+
COPY_ATTR(dev_mode);
`
``
1976
`+
COPY_ATTR(faulthandler);
`
``
1977
`+
COPY_ATTR(tracemalloc);
`
``
1978
`+
COPY_ATTR(import_time);
`
``
1979
`+
COPY_ATTR(show_ref_count);
`
``
1980
`+
COPY_ATTR(show_alloc_count);
`
``
1981
`+
COPY_ATTR(dump_refs);
`
``
1982
`+
COPY_ATTR(malloc_stats);
`
``
1983
`+
COPY_ATTR(utf8_mode);
`
``
1984
`+
#undef COPY_ATTR
`
``
1985
+
``
1986
`+
#define COPY_STR_ATTR(ATTR) \
`
``
1987
`+
do { \
`
``
1988
`+
if (config2->ATTR != NULL) { \
`
``
1989
`+
config->ATTR = _PyMem_RawWcsdup(config2->ATTR); \
`
``
1990
`+
if (config->ATTR == NULL) { \
`
``
1991
`+
return -1; \
`
``
1992
`+
} \
`
``
1993
`+
} \
`
``
1994
`+
} while (0)
`
``
1995
+
``
1996
`+
COPY_STR_ATTR(module_search_path_env);
`
``
1997
`+
COPY_STR_ATTR(home);
`
``
1998
`+
COPY_STR_ATTR(program_name);
`
``
1999
`+
#undef COPY_STR_ATTR
`
``
2000
`+
return 0;
`
``
2001
`+
}
`
``
2002
+
``
2003
+
``
2004
`+
void
`
``
2005
`+
_PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config)
`
``
2006
`+
{
`
``
2007
`+
Py_CLEAR(config->argv);
`
``
2008
`+
Py_CLEAR(config->module_search_path);
`
``
2009
`+
Py_CLEAR(config->warnoptions);
`
``
2010
`+
Py_CLEAR(config->xoptions);
`
``
2011
`+
}
`
``
2012
+
``
2013
+
``
2014
`+
static PyObject*
`
``
2015
`+
config_copy_attr(PyObject *obj)
`
``
2016
`+
{
`
``
2017
`+
if (PyUnicode_Check(obj)) {
`
``
2018
`+
Py_INCREF(obj);
`
``
2019
`+
return obj;
`
``
2020
`+
}
`
``
2021
`+
else if (PyList_Check(obj)) {
`
``
2022
`+
return PyList_GetSlice(obj, 0, Py_SIZE(obj));
`
``
2023
`+
}
`
``
2024
`+
else if (PyDict_Check(obj)) {
`
``
2025
`+
/* The dict type is used for xoptions. Make the assumption that keys
`
``
2026
`+
and values are immutables */
`
``
2027
`+
return PyDict_Copy(obj);
`
``
2028
`+
}
`
``
2029
`+
else {
`
``
2030
`+
PyErr_Format(PyExc_TypeError,
`
``
2031
`+
"cannot copy config attribute of type %.200s",
`
``
2032
`+
Py_TYPE(obj)->tp_name);
`
``
2033
`+
return NULL;
`
``
2034
`+
}
`
``
2035
`+
}
`
``
2036
+
``
2037
+
``
2038
`+
int
`
``
2039
`+
_PyMainInterpreterConfig_Copy(_PyMainInterpreterConfig *config,
`
``
2040
`+
const _PyMainInterpreterConfig *config2)
`
``
2041
`+
{
`
``
2042
`+
_PyMainInterpreterConfig_Clear(config);
`
``
2043
+
``
2044
`+
#define COPY_ATTR(ATTR) \
`
``
2045
`+
do { \
`
``
2046
`+
if (config2->ATTR != NULL) { \
`
``
2047
`+
config->ATTR = config_copy_attr(config2->ATTR); \
`
``
2048
`+
if (config->ATTR == NULL) { \
`
``
2049
`+
return -1; \
`
``
2050
`+
} \
`
``
2051
`+
} \
`
``
2052
`+
} while (0)
`
``
2053
+
``
2054
`+
COPY_ATTR(argv);
`
``
2055
`+
COPY_ATTR(module_search_path);
`
``
2056
`+
COPY_ATTR(warnoptions);
`
``
2057
`+
COPY_ATTR(xoptions);
`
``
2058
`+
#undef COPY_ATTR
`
``
2059
`+
return 0;
`
``
2060
`+
}
`
``
2061
+
``
2062
+
``
2063
+
``
2064
+
1917
2065
`static PyObject *
`
1918
2066
`config_create_path_list(const wchar_t *path, wchar_t delim)
`
1919
2067
`{
`