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 if sys.version_info.major == 2: 137 sys.stderr.write((u"%s%s: '%s'\n" % (indent, name, value)).encode('utf8')) 138 else: 139 sys.stderr.write((u"%s%s: '%s'\n" % (indent, name, value))) 140 141def log(name): 142 if debug: 143 frame = inspect.stack()[1][0] 144 value = eval(name, frame.f_globals, frame.f_locals) 145 indent = ' ' * (_report_indent[0]) 146 logger("%s%s: %s" % (indent, name, value)) 147 148def pprint(name): 149 if debug: 150 frame = inspect.stack()[1][0] 151 value = eval(name, frame.f_globals, frame.f_locals) 152 indent = ' ' * (_report_indent[0]) 153 sys.stderr.write("%s%s:\n" % (indent, name)) 154 lines = pformat(value).split('\n') 155 for line in lines: 156 sys.stderr.write("%s %s\n"%(indent, line)) 157 158def dir(name): 159 if debug: 160 name = "dir(%s)" % name 161 frame = inspect.stack()[1][0] 162 value = eval(name, frame.f_globals, frame.f_locals) 163 indent = ' ' * (_report_indent[0]) 164 sys.stderr.write("%s%s:\n" % (indent, name)) 165 lines = pformat(value).split('\n') 166 for line in lines: 167 sys.stderr.write("%s %s\n"%(indent, line)) 168 169def type(name): 170 if debug: 171 name = "type(%s)" % name 172 frame = inspect.stack()[1][0] 173 value = eval(name, frame.f_globals, frame.f_locals) 174 indent = ' ' * (_report_indent[0]) 175 sys.stderr.write("%s%s: %s\n" % (indent, name, value)) 176 177def say(s): 178 if debug: 179 indent = ' ' * (_report_indent[0]) 180 sys.stderr.write("%s%s\n" % (indent, s)) 181 sys.stderr.flush() 182 183def profile(fn): 184 def wrapper(*args, **kwargs): 185 datafn = fn.__name__ + ".profile" # Name the data file sensibly 186 prof = cProfile.Profile() 187 retval = prof.runcall(fn, *args, **kwargs) 188 prof.dump_stats(datafn) 189 return retval 190 if debug: 191 from decorator import decorator 192 return decorator(wrapper, fn) 193 else: 194 return fn 195 196def traceback(levels=None): 197 if debug: 198 indent = ' ' * (_report_indent[0]) 199 sys.stderr.write("\n%s---- Stack ----\n" % indent) 200 if levels: 201 start = -2-levels 202 else: 203 start = None 204 for s in tb.format_stack()[start:-1]: 205 sys.stderr.write("%s%s" % (indent, s)) 206 sys.stderr.write("%s---------------\n" % indent) 207 208def show_caller(level=None): 209 if debug: 210 indent = ' ' * (_report_indent[0]) 211 if level is None: 212 level = -3 213 sys.stderr.write("%sCalled from %s\n" % (indent, tb.format_stack()[level].strip()[4:])) 214 215def info(name): 216 if debug: 217 frame = inspect.stack()[1][0] 218 value = eval(name, frame.f_globals, frame.f_locals) 219 vtype = eval("type(%s)"%name, frame.f_globals, frame.f_locals) 220 indent = ' ' * (_report_indent[0]) 221 sys.stderr.write("%s%s: '%s' (%s)\n" % (indent, name, value, vtype)) 222