Skip to content

Instantly share code, notes, and snippets.

@williamsjj
Forked from grampelberg/gist:184044
Created September 9, 2009 20:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save williamsjj/184047 to your computer and use it in GitHub Desktop.
Save williamsjj/184047 to your computer and use it in GitHub Desktop.
import time
from traceback import extract_stack, format_list
def wrap_func(base_class):
def check_func(f):
old_func_name = 'old%s' % (f.__name__,)
if hasattr(base_class, f.__name__):
setattr(base_class, old_func_name,
getattr(base_class, f.__name__))
def new_func(*args, **kwargs):
f(*args, **kwargs)
if hasattr(base_class, old_func_name):
return getattr(base_class, old_func_name)(*args, **kwargs)
setattr(base_class, f.__name__, new_func)
return new_func
return check_func
def record(base_class):
"""Record the interactions on a specific class.
This method will take a class and wrap __setattr__ and record any time a
__setattr__ occurs with the name, value, time and *where* it was set from
via. the stack. Any potential name clashes after being wrapped first call
the wrapper's functions and then the base class'. The eventual, return
value will be from your function and not this class. To get any object's
history after being wrapped by this class, just call dump_history().
Usage:
@record
class A:
foo = 1
bar = A()
bar.foo = 2
bar.dump_history()
At runtime (or in the interpreter), instead of using the class decorator,
you can use:
A = record(A)
"""
@wrap_func(base_class)
def __init__(self, *args, **kwargs):
self._history = []
@wrap_func(base_class)
def __setattr__(self, key, value):
if key != "_history":
self._history.append((key, value, time.time(),
extract_stack()[:-1]))
if not hasattr(self, 'old__setattr__'):
self.__dict__[key] = value
@wrap_func(base_class)
def dump_history(self):
for key, value, t, stack in self._history:
print '%s = %s' % (key, value)
print '@= %s' % (t,)
print ''.join(format_list(stack))
print '--------------------'
return base_class
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment