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.
|
of HMAC is not available.
|
||||||
(Contributed by Bénédikt Tran in :gh:`99108`.)
|
(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:
|
.. _whatsnew314-pep765:
|
||||||
|
|
||||||
|
@ -1838,6 +1838,23 @@ class ClassCreationTests(unittest.TestCase):
|
|||||||
with self.assertRaises(RuntimeWarning):
|
with self.assertRaises(RuntimeWarning):
|
||||||
type("SouthPonies", (Model,), {})
|
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):
|
def test_tuple_subclass_as_bases(self):
|
||||||
# gh-132176: it used to crash on using
|
# gh-132176: it used to crash on using
|
||||||
# tuple subclass for as base classes.
|
# 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 {
|
else {
|
||||||
use_generic = 1;
|
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) {
|
if (p->function == slot_tp_call) {
|
||||||
/* A generic __call__ is incompatible with vectorcall */
|
/* A generic __call__ is incompatible with vectorcall */
|
||||||
type_clear_flags(type, Py_TPFLAGS_HAVE_VECTORCALL);
|
type_clear_flags(type, Py_TPFLAGS_HAVE_VECTORCALL);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user