| 502 | return explicit or (None if suppress_context else implicit) |
| 503 | |
| 504 | def get_traceback_frames(self): |
| 505 | # Get the exception and all its causes |
| 506 | exceptions = [] |
| 507 | exc_value = self.exc_value |
| 508 | while exc_value: |
| 509 | exceptions.append(exc_value) |
| 510 | exc_value = self._get_explicit_or_implicit_cause(exc_value) |
| 511 | if exc_value in exceptions: |
| 512 | warnings.warn( |
| 513 | "Cycle in the exception chain detected: exception '%s' " |
| 514 | "encountered again." % exc_value, |
| 515 | ExceptionCycleWarning, |
| 516 | ) |
| 517 | # Avoid infinite loop if there's a cyclic reference (#29393). |
| 518 | break |
| 519 | |
| 520 | frames = [] |
| 521 | # No exceptions were supplied to ExceptionReporter |
| 522 | if not exceptions: |
| 523 | return frames |
| 524 | |
| 525 | # In case there's just one exception, take the traceback from self.tb |
| 526 | exc_value = exceptions.pop() |
| 527 | tb = self.tb if not exceptions else exc_value.__traceback__ |
| 528 | while True: |
| 529 | frames.extend(self.get_exception_traceback_frames(exc_value, tb)) |
| 530 | try: |
| 531 | exc_value = exceptions.pop() |
| 532 | except IndexError: |
| 533 | break |
| 534 | tb = exc_value.__traceback__ |
| 535 | return frames |
| 536 | |
| 537 | def get_exception_traceback_frames(self, exc_value, tb): |
| 538 | exc_cause = self._get_explicit_or_implicit_cause(exc_value) |