--- a/Lib/traceback.py Tue Nov 11 21:13:28 2014 +0200 +++ b/Lib/traceback.py Tue Nov 11 19:54:22 2014 +0000 @@ -3,6 +3,8 @@ import linecache import sys import operator +import collections +import types __all__ = ['extract_stack', 'extract_tb', 'format_exception', 'format_exception_only', 'format_list', 'format_stack', @@ -50,10 +52,8 @@ # - Line number # - Next item (same type as curr) # In practice, curr is either a traceback or a frame. -def _extract_tb_or_stack_iter(curr, limit, extractor): - if limit is None: - limit = getattr(sys, 'tracebacklimit', None) - +def _extract_tb_or_stack_iter_raw(curr, limit, extractor): + # Yield (filename, lineno, name, f_globals) tuples n = 0 while curr is not None and (limit is None or n < limit): f, lineno, next_item = extractor(curr) @@ -61,18 +61,28 @@ filename = co.co_filename name = co.co_name - linecache.checkcache(filename) - line = linecache.getline(filename, lineno, f.f_globals) + yield (filename, lineno, name, f.f_globals) - if line: - line = line.strip() - else: - line = None - - yield (filename, lineno, name, line) curr = next_item n += 1 +def _extract_tb_or_stack_iter(curr, limit, extractor): + # Check if limit is negative + negative_limit = limit is not None and limit < 0 + + if limit is None or negative_limit: + _limit = getattr(sys, 'tracebacklimit', None) + else: + _limit = limit + + raw = _extract_tb_or_stack_iter_raw(curr, _limit, extractor) + it = collections.deque(raw, maxlen=abs(limit)) if negative_limit else raw + + for filename, lineno, name, f_globals in it: + linecache.checkcache(filename) + line = linecache.getline(filename, lineno, f_globals) + yield (filename, lineno, name, line.strip() if line else None) + def _extract_tb_iter(tb, limit): return _extract_tb_or_stack_iter( tb, limit, @@ -311,3 +321,4 @@ # Ignore the exception raised if the frame is still executing. pass tb = tb.tb_next +