mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	gh-107954, PEP 741: Add PyConfig_Get()/Set() functions (#123472)
Add PyConfig_Get(), PyConfig_GetInt(), PyConfig_Set() and PyConfig_Names() functions to get and set the current runtime Python configuration. Add visibility and "sys spec" to config and preconfig specifications. _PyConfig_AsDict() now converts PyConfig.xoptions as a dictionary. Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									db42934270
								
							
						
					
					
						commit
						33b790978d
					
				
					 19 changed files with 1468 additions and 259 deletions
				
			
		| 
						 | 
				
			
			@ -1845,6 +1845,7 @@ sys_get_int_max_str_digits_impl(PyObject *module)
 | 
			
		|||
    return PyLong_FromLong(interp->long_state.max_str_digits);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*[clinic input]
 | 
			
		||||
sys.set_int_max_str_digits
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1857,16 +1858,10 @@ static PyObject *
 | 
			
		|||
sys_set_int_max_str_digits_impl(PyObject *module, int maxdigits)
 | 
			
		||||
/*[clinic end generated code: output=734d4c2511f2a56d input=d7e3f325db6910c5]*/
 | 
			
		||||
{
 | 
			
		||||
    PyThreadState *tstate = _PyThreadState_GET();
 | 
			
		||||
    if ((!maxdigits) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD)) {
 | 
			
		||||
        tstate->interp->long_state.max_str_digits = maxdigits;
 | 
			
		||||
        Py_RETURN_NONE;
 | 
			
		||||
    } else {
 | 
			
		||||
        PyErr_Format(
 | 
			
		||||
            PyExc_ValueError, "maxdigits must be 0 or larger than %d",
 | 
			
		||||
            _PY_LONG_MAX_STR_DIGITS_THRESHOLD);
 | 
			
		||||
    if (_PySys_SetIntMaxStrDigits(maxdigits) < 0) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
    Py_RETURN_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t
 | 
			
		||||
| 
						 | 
				
			
			@ -3120,6 +3115,8 @@ static PyStructSequence_Field flags_fields[] = {
 | 
			
		|||
    {0}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define SYS_FLAGS_INT_MAX_STR_DIGITS 17
 | 
			
		||||
 | 
			
		||||
static PyStructSequence_Desc flags_desc = {
 | 
			
		||||
    "sys.flags",        /* name */
 | 
			
		||||
    flags__doc__,       /* doc */
 | 
			
		||||
| 
						 | 
				
			
			@ -3127,6 +3124,48 @@ static PyStructSequence_Desc flags_desc = {
 | 
			
		|||
    18
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
sys_set_flag(PyObject *flags, Py_ssize_t pos, PyObject *value)
 | 
			
		||||
{
 | 
			
		||||
    assert(pos >= 0 && pos < (Py_ssize_t)(Py_ARRAY_LENGTH(flags_fields) - 1));
 | 
			
		||||
 | 
			
		||||
    PyObject *old_value = PyStructSequence_GET_ITEM(flags, pos);
 | 
			
		||||
    PyStructSequence_SET_ITEM(flags, pos, Py_NewRef(value));
 | 
			
		||||
    Py_XDECREF(old_value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
_PySys_SetFlagObj(Py_ssize_t pos, PyObject *value)
 | 
			
		||||
{
 | 
			
		||||
    PyObject *flags = Py_XNewRef(PySys_GetObject("flags"));
 | 
			
		||||
    if (flags == NULL) {
 | 
			
		||||
        if (!PyErr_Occurred()) {
 | 
			
		||||
            PyErr_SetString(PyExc_RuntimeError, "lost sys.flags");
 | 
			
		||||
        }
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sys_set_flag(flags, pos, value);
 | 
			
		||||
    Py_DECREF(flags);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
_PySys_SetFlagInt(Py_ssize_t pos, int value)
 | 
			
		||||
{
 | 
			
		||||
    PyObject *obj = PyLong_FromLong(value);
 | 
			
		||||
    if (obj == NULL) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int res = _PySys_SetFlagObj(pos, obj);
 | 
			
		||||
    Py_DECREF(obj);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
set_flags_from_config(PyInterpreterState *interp, PyObject *flags)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -3142,8 +3181,8 @@ set_flags_from_config(PyInterpreterState *interp, PyObject *flags)
 | 
			
		|||
        if (value == NULL) { \
 | 
			
		||||
            return -1; \
 | 
			
		||||
        } \
 | 
			
		||||
        Py_XDECREF(PyStructSequence_GET_ITEM(flags, pos)); \
 | 
			
		||||
        PyStructSequence_SET_ITEM(flags, pos, value); \
 | 
			
		||||
        sys_set_flag(flags, pos, value); \
 | 
			
		||||
        Py_DECREF(value); \
 | 
			
		||||
        pos++; \
 | 
			
		||||
    } while (0)
 | 
			
		||||
#define SetFlag(expr) SetFlagObj(PyLong_FromLong(expr))
 | 
			
		||||
| 
						 | 
				
			
			@ -3599,64 +3638,6 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
 | 
			
		|||
    return _PyStatus_ERR("can't initialize sys module");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
sys_add_xoption(PyObject *opts, const wchar_t *s)
 | 
			
		||||
{
 | 
			
		||||
    PyObject *name, *value = NULL;
 | 
			
		||||
 | 
			
		||||
    const wchar_t *name_end = wcschr(s, L'=');
 | 
			
		||||
    if (!name_end) {
 | 
			
		||||
        name = PyUnicode_FromWideChar(s, -1);
 | 
			
		||||
        if (name == NULL) {
 | 
			
		||||
            goto error;
 | 
			
		||||
        }
 | 
			
		||||
        value = Py_NewRef(Py_True);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        name = PyUnicode_FromWideChar(s, name_end - s);
 | 
			
		||||
        if (name == NULL) {
 | 
			
		||||
            goto error;
 | 
			
		||||
        }
 | 
			
		||||
        value = PyUnicode_FromWideChar(name_end + 1, -1);
 | 
			
		||||
        if (value == NULL) {
 | 
			
		||||
            goto error;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (PyDict_SetItem(opts, name, value) < 0) {
 | 
			
		||||
        goto error;
 | 
			
		||||
    }
 | 
			
		||||
    Py_DECREF(name);
 | 
			
		||||
    Py_DECREF(value);
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
    Py_XDECREF(name);
 | 
			
		||||
    Py_XDECREF(value);
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static PyObject*
 | 
			
		||||
sys_create_xoptions_dict(const PyConfig *config)
 | 
			
		||||
{
 | 
			
		||||
    Py_ssize_t nxoption = config->xoptions.length;
 | 
			
		||||
    wchar_t * const * xoptions = config->xoptions.items;
 | 
			
		||||
    PyObject *dict = PyDict_New();
 | 
			
		||||
    if (dict == NULL) {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (Py_ssize_t i=0; i < nxoption; i++) {
 | 
			
		||||
        const wchar_t *option = xoptions[i];
 | 
			
		||||
        if (sys_add_xoption(dict, option) < 0) {
 | 
			
		||||
            Py_DECREF(dict);
 | 
			
		||||
            return NULL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return dict;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Update sys attributes for a new PyConfig configuration.
 | 
			
		||||
// This function also adds attributes that _PySys_InitCore() didn't add.
 | 
			
		||||
| 
						 | 
				
			
			@ -3703,7 +3684,7 @@ _PySys_UpdateConfig(PyThreadState *tstate)
 | 
			
		|||
    COPY_LIST("orig_argv", config->orig_argv);
 | 
			
		||||
    COPY_LIST("warnoptions", config->warnoptions);
 | 
			
		||||
 | 
			
		||||
    SET_SYS("_xoptions", sys_create_xoptions_dict(config));
 | 
			
		||||
    SET_SYS("_xoptions", _PyConfig_CreateXOptionsDict(config));
 | 
			
		||||
 | 
			
		||||
    const wchar_t *stdlibdir = _Py_GetStdlibDir();
 | 
			
		||||
    if (stdlibdir != NULL) {
 | 
			
		||||
| 
						 | 
				
			
			@ -4129,3 +4110,28 @@ PySys_FormatStderr(const char *format, ...)
 | 
			
		|||
    sys_format(&_Py_ID(stderr), stderr, format, va);
 | 
			
		||||
    va_end(va);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
_PySys_SetIntMaxStrDigits(int maxdigits)
 | 
			
		||||
{
 | 
			
		||||
    if (maxdigits != 0 && maxdigits < _PY_LONG_MAX_STR_DIGITS_THRESHOLD) {
 | 
			
		||||
        PyErr_Format(
 | 
			
		||||
            PyExc_ValueError, "maxdigits must be 0 or larger than %d",
 | 
			
		||||
            _PY_LONG_MAX_STR_DIGITS_THRESHOLD);
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Set sys.flags.int_max_str_digits
 | 
			
		||||
    const Py_ssize_t pos = SYS_FLAGS_INT_MAX_STR_DIGITS;
 | 
			
		||||
    if (_PySys_SetFlagInt(pos, maxdigits) < 0) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Set PyInterpreterState.long_state.max_str_digits
 | 
			
		||||
    // and PyInterpreterState.config.int_max_str_digits.
 | 
			
		||||
    PyInterpreterState *interp = _PyInterpreterState_GET();
 | 
			
		||||
    interp->long_state.max_str_digits = maxdigits;
 | 
			
		||||
    interp->config.int_max_str_digits = maxdigits;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue