gh-141510, PEP 814: Add built-in frozendict type (#144757)

Add TYPE_FROZENDICT to the marshal module.

Add C API functions:

* PyAnyDict_Check()
* PyAnyDict_CheckExact()
* PyFrozenDict_Check()
* PyFrozenDict_CheckExact()
* PyFrozenDict_New()

Add PyFrozenDict_Type C type.

Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Co-authored-by: Adam Johnson <me@adamj.eu>
Co-authored-by: Benedikt Johannes <benedikt.johannes.hofer@gmail.com>
This commit is contained in:
Victor Stinner 2026-02-17 10:54:41 +01:00 committed by GitHub
parent 63531a3867
commit 696cdfc0a2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 579 additions and 126 deletions

View file

@ -3536,6 +3536,7 @@ _PyBuiltin_Init(PyInterpreterState *interp)
SETBUILTIN("enumerate", &PyEnum_Type);
SETBUILTIN("filter", &PyFilter_Type);
SETBUILTIN("float", &PyFloat_Type);
SETBUILTIN("frozendict", &PyFrozenDict_Type);
SETBUILTIN("frozenset", &PyFrozenSet_Type);
SETBUILTIN("property", &PyProperty_Type);
SETBUILTIN("int", &PyLong_Type);

View file

@ -67,6 +67,7 @@ module marshal
#define TYPE_TUPLE '(' // See also TYPE_SMALL_TUPLE.
#define TYPE_LIST '['
#define TYPE_DICT '{'
#define TYPE_FROZENDICT '}'
#define TYPE_CODE 'c'
#define TYPE_UNICODE 'u'
#define TYPE_UNKNOWN '?'
@ -575,10 +576,15 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
w_object(PyList_GET_ITEM(v, i), p);
}
}
else if (PyDict_CheckExact(v)) {
else if (PyAnyDict_CheckExact(v)) {
Py_ssize_t pos;
PyObject *key, *value;
W_TYPE(TYPE_DICT, p);
if (PyFrozenDict_CheckExact(v)) {
W_TYPE(TYPE_FROZENDICT, p);
}
else {
W_TYPE(TYPE_DICT, p);
}
/* This one is NULL object terminated! */
pos = 0;
while (PyDict_Next(v, &pos, &key, &value)) {
@ -1420,6 +1426,7 @@ r_object(RFILE *p)
break;
case TYPE_DICT:
case TYPE_FROZENDICT:
v = PyDict_New();
R_REF(v);
if (v == NULL)
@ -1443,7 +1450,16 @@ r_object(RFILE *p)
Py_DECREF(val);
}
if (PyErr_Occurred()) {
Py_SETREF(v, NULL);
Py_CLEAR(v);
}
if (type == TYPE_FROZENDICT && v != NULL) {
PyObject *frozendict = PyFrozenDict_New(v);
if (frozendict != NULL) {
Py_SETREF(v, frozendict);
}
else {
Py_CLEAR(v);
}
}
retval = v;
break;