def iter_traceback(tb=None, enforce_most_recent_call_first=False):
    """
    Iterates a traceback of various formats:
      - traceback (types.TracebackType)
      - frame object (types.FrameType)
      - stack summary (traceback.StackSummary)

    :param types.TracebackType|types.FrameType|StackSummary|None tb: traceback. if None, will use sys._getframe
    :param bool enforce_most_recent_call_first:
        Frame or stack summery: most recent call first (top of the stack is the first entry in the result)
        Traceback: most recent call last
        If True, and we get traceback, will unroll and reverse, such that we have always the most recent call first.
    :return: yields the frames (types.FrameType)
    :rtype: list[types.FrameType|DummyFrame]
    """
    if tb is None:
        tb = get_current_frame()

    def is_stack_summary(_tb):
        """
        :param StackSummary|object _tb:
        :rtype: bool
        """
        return isinstance(_tb, StackSummary)

    is_frame = inspect.isframe
    is_traceback = inspect.istraceback
    assert is_traceback(tb) or is_frame(tb) or is_stack_summary(tb)
    # Frame or stack summery: most recent call first
    # Traceback: most recent call last
    if is_traceback(tb) and enforce_most_recent_call_first:
        frames = list(iter_traceback(tb))
        for frame in frames[::-1]:
            yield frame
        return

    _tb = tb
    while _tb is not None:
        if is_frame(_tb):
            frame = _tb
        elif is_stack_summary(_tb):
            if isinstance(_tb[0], ExtendedFrameSummary):
                frame = _tb[0].tb_frame
            else:
                frame = DummyFrame.from_frame_summary(_tb[0])
        else:
            frame = _tb.tb_frame
        yield frame
        if is_frame(_tb):
            _tb = _tb.f_back
        elif is_stack_summary(_tb):
            _tb = StackSummary.from_list(_tb[1:])
            if not _tb:
                _tb = None
        else:
            _tb = _tb.tb_next
def iter_traceback ( tb = None , enforce_most_recent_call_first = False ) : if tb is None : tb = get_current_frame ( ) def is_stack_summary ( _tb ) : return isinstance ( _tb , StackSummary ) is_frame = inspect . isframe is_traceback = inspect . istraceback assert is_traceback ( tb ) or is_frame ( tb ) or is_stack_summary ( tb ) if is_traceback ( tb ) and enforce_most_recent_call_first : frames = list ( iter_traceback ( tb ) ) for frame in frames [ : : - 1 ] : yield frame return _tb = tb while _tb is not None : if is_frame ( _tb ) : frame = _tb elif is_stack_summary ( _tb ) : if isinstance ( _tb [ 0 ] , ExtendedFrameSummary ) : frame = _tb [ 0 ] . tb_frame else : frame = DummyFrame . from_frame_summary ( _tb [ 0 ] ) else : frame = _tb . tb_frame yield frame if is_frame ( _tb ) : _tb = _tb . f_back elif is_stack_summary ( _tb ) : _tb = StackSummary . from_list ( _tb [ 1 : ] ) if not _tb : _tb = None else : _tb = _tb . tb_next
Iterates a traceback of various formats:
      - traceback (types.TracebackType)
      - frame object (types.FrameType)
      - stack summary (traceback.StackSummary)

    :param types.TracebackType|types.FrameType|StackSummary|None tb: traceback. if None, will use sys._getframe
    :param bool enforce_most_recent_call_first:
        Frame or stack summery: most recent call first (top of the stack is the first entry in the result)
        Traceback: most recent call last
        If True, and we get traceback, will unroll and reverse, such that we have always the most recent call first.
    :return: yields the frames (types.FrameType)
    :rtype: list[types.FrameType|DummyFrame]