mirror of https://github.com/python/cpython
bpo-37619: update_one_slot() should not ignore wrapper descriptors for wrong type (GH-14836)
This commit is contained in:
parent
f958377b67
commit
57ea335606
|
@ -4649,6 +4649,18 @@ order (MRO) for bases """
|
||||||
self.assertEqual(x["y"], 42)
|
self.assertEqual(x["y"], 42)
|
||||||
self.assertEqual(x, -x)
|
self.assertEqual(x, -x)
|
||||||
|
|
||||||
|
def test_wrong_class_slot_wrapper(self):
|
||||||
|
# Check bpo-37619: a wrapper descriptor taken from the wrong class
|
||||||
|
# should raise an exception instead of silently being ignored
|
||||||
|
class A(int):
|
||||||
|
__eq__ = str.__eq__
|
||||||
|
__add__ = str.__add__
|
||||||
|
a = A()
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
a == a
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
a + a
|
||||||
|
|
||||||
def test_slot_shadows_class_variable(self):
|
def test_slot_shadows_class_variable(self):
|
||||||
with self.assertRaises(ValueError) as cm:
|
with self.assertRaises(ValueError) as cm:
|
||||||
class X:
|
class X:
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
When adding a wrapper descriptor from one class to a different class
|
||||||
|
(for example, setting ``__add__ = str.__add__`` on an ``int`` subclass),
|
||||||
|
an exception is correctly raised when the operator is called.
|
|
@ -7307,13 +7307,20 @@ update_one_slot(PyTypeObject *type, slotdef *p)
|
||||||
if (tptr == NULL || tptr == ptr)
|
if (tptr == NULL || tptr == ptr)
|
||||||
generic = p->function;
|
generic = p->function;
|
||||||
d = (PyWrapperDescrObject *)descr;
|
d = (PyWrapperDescrObject *)descr;
|
||||||
if (d->d_base->wrapper == p->wrapper &&
|
if ((specific == NULL || specific == d->d_wrapped) &&
|
||||||
|
d->d_base->wrapper == p->wrapper &&
|
||||||
PyType_IsSubtype(type, PyDescr_TYPE(d)))
|
PyType_IsSubtype(type, PyDescr_TYPE(d)))
|
||||||
{
|
{
|
||||||
if (specific == NULL ||
|
|
||||||
specific == d->d_wrapped)
|
|
||||||
specific = d->d_wrapped;
|
specific = d->d_wrapped;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
|
/* We cannot use the specific slot function because either
|
||||||
|
- it is not unique: there are multiple methods for this
|
||||||
|
slot and they conflict
|
||||||
|
- the signature is wrong (as checked by the ->wrapper
|
||||||
|
comparison above)
|
||||||
|
- it's wrapping the wrong class
|
||||||
|
*/
|
||||||
use_generic = 1;
|
use_generic = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue