Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 1 | import sys |
| 2 | import inspect |
| 3 | from collections import OrderedDict |
| 4 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 5 | |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 6 | class TracebackFancy: |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 7 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 8 | def __init__(self, traceback): |
| 9 | self.t = traceback |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 10 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 11 | def getFrame(self): |
| 12 | return FrameFancy(self.t.tb_frame) |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 13 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 14 | def getLineNumber(self): |
| 15 | return self.t.tb_lineno if self.t is not None else None |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 16 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 17 | def getNext(self): |
| 18 | return TracebackFancy(self.t.tb_next) |
| 19 | |
| 20 | def __str__(self): |
| 21 | if self.t is None: |
| 22 | return "" |
| 23 | str_self = "%s @ %s" % ( |
| 24 | self.getFrame().getName(), self.getLineNumber()) |
| 25 | return str_self + "\n" + self.getNext().__str__() |
| 26 | |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 27 | |
| 28 | class ExceptionFancy: |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 29 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 30 | def __init__(self, frame): |
| 31 | self.etraceback = frame.f_exc_traceback |
| 32 | self.etype = frame.exc_type |
| 33 | self.evalue = frame.f_exc_value |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 34 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 35 | def __init__(self, tb, ty, va): |
| 36 | self.etraceback = tb |
| 37 | self.etype = ty |
| 38 | self.evalue = va |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 39 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 40 | def getTraceback(self): |
| 41 | return TracebackFancy(self.etraceback) |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 42 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 43 | def __nonzero__(self): |
| 44 | return self.etraceback is not None or self.etype is not None or self.evalue is not None |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 45 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 46 | def getType(self): |
| 47 | return str(self.etype) |
| 48 | |
| 49 | def getValue(self): |
| 50 | return self.evalue |
| 51 | |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 52 | |
| 53 | class CodeFancy: |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 54 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 55 | def __init__(self, code): |
| 56 | self.c = code |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 57 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 58 | def getArgCount(self): |
| 59 | return self.c.co_argcount if self.c is not None else 0 |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 60 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 61 | def getFilename(self): |
| 62 | return self.c.co_filename if self.c is not None else "" |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 63 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 64 | def getVariables(self): |
| 65 | return self.c.co_varnames if self.c is not None else [] |
Enrico Granata | 78f05f1 | 2013-05-07 21:42:18 +0000 | [diff] [blame] | 66 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 67 | def getName(self): |
| 68 | return self.c.co_name if self.c is not None else "" |
| 69 | |
| 70 | def getFileName(self): |
| 71 | return self.c.co_filename if self.c is not None else "" |
| 72 | |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 73 | |
| 74 | class ArgsFancy: |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 75 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 76 | def __init__(self, frame, arginfo): |
| 77 | self.f = frame |
| 78 | self.a = arginfo |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 79 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 80 | def __str__(self): |
| 81 | args, varargs, kwargs = self.getArgs(), self.getVarArgs(), self.getKWArgs() |
| 82 | ret = "" |
| 83 | count = 0 |
| 84 | size = len(args) |
| 85 | for arg in args: |
| 86 | ret = ret + ("%s = %s" % (arg, args[arg])) |
| 87 | count = count + 1 |
| 88 | if count < size: |
| 89 | ret = ret + ", " |
| 90 | if varargs: |
| 91 | if size > 0: |
| 92 | ret = ret + " " |
| 93 | ret = ret + "varargs are " + str(varargs) |
| 94 | if kwargs: |
| 95 | if size > 0: |
| 96 | ret = ret + " " |
| 97 | ret = ret + "kwargs are " + str(kwargs) |
| 98 | return ret |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 99 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 100 | def getNumArgs(wantVarargs=False, wantKWArgs=False): |
| 101 | args, varargs, keywords, values = self.a |
| 102 | size = len(args) |
| 103 | if varargs and wantVarargs: |
| 104 | size = size + len(self.getVarArgs()) |
| 105 | if keywords and wantKWArgs: |
| 106 | size = size + len(self.getKWArgs()) |
| 107 | return size |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 108 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 109 | def getArgs(self): |
| 110 | args, _, _, values = self.a |
| 111 | argWValues = OrderedDict() |
| 112 | for arg in args: |
| 113 | argWValues[arg] = values[arg] |
| 114 | return argWValues |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 115 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 116 | def getVarArgs(self): |
| 117 | _, vargs, _, _ = self.a |
| 118 | if vargs: |
| 119 | return self.f.f_locals[vargs] |
| 120 | return () |
| 121 | |
| 122 | def getKWArgs(self): |
| 123 | _, _, kwargs, _ = self.a |
| 124 | if kwargs: |
| 125 | return self.f.f_locals[kwargs] |
| 126 | return {} |
| 127 | |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 128 | |
| 129 | class FrameFancy: |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 130 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 131 | def __init__(self, frame): |
| 132 | self.f = frame |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 133 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 134 | def getCaller(self): |
| 135 | return FrameFancy(self.f.f_back) |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 136 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 137 | def getLineNumber(self): |
| 138 | return self.f.f_lineno if self.f is not None else 0 |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 139 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 140 | def getCodeInformation(self): |
| 141 | return CodeFancy(self.f.f_code) if self.f is not None else None |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 142 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 143 | def getExceptionInfo(self): |
| 144 | return ExceptionFancy(self.f) if self.f is not None else None |
Enrico Granata | 78f05f1 | 2013-05-07 21:42:18 +0000 | [diff] [blame] | 145 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 146 | def getName(self): |
| 147 | return self.getCodeInformation().getName() if self.f is not None else "" |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 148 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 149 | def getFileName(self): |
| 150 | return self.getCodeInformation().getFileName() if self.f is not None else "" |
| 151 | |
| 152 | def getLocals(self): |
| 153 | return self.f.f_locals if self.f is not None else {} |
| 154 | |
| 155 | def getArgumentInfo(self): |
| 156 | return ArgsFancy( |
| 157 | self.f, inspect.getargvalues( |
| 158 | self.f)) if self.f is not None else None |
| 159 | |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 160 | |
| 161 | class TracerClass: |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 162 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 163 | def callEvent(self, frame): |
| 164 | pass |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 165 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 166 | def lineEvent(self, frame): |
| 167 | pass |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 168 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 169 | def returnEvent(self, frame, retval): |
| 170 | pass |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 171 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 172 | def exceptionEvent(self, frame, exception, value, traceback): |
| 173 | pass |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 174 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 175 | def cCallEvent(self, frame, cfunct): |
| 176 | pass |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 177 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 178 | def cReturnEvent(self, frame, cfunct): |
| 179 | pass |
| 180 | |
| 181 | def cExceptionEvent(self, frame, cfunct): |
| 182 | pass |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 183 | |
| 184 | tracer_impl = TracerClass() |
| 185 | |
| 186 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 187 | def the_tracer_entrypoint(frame, event, args): |
| 188 | if tracer_impl is None: |
| 189 | return None |
| 190 | if event == "call": |
| 191 | call_retval = tracer_impl.callEvent(FrameFancy(frame)) |
| 192 | if not call_retval: |
| 193 | return None |
| 194 | return the_tracer_entrypoint |
| 195 | elif event == "line": |
| 196 | line_retval = tracer_impl.lineEvent(FrameFancy(frame)) |
| 197 | if not line_retval: |
| 198 | return None |
| 199 | return the_tracer_entrypoint |
| 200 | elif event == "return": |
| 201 | tracer_impl.returnEvent(FrameFancy(frame), args) |
| 202 | elif event == "exception": |
| 203 | exty, exva, extb = args |
| 204 | exception_retval = tracer_impl.exceptionEvent( |
| 205 | FrameFancy(frame), ExceptionFancy(extb, exty, exva)) |
| 206 | if not exception_retval: |
| 207 | return None |
| 208 | return the_tracer_entrypoint |
| 209 | elif event == "c_call": |
| 210 | tracer_impl.cCallEvent(FrameFancy(frame), args) |
| 211 | elif event == "c_return": |
| 212 | tracer_impl.cReturnEvent(FrameFancy(frame), args) |
| 213 | elif event == "c_exception": |
| 214 | tracer_impl.cExceptionEvent(FrameFancy(frame), args) |
| 215 | return None |
| 216 | |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 217 | |
| 218 | def enable(t=None): |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 219 | global tracer_impl |
| 220 | if t: |
| 221 | tracer_impl = t |
| 222 | sys.settrace(the_tracer_entrypoint) |
| 223 | |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 224 | |
| 225 | def disable(): |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 226 | sys.settrace(None) |
| 227 | |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 228 | |
| 229 | class LoggingTracer: |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 230 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 231 | def callEvent(self, frame): |
| 232 | print "call " + frame.getName() + " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo()) |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 233 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 234 | def lineEvent(self, frame): |
| 235 | print "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + " locals are " + str(frame.getLocals()) + " in " + frame.getFileName() |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 236 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 237 | def returnEvent(self, frame, retval): |
| 238 | print "return from " + frame.getName() + " value is " + str(retval) + " locals are " + str(frame.getLocals()) |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 239 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 240 | def exceptionEvent(self, frame, exception): |
| 241 | print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber()) |
| 242 | print "tb: " + str(exception.getTraceback()) |
| 243 | |
| 244 | # the same functionality as LoggingTracer, but with a little more |
| 245 | # lldb-specific smarts |
| 246 | |
| 247 | |
Enrico Granata | 78f05f1 | 2013-05-07 21:42:18 +0000 | [diff] [blame] | 248 | class LLDBAwareTracer: |
Enrico Granata | 78f05f1 | 2013-05-07 21:42:18 +0000 | [diff] [blame] | 249 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 250 | def callEvent(self, frame): |
| 251 | if frame.getName() == "<module>": |
| 252 | return |
| 253 | if frame.getName() == "run_one_line": |
| 254 | print "call run_one_line(%s)" % (frame.getArgumentInfo().getArgs()["input_string"]) |
| 255 | return |
| 256 | if "Python.framework" in frame.getFileName(): |
| 257 | print "call into Python at " + frame.getName() |
| 258 | return |
| 259 | if frame.getName() == "__init__" and frame.getCaller().getName( |
| 260 | ) == "run_one_line" and frame.getCaller().getLineNumber() == 101: |
| 261 | return False |
| 262 | strout = "call " + frame.getName() |
| 263 | if (frame.getCaller().getFileName() == ""): |
| 264 | strout += " from LLDB - args are " |
| 265 | args = frame.getArgumentInfo().getArgs() |
| 266 | for arg in args: |
| 267 | if arg == "dict" or arg == "internal_dict": |
| 268 | continue |
| 269 | strout = strout + ("%s = %s " % (arg, args[arg])) |
| 270 | else: |
| 271 | strout += " from " + frame.getCaller().getName() + " @ " + \ |
| 272 | str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo()) |
| 273 | print strout |
Enrico Granata | 78f05f1 | 2013-05-07 21:42:18 +0000 | [diff] [blame] | 274 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 275 | def lineEvent(self, frame): |
| 276 | if frame.getName() == "<module>": |
| 277 | return |
| 278 | if frame.getName() == "run_one_line": |
| 279 | print "running run_one_line(%s) @ %s" % (frame.getArgumentInfo().getArgs()["input_string"], frame.getLineNumber()) |
| 280 | return |
| 281 | if "Python.framework" in frame.getFileName(): |
| 282 | print "running into Python at " + frame.getName() + " @ " + str(frame.getLineNumber()) |
| 283 | return |
| 284 | strout = "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + \ |
| 285 | " locals are " |
| 286 | if (frame.getCaller().getFileName() == ""): |
| 287 | locals = frame.getLocals() |
| 288 | for local in locals: |
| 289 | if local == "dict" or local == "internal_dict": |
| 290 | continue |
| 291 | strout = strout + ("%s = %s " % (local, locals[local])) |
| 292 | else: |
| 293 | strout = strout + str(frame.getLocals()) |
| 294 | strout = strout + " in " + frame.getFileName() |
| 295 | print strout |
Enrico Granata | 78f05f1 | 2013-05-07 21:42:18 +0000 | [diff] [blame] | 296 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 297 | def returnEvent(self, frame, retval): |
| 298 | if frame.getName() == "<module>": |
| 299 | return |
| 300 | if frame.getName() == "run_one_line": |
| 301 | print "return from run_one_line(%s) return value is %s" % (frame.getArgumentInfo().getArgs()["input_string"], retval) |
| 302 | return |
| 303 | if "Python.framework" in frame.getFileName(): |
| 304 | print "return from Python at " + frame.getName() + " return value is " + str(retval) |
| 305 | return |
| 306 | strout = "return from " + frame.getName() + " return value is " + \ |
| 307 | str(retval) + " locals are " |
| 308 | if (frame.getCaller().getFileName() == ""): |
| 309 | locals = frame.getLocals() |
| 310 | for local in locals: |
| 311 | if local == "dict" or local == "internal_dict": |
| 312 | continue |
| 313 | strout = strout + ("%s = %s " % (local, locals[local])) |
| 314 | else: |
| 315 | strout = strout + str(frame.getLocals()) |
| 316 | strout = strout + " in " + frame.getFileName() |
| 317 | print strout |
Enrico Granata | 78f05f1 | 2013-05-07 21:42:18 +0000 | [diff] [blame] | 318 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 319 | def exceptionEvent(self, frame, exception): |
| 320 | if frame.getName() == "<module>": |
| 321 | return |
| 322 | print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber()) |
| 323 | print "tb: " + str(exception.getTraceback()) |
| 324 | |
| 325 | |
| 326 | def f(x, y=None): |
| 327 | if x > 0: |
| 328 | return 2 + f(x - 2) |
| 329 | return 35 |
| 330 | |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 331 | |
| 332 | def g(x): |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 333 | return 1.134 / x |
| 334 | |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 335 | |
| 336 | def print_keyword_args(**kwargs): |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 337 | # kwargs is a dict of the keyword args passed to the function |
| 338 | for key, value in kwargs.iteritems(): |
| 339 | print "%s = %s" % (key, value) |
| 340 | |
Enrico Granata | c8b36f1 | 2013-05-07 19:49:59 +0000 | [diff] [blame] | 341 | |
| 342 | def total(initial=5, *numbers, **keywords): |
| 343 | count = initial |
| 344 | for number in numbers: |
| 345 | count += number |
| 346 | for key in keywords: |
| 347 | count += keywords[key] |
| 348 | return count |
| 349 | |
| 350 | if __name__ == "__main__": |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 351 | enable(LoggingTracer()) |
| 352 | f(5) |
| 353 | f(5, 1) |
| 354 | print_keyword_args(first_name="John", last_name="Doe") |
| 355 | total(10, 1, 2, 3, vegetables=50, fruits=100) |
| 356 | try: |
| 357 | g(0) |
| 358 | except: |
| 359 | pass |
| 360 | disable() |