Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from time import time
2from sys import argv
3from functools import wraps
4from types import FunctionType
7def set_debug():
8 """
9 Allow for setting debugging from the command line.
11 eg. ``--debug [ io core ]``
12 """
13 try:
14 debug = argv.index("--debug")
15 string = set([])
17 try:
18 start = argv.index("[")
19 end = argv.index("]")
20 string = {argv[i] for i in range(start + 1, end)}
21 del argv[end]
22 for i, j in enumerate(string):
23 del argv[argv.index(j)]
24 del argv[start]
25 del argv[debug]
26 except ValueError:
27 del argv[debug]
29 WHAT_TO_DEBUG = string
30 DBG = True
31 except ValueError:
32 if argv[0] == "Regtests.py":
33 debug_v = input("Enter debugging variables:\n")
34 WHAT_TO_DEBUG = set(debug_v.split())
35 DBG = True
36 else:
37 WHAT_TO_DEBUG = set([])
38 DBG = False
40 return WHAT_TO_DEBUG, DBG
43class v_print():
44 """Debug printing."""
46 def __init__(self, verbose):
47 """Print switch."""
48 if verbose: 48 ↛ 49line 48 didn't jump to line 49, because the condition on line 48 was never true
49 self.print = self._print
50 else:
51 self.print = self._dont_print
53 @staticmethod
54 def _print(*a, **k):
55 return print(*a, **k)
57 @staticmethod
58 def _dont_print(*a, **k):
59 pass
62WHAT_TO_DEBUG, DBG = set_debug()
64verb = v_print(DBG)
67class debug:
68 """
69 Debugging helper.
71 Aspects are provided as list of arguments which are decorators of the function to debug.
73 eg. ``set(['io','core'])``
75 the flag TT will print out the run time for each function only
77 Inspiration from https://wiki.python.org/moin/PythonDecoratorLibrary#Controllable_DIY_debug
79 """
81 def __init__(self, aspects=None):
82 """Set __call__ to debug version if needed."""
83 if DBG:
84 self.aspects = set(aspects)
85 self.f_dict = {}
86 setattr(debug, '__call__', self.dcall)
87 self.call = self.dcall
88 self.no_parallel = "--no-parallel" in argv
90 @staticmethod
91 def __call__(f):
92 """Do nothing if not in debugging mode."""
93 return f
95 def dcall(self, f):
96 """
97 Wrap function to print debugging info.
99 Generically gives all wrapped class methods the DBG variable
100 Can be used to carry out debugging methods (eg. if hasattr(self, "DBG"): ...)
102 If specifically selected with aspects, prints timing and/or arguments
103 """
104 @wraps(f)
105 def f_DBG(*args, **kwds):
106 if f.__name__ == "__init__" and (hasattr(args[0], "__dict__") or hasattr(args[0], "__slots__")):
107 args[0].DBG = True
108 elif isinstance(f, FunctionType) and ((len(args) > 0 and not hasattr(args[0], "DBG")) or len(args) == 0):
109 f_DBG.DBG = True
110 return f(*args, **kwds)
112 if ((self.aspects & WHAT_TO_DEBUG) or ('all' in WHAT_TO_DEBUG)) and 'STEP_THROUGH' not in WHAT_TO_DEBUG:
113 @wraps(f_DBG)
114 def newf(*args, **kwds):
115 # checks for self could be better?
116 if "TT" not in WHAT_TO_DEBUG:
117 print(f.__name__, args, kwds, [a.__dict__ for a in args if hasattr(a, '__dict__')])
119 self.start_timer(f.__name__)
121 f_result = f_DBG(*args, **kwds)
123 timing(f.__name__, self.f_dict[f.__name__], f_result)
125 return f_result
126 return newf
128 if ("STEP_THROUGH" in WHAT_TO_DEBUG) and (self.aspects & WHAT_TO_DEBUG): 128 ↛ 129line 128 didn't jump to line 129, because the condition on line 128 was never true
129 from numpy import ndarray
130 @wraps(f_DBG)
131 def stepthrough(*args, **kwds):
132 print(f_DBG.__name__)
133 print(*args[1:], **kwds)
134 out = f_DBG(*args, **kwds)
135 for i, j in out.items():
136 print(i)
137 if isinstance(j, ndarray):
138 for v in j:
139 for vv in v:
140 print(vv)
141 else:
142 print(j)
143 if self.no_parallel:
144 input()
145 return out
146 return stepthrough
148 return f_DBG
150 def start_timer(self, fname):
151 """Start timer."""
152 if fname not in self.f_dict:
153 self.f_dict[fname] = {"startf": time(), 'tt': 0}
154 else:
155 self.f_dict[fname]['startf'] = time()
158def timing(name, f_dict, f_result=None):
159 """
160 Time functions.
162 Get total run time of functions
163 """
164 f_dict["endf"] = time()
165 f_dict["step"] = f_dict["endf"] - f_dict["startf"]
167 f_dict["tt"] += f_dict["step"]
169 if f_result is None:
170 print(name, "took {:13.5e}s total {:13.5e}s".format(f_dict[
171 "step"], f_dict["tt"]))
172 else:
173 print(name, "took {:13.5e}s total {:13.5e}s".format(f_dict[
174 "step"], f_dict["tt"]), "returned", f_result)
177def profile(*args, file=None):
178 """Profile code."""
179 from cProfile import Profile
180 import pstats
181 prof = Profile()
182 out = prof.runcall(*args) # main, argparse, opts) calc.run, stat)
183 pstats.Stats(prof).strip_dirs().dump_stats(file)
184 return out
187if __name__ == '__main__':
188 pass