summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErlend Egeberg Aasland <erlend.aasland@innova.no>2021-04-30 15:25:43 +0200
committerGitHub <noreply@github.com>2021-04-30 15:25:43 +0200
commit64141382ecbad665d5738ff26d15505f3427c724 (patch)
tree4e651b277dd979d635cc55fa5b5bf33864a20d69
parent9032cf5cb1e33c0349089cfb0f6bf11ed3c30e86 (diff)
downloadcpython-git-64141382ecbad665d5738ff26d15505f3427c724.tar.gz
bpo-43908: check_set_special_type_attr() checks Py_TPFLAGS_IMMUTABLETYPE (GH-25743)
check_set_special_type_attr() and type_set_annotations() now check for immutable flag (Py_TPFLAGS_IMMUTABLETYPE). Co-authored-by: Victor Stinner <vstinner@python.org>
-rw-r--r--Lib/test/test_descr.py6
-rw-r--r--Objects/typeobject.c18
2 files changed, 15 insertions, 9 deletions
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index 79d6c4b5e7..3cb923ed05 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -4763,12 +4763,14 @@ order (MRO) for bases """
"elephant"
X.__doc__ = "banana"
self.assertEqual(X.__doc__, "banana")
+
with self.assertRaises(TypeError) as cm:
type(list).__dict__["__doc__"].__set__(list, "blah")
- self.assertIn("can't set list.__doc__", str(cm.exception))
+ self.assertIn("cannot set '__doc__' attribute of immutable type 'list'", str(cm.exception))
+
with self.assertRaises(TypeError) as cm:
type(X).__dict__["__doc__"].__delete__(X)
- self.assertIn("can't delete X.__doc__", str(cm.exception))
+ self.assertIn("cannot delete '__doc__' attribute of immutable type 'X'", str(cm.exception))
self.assertEqual(X.__doc__, "banana")
def test_qualname(self):
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 0f7f280bca..621bb0ca93 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -466,14 +466,16 @@ static PyMemberDef type_members[] = {
static int
check_set_special_type_attr(PyTypeObject *type, PyObject *value, const char *name)
{
- if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
+ if (_PyType_HasFeature(type, Py_TPFLAGS_IMMUTABLETYPE)) {
PyErr_Format(PyExc_TypeError,
- "can't set %s.%s", type->tp_name, name);
+ "cannot set '%s' attribute of immutable type '%s'",
+ name, type->tp_name);
return 0;
}
if (!value) {
PyErr_Format(PyExc_TypeError,
- "can't delete %s.%s", type->tp_name, name);
+ "cannot delete '%s' attribute of immutable type '%s'",
+ name, type->tp_name);
return 0;
}
@@ -978,8 +980,10 @@ type_get_annotations(PyTypeObject *type, void *context)
static int
type_set_annotations(PyTypeObject *type, PyObject *value, void *context)
{
- if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
- PyErr_Format(PyExc_TypeError, "can't set attributes of built-in/extension type '%s'", type->tp_name);
+ if (_PyType_HasFeature(type, Py_TPFLAGS_IMMUTABLETYPE)) {
+ PyErr_Format(PyExc_TypeError,
+ "cannot set '__annotations__' attribute of immutable type '%s'",
+ type->tp_name);
return -1;
}
@@ -3953,8 +3957,8 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
if (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
PyErr_Format(
PyExc_TypeError,
- "can't set attributes of built-in/extension type '%s'",
- type->tp_name);
+ "cannot set %R attribute of immutable type '%s'",
+ name, type->tp_name);
return -1;
}
if (PyUnicode_Check(name)) {