bdb.py 21 KB

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