From 3b52c8d66b25415f09478ab43f93d59a3547dc13 Mon Sep 17 00:00:00 2001 From: Erlend Egeberg Aasland Date: Wed, 28 Apr 2021 19:02:42 +0200 Subject: bpo-43908: Add Py_TPFLAGS_IMMUTABLETYPE flag (GH-25520) Introduce Py_TPFLAGS_IMMUTABLETYPE flag for immutable type objects, and modify PyType_Ready() to set it for static types. Co-authored-by: Victor Stinner --- Doc/c-api/typeobj.rst | 12 ++++++++++++ Include/object.h | 3 +++ .../next/C API/2021-04-22-10-46-40.bpo-43908.Co3YhZ.rst | 3 +++ Objects/typeobject.c | 7 ++++++- 4 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/C API/2021-04-22-10-46-40.bpo-43908.Co3YhZ.rst diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index 9efe3aa..4c75a12 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1177,6 +1177,18 @@ and :c:type:`PyType_Type` effectively act as defaults.) .. versionadded:: 3.10 + .. data:: Py_TPFLAGS_IMMUTABLETYPE + + This bit is set for type objects that are immutable: type attributes cannot be set nor deleted. + + :c:func:`PyType_Ready` automatically applies this flag to static types. + + **Inheritance:** + + This flag is not inherited. + + .. versionadded:: 3.10 + .. c:member:: const char* PyTypeObject.tp_doc diff --git a/Include/object.h b/Include/object.h index 695f015..d8476f9 100644 --- a/Include/object.h +++ b/Include/object.h @@ -320,6 +320,9 @@ Code can use PyType_HasFeature(type_ob, flag_value) to test whether the given type object has a specified feature. */ +/* Set if the type object is immutable: type attributes cannot be set nor deleted */ +#define Py_TPFLAGS_IMMUTABLETYPE (1UL << 8) + /* Set if the type object is dynamically allocated */ #define Py_TPFLAGS_HEAPTYPE (1UL << 9) diff --git a/Misc/NEWS.d/next/C API/2021-04-22-10-46-40.bpo-43908.Co3YhZ.rst b/Misc/NEWS.d/next/C API/2021-04-22-10-46-40.bpo-43908.Co3YhZ.rst new file mode 100644 index 0000000..0413c20 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2021-04-22-10-46-40.bpo-43908.Co3YhZ.rst @@ -0,0 +1,3 @@ +Introduce :const:`Py_TPFLAGS_IMMUTABLETYPE` flag for immutable type objects, and +modify :c:func:`PyType_Ready` to set it for static types. Patch by +Erlend E. Aasland. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 254d12c..e1c8be4 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3875,7 +3875,7 @@ static int type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) { int res; - if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { + if (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) { PyErr_Format( PyExc_TypeError, "can't set attributes of built-in/extension type '%s'", @@ -6229,6 +6229,11 @@ PyType_Ready(PyTypeObject *type) type->tp_flags |= Py_TPFLAGS_READYING; + /* Historically, all static types were immutable. See bpo-43908 */ + if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { + type->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE; + } + if (type_ready(type) < 0) { type->tp_flags &= ~Py_TPFLAGS_READYING; return -1; -- cgit v0.12