def _truncate_recursive_traceback(self, traceback): """ Truncate the given recursive traceback trying to find the starting point of the recursion. The detection is done by going through each traceback entry and finding the point in which the locals of the frame are equal to the locals of a previous frame (see ``recursionindex()``. Handle the situation where the recursion process might raise an exception (for example comparing numpy arrays using equality raises a TypeError), in which case we do our best to warn the user of the error and show a limited traceback. """ try: recursionindex = traceback.recursionindex() except Exception as e: max_frames = 10 extraline = ( '!!! Recursion error detected, but an error occurred locating the origin of recursion.\n' ' The following exception happened when comparing locals in the stack frame:\n' ' {exc_type}: {exc_msg}\n' ' Displaying first and last {max_frames} stack frames out of {total}.' ).format(exc_type=type(e).__name__, exc_msg=safe_str(e), max_frames=max_frames, total=len(traceback)) traceback = traceback[:max_frames] + traceback[-max_frames:] else: if recursionindex is not None: extraline = "!!! Recursion detected (same locals & position)" traceback = traceback[:recursionindex + 1] else: extraline = None return traceback, extraline
def repr_traceback(self, excinfo): traceback = excinfo.traceback if self.tbfilter: traceback = traceback.filter() recursionindex = None if excinfo.errisinstance(RuntimeError): recursionindex = traceback.recursionindex() last = traceback[-1] entries = [] extraline = None for index, entry in enumerate(traceback): einfo = (last == entry) and excinfo or None reprentry = self.repr_traceback_entry(entry, einfo) entries.append(reprentry) if index == recursionindex: extraline = "!!! Recursion detected (same locals & position)" break return ReprTraceback(entries, extraline, style=self.style)