Source (Text):
import inspect, os, sys
DEBUG = int(os.environ.get('DEBUG_MYPRODUCT', 0))
def ObserverProxy(method_names):
class Proxy:
def __init__(self):
self._observers = []
def add_observer(self, observer):
self._observers.append(observer)
def remove_observer(self, observer):
self._observers.remove(observer)
def create_method_proxy(method_name):
def method_proxy(self, *args, **kwargs):
for observer in self._observers:
getattr(observer, method_name)(*args, **kwargs)
return method_proxy
for method_name in method_names:
setattr(Proxy, method_name, create_method_proxy(method_name))
return Proxy()
debugobserver = ObserverProxy(["write", "close"])
debugobserver.add_observer(sys.stdout)
def debug(s, tabs=0, steps=(1,), f=False):
if DEBUG or f:
inspect_dbg = []
if type(steps)==type(1):
steps = range(1, steps+1)
for i in steps:
try:
caller_method = inspect.stack()[i][3]
caller_method_line = inspect.stack()[i][2]
except IndexError:
break
inspect_dbg.append("%s:%s"%(caller_method, caller_method_line))
out = "\t"*tabs + "%s (%s)"%(s, ", ".join(inspect_dbg))
print >>debugobserver, out
|
Explanation:
You might want to use it differently in your particular environment but this will give you some ideas. For example, look at the way 'debugobserver' accepts any objects that have a 'write' method.
Usage of this (installing you have to figure out yourself :)
class MyProduct(...)
....def foo(self, x):
........debug("We're calling foo() with %r" % x)
........if True:
............debug("Definitely true", 1) # shows outout 1 tab indented
........debug("how is this called?", steps=5)
class MyProduct:
....def foo(self, x):
........debug("We're calling foo() with %r" % x)
........if True:
............debug("Definitely true", 1)
........debug("how is this called?", steps=3)
....def bar1(self):
........self.bar2("anything")
....def bar2(self, x):
........self.foo(x)
m = MyProduct()
m.bar1()
And the outcome of this is:
We're calling foo() with 'anything' (foo:52)
Definitely true (foo:54)
how is this called? (foo:55, bar2:61, bar1:58)
(the numbers mean which line in the code from which they're being called)
|