bpo-24329: allow __qualname__ and __classcell__ in __slots__ (GH-495)

This commit is contained in:
Xiang Zhang 2017-03-08 11:18:49 +08:00 committed by GitHub
parent d5d3249e8a
commit c393ee8589
2 changed files with 51 additions and 5 deletions

View file

@ -1322,6 +1322,46 @@ order (MRO) for bases """
a.foo = 42
self.assertEqual(a.__dict__, {"foo": 42})
def test_slots_special2(self):
# Testing __qualname__ and __classcell__ in __slots__
class Meta(type):
def __new__(cls, name, bases, namespace, attr):
self.assertIn(attr, namespace)
return super().__new__(cls, name, bases, namespace)
class C1:
def __init__(self):
self.b = 42
class C2(C1, metaclass=Meta, attr="__classcell__"):
__slots__ = ["__classcell__"]
def __init__(self):
super().__init__()
self.assertIsInstance(C2.__dict__["__classcell__"],
types.MemberDescriptorType)
c = C2()
self.assertEqual(c.b, 42)
self.assertNotHasAttr(c, "__classcell__")
c.__classcell__ = 42
self.assertEqual(c.__classcell__, 42)
with self.assertRaises(TypeError):
class C3:
__classcell__ = 42
__slots__ = ["__classcell__"]
class Q1(metaclass=Meta, attr="__qualname__"):
__slots__ = ["__qualname__"]
self.assertEqual(Q1.__qualname__, C1.__qualname__[:-2] + "Q1")
self.assertIsInstance(Q1.__dict__["__qualname__"],
types.MemberDescriptorType)
q = Q1()
self.assertNotHasAttr(q, "__qualname__")
q.__qualname__ = "q"
self.assertEqual(q.__qualname__, "q")
with self.assertRaises(TypeError):
class Q2:
__qualname__ = object()
__slots__ = ["__qualname__"]
def test_slots_descriptor(self):
# Issue2115: slot descriptors did not correctly check
# the type of the given object

View file

@ -2478,11 +2478,17 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
}
PyList_SET_ITEM(newslots, j, tmp);
if (PyDict_GetItem(dict, tmp)) {
PyErr_Format(PyExc_ValueError,
"%R in __slots__ conflicts with class variable",
tmp);
Py_DECREF(newslots);
goto error;
/* CPython inserts __qualname__ and __classcell__ (when needed)
into the namespace when creating a class. They will be deleted
below so won't act as class variables. */
if (!_PyUnicode_EqualToASCIIId(tmp, &PyId___qualname__) &&
!_PyUnicode_EqualToASCIIId(tmp, &PyId___classcell__)) {
PyErr_Format(PyExc_ValueError,
"%R in __slots__ conflicts with class variable",
tmp);
Py_DECREF(newslots);
goto error;
}
}
j++;
}