svn-gvsig-desktop / tags / v1_1_Build_914 / extensions / extScripting / scripts / jython / Lib / pdb.py @ 11873
History | View | Annotate | Download (29.5 KB)
1 | 5782 | jmvivo | #! /usr/bin/env python
|
---|---|---|---|
2 | |||
3 | """A Python debugger."""
|
||
4 | |||
5 | # (See pdb.doc for documentation.)
|
||
6 | |||
7 | import sys |
||
8 | import linecache |
||
9 | import cmd |
||
10 | import bdb |
||
11 | from repr import repr as _saferepr |
||
12 | import os |
||
13 | import re |
||
14 | |||
15 | __all__ = ["run", "pm", "Pdb", "runeval", "runctx", "runcall", "set_trace", |
||
16 | "post_mortem", "help"] |
||
17 | |||
18 | def find_function(funcname, filename): |
||
19 | cre = re.compile(r'def\s+%s\s*[(]' % funcname)
|
||
20 | try:
|
||
21 | fp = open(filename)
|
||
22 | except IOError: |
||
23 | return None |
||
24 | # consumer of this info expects the first line to be 1
|
||
25 | lineno = 1
|
||
26 | answer = None
|
||
27 | while 1: |
||
28 | line = fp.readline() |
||
29 | if line == '': |
||
30 | break
|
||
31 | if cre.match(line):
|
||
32 | answer = funcname, filename, lineno |
||
33 | break
|
||
34 | lineno = lineno + 1
|
||
35 | fp.close() |
||
36 | return answer
|
||
37 | |||
38 | |||
39 | # Interaction prompt line will separate file and call info from code
|
||
40 | # text using value of line_prefix string. A newline and arrow may
|
||
41 | # be to your liking. You can set it once pdb is imported using the
|
||
42 | # command "pdb.line_prefix = '\n% '".
|
||
43 | # line_prefix = ': ' # Use this to get the old situation back
|
||
44 | line_prefix = '\n-> ' # Probably a better default |
||
45 | |||
46 | class Pdb(bdb.Bdb, cmd.Cmd): |
||
47 | |||
48 | def __init__(self): |
||
49 | bdb.Bdb.__init__(self)
|
||
50 | cmd.Cmd.__init__(self)
|
||
51 | self.prompt = '(Pdb) ' |
||
52 | self.aliases = {}
|
||
53 | # Try to load readline if it exists
|
||
54 | try:
|
||
55 | import readline |
||
56 | except ImportError: |
||
57 | pass
|
||
58 | |||
59 | # Read $HOME/.pdbrc and ./.pdbrc
|
||
60 | self.rcLines = []
|
||
61 | if os.environ.has_key('HOME'): |
||
62 | envHome = os.environ['HOME']
|
||
63 | try:
|
||
64 | rcFile = open(os.path.join(envHome, ".pdbrc")) |
||
65 | except IOError: |
||
66 | pass
|
||
67 | else:
|
||
68 | for line in rcFile.readlines(): |
||
69 | self.rcLines.append(line)
|
||
70 | rcFile.close() |
||
71 | try:
|
||
72 | rcFile = open(".pdbrc") |
||
73 | except IOError: |
||
74 | pass
|
||
75 | else:
|
||
76 | for line in rcFile.readlines(): |
||
77 | self.rcLines.append(line)
|
||
78 | rcFile.close() |
||
79 | |||
80 | def reset(self): |
||
81 | bdb.Bdb.reset(self)
|
||
82 | self.forget()
|
||
83 | |||
84 | def forget(self): |
||
85 | self.lineno = None |
||
86 | self.stack = []
|
||
87 | self.curindex = 0 |
||
88 | self.curframe = None |
||
89 | |||
90 | def setup(self, f, t): |
||
91 | self.forget()
|
||
92 | self.stack, self.curindex = self.get_stack(f, t) |
||
93 | self.curframe = self.stack[self.curindex][0] |
||
94 | self.execRcLines()
|
||
95 | |||
96 | # Can be executed earlier than 'setup' if desired
|
||
97 | def execRcLines(self): |
||
98 | if self.rcLines: |
||
99 | # Make local copy because of recursion
|
||
100 | rcLines = self.rcLines
|
||
101 | # executed only once
|
||
102 | self.rcLines = []
|
||
103 | for line in rcLines: |
||
104 | line = line[:-1]
|
||
105 | if len (line) > 0 and line[0] != '#': |
||
106 | self.onecmd (line)
|
||
107 | |||
108 | # Override Bdb methods (except user_call, for now)
|
||
109 | |||
110 | def user_line(self, frame): |
||
111 | """This function is called when we stop or break at this line."""
|
||
112 | self.interaction(frame, None) |
||
113 | |||
114 | def user_return(self, frame, return_value): |
||
115 | """This function is called when a return trap is set here."""
|
||
116 | frame.f_locals['__return__'] = return_value
|
||
117 | print '--Return--' |
||
118 | self.interaction(frame, None) |
||
119 | |||
120 | def user_exception(self, frame, (exc_type, exc_value, exc_traceback)): |
||
121 | """This function is called if an exception occurs,
|
||
122 | but only if we are to stop at or just below this level."""
|
||
123 | frame.f_locals['__exception__'] = exc_type, exc_value
|
||
124 | if type(exc_type) == type(''): |
||
125 | exc_type_name = exc_type |
||
126 | else: exc_type_name = exc_type.__name__
|
||
127 | print exc_type_name + ':', _saferepr(exc_value) |
||
128 | self.interaction(frame, exc_traceback)
|
||
129 | |||
130 | # General interaction function
|
||
131 | |||
132 | def interaction(self, frame, traceback): |
||
133 | self.setup(frame, traceback)
|
||
134 | self.print_stack_entry(self.stack[self.curindex]) |
||
135 | self.cmdloop()
|
||
136 | self.forget()
|
||
137 | |||
138 | def default(self, line): |
||
139 | if line[:1] == '!': line = line[1:] |
||
140 | locals = self.curframe.f_locals
|
||
141 | globals = self.curframe.f_globals
|
||
142 | try:
|
||
143 | code = compile(line + '\n', '<stdin>', 'single') |
||
144 | exec code in globals, locals |
||
145 | except:
|
||
146 | t, v = sys.exc_info()[:2]
|
||
147 | if type(t) == type(''): |
||
148 | exc_type_name = t |
||
149 | else: exc_type_name = t.__name__
|
||
150 | print '***', exc_type_name + ':', v |
||
151 | |||
152 | def precmd(self, line): |
||
153 | """Handle alias expansion and ';;' separator."""
|
||
154 | if not line: |
||
155 | return line
|
||
156 | args = line.split() |
||
157 | while self.aliases.has_key(args[0]): |
||
158 | line = self.aliases[args[0]] |
||
159 | ii = 1
|
||
160 | for tmpArg in args[1:]: |
||
161 | line = line.replace("%" + str(ii), |
||
162 | tmpArg) |
||
163 | ii = ii + 1
|
||
164 | line = line.replace("%*", ' '.join(args[1:])) |
||
165 | args = line.split() |
||
166 | # split into ';;' separated commands
|
||
167 | # unless it's an alias command
|
||
168 | if args[0] != 'alias': |
||
169 | marker = line.find(';;')
|
||
170 | if marker >= 0: |
||
171 | # queue up everything after marker
|
||
172 | next = line[marker+2:].lstrip()
|
||
173 | self.cmdqueue.append(next) |
||
174 | line = line[:marker].rstrip() |
||
175 | return line
|
||
176 | |||
177 | # Command definitions, called by cmdloop()
|
||
178 | # The argument is the remaining string on the command line
|
||
179 | # Return true to exit from the command loop
|
||
180 | |||
181 | do_h = cmd.Cmd.do_help |
||
182 | |||
183 | def do_EOF(self, arg): |
||
184 | return 0 # Don't die on EOF |
||
185 | |||
186 | def do_break(self, arg, temporary = 0): |
||
187 | # break [ ([filename:]lineno | function) [, "condition"] ]
|
||
188 | if not arg: |
||
189 | if self.breaks: # There's at least one |
||
190 | print "Num Type Disp Enb Where" |
||
191 | for bp in bdb.Breakpoint.bpbynumber: |
||
192 | if bp:
|
||
193 | bp.bpprint() |
||
194 | return
|
||
195 | # parse arguments; comma has lowest precedence
|
||
196 | # and cannot occur in filename
|
||
197 | filename = None
|
||
198 | lineno = None
|
||
199 | cond = None
|
||
200 | comma = arg.find(',')
|
||
201 | if comma > 0: |
||
202 | # parse stuff after comma: "condition"
|
||
203 | cond = arg[comma+1:].lstrip()
|
||
204 | arg = arg[:comma].rstrip() |
||
205 | # parse stuff before comma: [filename:]lineno | function
|
||
206 | colon = arg.rfind(':')
|
||
207 | if colon >= 0: |
||
208 | filename = arg[:colon].rstrip() |
||
209 | f = self.lookupmodule(filename)
|
||
210 | if not f: |
||
211 | print '*** ', `filename`, |
||
212 | print 'not found from sys.path' |
||
213 | return
|
||
214 | else:
|
||
215 | filename = f |
||
216 | arg = arg[colon+1:].lstrip()
|
||
217 | try:
|
||
218 | lineno = int(arg)
|
||
219 | except ValueError, msg: |
||
220 | print '*** Bad lineno:', arg |
||
221 | return
|
||
222 | else:
|
||
223 | # no colon; can be lineno or function
|
||
224 | try:
|
||
225 | lineno = int(arg)
|
||
226 | except ValueError: |
||
227 | try:
|
||
228 | func = eval(arg,
|
||
229 | self.curframe.f_globals,
|
||
230 | self.curframe.f_locals)
|
||
231 | except:
|
||
232 | func = arg |
||
233 | try:
|
||
234 | if hasattr(func, 'im_func'): |
||
235 | func = func.im_func |
||
236 | code = func.func_code |
||
237 | lineno = code.co_firstlineno |
||
238 | filename = code.co_filename |
||
239 | except:
|
||
240 | # last thing to try
|
||
241 | (ok, filename, ln) = self.lineinfo(arg)
|
||
242 | if not ok: |
||
243 | print '*** The specified object', |
||
244 | print `arg`,
|
||
245 | print 'is not a function' |
||
246 | print ('or was not found ' |
||
247 | 'along sys.path.')
|
||
248 | return
|
||
249 | lineno = int(ln)
|
||
250 | if not filename: |
||
251 | filename = self.defaultFile()
|
||
252 | # Check for reasonable breakpoint
|
||
253 | line = self.checkline(filename, lineno)
|
||
254 | if line:
|
||
255 | # now set the break point
|
||
256 | err = self.set_break(filename, line, temporary, cond)
|
||
257 | if err: print '***', err |
||
258 | else:
|
||
259 | bp = self.get_breaks(filename, line)[-1] |
||
260 | print "Breakpoint %d at %s:%d" % (bp.number, |
||
261 | bp.file, |
||
262 | bp.line) |
||
263 | |||
264 | # To be overridden in derived debuggers
|
||
265 | def defaultFile(self): |
||
266 | """Produce a reasonable default."""
|
||
267 | filename = self.curframe.f_code.co_filename
|
||
268 | if filename == '<string>' and mainpyfile: |
||
269 | filename = mainpyfile |
||
270 | return filename
|
||
271 | |||
272 | do_b = do_break |
||
273 | |||
274 | def do_tbreak(self, arg): |
||
275 | self.do_break(arg, 1) |
||
276 | |||
277 | def lineinfo(self, identifier): |
||
278 | failed = (None, None, None) |
||
279 | # Input is identifier, may be in single quotes
|
||
280 | idstring = identifier.split("'")
|
||
281 | if len(idstring) == 1: |
||
282 | # not in single quotes
|
||
283 | id = idstring[0].strip()
|
||
284 | elif len(idstring) == 3: |
||
285 | # quoted
|
||
286 | id = idstring[1].strip()
|
||
287 | else:
|
||
288 | return failed
|
||
289 | if id == '': return failed |
||
290 | parts = id.split('.') |
||
291 | # Protection for derived debuggers
|
||
292 | if parts[0] == 'self': |
||
293 | del parts[0] |
||
294 | if len(parts) == 0: |
||
295 | return failed
|
||
296 | # Best first guess at file to look at
|
||
297 | fname = self.defaultFile()
|
||
298 | if len(parts) == 1: |
||
299 | item = parts[0]
|
||
300 | else:
|
||
301 | # More than one part.
|
||
302 | # First is module, second is method/class
|
||
303 | f = self.lookupmodule(parts[0]) |
||
304 | if f:
|
||
305 | fname = f |
||
306 | item = parts[1]
|
||
307 | answer = find_function(item, fname) |
||
308 | return answer or failed |
||
309 | |||
310 | def checkline(self, filename, lineno): |
||
311 | """Return line number of first line at or after input
|
||
312 | argument such that if the input points to a 'def', the
|
||
313 | returned line number is the first
|
||
314 | non-blank/non-comment line to follow. If the input
|
||
315 | points to a blank or comment line, return 0. At end
|
||
316 | of file, also return 0."""
|
||
317 | |||
318 | line = linecache.getline(filename, lineno) |
||
319 | if not line: |
||
320 | print 'End of file' |
||
321 | return 0 |
||
322 | line = line.strip() |
||
323 | # Don't allow setting breakpoint at a blank line
|
||
324 | if ( not line or (line[0] == '#') or |
||
325 | (line[:3] == '"""') or line[:3] == "'''" ): |
||
326 | print '*** Blank or comment' |
||
327 | return 0 |
||
328 | # When a file is read in and a breakpoint is at
|
||
329 | # the 'def' statement, the system stops there at
|
||
330 | # code parse time. We don't want that, so all breakpoints
|
||
331 | # set at 'def' statements are moved one line onward
|
||
332 | if line[:3] == 'def': |
||
333 | instr = ''
|
||
334 | brackets = 0
|
||
335 | while 1: |
||
336 | skipone = 0
|
||
337 | for c in line: |
||
338 | if instr:
|
||
339 | if skipone:
|
||
340 | skipone = 0
|
||
341 | elif c == '\\': |
||
342 | skipone = 1
|
||
343 | elif c == instr:
|
||
344 | instr = ''
|
||
345 | elif c == '#': |
||
346 | break
|
||
347 | elif c in ('"',"'"): |
||
348 | instr = c |
||
349 | elif c in ('(','{','['): |
||
350 | brackets = brackets + 1
|
||
351 | elif c in (')','}',']'): |
||
352 | brackets = brackets - 1
|
||
353 | lineno = lineno+1
|
||
354 | line = linecache.getline(filename, lineno) |
||
355 | if not line: |
||
356 | print 'end of file' |
||
357 | return 0 |
||
358 | line = line.strip() |
||
359 | if not line: continue # Blank line |
||
360 | if brackets <= 0 and line[0] not in ('#','"',"'"): |
||
361 | break
|
||
362 | return lineno
|
||
363 | |||
364 | def do_enable(self, arg): |
||
365 | args = arg.split() |
||
366 | for i in args: |
||
367 | bp = bdb.Breakpoint.bpbynumber[int(i)]
|
||
368 | if bp:
|
||
369 | bp.enable() |
||
370 | |||
371 | def do_disable(self, arg): |
||
372 | args = arg.split() |
||
373 | for i in args: |
||
374 | bp = bdb.Breakpoint.bpbynumber[int(i)]
|
||
375 | if bp:
|
||
376 | bp.disable() |
||
377 | |||
378 | def do_condition(self, arg): |
||
379 | # arg is breakpoint number and condition
|
||
380 | args = arg.split(' ', 1) |
||
381 | bpnum = int(args[0].strip()) |
||
382 | try:
|
||
383 | cond = args[1]
|
||
384 | except:
|
||
385 | cond = None
|
||
386 | bp = bdb.Breakpoint.bpbynumber[bpnum] |
||
387 | if bp:
|
||
388 | bp.cond = cond |
||
389 | if not cond: |
||
390 | print 'Breakpoint', bpnum, |
||
391 | print 'is now unconditional.' |
||
392 | |||
393 | def do_ignore(self,arg): |
||
394 | """arg is bp number followed by ignore count."""
|
||
395 | args = arg.split() |
||
396 | bpnum = int(args[0].strip()) |
||
397 | try:
|
||
398 | count = int(args[1].strip()) |
||
399 | except:
|
||
400 | count = 0
|
||
401 | bp = bdb.Breakpoint.bpbynumber[bpnum] |
||
402 | if bp:
|
||
403 | bp.ignore = count |
||
404 | if (count > 0): |
||
405 | reply = 'Will ignore next '
|
||
406 | if (count > 1): |
||
407 | reply = reply + '%d crossings' % count
|
||
408 | else:
|
||
409 | reply = reply + '1 crossing'
|
||
410 | print reply + ' of breakpoint %d.' % bpnum |
||
411 | else:
|
||
412 | print 'Will stop next time breakpoint', |
||
413 | print bpnum, 'is reached.' |
||
414 | |||
415 | def do_clear(self, arg): |
||
416 | """Three possibilities, tried in this order:
|
||
417 | clear -> clear all breaks, ask for confirmation
|
||
418 | clear file:lineno -> clear all breaks at file:lineno
|
||
419 | clear bpno bpno ... -> clear breakpoints by number"""
|
||
420 | if not arg: |
||
421 | try:
|
||
422 | reply = raw_input('Clear all breaks? ') |
||
423 | except EOFError: |
||
424 | reply = 'no'
|
||
425 | reply = reply.strip().lower() |
||
426 | if reply in ('y', 'yes'): |
||
427 | self.clear_all_breaks()
|
||
428 | return
|
||
429 | if ':' in arg: |
||
430 | # Make sure it works for "clear C:\foo\bar.py:12"
|
||
431 | i = arg.rfind(':')
|
||
432 | filename = arg[:i] |
||
433 | arg = arg[i+1:]
|
||
434 | try:
|
||
435 | lineno = int(arg)
|
||
436 | except:
|
||
437 | err = "Invalid line number (%s)" % arg
|
||
438 | else:
|
||
439 | err = self.clear_break(filename, lineno)
|
||
440 | if err: print '***', err |
||
441 | return
|
||
442 | numberlist = arg.split() |
||
443 | for i in numberlist: |
||
444 | err = self.clear_bpbynumber(i)
|
||
445 | if err:
|
||
446 | print '***', err |
||
447 | else:
|
||
448 | print 'Deleted breakpoint %s ' % (i,) |
||
449 | do_cl = do_clear # 'c' is already an abbreviation for 'continue'
|
||
450 | |||
451 | def do_where(self, arg): |
||
452 | self.print_stack_trace()
|
||
453 | do_w = do_where |
||
454 | do_bt = do_where |
||
455 | |||
456 | def do_up(self, arg): |
||
457 | if self.curindex == 0: |
||
458 | print '*** Oldest frame' |
||
459 | else:
|
||
460 | self.curindex = self.curindex - 1 |
||
461 | self.curframe = self.stack[self.curindex][0] |
||
462 | self.print_stack_entry(self.stack[self.curindex]) |
||
463 | self.lineno = None |
||
464 | do_u = do_up |
||
465 | |||
466 | def do_down(self, arg): |
||
467 | if self.curindex + 1 == len(self.stack): |
||
468 | print '*** Newest frame' |
||
469 | else:
|
||
470 | self.curindex = self.curindex + 1 |
||
471 | self.curframe = self.stack[self.curindex][0] |
||
472 | self.print_stack_entry(self.stack[self.curindex]) |
||
473 | self.lineno = None |
||
474 | do_d = do_down |
||
475 | |||
476 | def do_step(self, arg): |
||
477 | self.set_step()
|
||
478 | return 1 |
||
479 | do_s = do_step |
||
480 | |||
481 | def do_next(self, arg): |
||
482 | self.set_next(self.curframe) |
||
483 | return 1 |
||
484 | do_n = do_next |
||
485 | |||
486 | def do_return(self, arg): |
||
487 | self.set_return(self.curframe) |
||
488 | return 1 |
||
489 | do_r = do_return |
||
490 | |||
491 | def do_continue(self, arg): |
||
492 | self.set_continue()
|
||
493 | return 1 |
||
494 | do_c = do_cont = do_continue |
||
495 | |||
496 | def do_quit(self, arg): |
||
497 | self.set_quit()
|
||
498 | return 1 |
||
499 | do_q = do_quit |
||
500 | |||
501 | def do_args(self, arg): |
||
502 | f = self.curframe
|
||
503 | co = f.f_code |
||
504 | dict = f.f_locals |
||
505 | n = co.co_argcount |
||
506 | if co.co_flags & 4: n = n+1 |
||
507 | if co.co_flags & 8: n = n+1 |
||
508 | for i in range(n): |
||
509 | name = co.co_varnames[i] |
||
510 | print name, '=', |
||
511 | if dict.has_key(name): print dict[name] |
||
512 | else: print "*** undefined ***" |
||
513 | do_a = do_args |
||
514 | |||
515 | def do_retval(self, arg): |
||
516 | if self.curframe.f_locals.has_key('__return__'): |
||
517 | print self.curframe.f_locals['__return__'] |
||
518 | else:
|
||
519 | print '*** Not yet returned!' |
||
520 | do_rv = do_retval |
||
521 | |||
522 | def do_p(self, arg): |
||
523 | try:
|
||
524 | value = eval(arg, self.curframe.f_globals, |
||
525 | self.curframe.f_locals)
|
||
526 | except:
|
||
527 | t, v = sys.exc_info()[:2]
|
||
528 | if type(t) == type(''): |
||
529 | exc_type_name = t |
||
530 | else: exc_type_name = t.__name__
|
||
531 | print '***', exc_type_name + ':', `v` |
||
532 | return
|
||
533 | |||
534 | print `value`
|
||
535 | |||
536 | def do_list(self, arg): |
||
537 | self.lastcmd = 'list' |
||
538 | last = None
|
||
539 | if arg:
|
||
540 | try:
|
||
541 | x = eval(arg, {}, {})
|
||
542 | if type(x) == type(()): |
||
543 | first, last = x |
||
544 | first = int(first)
|
||
545 | last = int(last)
|
||
546 | if last < first:
|
||
547 | # Assume it's a count
|
||
548 | last = first + last |
||
549 | else:
|
||
550 | first = max(1, int(x) - 5) |
||
551 | except:
|
||
552 | print '*** Error in argument:', `arg` |
||
553 | return
|
||
554 | elif self.lineno is None: |
||
555 | first = max(1, self.curframe.f_lineno - 5) |
||
556 | else:
|
||
557 | first = self.lineno + 1 |
||
558 | if last is None: |
||
559 | last = first + 10
|
||
560 | filename = self.curframe.f_code.co_filename
|
||
561 | breaklist = self.get_file_breaks(filename)
|
||
562 | try:
|
||
563 | for lineno in range(first, last+1): |
||
564 | line = linecache.getline(filename, lineno) |
||
565 | if not line: |
||
566 | print '[EOF]' |
||
567 | break
|
||
568 | else:
|
||
569 | s = `lineno`.rjust(3)
|
||
570 | if len(s) < 4: s = s + ' ' |
||
571 | if lineno in breaklist: s = s + 'B' |
||
572 | else: s = s + ' ' |
||
573 | if lineno == self.curframe.f_lineno: |
||
574 | s = s + '->'
|
||
575 | print s + '\t' + line, |
||
576 | self.lineno = lineno
|
||
577 | except KeyboardInterrupt: |
||
578 | pass
|
||
579 | do_l = do_list |
||
580 | |||
581 | def do_whatis(self, arg): |
||
582 | try:
|
||
583 | value = eval(arg, self.curframe.f_globals, |
||
584 | self.curframe.f_locals)
|
||
585 | except:
|
||
586 | t, v = sys.exc_info()[:2]
|
||
587 | if type(t) == type(''): |
||
588 | exc_type_name = t |
||
589 | else: exc_type_name = t.__name__
|
||
590 | print '***', exc_type_name + ':', `v` |
||
591 | return
|
||
592 | code = None
|
||
593 | # Is it a function?
|
||
594 | try: code = value.func_code
|
||
595 | except: pass |
||
596 | if code:
|
||
597 | print 'Function', code.co_name |
||
598 | return
|
||
599 | # Is it an instance method?
|
||
600 | try: code = value.im_func.func_code
|
||
601 | except: pass |
||
602 | if code:
|
||
603 | print 'Method', code.co_name |
||
604 | return
|
||
605 | # None of the above...
|
||
606 | print type(value) |
||
607 | |||
608 | def do_alias(self, arg): |
||
609 | args = arg.split() |
||
610 | if len(args) == 0: |
||
611 | keys = self.aliases.keys()
|
||
612 | keys.sort() |
||
613 | for alias in keys: |
||
614 | print "%s = %s" % (alias, self.aliases[alias]) |
||
615 | return
|
||
616 | if self.aliases.has_key(args[0]) and len (args) == 1: |
||
617 | print "%s = %s" % (args[0], self.aliases[args[0]]) |
||
618 | else:
|
||
619 | self.aliases[args[0]] = ' '.join(args[1:]) |
||
620 | |||
621 | def do_unalias(self, arg): |
||
622 | args = arg.split() |
||
623 | if len(args) == 0: return |
||
624 | if self.aliases.has_key(args[0]): |
||
625 | del self.aliases[args[0]] |
||
626 | |||
627 | # Print a traceback starting at the top stack frame.
|
||
628 | # The most recently entered frame is printed last;
|
||
629 | # this is different from dbx and gdb, but consistent with
|
||
630 | # the Python interpreter's stack trace.
|
||
631 | # It is also consistent with the up/down commands (which are
|
||
632 | # compatible with dbx and gdb: up moves towards 'main()'
|
||
633 | # and down moves towards the most recent stack frame).
|
||
634 | |||
635 | def print_stack_trace(self): |
||
636 | try:
|
||
637 | for frame_lineno in self.stack: |
||
638 | self.print_stack_entry(frame_lineno)
|
||
639 | except KeyboardInterrupt: |
||
640 | pass
|
||
641 | |||
642 | def print_stack_entry(self, frame_lineno, prompt_prefix=line_prefix): |
||
643 | frame, lineno = frame_lineno |
||
644 | if frame is self.curframe: |
||
645 | print '>', |
||
646 | else:
|
||
647 | print ' ', |
||
648 | print self.format_stack_entry(frame_lineno, prompt_prefix) |
||
649 | |||
650 | |||
651 | # Help methods (derived from pdb.doc)
|
||
652 | |||
653 | def help_help(self): |
||
654 | self.help_h()
|
||
655 | |||
656 | def help_h(self): |
||
657 | print """h(elp) |
||
658 | Without argument, print the list of available commands.
|
||
659 | With a command name as argument, print help about that command
|
||
660 | "help pdb" pipes the full documentation file to the $PAGER
|
||
661 | "help exec" gives help on the ! command"""
|
||
662 | |||
663 | def help_where(self): |
||
664 | self.help_w()
|
||
665 | |||
666 | def help_w(self): |
||
667 | print """w(here) |
||
668 | Print a stack trace, with the most recent frame at the bottom.
|
||
669 | An arrow indicates the "current frame", which determines the
|
||
670 | context of most commands. 'bt' is an alias for this command."""
|
||
671 | |||
672 | help_bt = help_w |
||
673 | |||
674 | def help_down(self): |
||
675 | self.help_d()
|
||
676 | |||
677 | def help_d(self): |
||
678 | print """d(own) |
||
679 | Move the current frame one level down in the stack trace
|
||
680 | (to an older frame)."""
|
||
681 | |||
682 | def help_up(self): |
||
683 | self.help_u()
|
||
684 | |||
685 | def help_u(self): |
||
686 | print """u(p) |
||
687 | Move the current frame one level up in the stack trace
|
||
688 | (to a newer frame)."""
|
||
689 | |||
690 | def help_break(self): |
||
691 | self.help_b()
|
||
692 | |||
693 | def help_b(self): |
||
694 | print """b(reak) ([file:]lineno | function) [, condition] |
||
695 | With a line number argument, set a break there in the current
|
||
696 | file. With a function name, set a break at first executable line
|
||
697 | of that function. Without argument, list all breaks. If a second
|
||
698 | argument is present, it is a string specifying an expression
|
||
699 | which must evaluate to true before the breakpoint is honored.
|
||
700 |
|
||
701 | The line number may be prefixed with a filename and a colon,
|
||
702 | to specify a breakpoint in another file (probably one that
|
||
703 | hasn't been loaded yet). The file is searched for on sys.path;
|
||
704 | the .py suffix may be omitted."""
|
||
705 | |||
706 | def help_clear(self): |
||
707 | self.help_cl()
|
||
708 | |||
709 | def help_cl(self): |
||
710 | print "cl(ear) filename:lineno" |
||
711 | print """cl(ear) [bpnumber [bpnumber...]] |
||
712 | With a space separated list of breakpoint numbers, clear
|
||
713 | those breakpoints. Without argument, clear all breaks (but
|
||
714 | first ask confirmation). With a filename:lineno argument,
|
||
715 | clear all breaks at that line in that file.
|
||
716 |
|
||
717 | Note that the argument is different from previous versions of
|
||
718 | the debugger (in python distributions 1.5.1 and before) where
|
||
719 | a linenumber was used instead of either filename:lineno or
|
||
720 | breakpoint numbers."""
|
||
721 | |||
722 | def help_tbreak(self): |
||
723 | print """tbreak same arguments as break, but breakpoint is |
||
724 | removed when first hit."""
|
||
725 | |||
726 | def help_enable(self): |
||
727 | print """enable bpnumber [bpnumber ...] |
||
728 | Enables the breakpoints given as a space separated list of
|
||
729 | bp numbers."""
|
||
730 | |||
731 | def help_disable(self): |
||
732 | print """disable bpnumber [bpnumber ...] |
||
733 | Disables the breakpoints given as a space separated list of
|
||
734 | bp numbers."""
|
||
735 | |||
736 | def help_ignore(self): |
||
737 | print """ignore bpnumber count |
||
738 | Sets the ignore count for the given breakpoint number. A breakpoint
|
||
739 | becomes active when the ignore count is zero. When non-zero, the
|
||
740 | count is decremented each time the breakpoint is reached and the
|
||
741 | breakpoint is not disabled and any associated condition evaluates
|
||
742 | to true."""
|
||
743 | |||
744 | def help_condition(self): |
||
745 | print """condition bpnumber str_condition |
||
746 | str_condition is a string specifying an expression which
|
||
747 | must evaluate to true before the breakpoint is honored.
|
||
748 | If str_condition is absent, any existing condition is removed;
|
||
749 | i.e., the breakpoint is made unconditional."""
|
||
750 | |||
751 | def help_step(self): |
||
752 | self.help_s()
|
||
753 | |||
754 | def help_s(self): |
||
755 | print """s(tep) |
||
756 | Execute the current line, stop at the first possible occasion
|
||
757 | (either in a function that is called or in the current function)."""
|
||
758 | |||
759 | def help_next(self): |
||
760 | self.help_n()
|
||
761 | |||
762 | def help_n(self): |
||
763 | print """n(ext) |
||
764 | Continue execution until the next line in the current function
|
||
765 | is reached or it returns."""
|
||
766 | |||
767 | def help_return(self): |
||
768 | self.help_r()
|
||
769 | |||
770 | def help_r(self): |
||
771 | print """r(eturn) |
||
772 | Continue execution until the current function returns."""
|
||
773 | |||
774 | def help_continue(self): |
||
775 | self.help_c()
|
||
776 | |||
777 | def help_cont(self): |
||
778 | self.help_c()
|
||
779 | |||
780 | def help_c(self): |
||
781 | print """c(ont(inue)) |
||
782 | Continue execution, only stop when a breakpoint is encountered."""
|
||
783 | |||
784 | def help_list(self): |
||
785 | self.help_l()
|
||
786 | |||
787 | def help_l(self): |
||
788 | print """l(ist) [first [,last]] |
||
789 | List source code for the current file.
|
||
790 | Without arguments, list 11 lines around the current line
|
||
791 | or continue the previous listing.
|
||
792 | With one argument, list 11 lines starting at that line.
|
||
793 | With two arguments, list the given range;
|
||
794 | if the second argument is less than the first, it is a count."""
|
||
795 | |||
796 | def help_args(self): |
||
797 | self.help_a()
|
||
798 | |||
799 | def help_a(self): |
||
800 | print """a(rgs) |
||
801 | Print the arguments of the current function."""
|
||
802 | |||
803 | def help_p(self): |
||
804 | print """p expression |
||
805 | Print the value of the expression."""
|
||
806 | |||
807 | def help_exec(self): |
||
808 | print """(!) statement |
||
809 | Execute the (one-line) statement in the context of
|
||
810 | the current stack frame.
|
||
811 | The exclamation point can be omitted unless the first word
|
||
812 | of the statement resembles a debugger command.
|
||
813 | To assign to a global variable you must always prefix the
|
||
814 | command with a 'global' command, e.g.:
|
||
815 | (Pdb) global list_options; list_options = ['-l']
|
||
816 | (Pdb)"""
|
||
817 | |||
818 | def help_quit(self): |
||
819 | self.help_q()
|
||
820 | |||
821 | def help_q(self): |
||
822 | print """q(uit) Quit from the debugger. |
||
823 | The program being executed is aborted."""
|
||
824 | |||
825 | def help_whatis(self): |
||
826 | print """whatis arg |
||
827 | Prints the type of the argument."""
|
||
828 | |||
829 | def help_EOF(self): |
||
830 | print """EOF |
||
831 | Handles the receipt of EOF as a command."""
|
||
832 | |||
833 | def help_alias(self): |
||
834 | print """alias [name [command [parameter parameter ...] ]] |
||
835 | Creates an alias called 'name' the executes 'command'. The command
|
||
836 | must *not* be enclosed in quotes. Replaceable parameters are
|
||
837 | indicated by %1, %2, and so on, while %* is replaced by all the
|
||
838 | parameters. If no command is given, the current alias for name
|
||
839 | is shown. If no name is given, all aliases are listed.
|
||
840 |
|
||
841 | Aliases may be nested and can contain anything that can be
|
||
842 | legally typed at the pdb prompt. Note! You *can* override
|
||
843 | internal pdb commands with aliases! Those internal commands
|
||
844 | are then hidden until the alias is removed. Aliasing is recursively
|
||
845 | applied to the first word of the command line; all other words
|
||
846 | in the line are left alone.
|
||
847 |
|
||
848 | Some useful aliases (especially when placed in the .pdbrc file) are:
|
||
849 |
|
||
850 | #Print instance variables (usage "pi classInst")
|
||
851 | alias pi for k in %1.__dict__.keys(): print "%1.",k,"=",%1.__dict__[k]
|
||
852 |
|
||
853 | #Print instance variables in self
|
||
854 | alias ps pi self
|
||
855 | """
|
||
856 | |||
857 | def help_unalias(self): |
||
858 | print """unalias name |
||
859 | Deletes the specified alias."""
|
||
860 | |||
861 | def help_pdb(self): |
||
862 | help() |
||
863 | |||
864 | def lookupmodule(self, filename): |
||
865 | """Helper function for break/clear parsing -- may be overridden."""
|
||
866 | root, ext = os.path.splitext(filename) |
||
867 | if ext == '': |
||
868 | filename = filename + '.py'
|
||
869 | if os.path.isabs(filename):
|
||
870 | return filename
|
||
871 | for dirname in sys.path: |
||
872 | while os.path.islink(dirname):
|
||
873 | dirname = os.readlink(dirname) |
||
874 | fullname = os.path.join(dirname, filename) |
||
875 | if os.path.exists(fullname):
|
||
876 | return fullname
|
||
877 | return None |
||
878 | |||
879 | # Simplified interface
|
||
880 | |||
881 | def run(statement, globals=None, locals=None): |
||
882 | Pdb().run(statement, globals, locals) |
||
883 | |||
884 | def runeval(expression, globals=None, locals=None): |
||
885 | return Pdb().runeval(expression, globals, locals) |
||
886 | |||
887 | def runctx(statement, globals, locals): |
||
888 | # B/W compatibility
|
||
889 | run(statement, globals, locals) |
||
890 | |||
891 | def runcall(*args): |
||
892 | return apply(Pdb().runcall, args) |
||
893 | |||
894 | def set_trace(): |
||
895 | Pdb().set_trace() |
||
896 | |||
897 | # Post-Mortem interface
|
||
898 | |||
899 | def post_mortem(t): |
||
900 | p = Pdb() |
||
901 | p.reset() |
||
902 | while t.tb_next is not None: |
||
903 | t = t.tb_next |
||
904 | p.interaction(t.tb_frame, t) |
||
905 | |||
906 | def pm(): |
||
907 | post_mortem(sys.last_traceback) |
||
908 | |||
909 | |||
910 | # Main program for testing
|
||
911 | |||
912 | TESTCMD = 'import x; x.main()'
|
||
913 | |||
914 | def test(): |
||
915 | run(TESTCMD) |
||
916 | |||
917 | # print help
|
||
918 | def help(): |
||
919 | for dirname in sys.path: |
||
920 | fullname = os.path.join(dirname, 'pdb.doc')
|
||
921 | if os.path.exists(fullname):
|
||
922 | sts = os.system('${PAGER-more} '+fullname)
|
||
923 | if sts: print '*** Pager exit status:', sts |
||
924 | break
|
||
925 | else:
|
||
926 | print 'Sorry, can\'t find the help file "pdb.doc"', |
||
927 | print 'along the Python search path' |
||
928 | |||
929 | mainmodule = ''
|
||
930 | mainpyfile = ''
|
||
931 | |||
932 | # When invoked as main program, invoke the debugger on a script
|
||
933 | if __name__=='__main__': |
||
934 | if not sys.argv[1:]: |
||
935 | print "usage: pdb.py scriptfile [arg] ..." |
||
936 | sys.exit(2)
|
||
937 | |||
938 | mainpyfile = filename = sys.argv[1] # Get script filename |
||
939 | if not os.path.exists(filename): |
||
940 | print 'Error:', `filename`, 'does not exist' |
||
941 | sys.exit(1)
|
||
942 | mainmodule = os.path.basename(filename) |
||
943 | del sys.argv[0] # Hide "pdb.py" from argument list |
||
944 | |||
945 | # Insert script directory in front of module search path
|
||
946 | sys.path.insert(0, os.path.dirname(filename))
|
||
947 | |||
948 | run('execfile(' + `filename` + ')') |