https://github.com/python/cpython/commit/4169cd9b02d417b4f8703bed845dd3232488bf8b commit: 4169cd9b02d417b4f8703bed845dd3232488bf8b branch: 3.15 author: Miss Islington (bot) <[email protected]> committer: nascheme <[email protected]> date: 2026-11-08T21:10:08-07:00 summary:
[3.15] Propagate errors from slot updates in type_setattro() (gh-161587) (gh-161642) Handle failures of update_slot(), since it can fail in the default build due to non-str keys. (cherry picked from commit 0bb9ef9695d30c9ca90a8773e40b05ff5073cc17) Co-authored-by: Neil Schemenauer <[email protected]> files: M Lib/test/test_descr.py M Objects/typeobject.c diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 4a47193841503b..3666e66bce91cc 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -4181,6 +4181,28 @@ def test_pow_wrapper_error_messages(self): 'expected 1 or 2 arguments, got 3', int().__rpow__, 1, 2, 3) + def test_setattr_slot_update_error(self): + # An error raised while updating the slots of subclasses must be + # propagated by the attribute assignment. + class K: + def __hash__(self): + return hash('__repr__') + def __eq__(self, other): + raise ZeroDivisionError + + class A: + pass + + with self.assertWarns(RuntimeWarning): + B = type('B', (A,), {K(): 1}) + if support.Py_GIL_DISABLED: + # The slot update skips non-str keys without comparing them. + A.__repr__ = lambda self: 'A' + else: + with self.assertRaises(ZeroDivisionError): + A.__repr__ = lambda self: 'A' + self.assertEqual(repr(A()), 'A') + def test_mutable_bases(self): # Testing mutable bases... diff --git a/Objects/typeobject.c b/Objects/typeobject.c index fdd393c79fcb24..520757f756820f 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -6835,11 +6835,11 @@ type_update_dict(PyTypeObject *type, PyDictObject *dict, PyObject *name, return 0; } -static void +static int update_slot_after_setattr(PyTypeObject *type, PyObject *name) { types_stop_world(); - update_slot(type, name); + int res = update_slot(type, name); types_start_world(); #ifdef Py_GIL_DISABLED // Invalidate again, after the slots are updated and while TYPE_LOCK is @@ -6850,6 +6850,7 @@ update_slot_after_setattr(PyTypeObject *type, PyObject *name) ASSERT_TYPE_LOCK_HELD(); type_modified_unlocked(type); #endif + return res; } static int @@ -6938,7 +6939,7 @@ type_setattro(PyObject *self, PyObject *name, PyObject *value) if (res == 0) { if (is_dunder_name(name) && has_slotdef(name)) { // The name corresponds to a type slot. - update_slot_after_setattr(type, name); + res = update_slot_after_setattr(type, name); } } END_TYPE_DICT_LOCK(); _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
