2008-04-27
Attribute tracing as a mixin class
Attribute tracing as a standalone class has limits if you want to trace access to all objects of a particular class, not just a few of them; you wind up having to hunt down all the places where you manufacture new instances and modify them and so on. So let's try an attribute tracer as a mixin:
def _getname(obj): cl = obj.__class__ return "<%s.%s>" % \ (cl.__module__, cl.__name__) def _repon(obj, n): t = obj._t_il return (not t) or (n in t) class GTrace(object): _t_il = None def __getattribute__(self, n): if n in ("__class__", "_t_il"): return super(GTrace, self).__getattribute__(n) if _repon(self, n): print "get %s.%s" % (_getname(self), n) return super(GTrace, self).__getattribute__(n) class Trace(GTrace): def __setattr__(self, n, v): if _repon(self, n): print "set %s.%s" % (_getname(self), n) super(Trace, self).__setattr__(n, v) def __delattr__(self, n): if _repon(self, n): print "del %s.%s" % (_getname(self), n) super(Trace, self).__delattr__(n)
(You select what attributes are traced by creating a subclass that
has _t_il
set to something, and then mixing in that instead of
GTrace
or Trace
.)
Unfortunately, it turns out that this simple mixin implementation is not too useful. The problem is that it gives you too much information; because it is mixed in to the class itself, it reports on access to attributes even from code inside the class. The result is that you are probably going to drown in information, unless you're only interested in access to things that are only used from the outside.
Being more selective would require being able to work out if the attribute access is being done by a class method or by an external function. Unfortunately there is no direct access to this information; it would have to be inferred from frame and code information.