bpo-43908: Add Py_TPFLAGS_IMMUTABLETYPE flag (GH-25520) · python/cpython@3b52c8d (original) (raw)

4 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -1177,6 +1177,18 @@ and :c:type:`PyType_Type` effectively act as defaults.)
1177 1177
1178 1178 .. versionadded:: 3.10
1179 1179
1180 + .. data:: Py_TPFLAGS_IMMUTABLETYPE
1181 +
1182 + This bit is set for type objects that are immutable: type attributes cannot be set nor deleted.
1183 +
1184 +:c:func:`PyType_Ready` automatically applies this flag to static types.
1185 +
1186 + **Inheritance:**
1187 +
1188 + This flag is not inherited.
1189 +
1190 + .. versionadded:: 3.10
1191 +
1180 1192
1181 1193 .. c:member:: const char* PyTypeObject.tp_doc
1182 1194
Original file line number Diff line number Diff line change
@@ -320,6 +320,9 @@ Code can use PyType_HasFeature(type_ob, flag_value) to test whether the
320 320 given type object has a specified feature.
321 321 */
322 322
323 +/* Set if the type object is immutable: type attributes cannot be set nor deleted */
324 +#define Py_TPFLAGS_IMMUTABLETYPE (1UL << 8)
325 +
323 326 /* Set if the type object is dynamically allocated */
324 327 #define Py_TPFLAGS_HEAPTYPE (1UL << 9)
325 328
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
1 +Introduce :const:`Py_TPFLAGS_IMMUTABLETYPE` flag for immutable type objects, and
2 +modify :c:func:`PyType_Ready` to set it for static types. Patch by
3 +Erlend E. Aasland.
Original file line number Diff line number Diff line change
@@ -3875,7 +3875,7 @@ static int
3875 3875 type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
3876 3876 {
3877 3877 int res;
3878 -if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
3878 +if (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
3879 3879 PyErr_Format(
3880 3880 PyExc_TypeError,
3881 3881 "can't set attributes of built-in/extension type '%s'",
@@ -6229,6 +6229,11 @@ PyType_Ready(PyTypeObject *type)
6229 6229
6230 6230 type->tp_flags |= Py_TPFLAGS_READYING;
6231 6231
6232 +/* Historically, all static types were immutable. See bpo-43908 */
6233 +if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
6234 +type->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE;
6235 + }
6236 +
6232 6237 if (type_ready(type) < 0) {
6233 6238 type->tp_flags &= ~Py_TPFLAGS_READYING;
6234 6239 return -1;