import types

def simplify(s):
    if isinstance(s,unicode):
        return s.encode("unicode_escape")[:100]
    elif isinstance(s,str):
        return s.encode("string_escape")[:100]
    else:
        return str(s)[:100]

class debugWrapper(object):
	indent = 0
	__slots__ = ("func", "__name__","log")
	def __init__(self, log, func):
		if not callable(func):
			raise "%s func is not callable"%func
		self.log = log
		self.func = func
		self.__name__ = func.__name__
	def __call__(self, *args,**kwargs):
		debugWrapper.indent += 1
		try:
			args0=map(simplify,args)
			self.log.debug("%sCalling %s with %s %s",' '*debugWrapper.indent,self.__name__,args0,kwargs)
			r = self.func(*args,**kwargs)
			self.log.debug("%s%s returns %s",' '*debugWrapper.indent,self.__name__,simplify(r))
			debugWrapper.indent -= 1
			return r
		except:
			self.log.exception("%sin %s",' '*debugWrapper.indent,self.__name__)
			debugWrapper.indent -= 1
			return None
	def wrapFunc(cls, log, func):
		if not callable(func):
			raise "%s func is not callable"%func
		func = cls(log, func)
		return func
	wrapFunc = classmethod(wrapFunc)
	def wrapClass(cls, log, wcls):
		for mn in dir(wcls):
			m = getattr(wcls,mn)
			if isinstance(m,types.MethodType):
				if m.im_func.func_name in ("__str__","__repr__"):
					continue
				setattr(wcls,mn,types.MethodType(cls(log, m.im_func),m.im_self,wcls))
			elif isinstance(m,types.FunctionType):
				setattr(wcls,mn,cls(log, m))
			elif isinstance(m,types.ClassType):
				cls.wrapClass(log, m)
	wrapClass = classmethod(wrapClass)

