def inspect_frames(frames): for fi in frames: if isinstance(fi, ex.FrameInfo): yield fi elif isinstance(fi, types.FrameType): yield ex.get_info(fi) else: raise ValueError("Expected a frame or a FrameInfo tuple, got %r" % fi)
def format_stack(frames, style='plaintext', source_lines=5, show_signature=True, show_vals='like_source', truncate_vals=500, line_wrap=60, reverse=False, suppressed_paths=None): """ Render a list of frames (or FrameInfo tuples) keyword args like stackprinter.format() """ min_src_lines = 0 if source_lines == 0 else 1 minimal_formatter = get_formatter(style=style, source_lines=min_src_lines, show_signature=False, show_vals=False) reduced_formatter = get_formatter(style=style, source_lines=min_src_lines, show_signature=show_signature, show_vals=show_vals, truncate_vals=truncate_vals, line_wrap=line_wrap, suppressed_paths=suppressed_paths) verbose_formatter = get_formatter(style=style, source_lines=source_lines, show_signature=show_signature, show_vals=show_vals, truncate_vals=truncate_vals, line_wrap=line_wrap, suppressed_paths=suppressed_paths) frame_msgs = [] parent_is_boring = True for frame in frames: fi = ex.get_info(frame) is_boring = match(fi.filename, suppressed_paths) if is_boring: if parent_is_boring: formatter = minimal_formatter else: formatter = reduced_formatter else: formatter = verbose_formatter parent_is_boring = is_boring frame_msgs.append(formatter(fi)) if reverse: frame_msgs = reversed(frame_msgs) return ''.join(frame_msgs)
def format_exc_info(etype, evalue, tb, style='plaintext', add_summary='auto', reverse=False, **kwargs): """ Format an exception traceback, including the exception message keyword args like stackprinter.format() """ try: msgs = [] if tb: frameinfos = [ex.get_info(tb_) for tb_ in _walk_traceback(tb)] stack_msg = format_stack(frameinfos, style=style, reverse=reverse, **kwargs) msgs.append(stack_msg) if add_summary == 'auto': add_summary = stack_msg.count('\n') > 50 if add_summary: summ = format_summary(frameinfos, style=style, reverse=reverse, **kwargs) summ += '\n' msgs.append('---- (full traceback below) ----\n\n' if reverse else '---- (full traceback above) ----\n') msgs.append(summ) exc = format_exception_message(etype, evalue, style=style) msgs.append('\n\n' if reverse else '') msgs.append(exc) if reverse: msgs = reversed(msgs) msg = ''.join(msgs) except Exception as exc: our_tb = traceback.format_exception(exc.__class__, exc, exc.__traceback__, chain=False) msg = 'Stackprinter failed:\n%s' % ''.join(our_tb[-2:]) msg += 'So here is the original traceback at least:\n\n' msg += ''.join(traceback.format_exception(etype, evalue, tb)) return msg
def frameinfo(): somevalue = 'spam' supersecretthings = "gaaaah" class Blob(): pass someobject = Blob() someobject.secretattribute = "uarrgh" fr = sys._getframe() hidden = [r".*secret.*", r"someobject\..*attribute"] return ex.get_info(fr, suppressed_vars=hidden)
def format_stack_from_frame(fr, add_summary=False, **kwargs): """ Render a frame and its parents keyword args like stackprinter.format() """ stack = [] while fr is not None: stack.append(ex.get_info(fr)) fr = fr.f_back stack = reversed(stack) return format_stack(stack, **kwargs)
def __call__(self, frame, lineno=None): """ Render a single stack frame or traceback entry Params ---- frame: Frame object, Traceback object (or FrameInfo tuple) The frame or traceback entry to be formatted. The only difference between passing a frame or a traceback object is which line gets highlighted in the source listing: For a frame, it's the currently executed line; for a traceback, it's the line where an error occurred. (technically: `frame.f_lineno` vs. `tb.tb_lineno`) The third option is interesting only if you're planning to format one frame multiple different ways: It is a little faster to format a pre-chewed verion of the frame, since non-formatting-specific steps like "finding the source code", "finding all the variables" etc only need to be done once per frame. So, this method also accepts the raw results of `extraction.get_info()` of type FrameInfo. In that case, this method will really just do formatting, no more chewing. lineno: int override which line gets highlighted """ accepted_types = (types.FrameType, types.TracebackType, ex.FrameInfo) if not isinstance(frame, accepted_types): raise ValueError("Expected one of these types: " "%s. Got %r" % (accepted_types, frame)) try: if isinstance(frame, ex.FrameInfo): finfo = frame else: finfo = ex.get_info(frame, lineno) return self._format_frame(finfo, self.lines, self.lines_after, self.show_vals, self.show_signature, self.truncate_vals, self.suppressed_paths) except Exception as exc: if isinstance(frame, ex.FrameInfo): exc.where = [finfo.filename, finfo.function, finfo.lineno] else: exc.where = frame raise
def format_exc_info(etype, evalue, tb, style='plaintext', add_summary='auto', reverse=False, **kwargs): """ Format an exception traceback, including the exception message keyword args like stackprinter.format() """ msg = '' try: # First, recursively format any chained exceptions (exceptions during whose handling # the given one happened). # TODO: refactor this whole messy function to return a more... structured datastructure # before assembling a string, so that e.g. a summary of the whole chain can be shown at # the end. context = getattr(evalue, '__context__', None) cause = getattr(evalue, '__cause__', None) suppress_context = getattr(evalue, '__suppress_context__', False) if cause: chained_exc = cause chain_hint = ("\n\nThe above exception was the direct cause " "of the following exception:\n\n") elif context and not suppress_context: chained_exc = context chain_hint = ("\n\nWhile handling the above exception, " "another exception occurred:\n\n") else: chained_exc = None if chained_exc: msg += format_exc_info(chained_exc.__class__, chained_exc, chained_exc.__traceback__, style=style, add_summary=add_summary, reverse=reverse, **kwargs) if style == 'plaintext': msg += chain_hint else: sc = getattr(colorschemes, style) clr = get_ansi_tpl(*sc.colors['exception_type']) msg += clr % chain_hint # Now, actually do some formatting: msgs = [] if tb: frameinfos = [ex.get_info(tb_) for tb_ in _walk_traceback(tb)] stack_msg = format_stack(frameinfos, style=style, reverse=reverse, **kwargs) msgs.append(stack_msg) if add_summary == 'auto': add_summary = stack_msg.count('\n') > 50 if add_summary: summ = format_summary(frameinfos, style=style, reverse=reverse, **kwargs) summ += '\n' msgs.append('---- (full traceback below) ----\n\n' if reverse else '---- (full traceback above) ----\n') msgs.append(summ) exc = format_exception_message(etype, evalue, style=style) msgs.append('\n\n' if reverse else '') msgs.append(exc) if reverse: msgs = reversed(msgs) msg += ''.join(msgs) except Exception as exc: import os if 'PY_STACKPRINTER_DEBUG' in os.environ: raise our_tb = traceback.format_exception(exc.__class__, exc, exc.__traceback__, chain=False) where = getattr(exc, 'where', None) context = " while formatting " + str(where) if where else '' msg = 'Stackprinter failed%s:\n%s\n' % (context, ''.join(our_tb[-2:])) msg += 'So here is your original traceback at least:\n\n' msg += ''.join(traceback.format_exception(etype, evalue, tb)) return msg
def frameinfo(): somevalue = 'spam' fr = sys._getframe() return ex.get_info(fr)