summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/c-api/typeobj.rst12
-rw-r--r--Include/object.h3
-rw-r--r--Misc/NEWS.d/next/C API/2021-04-22-10-46-40.bpo-43908.Co3YhZ.rst3
-rw-r--r--Objects/typeobject.c7
4 files changed, 24 insertions, 1 deletions
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;