gh-132284: Don't wrap base PyCFunction slots on class creation if not overridden (#132329)
This commit is contained in:
parent
5707837049
commit
a23ed8b379
@ -469,6 +469,10 @@ Other language changes
|
||||
of HMAC is not available.
|
||||
(Contributed by Bénédikt Tran in :gh:`99108`.)
|
||||
|
||||
* When subclassing from a pure C type, the C slots for the new type are no
|
||||
longer replaced with a wrapped version on class creation if they are not
|
||||
explicitly overridden in the subclass.
|
||||
(Contributed by Tomasz Pytel in :gh:`132329`.)
|
||||
|
||||
.. _whatsnew314-pep765:
|
||||
|
||||
|
@ -1838,6 +1838,23 @@ class ClassCreationTests(unittest.TestCase):
|
||||
with self.assertRaises(RuntimeWarning):
|
||||
type("SouthPonies", (Model,), {})
|
||||
|
||||
def test_subclass_inherited_slot_update(self):
|
||||
# gh-132284: Make sure slot update still works after fix.
|
||||
# Note that after assignment to D.__getitem__ the actual C slot will
|
||||
# never go back to dict_subscript as it was on class type creation but
|
||||
# rather be set to slot_mp_subscript, unfortunately there is no way to
|
||||
# check that here.
|
||||
|
||||
class D(dict):
|
||||
pass
|
||||
|
||||
d = D({None: None})
|
||||
self.assertIs(d[None], None)
|
||||
D.__getitem__ = lambda self, item: 42
|
||||
self.assertEqual(d[None], 42)
|
||||
D.__getitem__ = dict.__getitem__
|
||||
self.assertIs(d[None], None)
|
||||
|
||||
def test_tuple_subclass_as_bases(self):
|
||||
# gh-132176: it used to crash on using
|
||||
# tuple subclass for as base classes.
|
||||
|
@ -0,0 +1 @@
|
||||
Don't wrap base ``PyCFunction`` slots on class creation if not overridden.
|
@ -11233,7 +11233,14 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p)
|
||||
}
|
||||
else {
|
||||
use_generic = 1;
|
||||
generic = p->function;
|
||||
if (generic == NULL && Py_IS_TYPE(descr, &PyMethodDescr_Type) &&
|
||||
*ptr == ((PyMethodDescrObject *)descr)->d_method->ml_meth)
|
||||
{
|
||||
generic = *ptr;
|
||||
}
|
||||
else {
|
||||
generic = p->function;
|
||||
}
|
||||
if (p->function == slot_tp_call) {
|
||||
/* A generic __call__ is incompatible with vectorcall */
|
||||
type_clear_flags(type, Py_TPFLAGS_HAVE_VECTORCALL);
|
||||
|
Loading…
x
Reference in New Issue
Block a user