]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.2/Lib/bdb.py
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Lib / bdb.py
CommitLineData
4710c53d 1"""Debugger basics"""\r
2\r
3import fnmatch\r
4import sys\r
5import os\r
6import types\r
7\r
8__all__ = ["BdbQuit","Bdb","Breakpoint"]\r
9\r
10class BdbQuit(Exception):\r
11 """Exception to give up completely"""\r
12\r
13\r
14class Bdb:\r
15\r
16 """Generic Python debugger base class.\r
17\r
18 This class takes care of details of the trace facility;\r
19 a derived class should implement user interaction.\r
20 The standard debugger class (pdb.Pdb) is an example.\r
21 """\r
22\r
23 def __init__(self, skip=None):\r
24 self.skip = set(skip) if skip else None\r
25 self.breaks = {}\r
26 self.fncache = {}\r
27\r
28 def canonic(self, filename):\r
29 if filename == "<" + filename[1:-1] + ">":\r
30 return filename\r
31 canonic = self.fncache.get(filename)\r
32 if not canonic:\r
33 canonic = os.path.abspath(filename)\r
34 canonic = os.path.normcase(canonic)\r
35 self.fncache[filename] = canonic\r
36 return canonic\r
37\r
38 def reset(self):\r
39 import linecache\r
40 linecache.checkcache()\r
41 self.botframe = None\r
42 self._set_stopinfo(None, None)\r
43\r
44 def trace_dispatch(self, frame, event, arg):\r
45 if self.quitting:\r
46 return # None\r
47 if event == 'line':\r
48 return self.dispatch_line(frame)\r
49 if event == 'call':\r
50 return self.dispatch_call(frame, arg)\r
51 if event == 'return':\r
52 return self.dispatch_return(frame, arg)\r
53 if event == 'exception':\r
54 return self.dispatch_exception(frame, arg)\r
55 if event == 'c_call':\r
56 return self.trace_dispatch\r
57 if event == 'c_exception':\r
58 return self.trace_dispatch\r
59 if event == 'c_return':\r
60 return self.trace_dispatch\r
61 print 'bdb.Bdb.dispatch: unknown debugging event:', repr(event)\r
62 return self.trace_dispatch\r
63\r
64 def dispatch_line(self, frame):\r
65 if self.stop_here(frame) or self.break_here(frame):\r
66 self.user_line(frame)\r
67 if self.quitting: raise BdbQuit\r
68 return self.trace_dispatch\r
69\r
70 def dispatch_call(self, frame, arg):\r
71 # XXX 'arg' is no longer used\r
72 if self.botframe is None:\r
73 # First call of dispatch since reset()\r
74 self.botframe = frame.f_back # (CT) Note that this may also be None!\r
75 return self.trace_dispatch\r
76 if not (self.stop_here(frame) or self.break_anywhere(frame)):\r
77 # No need to trace this function\r
78 return # None\r
79 self.user_call(frame, arg)\r
80 if self.quitting: raise BdbQuit\r
81 return self.trace_dispatch\r
82\r
83 def dispatch_return(self, frame, arg):\r
84 if self.stop_here(frame) or frame == self.returnframe:\r
85 self.user_return(frame, arg)\r
86 if self.quitting: raise BdbQuit\r
87 return self.trace_dispatch\r
88\r
89 def dispatch_exception(self, frame, arg):\r
90 if self.stop_here(frame):\r
91 self.user_exception(frame, arg)\r
92 if self.quitting: raise BdbQuit\r
93 return self.trace_dispatch\r
94\r
95 # Normally derived classes don't override the following\r
96 # methods, but they may if they want to redefine the\r
97 # definition of stopping and breakpoints.\r
98\r
99 def is_skipped_module(self, module_name):\r
100 for pattern in self.skip:\r
101 if fnmatch.fnmatch(module_name, pattern):\r
102 return True\r
103 return False\r
104\r
105 def stop_here(self, frame):\r
106 # (CT) stopframe may now also be None, see dispatch_call.\r
107 # (CT) the former test for None is therefore removed from here.\r
108 if self.skip and \\r
109 self.is_skipped_module(frame.f_globals.get('__name__')):\r
110 return False\r
111 if frame is self.stopframe:\r
112 if self.stoplineno == -1:\r
113 return False\r
114 return frame.f_lineno >= self.stoplineno\r
115 while frame is not None and frame is not self.stopframe:\r
116 if frame is self.botframe:\r
117 return True\r
118 frame = frame.f_back\r
119 return False\r
120\r
121 def break_here(self, frame):\r
122 filename = self.canonic(frame.f_code.co_filename)\r
123 if not filename in self.breaks:\r
124 return False\r
125 lineno = frame.f_lineno\r
126 if not lineno in self.breaks[filename]:\r
127 # The line itself has no breakpoint, but maybe the line is the\r
128 # first line of a function with breakpoint set by function name.\r
129 lineno = frame.f_code.co_firstlineno\r
130 if not lineno in self.breaks[filename]:\r
131 return False\r
132\r
133 # flag says ok to delete temp. bp\r
134 (bp, flag) = effective(filename, lineno, frame)\r
135 if bp:\r
136 self.currentbp = bp.number\r
137 if (flag and bp.temporary):\r
138 self.do_clear(str(bp.number))\r
139 return True\r
140 else:\r
141 return False\r
142\r
143 def do_clear(self, arg):\r
144 raise NotImplementedError, "subclass of bdb must implement do_clear()"\r
145\r
146 def break_anywhere(self, frame):\r
147 return self.canonic(frame.f_code.co_filename) in self.breaks\r
148\r
149 # Derived classes should override the user_* methods\r
150 # to gain control.\r
151\r
152 def user_call(self, frame, argument_list):\r
153 """This method is called when there is the remote possibility\r
154 that we ever need to stop in this function."""\r
155 pass\r
156\r
157 def user_line(self, frame):\r
158 """This method is called when we stop or break at this line."""\r
159 pass\r
160\r
161 def user_return(self, frame, return_value):\r
162 """This method is called when a return trap is set here."""\r
163 pass\r
164\r
165 def user_exception(self, frame, exc_info):\r
166 exc_type, exc_value, exc_traceback = exc_info\r
167 """This method is called if an exception occurs,\r
168 but only if we are to stop at or just below this level."""\r
169 pass\r
170\r
171 def _set_stopinfo(self, stopframe, returnframe, stoplineno=0):\r
172 self.stopframe = stopframe\r
173 self.returnframe = returnframe\r
174 self.quitting = 0\r
175 # stoplineno >= 0 means: stop at line >= the stoplineno\r
176 # stoplineno -1 means: don't stop at all\r
177 self.stoplineno = stoplineno\r
178\r
179 # Derived classes and clients can call the following methods\r
180 # to affect the stepping state.\r
181\r
182 def set_until(self, frame): #the name "until" is borrowed from gdb\r
183 """Stop when the line with the line no greater than the current one is\r
184 reached or when returning from current frame"""\r
185 self._set_stopinfo(frame, frame, frame.f_lineno+1)\r
186\r
187 def set_step(self):\r
188 """Stop after one line of code."""\r
189 self._set_stopinfo(None, None)\r
190\r
191 def set_next(self, frame):\r
192 """Stop on the next line in or below the given frame."""\r
193 self._set_stopinfo(frame, None)\r
194\r
195 def set_return(self, frame):\r
196 """Stop when returning from the given frame."""\r
197 self._set_stopinfo(frame.f_back, frame)\r
198\r
199 def set_trace(self, frame=None):\r
200 """Start debugging from `frame`.\r
201\r
202 If frame is not specified, debugging starts from caller's frame.\r
203 """\r
204 if frame is None:\r
205 frame = sys._getframe().f_back\r
206 self.reset()\r
207 while frame:\r
208 frame.f_trace = self.trace_dispatch\r
209 self.botframe = frame\r
210 frame = frame.f_back\r
211 self.set_step()\r
212 sys.settrace(self.trace_dispatch)\r
213\r
214 def set_continue(self):\r
215 # Don't stop except at breakpoints or when finished\r
216 self._set_stopinfo(self.botframe, None, -1)\r
217 if not self.breaks:\r
218 # no breakpoints; run without debugger overhead\r
219 sys.settrace(None)\r
220 frame = sys._getframe().f_back\r
221 while frame and frame is not self.botframe:\r
222 del frame.f_trace\r
223 frame = frame.f_back\r
224\r
225 def set_quit(self):\r
226 self.stopframe = self.botframe\r
227 self.returnframe = None\r
228 self.quitting = 1\r
229 sys.settrace(None)\r
230\r
231 # Derived classes and clients can call the following methods\r
232 # to manipulate breakpoints. These methods return an\r
233 # error message is something went wrong, None if all is well.\r
234 # Set_break prints out the breakpoint line and file:lineno.\r
235 # Call self.get_*break*() to see the breakpoints or better\r
236 # for bp in Breakpoint.bpbynumber: if bp: bp.bpprint().\r
237\r
238 def set_break(self, filename, lineno, temporary=0, cond = None,\r
239 funcname=None):\r
240 filename = self.canonic(filename)\r
241 import linecache # Import as late as possible\r
242 line = linecache.getline(filename, lineno)\r
243 if not line:\r
244 return 'Line %s:%d does not exist' % (filename,\r
245 lineno)\r
246 if not filename in self.breaks:\r
247 self.breaks[filename] = []\r
248 list = self.breaks[filename]\r
249 if not lineno in list:\r
250 list.append(lineno)\r
251 bp = Breakpoint(filename, lineno, temporary, cond, funcname)\r
252\r
253 def _prune_breaks(self, filename, lineno):\r
254 if (filename, lineno) not in Breakpoint.bplist:\r
255 self.breaks[filename].remove(lineno)\r
256 if not self.breaks[filename]:\r
257 del self.breaks[filename]\r
258\r
259 def clear_break(self, filename, lineno):\r
260 filename = self.canonic(filename)\r
261 if not filename in self.breaks:\r
262 return 'There are no breakpoints in %s' % filename\r
263 if lineno not in self.breaks[filename]:\r
264 return 'There is no breakpoint at %s:%d' % (filename,\r
265 lineno)\r
266 # If there's only one bp in the list for that file,line\r
267 # pair, then remove the breaks entry\r
268 for bp in Breakpoint.bplist[filename, lineno][:]:\r
269 bp.deleteMe()\r
270 self._prune_breaks(filename, lineno)\r
271\r
272 def clear_bpbynumber(self, arg):\r
273 try:\r
274 number = int(arg)\r
275 except:\r
276 return 'Non-numeric breakpoint number (%s)' % arg\r
277 try:\r
278 bp = Breakpoint.bpbynumber[number]\r
279 except IndexError:\r
280 return 'Breakpoint number (%d) out of range' % number\r
281 if not bp:\r
282 return 'Breakpoint (%d) already deleted' % number\r
283 bp.deleteMe()\r
284 self._prune_breaks(bp.file, bp.line)\r
285\r
286 def clear_all_file_breaks(self, filename):\r
287 filename = self.canonic(filename)\r
288 if not filename in self.breaks:\r
289 return 'There are no breakpoints in %s' % filename\r
290 for line in self.breaks[filename]:\r
291 blist = Breakpoint.bplist[filename, line]\r
292 for bp in blist:\r
293 bp.deleteMe()\r
294 del self.breaks[filename]\r
295\r
296 def clear_all_breaks(self):\r
297 if not self.breaks:\r
298 return 'There are no breakpoints'\r
299 for bp in Breakpoint.bpbynumber:\r
300 if bp:\r
301 bp.deleteMe()\r
302 self.breaks = {}\r
303\r
304 def get_break(self, filename, lineno):\r
305 filename = self.canonic(filename)\r
306 return filename in self.breaks and \\r
307 lineno in self.breaks[filename]\r
308\r
309 def get_breaks(self, filename, lineno):\r
310 filename = self.canonic(filename)\r
311 return filename in self.breaks and \\r
312 lineno in self.breaks[filename] and \\r
313 Breakpoint.bplist[filename, lineno] or []\r
314\r
315 def get_file_breaks(self, filename):\r
316 filename = self.canonic(filename)\r
317 if filename in self.breaks:\r
318 return self.breaks[filename]\r
319 else:\r
320 return []\r
321\r
322 def get_all_breaks(self):\r
323 return self.breaks\r
324\r
325 # Derived classes and clients can call the following method\r
326 # to get a data structure representing a stack trace.\r
327\r
328 def get_stack(self, f, t):\r
329 stack = []\r
330 if t and t.tb_frame is f:\r
331 t = t.tb_next\r
332 while f is not None:\r
333 stack.append((f, f.f_lineno))\r
334 if f is self.botframe:\r
335 break\r
336 f = f.f_back\r
337 stack.reverse()\r
338 i = max(0, len(stack) - 1)\r
339 while t is not None:\r
340 stack.append((t.tb_frame, t.tb_lineno))\r
341 t = t.tb_next\r
342 if f is None:\r
343 i = max(0, len(stack) - 1)\r
344 return stack, i\r
345\r
346 #\r
347\r
348 def format_stack_entry(self, frame_lineno, lprefix=': '):\r
349 import linecache, repr\r
350 frame, lineno = frame_lineno\r
351 filename = self.canonic(frame.f_code.co_filename)\r
352 s = '%s(%r)' % (filename, lineno)\r
353 if frame.f_code.co_name:\r
354 s = s + frame.f_code.co_name\r
355 else:\r
356 s = s + "<lambda>"\r
357 if '__args__' in frame.f_locals:\r
358 args = frame.f_locals['__args__']\r
359 else:\r
360 args = None\r
361 if args:\r
362 s = s + repr.repr(args)\r
363 else:\r
364 s = s + '()'\r
365 if '__return__' in frame.f_locals:\r
366 rv = frame.f_locals['__return__']\r
367 s = s + '->'\r
368 s = s + repr.repr(rv)\r
369 line = linecache.getline(filename, lineno, frame.f_globals)\r
370 if line: s = s + lprefix + line.strip()\r
371 return s\r
372\r
373 # The following two methods can be called by clients to use\r
374 # a debugger to debug a statement, given as a string.\r
375\r
376 def run(self, cmd, globals=None, locals=None):\r
377 if globals is None:\r
378 import __main__\r
379 globals = __main__.__dict__\r
380 if locals is None:\r
381 locals = globals\r
382 self.reset()\r
383 sys.settrace(self.trace_dispatch)\r
384 if not isinstance(cmd, types.CodeType):\r
385 cmd = cmd+'\n'\r
386 try:\r
387 exec cmd in globals, locals\r
388 except BdbQuit:\r
389 pass\r
390 finally:\r
391 self.quitting = 1\r
392 sys.settrace(None)\r
393\r
394 def runeval(self, expr, globals=None, locals=None):\r
395 if globals is None:\r
396 import __main__\r
397 globals = __main__.__dict__\r
398 if locals is None:\r
399 locals = globals\r
400 self.reset()\r
401 sys.settrace(self.trace_dispatch)\r
402 if not isinstance(expr, types.CodeType):\r
403 expr = expr+'\n'\r
404 try:\r
405 return eval(expr, globals, locals)\r
406 except BdbQuit:\r
407 pass\r
408 finally:\r
409 self.quitting = 1\r
410 sys.settrace(None)\r
411\r
412 def runctx(self, cmd, globals, locals):\r
413 # B/W compatibility\r
414 self.run(cmd, globals, locals)\r
415\r
416 # This method is more useful to debug a single function call.\r
417\r
418 def runcall(self, func, *args, **kwds):\r
419 self.reset()\r
420 sys.settrace(self.trace_dispatch)\r
421 res = None\r
422 try:\r
423 res = func(*args, **kwds)\r
424 except BdbQuit:\r
425 pass\r
426 finally:\r
427 self.quitting = 1\r
428 sys.settrace(None)\r
429 return res\r
430\r
431\r
432def set_trace():\r
433 Bdb().set_trace()\r
434\r
435\r
436class Breakpoint:\r
437\r
438 """Breakpoint class\r
439\r
440 Implements temporary breakpoints, ignore counts, disabling and\r
441 (re)-enabling, and conditionals.\r
442\r
443 Breakpoints are indexed by number through bpbynumber and by\r
444 the file,line tuple using bplist. The former points to a\r
445 single instance of class Breakpoint. The latter points to a\r
446 list of such instances since there may be more than one\r
447 breakpoint per line.\r
448\r
449 """\r
450\r
451 # XXX Keeping state in the class is a mistake -- this means\r
452 # you cannot have more than one active Bdb instance.\r
453\r
454 next = 1 # Next bp to be assigned\r
455 bplist = {} # indexed by (file, lineno) tuple\r
456 bpbynumber = [None] # Each entry is None or an instance of Bpt\r
457 # index 0 is unused, except for marking an\r
458 # effective break .... see effective()\r
459\r
460 def __init__(self, file, line, temporary=0, cond=None, funcname=None):\r
461 self.funcname = funcname\r
462 # Needed if funcname is not None.\r
463 self.func_first_executable_line = None\r
464 self.file = file # This better be in canonical form!\r
465 self.line = line\r
466 self.temporary = temporary\r
467 self.cond = cond\r
468 self.enabled = 1\r
469 self.ignore = 0\r
470 self.hits = 0\r
471 self.number = Breakpoint.next\r
472 Breakpoint.next = Breakpoint.next + 1\r
473 # Build the two lists\r
474 self.bpbynumber.append(self)\r
475 if (file, line) in self.bplist:\r
476 self.bplist[file, line].append(self)\r
477 else:\r
478 self.bplist[file, line] = [self]\r
479\r
480\r
481 def deleteMe(self):\r
482 index = (self.file, self.line)\r
483 self.bpbynumber[self.number] = None # No longer in list\r
484 self.bplist[index].remove(self)\r
485 if not self.bplist[index]:\r
486 # No more bp for this f:l combo\r
487 del self.bplist[index]\r
488\r
489 def enable(self):\r
490 self.enabled = 1\r
491\r
492 def disable(self):\r
493 self.enabled = 0\r
494\r
495 def bpprint(self, out=None):\r
496 if out is None:\r
497 out = sys.stdout\r
498 if self.temporary:\r
499 disp = 'del '\r
500 else:\r
501 disp = 'keep '\r
502 if self.enabled:\r
503 disp = disp + 'yes '\r
504 else:\r
505 disp = disp + 'no '\r
506 print >>out, '%-4dbreakpoint %s at %s:%d' % (self.number, disp,\r
507 self.file, self.line)\r
508 if self.cond:\r
509 print >>out, '\tstop only if %s' % (self.cond,)\r
510 if self.ignore:\r
511 print >>out, '\tignore next %d hits' % (self.ignore)\r
512 if (self.hits):\r
513 if (self.hits > 1): ss = 's'\r
514 else: ss = ''\r
515 print >>out, ('\tbreakpoint already hit %d time%s' %\r
516 (self.hits, ss))\r
517\r
518# -----------end of Breakpoint class----------\r
519\r
520def checkfuncname(b, frame):\r
521 """Check whether we should break here because of `b.funcname`."""\r
522 if not b.funcname:\r
523 # Breakpoint was set via line number.\r
524 if b.line != frame.f_lineno:\r
525 # Breakpoint was set at a line with a def statement and the function\r
526 # defined is called: don't break.\r
527 return False\r
528 return True\r
529\r
530 # Breakpoint set via function name.\r
531\r
532 if frame.f_code.co_name != b.funcname:\r
533 # It's not a function call, but rather execution of def statement.\r
534 return False\r
535\r
536 # We are in the right frame.\r
537 if not b.func_first_executable_line:\r
538 # The function is entered for the 1st time.\r
539 b.func_first_executable_line = frame.f_lineno\r
540\r
541 if b.func_first_executable_line != frame.f_lineno:\r
542 # But we are not at the first line number: don't break.\r
543 return False\r
544 return True\r
545\r
546# Determines if there is an effective (active) breakpoint at this\r
547# line of code. Returns breakpoint number or 0 if none\r
548def effective(file, line, frame):\r
549 """Determine which breakpoint for this file:line is to be acted upon.\r
550\r
551 Called only if we know there is a bpt at this\r
552 location. Returns breakpoint that was triggered and a flag\r
553 that indicates if it is ok to delete a temporary bp.\r
554\r
555 """\r
556 possibles = Breakpoint.bplist[file,line]\r
557 for i in range(0, len(possibles)):\r
558 b = possibles[i]\r
559 if b.enabled == 0:\r
560 continue\r
561 if not checkfuncname(b, frame):\r
562 continue\r
563 # Count every hit when bp is enabled\r
564 b.hits = b.hits + 1\r
565 if not b.cond:\r
566 # If unconditional, and ignoring,\r
567 # go on to next, else break\r
568 if b.ignore > 0:\r
569 b.ignore = b.ignore -1\r
570 continue\r
571 else:\r
572 # breakpoint and marker that's ok\r
573 # to delete if temporary\r
574 return (b,1)\r
575 else:\r
576 # Conditional bp.\r
577 # Ignore count applies only to those bpt hits where the\r
578 # condition evaluates to true.\r
579 try:\r
580 val = eval(b.cond, frame.f_globals,\r
581 frame.f_locals)\r
582 if val:\r
583 if b.ignore > 0:\r
584 b.ignore = b.ignore -1\r
585 # continue\r
586 else:\r
587 return (b,1)\r
588 # else:\r
589 # continue\r
590 except:\r
591 # if eval fails, most conservative\r
592 # thing is to stop on breakpoint\r
593 # regardless of ignore count.\r
594 # Don't delete temporary,\r
595 # as another hint to user.\r
596 return (b,0)\r
597 return (None, None)\r
598\r
599# -------------------- testing --------------------\r
600\r
601class Tdb(Bdb):\r
602 def user_call(self, frame, args):\r
603 name = frame.f_code.co_name\r
604 if not name: name = '???'\r
605 print '+++ call', name, args\r
606 def user_line(self, frame):\r
607 import linecache\r
608 name = frame.f_code.co_name\r
609 if not name: name = '???'\r
610 fn = self.canonic(frame.f_code.co_filename)\r
611 line = linecache.getline(fn, frame.f_lineno, frame.f_globals)\r
612 print '+++', fn, frame.f_lineno, name, ':', line.strip()\r
613 def user_return(self, frame, retval):\r
614 print '+++ return', retval\r
615 def user_exception(self, frame, exc_stuff):\r
616 print '+++ exception', exc_stuff\r
617 self.set_continue()\r
618\r
619def foo(n):\r
620 print 'foo(', n, ')'\r
621 x = bar(n*10)\r
622 print 'bar returned', x\r
623\r
624def bar(a):\r
625 print 'bar(', a, ')'\r
626 return a/2\r
627\r
628def test():\r
629 t = Tdb()\r
630 t.run('import bdb; bdb.foo(10)')\r
631\r
632# end\r