1import os 2import sys 3import time as timeutils 4import inspect 5 6try: 7 import syslog 8 logger = syslog.syslog 9except ImportError: # import syslog will fail on Windows boxes 10 import logging 11 logging.basicConfig(filename='tracker.log',level=logging.INFO) 12 logger = logging.info 13 14try: 15 from pprint import pformat 16except ImportError: 17 pformat = lambda x: x 18 19import cProfile 20import traceback as tb 21 22# A debug decorator, written by Paul Butler, taken from 23# http://paulbutler.org/archives/python-debugging-with-decorators/ 24# Additional functions and decorator functionality added by 25# Henrik Levkowetz 26 27__version__ = "0.16" 28 29increment = 2 30 31debug = False 32 33# Number of times to indent output 34# A list is used to force access by reference 35_report_indent = [4] 36_mark = [ timeutils.time() ] 37 38def set_indent(i): 39 _report_indent[0] = i 40 41def trace(fn): # renamed from 'report' by henrik 16 Jun 2011 42 """Decorator to print information about a function 43 call for use while debugging. 44 Prints function name, arguments, and call number 45 when the function is called. Prints this information 46 again along with the return value when the function 47 returns. 48 """ 49 def fix(s,n=64): 50 import re 51 s = re.sub(r'\\t', ' ', s) 52 s = re.sub(r'\s+', ' ', s) 53 if len(s) > n+3: 54 s = s[:n]+"..." 55 return s 56 def wrap(fn, *params,**kwargs): 57 call = wrap.callcount = wrap.callcount + 1 58 59 indent = ' ' * _report_indent[0] 60 fr = tb.format_stack()[-3].strip()[4:] # call from 61 fi, co = [ l.strip() for l in fr.splitlines()[:2] ] # file info, code 62 fu = "%s.%s()" % (fn.__module__, fn.__name__) # function name 63 fc = "%s(%s)" % (fn.__name__, ', '.join( # function call 64 [fix(repr(a)) for a in params] + 65 ["%s = %s" % (a, fix(repr(b))) for a,b in kwargs.items()] 66 )) 67 68 if debug: 69 sys.stderr.write("\n%s From %s:\n%s | %s\n%s %s\n%s* %s [#%s]\n" % 70 (indent, fi, indent, co, indent, fu, indent, fc, call)) 71 _report_indent[0] += increment 72 mark = timeutils.time() 73 ret = fn(*params,**kwargs) 74 tau = timeutils.time() - mark 75 _report_indent[0] -= increment 76 if debug: 77 sys.stderr.write("%s %s | %.3fs [#%s] ==> %s\n" % (indent, fc, tau, call, fix(repr(ret)))) 78 79 return ret 80 wrap.callcount = 0 81 if debug: 82 from decorator import decorator 83 return decorator(wrap, fn) 84 else: 85 return fn 86 87def mark(): 88 def show_entry(e): 89 sys.stderr.write(" at %s:L%s %s() %s\n" % e) 90 if debug: 91 indent = ' ' * (_report_indent[0]) 92 file, line, func, text = tb.extract_stack(None, 2)[0] 93 parts = file.split(os.sep) 94 name = os.sep.join(parts[-2:]) 95 sys.stderr.write("%sMark %s:%s\n" % (indent, name, line)) 96 _mark[0] = timeutils.time() 97 98def lap(s): 99 if debug: 100 clk = timeutils.time() 101 tau = clk - _mark[0] 102 ts = timeutils.strftime("%H:%M:%S", timeutils.localtime(clk)) 103 say("%s: %.3fs since mark: %s" % (ts, tau, s)) 104 105def clock(s): 106 if debug: 107 lap(s) 108 _mark[0] = timeutils.time() 109 110def time(fn): 111 """Decorator to print timing information about a function call. 112 """ 113 def wrap(fn, *params,**kwargs): 114 115 indent = ' ' * _report_indent[0] 116 fc = "%s.%s()" % (fn.__module__, fn.__name__,) 117 118 mark = timeutils.time() 119 ret = fn(*params,**kwargs) 120 tau = timeutils.time() - mark 121 sys.stderr.write("%s| %s | %.3fs\n" % (indent, fc, tau)) 122 123 return ret 124 wrap.callcount = 0 125 if debug: 126 from decorator import decorator 127 return decorator(wrap, fn) 128 else: 129 return fn 130 131def show(name): 132 if debug: 133 frame = inspect.stack()[1][0] 134 value = eval(name, frame.f_globals, frame.f_locals) 135 indent = ' ' * (_report_indent[0]) 136 sys.stderr.write("%s%s: '%s'\n" % (indent, name, value)) 137 138def log(name): 139 if debug: 140 frame = inspect.stack()[1][0] 141 value = eval(name, frame.f_globals, frame.f_locals) 142 indent = ' ' * (_report_indent[0]) 143 logger("%s%s: %s" % (indent, name, value)) 144 145def pprint(name): 146 if debug: 147 frame = inspect.stack()[1][0] 148 value = eval(name, frame.f_globals, frame.f_locals) 149 indent = ' ' * (_report_indent[0]) 150 sys.stderr.write("%s%s:\n" % (indent, name)) 151 lines = pformat(value).split('\n') 152 for line in lines: 153 sys.stderr.write("%s %s\n"%(indent, line)) 154 155def dir(name): 156 if debug: 157 name = "dir(%s)" % name 158 frame = inspect.stack()[1][0] 159 value = eval(name, frame.f_globals, frame.f_locals) 160 indent = ' ' * (_report_indent[0]) 161 sys.stderr.write("%s%s:\n" % (indent, name)) 162 lines = pformat(value).split('\n') 163 for line in lines: 164 sys.stderr.write("%s %s\n"%(indent, line)) 165 166def type(name): 167 if debug: 168 name = "type(%s)" % name 169 frame = inspect.stack()[1][0] 170 value = eval(name, frame.f_globals, frame.f_locals) 171 indent = ' ' * (_report_indent[0]) 172 sys.stderr.write("%s%s: %s\n" % (indent, name, value)) 173 174def say(s): 175 if debug: 176 indent = ' ' * (_report_indent[0]) 177 sys.stderr.write("%s%s\n" % (indent, s)) 178 sys.stderr.flush() 179 180def profile(fn): 181 def wrapper(*args, **kwargs): 182 datafn = fn.__name__ + ".profile" # Name the data file sensibly 183 prof = cProfile.Profile() 184 retval = prof.runcall(fn, *args, **kwargs) 185 prof.dump_stats(datafn) 186 return retval 187 if debug: 188 from decorator import decorator 189 return decorator(wrapper, fn) 190 else: 191 return fn 192 193def traceback(levels=None): 194 if debug: 195 indent = ' ' * (_report_indent[0]) 196 sys.stderr.write("\n%s---- Stack ----\n" % indent) 197 if levels: 198 start = -2-levels 199 else: 200 start = None 201 for s in tb.format_stack()[start:-1]: 202 sys.stderr.write("%s%s" % (indent, s)) 203 sys.stderr.write("%s---------------\n" % indent) 204 205def show_caller(level=None): 206 if debug: 207 indent = ' ' * (_report_indent[0]) 208 if level is None: 209 level = -3 210 sys.stderr.write("%sCalled from %s\n" % (indent, tb.format_stack()[level].strip()[4:])) 211 212def info(name): 213 if debug: 214 frame = inspect.stack()[1][0] 215 value = eval(name, frame.f_globals, frame.f_locals) 216 vtype = eval("type(%s)"%name, frame.f_globals, frame.f_locals) 217 indent = ' ' * (_report_indent[0]) 218 sys.stderr.write("%s%s: '%s' (%s)\n" % (indent, name, value, vtype)) 219