mirror of https://github.com/python/cpython
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>
This commit is contained in:
parent
9032cf5cb1
commit
64141382ec
|
@ -4763,12 +4763,14 @@ order (MRO) for bases """
|
||||||
"elephant"
|
"elephant"
|
||||||
X.__doc__ = "banana"
|
X.__doc__ = "banana"
|
||||||
self.assertEqual(X.__doc__, "banana")
|
self.assertEqual(X.__doc__, "banana")
|
||||||
|
|
||||||
with self.assertRaises(TypeError) as cm:
|
with self.assertRaises(TypeError) as cm:
|
||||||
type(list).__dict__["__doc__"].__set__(list, "blah")
|
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:
|
with self.assertRaises(TypeError) as cm:
|
||||||
type(X).__dict__["__doc__"].__delete__(X)
|
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")
|
self.assertEqual(X.__doc__, "banana")
|
||||||
|
|
||||||
def test_qualname(self):
|
def test_qualname(self):
|
||||||
|
|
|
@ -466,14 +466,16 @@ static PyMemberDef type_members[] = {
|
||||||
static int
|
static int
|
||||||
check_set_special_type_attr(PyTypeObject *type, PyObject *value, const char *name)
|
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,
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!value) {
|
if (!value) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -978,8 +980,10 @@ type_get_annotations(PyTypeObject *type, void *context)
|
||||||
static int
|
static int
|
||||||
type_set_annotations(PyTypeObject *type, PyObject *value, void *context)
|
type_set_annotations(PyTypeObject *type, PyObject *value, void *context)
|
||||||
{
|
{
|
||||||
if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
|
if (_PyType_HasFeature(type, Py_TPFLAGS_IMMUTABLETYPE)) {
|
||||||
PyErr_Format(PyExc_TypeError, "can't set attributes of built-in/extension type '%s'", type->tp_name);
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
"cannot set '__annotations__' attribute of immutable type '%s'",
|
||||||
|
type->tp_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3953,8 +3957,8 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
|
||||||
if (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
|
if (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
|
||||||
PyErr_Format(
|
PyErr_Format(
|
||||||
PyExc_TypeError,
|
PyExc_TypeError,
|
||||||
"can't set attributes of built-in/extension type '%s'",
|
"cannot set %R attribute of immutable type '%s'",
|
||||||
type->tp_name);
|
name, type->tp_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (PyUnicode_Check(name)) {
|
if (PyUnicode_Check(name)) {
|
||||||
|
|
Loading…
Reference in New Issue