bpo-24959: fix unittest.assertRaises bug where traceback entries are … · python/cpython@f3ea249 (original) (raw)
`@@ -173,17 +173,9 @@ def stop(self):
`
173
173
`def _exc_info_to_string(self, err, test):
`
174
174
`"""Converts a sys.exc_info()-style tuple of values into a string."""
`
175
175
`exctype, value, tb = err
`
176
``
`-
Skip test runner traceback levels
`
177
``
`-
while tb and self._is_relevant_tb_level(tb):
`
178
``
`-
tb = tb.tb_next
`
179
``
-
180
``
`-
if exctype is test.failureException:
`
181
``
`-
Skip assert*() traceback levels
`
182
``
`-
length = self._count_relevant_tb_levels(tb)
`
183
``
`-
else:
`
184
``
`-
length = None
`
``
176
`+
tb = self._clean_tracebacks(exctype, value, tb, test)
`
185
177
`tb_e = traceback.TracebackException(
`
186
``
`-
exctype, value, tb, limit=length, capture_locals=self.tb_locals)
`
``
178
`+
exctype, value, tb, capture_locals=self.tb_locals)
`
187
179
`msgLines = list(tb_e.format())
`
188
180
``
189
181
`if self.buffer:
`
`@@ -199,16 +191,49 @@ def _exc_info_to_string(self, err, test):
`
199
191
`msgLines.append(STDERR_LINE % error)
`
200
192
`return ''.join(msgLines)
`
201
193
``
``
194
`+
def _clean_tracebacks(self, exctype, value, tb, test):
`
``
195
`+
ret = None
`
``
196
`+
first = True
`
``
197
`+
excs = [(exctype, value, tb)]
`
``
198
`+
while excs:
`
``
199
`+
(exctype, value, tb) = excs.pop()
`
``
200
`+
Skip test runner traceback levels
`
``
201
`+
while tb and self._is_relevant_tb_level(tb):
`
``
202
`+
tb = tb.tb_next
`
``
203
+
``
204
`+
Skip assert*() traceback levels
`
``
205
`+
if exctype is test.failureException:
`
``
206
`+
self._remove_unittest_tb_frames(tb)
`
``
207
+
``
208
`+
if first:
`
``
209
`+
ret = tb
`
``
210
`+
first = False
`
``
211
`+
else:
`
``
212
`+
value.traceback = tb
`
``
213
+
``
214
`+
if value is not None:
`
``
215
`+
for c in (value.cause, value.context):
`
``
216
`+
if c is not None:
`
``
217
`+
excs.append((type(c), c, c.traceback))
`
``
218
`+
return ret
`
202
219
``
203
220
`def _is_relevant_tb_level(self, tb):
`
204
221
`return '__unittest' in tb.tb_frame.f_globals
`
205
222
``
206
``
`-
def _count_relevant_tb_levels(self, tb):
`
207
``
`-
length = 0
`
``
223
`+
def _remove_unittest_tb_frames(self, tb):
`
``
224
`+
'''Truncates usercode tb at the first unittest frame.
`
``
225
+
``
226
`+
If the first frame of the traceback is in user code,
`
``
227
`+
the prefix up to the first unittest frame is returned.
`
``
228
`+
If the first frame is already in the unittest module,
`
``
229
`+
the traceback is not modified.
`
``
230
`+
'''
`
``
231
`+
prev = None
`
208
232
`while tb and not self._is_relevant_tb_level(tb):
`
209
``
`-
length += 1
`
``
233
`+
prev = tb
`
210
234
`tb = tb.tb_next
`
211
``
`-
return length
`
``
235
`+
if prev is not None:
`
``
236
`+
prev.tb_next = None
`
212
237
``
213
238
`def repr(self):
`
214
239
`return ("<%s run=%i errors=%i failures=%i>" %
`