diff --git a/Include/object.h b/Include/object.h index 695f015642..66e48cb0be 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 if immutable */ +#define Py_TPFLAGS_IMMUTABLE (1UL << 8) + /* Set if the type object is dynamically allocated */ #define Py_TPFLAGS_HEAPTYPE (1UL << 9) diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index bdcd1254b3..d419d59ad2 100644 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -50,6 +50,10 @@ def test_empty(self): a += a self.assertEqual(len(a), 0) + def test_immutable(self): + with self.assertRaises(TypeError): + array.array.foo = 1 + # Machine format codes. # diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index fb9ebbe9f4..6c1fcf26aa 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -2846,7 +2846,7 @@ static PyType_Slot array_slots[] = { static PyType_Spec array_spec = { .name = "array.array", .basicsize = sizeof(arrayobject), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLE, .slots = array_slots, }; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index a957c832b9..32498d8e57 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3859,7 +3859,9 @@ 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_HEAPTYPE) || + type->tp_flags & Py_TPFLAGS_IMMUTABLE) + { PyErr_Format( PyExc_TypeError, "can't set attributes of built-in/extension type '%s'",