@@ -0,0 +1,1984 @@
+%22%22%22%0ATrack important values, print on exceptions.%0A%0ASample use:%0A%0A@tracked%0Adef foo(a=1):%0A  divisor = a - 1%0A  track(%22Dividing by %25r%22, divisor)%0A  return 1 / divisor%0A%0A@tracked%0Adef bar(x):%0A    track('before foo(%25r)', x)%0A    return foo(x)%0A%0A%3E%3E%3E bar(1)%0Abar: before foo(1)%0Afoo: Dividing by 0%0A%3CNormal stacktrace%3E%0A%22%22%22%0A%0A__all__ = %5B'track', 'tracked'%5D%0A%0Afrom threading import local%0Aimport sys%0A%0A_local = local()%0A_local.stack = %5B%5D # contains mutable %5Bfunc_name, current_message%5D items%0A%0Adef _say(func_name, msg):%0A    %22%22%22%0A    Output a stack line to stderr.%0A    %22%22%22%0A    for s in func_name, ': ', msg, '%5Cn':%0A        sys.stderr.write(s)%0A%0Adef track(msg, *data):%0A    %22%22%22%0A    Store a string msg %25 data in a tracking stack.%0A    It will be printed if an unhandled exception is raised%0A    in a function decorated with @tracked.%0A    %22%22%22%0A    _local.stack%5B-1%5D%5B1%5D = msg %25 data%0A%0Adef tracked(func):%0A    %22%22%22%0A    Decorator to use on functions where track() is used.%0A    If an unhandled exception happens in the function,%0A    the whole stack of  strings accumulated by track() calls%0A    in the decorated functions, with function names, is printed.%0A    The exception is then re-raised.%0A    %22%22%22%0A    def printCrashTrack(*args, **kwargs):%0A        _local.stack.append(%5Bfunc.__name__, 'entered'%5D)%0A        try:%0A            return func(*args, **kwargs)%0A        except:%0A            for func_name, msg in _local.stack:%0A                _say(func_name, msg)%0A            _local.stack = %5B%5D # so that upper levels don't print it%0A            raise%0A        finally:%0A            if _local.stack:%0A                _local.stack.pop()%0A    return printCrashTrack%0A%0A%0A# TODO:%0A# def trackedAllowing(*exception_classes):%0A#     %22%22%22%0A#     Same as @tracked, but does not print the trace%0A#     if an exception for exception_classes is raised.%0A#     %22%22%22%0A# Problem: how to cut the tracking stack exactly up to the handler?%0A# Storing actual call frame IDs could be a solution.%0A# It would allow to match tracking stack with excpetion stack trace if desired.%0A

Introduce crashtrack.py