Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d7156e6

Browse files
committed
gh-77757: replace exception wrapping by PEP-678 notes in typeobject's __set_name__
1 parent 6d97e52 commit d7156e6

File tree

3 files changed

+29
-16
lines changed

3 files changed

+29
-16
lines changed

Lib/test/test_functools.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2980,7 +2980,7 @@ class MyClass(metaclass=MyMeta):
29802980

29812981
def test_reuse_different_names(self):
29822982
"""Disallow this case because decorated function a would not be cached."""
2983-
with self.assertRaises(RuntimeError) as ctx:
2983+
with self.assertRaises(TypeError) as ctx:
29842984
class ReusedCachedProperty:
29852985
@py_functools.cached_property
29862986
def a(self):
@@ -2989,7 +2989,7 @@ def a(self):
29892989
b = a
29902990

29912991
self.assertEqual(
2992-
str(ctx.exception.__context__),
2992+
str(ctx.exception),
29932993
str(TypeError("Cannot assign the same cached_property to two different names ('a' and 'b')."))
29942994
)
29952995

Lib/test/test_subclassinit.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -134,30 +134,28 @@ class Descriptor:
134134
def __set_name__(self, owner, name):
135135
1/0
136136

137-
with self.assertRaises(RuntimeError) as cm:
137+
with self.assertRaises(ZeroDivisionError) as cm:
138138
class NotGoingToWork:
139139
attr = Descriptor()
140140

141-
exc = cm.exception
142-
self.assertRegex(str(exc), r'\bNotGoingToWork\b')
143-
self.assertRegex(str(exc), r'\battr\b')
144-
self.assertRegex(str(exc), r'\bDescriptor\b')
145-
self.assertIsInstance(exc.__cause__, ZeroDivisionError)
141+
notes = cm.exception.__notes__
142+
self.assertRegex(str(notes), r'\bNotGoingToWork\b')
143+
self.assertRegex(str(notes), r'\battr\b')
144+
self.assertRegex(str(notes), r'\bDescriptor\b')
146145

147146
def test_set_name_wrong(self):
148147
class Descriptor:
149148
def __set_name__(self):
150149
pass
151150

152-
with self.assertRaises(RuntimeError) as cm:
151+
with self.assertRaises(TypeError) as cm:
153152
class NotGoingToWork:
154153
attr = Descriptor()
155154

156-
exc = cm.exception
157-
self.assertRegex(str(exc), r'\bNotGoingToWork\b')
158-
self.assertRegex(str(exc), r'\battr\b')
159-
self.assertRegex(str(exc), r'\bDescriptor\b')
160-
self.assertIsInstance(exc.__cause__, TypeError)
155+
notes = cm.exception.__notes__
156+
self.assertRegex(str(notes), r'\bNotGoingToWork\b')
157+
self.assertRegex(str(notes), r'\battr\b')
158+
self.assertRegex(str(notes), r'\bDescriptor\b')
161159

162160
def test_set_name_lookup(self):
163161
resolved = []

Objects/typeobject.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9137,13 +9137,28 @@ type_new_set_names(PyTypeObject *type)
91379137
Py_DECREF(set_name);
91389138

91399139
if (res == NULL) {
9140-
_PyErr_FormatFromCause(PyExc_RuntimeError,
9140+
/* Add note to the exception */
9141+
PyObject *exc = PyErr_GetRaisedException();
9142+
assert(exc != NULL);
9143+
PyObject *note = PyUnicode_FromFormat(
91419144
"Error calling __set_name__ on '%.100s' instance %R "
91429145
"in '%.100s'",
91439146
Py_TYPE(value)->tp_name, key, type->tp_name);
9147+
9148+
if (note) {
9149+
int res = _PyException_AddNote(exc, note);
9150+
Py_DECREF(note);
9151+
if (res == 0) {
9152+
PyErr_SetRaisedException(exc);
9153+
goto error;
9154+
}
9155+
}
9156+
_PyErr_ChainExceptions1(exc);
91449157
goto error;
91459158
}
9146-
Py_DECREF(res);
9159+
else {
9160+
Py_DECREF(res);
9161+
}
91479162
}
91489163

91499164
Py_DECREF(names_to_set);

0 commit comments

Comments
 (0)