bdb.py 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920
  1. """Debugger basics"""
  2. import fnmatch
  3. import sys
  4. import os
  5. from contextlib import contextmanager
  6. from inspect import CO_GENERATOR, CO_COROUTINE, CO_ASYNC_GENERATOR
  7. __all__ = ["BdbQuit", "Bdb", "Breakpoint"]
  8. GENERATOR_AND_COROUTINE_FLAGS = CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR
  9. class BdbQuit(Exception):
  10. """Exception to give up completely."""
  11. class Bdb:
  12. """Generic Python debugger base class.
  13. This class takes care of details of the trace facility;
  14. a derived class should implement user interaction.
  15. The standard debugger class (pdb.Pdb) is an example.
  16. The optional skip argument must be an iterable of glob-style
  17. module name patterns. The debugger will not step into frames
  18. that originate in a module that matches one of these patterns.
  19. Whether a frame is considered to originate in a certain module
  20. is determined by the __name__ in the frame globals.
  21. """
  22. def __init__(self, skip=None):
  23. self.skip = set(skip) if skip else None
  24. self.breaks = {}
  25. self.fncache = {}
  26. self.frame_returning = None
  27. self.enterframe = None
  28. self._load_breaks()
  29. def canonic(self, filename):
  30. """Return canonical form of filename.
  31. For real filenames, the canonical form is a case-normalized (on
  32. case insensitive filesystems) absolute path. 'Filenames' with
  33. angle brackets, such as "<stdin>", generated in interactive
  34. mode, are returned unchanged.
  35. """
  36. if filename == "<" + filename[1:-1] + ">":
  37. return filename
  38. canonic = self.fncache.get(filename)
  39. if not canonic:
  40. canonic = os.path.abspath(filename)
  41. canonic = os.path.normcase(canonic)
  42. self.fncache[filename] = canonic
  43. return canonic
  44. def reset(self):
  45. """Set values of attributes as ready to start debugging."""
  46. import linecache
  47. linecache.checkcache()
  48. self.botframe = None
  49. self._set_stopinfo(None, None)
  50. @contextmanager
  51. def set_enterframe(self, frame):
  52. self.enterframe = frame
  53. yield
  54. self.enterframe = None
  55. def trace_dispatch(self, frame, event, arg):
  56. """Dispatch a trace function for debugged frames based on the event.
  57. This function is installed as the trace function for debugged
  58. frames. Its return value is the new trace function, which is
  59. usually itself. The default implementation decides how to
  60. dispatch a frame, depending on the type of event (passed in as a
  61. string) that is about to be executed.
  62. The event can be one of the following:
  63. line: A new line of code is going to be executed.
  64. call: A function is about to be called or another code block
  65. is entered.
  66. return: A function or other code block is about to return.
  67. exception: An exception has occurred.
  68. c_call: A C function is about to be called.
  69. c_return: A C function has returned.
  70. c_exception: A C function has raised an exception.
  71. For the Python events, specialized functions (see the dispatch_*()
  72. methods) are called. For the C events, no action is taken.
  73. The arg parameter depends on the previous event.
  74. """
  75. with self.set_enterframe(frame):
  76. if self.quitting:
  77. return # None
  78. if event == 'line':
  79. return self.dispatch_line(frame)
  80. if event == 'call':
  81. return self.dispatch_call(frame, arg)
  82. if event == 'return':
  83. return self.dispatch_return(frame, arg)
  84. if event == 'exception':
  85. return self.dispatch_exception(frame, arg)
  86. if event == 'c_call':
  87. return self.trace_dispatch
  88. if event == 'c_exception':
  89. return self.trace_dispatch
  90. if event == 'c_return':
  91. return self.trace_dispatch
  92. print('bdb.Bdb.dispatch: unknown debugging event:', repr(event))
  93. return self.trace_dispatch
  94. def dispatch_line(self, frame):
  95. """Invoke user function and return trace function for line event.
  96. If the debugger stops on the current line, invoke
  97. self.user_line(). Raise BdbQuit if self.quitting is set.
  98. Return self.trace_dispatch to continue tracing in this scope.
  99. """
  100. if self.stop_here(frame) or self.break_here(frame):
  101. self.user_line(frame)
  102. if self.quitting: raise BdbQuit
  103. return self.trace_dispatch
  104. def dispatch_call(self, frame, arg):
  105. """Invoke user function and return trace function for call event.
  106. If the debugger stops on this function call, invoke
  107. self.user_call(). Raise BdbQuit if self.quitting is set.
  108. Return self.trace_dispatch to continue tracing in this scope.
  109. """
  110. # XXX 'arg' is no longer used
  111. if self.botframe is None:
  112. # First call of dispatch since reset()
  113. self.botframe = frame.f_back # (CT) Note that this may also be None!
  114. return self.trace_dispatch
  115. if not (self.stop_here(frame) or self.break_anywhere(frame)):
  116. # No need to trace this function
  117. return # None
  118. # Ignore call events in generator except when stepping.
  119. if self.stopframe and frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS:
  120. return self.trace_dispatch
  121. self.user_call(frame, arg)
  122. if self.quitting: raise BdbQuit
  123. return self.trace_dispatch
  124. def dispatch_return(self, frame, arg):
  125. """Invoke user function and return trace function for return event.
  126. If the debugger stops on this function return, invoke
  127. self.user_return(). Raise BdbQuit if self.quitting is set.
  128. Return self.trace_dispatch to continue tracing in this scope.
  129. """
  130. if self.stop_here(frame) or frame == self.returnframe:
  131. # Ignore return events in generator except when stepping.
  132. if self.stopframe and frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS:
  133. return self.trace_dispatch
  134. try:
  135. self.frame_returning = frame
  136. self.user_return(frame, arg)
  137. finally:
  138. self.frame_returning = None
  139. if self.quitting: raise BdbQuit
  140. # The user issued a 'next' or 'until' command.
  141. if self.stopframe is frame and self.stoplineno != -1:
  142. self._set_stopinfo(None, None)
  143. # The previous frame might not have f_trace set, unless we are
  144. # issuing a command that does not expect to stop, we should set
  145. # f_trace
  146. if self.stoplineno != -1:
  147. self._set_caller_tracefunc(frame)
  148. return self.trace_dispatch
  149. def dispatch_exception(self, frame, arg):
  150. """Invoke user function and return trace function for exception event.
  151. If the debugger stops on this exception, invoke
  152. self.user_exception(). Raise BdbQuit if self.quitting is set.
  153. Return self.trace_dispatch to continue tracing in this scope.
  154. """
  155. if self.stop_here(frame):
  156. # When stepping with next/until/return in a generator frame, skip
  157. # the internal StopIteration exception (with no traceback)
  158. # triggered by a subiterator run with the 'yield from' statement.
  159. if not (frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS
  160. and arg[0] is StopIteration and arg[2] is None):
  161. self.user_exception(frame, arg)
  162. if self.quitting: raise BdbQuit
  163. # Stop at the StopIteration or GeneratorExit exception when the user
  164. # has set stopframe in a generator by issuing a return command, or a
  165. # next/until command at the last statement in the generator before the
  166. # exception.
  167. elif (self.stopframe and frame is not self.stopframe
  168. and self.stopframe.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS
  169. and arg[0] in (StopIteration, GeneratorExit)):
  170. self.user_exception(frame, arg)
  171. if self.quitting: raise BdbQuit
  172. return self.trace_dispatch
  173. # Normally derived classes don't override the following
  174. # methods, but they may if they want to redefine the
  175. # definition of stopping and breakpoints.
  176. def is_skipped_module(self, module_name):
  177. "Return True if module_name matches any skip pattern."
  178. if module_name is None: # some modules do not have names
  179. return False
  180. for pattern in self.skip:
  181. if fnmatch.fnmatch(module_name, pattern):
  182. return True
  183. return False
  184. def stop_here(self, frame):
  185. "Return True if frame is below the starting frame in the stack."
  186. # (CT) stopframe may now also be None, see dispatch_call.
  187. # (CT) the former test for None is therefore removed from here.
  188. if self.skip and \
  189. self.is_skipped_module(frame.f_globals.get('__name__')):
  190. return False
  191. if frame is self.stopframe:
  192. if self.stoplineno == -1:
  193. return False
  194. return frame.f_lineno >= self.stoplineno
  195. if not self.stopframe:
  196. return True
  197. return False
  198. def break_here(self, frame):
  199. """Return True if there is an effective breakpoint for this line.
  200. Check for line or function breakpoint and if in effect.
  201. Delete temporary breakpoints if effective() says to.
  202. """
  203. filename = self.canonic(frame.f_code.co_filename)
  204. if filename not in self.breaks:
  205. return False
  206. lineno = frame.f_lineno
  207. if lineno not in self.breaks[filename]:
  208. # The line itself has no breakpoint, but maybe the line is the
  209. # first line of a function with breakpoint set by function name.
  210. lineno = frame.f_code.co_firstlineno
  211. if lineno not in self.breaks[filename]:
  212. return False
  213. # flag says ok to delete temp. bp
  214. (bp, flag) = effective(filename, lineno, frame)
  215. if bp:
  216. self.currentbp = bp.number
  217. if (flag and bp.temporary):
  218. self.do_clear(str(bp.number))
  219. return True
  220. else:
  221. return False
  222. def do_clear(self, arg):
  223. """Remove temporary breakpoint.
  224. Must implement in derived classes or get NotImplementedError.
  225. """
  226. raise NotImplementedError("subclass of bdb must implement do_clear()")
  227. def break_anywhere(self, frame):
  228. """Return True if there is any breakpoint for frame's filename.
  229. """
  230. return self.canonic(frame.f_code.co_filename) in self.breaks
  231. # Derived classes should override the user_* methods
  232. # to gain control.
  233. def user_call(self, frame, argument_list):
  234. """Called if we might stop in a function."""
  235. pass
  236. def user_line(self, frame):
  237. """Called when we stop or break at a line."""
  238. pass
  239. def user_return(self, frame, return_value):
  240. """Called when a return trap is set here."""
  241. pass
  242. def user_exception(self, frame, exc_info):
  243. """Called when we stop on an exception."""
  244. pass
  245. def _set_stopinfo(self, stopframe, returnframe, stoplineno=0):
  246. """Set the attributes for stopping.
  247. If stoplineno is greater than or equal to 0, then stop at line
  248. greater than or equal to the stopline. If stoplineno is -1, then
  249. don't stop at all.
  250. """
  251. self.stopframe = stopframe
  252. self.returnframe = returnframe
  253. self.quitting = False
  254. # stoplineno >= 0 means: stop at line >= the stoplineno
  255. # stoplineno -1 means: don't stop at all
  256. self.stoplineno = stoplineno
  257. def _set_caller_tracefunc(self, current_frame):
  258. # Issue #13183: pdb skips frames after hitting a breakpoint and running
  259. # step commands.
  260. # Restore the trace function in the caller (that may not have been set
  261. # for performance reasons) when returning from the current frame, unless
  262. # the caller is the botframe.
  263. caller_frame = current_frame.f_back
  264. if caller_frame and not caller_frame.f_trace and caller_frame is not self.botframe:
  265. caller_frame.f_trace = self.trace_dispatch
  266. # Derived classes and clients can call the following methods
  267. # to affect the stepping state.
  268. def set_until(self, frame, lineno=None):
  269. """Stop when the line with the lineno greater than the current one is
  270. reached or when returning from current frame."""
  271. # the name "until" is borrowed from gdb
  272. if lineno is None:
  273. lineno = frame.f_lineno + 1
  274. self._set_stopinfo(frame, frame, lineno)
  275. def set_step(self):
  276. """Stop after one line of code."""
  277. self._set_stopinfo(None, None)
  278. def set_next(self, frame):
  279. """Stop on the next line in or below the given frame."""
  280. self._set_stopinfo(frame, None)
  281. def set_return(self, frame):
  282. """Stop when returning from the given frame."""
  283. if frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS:
  284. self._set_stopinfo(frame, None, -1)
  285. else:
  286. self._set_stopinfo(frame.f_back, frame)
  287. def set_trace(self, frame=None):
  288. """Start debugging from frame.
  289. If frame is not specified, debugging starts from caller's frame.
  290. """
  291. sys.settrace(None)
  292. if frame is None:
  293. frame = sys._getframe().f_back
  294. self.reset()
  295. with self.set_enterframe(frame):
  296. while frame:
  297. frame.f_trace = self.trace_dispatch
  298. self.botframe = frame
  299. frame = frame.f_back
  300. self.set_step()
  301. sys.settrace(self.trace_dispatch)
  302. def set_continue(self):
  303. """Stop only at breakpoints or when finished.
  304. If there are no breakpoints, set the system trace function to None.
  305. """
  306. # Don't stop except at breakpoints or when finished
  307. self._set_stopinfo(self.botframe, None, -1)
  308. if not self.breaks:
  309. # no breakpoints; run without debugger overhead
  310. sys.settrace(None)
  311. frame = sys._getframe().f_back
  312. while frame and frame is not self.botframe:
  313. del frame.f_trace
  314. frame = frame.f_back
  315. def set_quit(self):
  316. """Set quitting attribute to True.
  317. Raises BdbQuit exception in the next call to a dispatch_*() method.
  318. """
  319. self.stopframe = self.botframe
  320. self.returnframe = None
  321. self.quitting = True
  322. sys.settrace(None)
  323. # Derived classes and clients can call the following methods
  324. # to manipulate breakpoints. These methods return an
  325. # error message if something went wrong, None if all is well.
  326. # Set_break prints out the breakpoint line and file:lineno.
  327. # Call self.get_*break*() to see the breakpoints or better
  328. # for bp in Breakpoint.bpbynumber: if bp: bp.bpprint().
  329. def _add_to_breaks(self, filename, lineno):
  330. """Add breakpoint to breaks, if not already there."""
  331. bp_linenos = self.breaks.setdefault(filename, [])
  332. if lineno not in bp_linenos:
  333. bp_linenos.append(lineno)
  334. def set_break(self, filename, lineno, temporary=False, cond=None,
  335. funcname=None):
  336. """Set a new breakpoint for filename:lineno.
  337. If lineno doesn't exist for the filename, return an error message.
  338. The filename should be in canonical form.
  339. """
  340. filename = self.canonic(filename)
  341. import linecache # Import as late as possible
  342. line = linecache.getline(filename, lineno)
  343. if not line:
  344. return 'Line %s:%d does not exist' % (filename, lineno)
  345. self._add_to_breaks(filename, lineno)
  346. bp = Breakpoint(filename, lineno, temporary, cond, funcname)
  347. # After we set a new breakpoint, we need to search through all frames
  348. # and set f_trace to trace_dispatch if there could be a breakpoint in
  349. # that frame.
  350. frame = self.enterframe
  351. while frame:
  352. if self.break_anywhere(frame):
  353. frame.f_trace = self.trace_dispatch
  354. frame = frame.f_back
  355. return None
  356. def _load_breaks(self):
  357. """Apply all breakpoints (set in other instances) to this one.
  358. Populates this instance's breaks list from the Breakpoint class's
  359. list, which can have breakpoints set by another Bdb instance. This
  360. is necessary for interactive sessions to keep the breakpoints
  361. active across multiple calls to run().
  362. """
  363. for (filename, lineno) in Breakpoint.bplist.keys():
  364. self._add_to_breaks(filename, lineno)
  365. def _prune_breaks(self, filename, lineno):
  366. """Prune breakpoints for filename:lineno.
  367. A list of breakpoints is maintained in the Bdb instance and in
  368. the Breakpoint class. If a breakpoint in the Bdb instance no
  369. longer exists in the Breakpoint class, then it's removed from the
  370. Bdb instance.
  371. """
  372. if (filename, lineno) not in Breakpoint.bplist:
  373. self.breaks[filename].remove(lineno)
  374. if not self.breaks[filename]:
  375. del self.breaks[filename]
  376. def clear_break(self, filename, lineno):
  377. """Delete breakpoints for filename:lineno.
  378. If no breakpoints were set, return an error message.
  379. """
  380. filename = self.canonic(filename)
  381. if filename not in self.breaks:
  382. return 'There are no breakpoints in %s' % filename
  383. if lineno not in self.breaks[filename]:
  384. return 'There is no breakpoint at %s:%d' % (filename, lineno)
  385. # If there's only one bp in the list for that file,line
  386. # pair, then remove the breaks entry
  387. for bp in Breakpoint.bplist[filename, lineno][:]:
  388. bp.deleteMe()
  389. self._prune_breaks(filename, lineno)
  390. return None
  391. def clear_bpbynumber(self, arg):
  392. """Delete a breakpoint by its index in Breakpoint.bpbynumber.
  393. If arg is invalid, return an error message.
  394. """
  395. try:
  396. bp = self.get_bpbynumber(arg)
  397. except ValueError as err:
  398. return str(err)
  399. bp.deleteMe()
  400. self._prune_breaks(bp.file, bp.line)
  401. return None
  402. def clear_all_file_breaks(self, filename):
  403. """Delete all breakpoints in filename.
  404. If none were set, return an error message.
  405. """
  406. filename = self.canonic(filename)
  407. if filename not in self.breaks:
  408. return 'There are no breakpoints in %s' % filename
  409. for line in self.breaks[filename]:
  410. blist = Breakpoint.bplist[filename, line]
  411. for bp in blist:
  412. bp.deleteMe()
  413. del self.breaks[filename]
  414. return None
  415. def clear_all_breaks(self):
  416. """Delete all existing breakpoints.
  417. If none were set, return an error message.
  418. """
  419. if not self.breaks:
  420. return 'There are no breakpoints'
  421. for bp in Breakpoint.bpbynumber:
  422. if bp:
  423. bp.deleteMe()
  424. self.breaks = {}
  425. return None
  426. def get_bpbynumber(self, arg):
  427. """Return a breakpoint by its index in Breakpoint.bybpnumber.
  428. For invalid arg values or if the breakpoint doesn't exist,
  429. raise a ValueError.
  430. """
  431. if not arg:
  432. raise ValueError('Breakpoint number expected')
  433. try:
  434. number = int(arg)
  435. except ValueError:
  436. raise ValueError('Non-numeric breakpoint number %s' % arg) from None
  437. try:
  438. bp = Breakpoint.bpbynumber[number]
  439. except IndexError:
  440. raise ValueError('Breakpoint number %d out of range' % number) from None
  441. if bp is None:
  442. raise ValueError('Breakpoint %d already deleted' % number)
  443. return bp
  444. def get_break(self, filename, lineno):
  445. """Return True if there is a breakpoint for filename:lineno."""
  446. filename = self.canonic(filename)
  447. return filename in self.breaks and \
  448. lineno in self.breaks[filename]
  449. def get_breaks(self, filename, lineno):
  450. """Return all breakpoints for filename:lineno.
  451. If no breakpoints are set, return an empty list.
  452. """
  453. filename = self.canonic(filename)
  454. return filename in self.breaks and \
  455. lineno in self.breaks[filename] and \
  456. Breakpoint.bplist[filename, lineno] or []
  457. def get_file_breaks(self, filename):
  458. """Return all lines with breakpoints for filename.
  459. If no breakpoints are set, return an empty list.
  460. """
  461. filename = self.canonic(filename)
  462. if filename in self.breaks:
  463. return self.breaks[filename]
  464. else:
  465. return []
  466. def get_all_breaks(self):
  467. """Return all breakpoints that are set."""
  468. return self.breaks
  469. # Derived classes and clients can call the following method
  470. # to get a data structure representing a stack trace.
  471. def get_stack(self, f, t):
  472. """Return a list of (frame, lineno) in a stack trace and a size.
  473. List starts with original calling frame, if there is one.
  474. Size may be number of frames above or below f.
  475. """
  476. stack = []
  477. if t and t.tb_frame is f:
  478. t = t.tb_next
  479. while f is not None:
  480. stack.append((f, f.f_lineno))
  481. if f is self.botframe:
  482. break
  483. f = f.f_back
  484. stack.reverse()
  485. i = max(0, len(stack) - 1)
  486. while t is not None:
  487. stack.append((t.tb_frame, t.tb_lineno))
  488. t = t.tb_next
  489. if f is None:
  490. i = max(0, len(stack) - 1)
  491. return stack, i
  492. def format_stack_entry(self, frame_lineno, lprefix=': '):
  493. """Return a string with information about a stack entry.
  494. The stack entry frame_lineno is a (frame, lineno) tuple. The
  495. return string contains the canonical filename, the function name
  496. or '<lambda>', the input arguments, the return value, and the
  497. line of code (if it exists).
  498. """
  499. import linecache, reprlib
  500. frame, lineno = frame_lineno
  501. filename = self.canonic(frame.f_code.co_filename)
  502. s = '%s(%r)' % (filename, lineno)
  503. if frame.f_code.co_name:
  504. s += frame.f_code.co_name
  505. else:
  506. s += "<lambda>"
  507. s += '()'
  508. if '__return__' in frame.f_locals:
  509. rv = frame.f_locals['__return__']
  510. s += '->'
  511. s += reprlib.repr(rv)
  512. if lineno is not None:
  513. line = linecache.getline(filename, lineno, frame.f_globals)
  514. if line:
  515. s += lprefix + line.strip()
  516. else:
  517. s += f'{lprefix}Warning: lineno is None'
  518. return s
  519. # The following methods can be called by clients to use
  520. # a debugger to debug a statement or an expression.
  521. # Both can be given as a string, or a code object.
  522. def run(self, cmd, globals=None, locals=None):
  523. """Debug a statement executed via the exec() function.
  524. globals defaults to __main__.dict; locals defaults to globals.
  525. """
  526. if globals is None:
  527. import __main__
  528. globals = __main__.__dict__
  529. if locals is None:
  530. locals = globals
  531. self.reset()
  532. if isinstance(cmd, str):
  533. cmd = compile(cmd, "<string>", "exec")
  534. sys.settrace(self.trace_dispatch)
  535. try:
  536. exec(cmd, globals, locals)
  537. except BdbQuit:
  538. pass
  539. finally:
  540. self.quitting = True
  541. sys.settrace(None)
  542. def runeval(self, expr, globals=None, locals=None):
  543. """Debug an expression executed via the eval() function.
  544. globals defaults to __main__.dict; locals defaults to globals.
  545. """
  546. if globals is None:
  547. import __main__
  548. globals = __main__.__dict__
  549. if locals is None:
  550. locals = globals
  551. self.reset()
  552. sys.settrace(self.trace_dispatch)
  553. try:
  554. return eval(expr, globals, locals)
  555. except BdbQuit:
  556. pass
  557. finally:
  558. self.quitting = True
  559. sys.settrace(None)
  560. def runctx(self, cmd, globals, locals):
  561. """For backwards-compatibility. Defers to run()."""
  562. # B/W compatibility
  563. self.run(cmd, globals, locals)
  564. # This method is more useful to debug a single function call.
  565. def runcall(self, func, /, *args, **kwds):
  566. """Debug a single function call.
  567. Return the result of the function call.
  568. """
  569. self.reset()
  570. sys.settrace(self.trace_dispatch)
  571. res = None
  572. try:
  573. res = func(*args, **kwds)
  574. except BdbQuit:
  575. pass
  576. finally:
  577. self.quitting = True
  578. sys.settrace(None)
  579. return res
  580. def set_trace():
  581. """Start debugging with a Bdb instance from the caller's frame."""
  582. Bdb().set_trace()
  583. class Breakpoint:
  584. """Breakpoint class.
  585. Implements temporary breakpoints, ignore counts, disabling and
  586. (re)-enabling, and conditionals.
  587. Breakpoints are indexed by number through bpbynumber and by
  588. the (file, line) tuple using bplist. The former points to a
  589. single instance of class Breakpoint. The latter points to a
  590. list of such instances since there may be more than one
  591. breakpoint per line.
  592. When creating a breakpoint, its associated filename should be
  593. in canonical form. If funcname is defined, a breakpoint hit will be
  594. counted when the first line of that function is executed. A
  595. conditional breakpoint always counts a hit.
  596. """
  597. # XXX Keeping state in the class is a mistake -- this means
  598. # you cannot have more than one active Bdb instance.
  599. next = 1 # Next bp to be assigned
  600. bplist = {} # indexed by (file, lineno) tuple
  601. bpbynumber = [None] # Each entry is None or an instance of Bpt
  602. # index 0 is unused, except for marking an
  603. # effective break .... see effective()
  604. def __init__(self, file, line, temporary=False, cond=None, funcname=None):
  605. self.funcname = funcname
  606. # Needed if funcname is not None.
  607. self.func_first_executable_line = None
  608. self.file = file # This better be in canonical form!
  609. self.line = line
  610. self.temporary = temporary
  611. self.cond = cond
  612. self.enabled = True
  613. self.ignore = 0
  614. self.hits = 0
  615. self.number = Breakpoint.next
  616. Breakpoint.next += 1
  617. # Build the two lists
  618. self.bpbynumber.append(self)
  619. if (file, line) in self.bplist:
  620. self.bplist[file, line].append(self)
  621. else:
  622. self.bplist[file, line] = [self]
  623. @staticmethod
  624. def clearBreakpoints():
  625. Breakpoint.next = 1
  626. Breakpoint.bplist = {}
  627. Breakpoint.bpbynumber = [None]
  628. def deleteMe(self):
  629. """Delete the breakpoint from the list associated to a file:line.
  630. If it is the last breakpoint in that position, it also deletes
  631. the entry for the file:line.
  632. """
  633. index = (self.file, self.line)
  634. self.bpbynumber[self.number] = None # No longer in list
  635. self.bplist[index].remove(self)
  636. if not self.bplist[index]:
  637. # No more bp for this f:l combo
  638. del self.bplist[index]
  639. def enable(self):
  640. """Mark the breakpoint as enabled."""
  641. self.enabled = True
  642. def disable(self):
  643. """Mark the breakpoint as disabled."""
  644. self.enabled = False
  645. def bpprint(self, out=None):
  646. """Print the output of bpformat().
  647. The optional out argument directs where the output is sent
  648. and defaults to standard output.
  649. """
  650. if out is None:
  651. out = sys.stdout
  652. print(self.bpformat(), file=out)
  653. def bpformat(self):
  654. """Return a string with information about the breakpoint.
  655. The information includes the breakpoint number, temporary
  656. status, file:line position, break condition, number of times to
  657. ignore, and number of times hit.
  658. """
  659. if self.temporary:
  660. disp = 'del '
  661. else:
  662. disp = 'keep '
  663. if self.enabled:
  664. disp = disp + 'yes '
  665. else:
  666. disp = disp + 'no '
  667. ret = '%-4dbreakpoint %s at %s:%d' % (self.number, disp,
  668. self.file, self.line)
  669. if self.cond:
  670. ret += '\n\tstop only if %s' % (self.cond,)
  671. if self.ignore:
  672. ret += '\n\tignore next %d hits' % (self.ignore,)
  673. if self.hits:
  674. if self.hits > 1:
  675. ss = 's'
  676. else:
  677. ss = ''
  678. ret += '\n\tbreakpoint already hit %d time%s' % (self.hits, ss)
  679. return ret
  680. def __str__(self):
  681. "Return a condensed description of the breakpoint."
  682. return 'breakpoint %s at %s:%s' % (self.number, self.file, self.line)
  683. # -----------end of Breakpoint class----------
  684. def checkfuncname(b, frame):
  685. """Return True if break should happen here.
  686. Whether a break should happen depends on the way that b (the breakpoint)
  687. was set. If it was set via line number, check if b.line is the same as
  688. the one in the frame. If it was set via function name, check if this is
  689. the right function and if it is on the first executable line.
  690. """
  691. if not b.funcname:
  692. # Breakpoint was set via line number.
  693. if b.line != frame.f_lineno:
  694. # Breakpoint was set at a line with a def statement and the function
  695. # defined is called: don't break.
  696. return False
  697. return True
  698. # Breakpoint set via function name.
  699. if frame.f_code.co_name != b.funcname:
  700. # It's not a function call, but rather execution of def statement.
  701. return False
  702. # We are in the right frame.
  703. if not b.func_first_executable_line:
  704. # The function is entered for the 1st time.
  705. b.func_first_executable_line = frame.f_lineno
  706. if b.func_first_executable_line != frame.f_lineno:
  707. # But we are not at the first line number: don't break.
  708. return False
  709. return True
  710. def effective(file, line, frame):
  711. """Return (active breakpoint, delete temporary flag) or (None, None) as
  712. breakpoint to act upon.
  713. The "active breakpoint" is the first entry in bplist[line, file] (which
  714. must exist) that is enabled, for which checkfuncname is True, and that
  715. has neither a False condition nor a positive ignore count. The flag,
  716. meaning that a temporary breakpoint should be deleted, is False only
  717. when the condiion cannot be evaluated (in which case, ignore count is
  718. ignored).
  719. If no such entry exists, then (None, None) is returned.
  720. """
  721. possibles = Breakpoint.bplist[file, line]
  722. for b in possibles:
  723. if not b.enabled:
  724. continue
  725. if not checkfuncname(b, frame):
  726. continue
  727. # Count every hit when bp is enabled
  728. b.hits += 1
  729. if not b.cond:
  730. # If unconditional, and ignoring go on to next, else break
  731. if b.ignore > 0:
  732. b.ignore -= 1
  733. continue
  734. else:
  735. # breakpoint and marker that it's ok to delete if temporary
  736. return (b, True)
  737. else:
  738. # Conditional bp.
  739. # Ignore count applies only to those bpt hits where the
  740. # condition evaluates to true.
  741. try:
  742. val = eval(b.cond, frame.f_globals, frame.f_locals)
  743. if val:
  744. if b.ignore > 0:
  745. b.ignore -= 1
  746. # continue
  747. else:
  748. return (b, True)
  749. # else:
  750. # continue
  751. except:
  752. # if eval fails, most conservative thing is to stop on
  753. # breakpoint regardless of ignore count. Don't delete
  754. # temporary, as another hint to user.
  755. return (b, False)
  756. return (None, None)
  757. # -------------------- testing --------------------
  758. class Tdb(Bdb):
  759. def user_call(self, frame, args):
  760. name = frame.f_code.co_name
  761. if not name: name = '???'
  762. print('+++ call', name, args)
  763. def user_line(self, frame):
  764. import linecache
  765. name = frame.f_code.co_name
  766. if not name: name = '???'
  767. fn = self.canonic(frame.f_code.co_filename)
  768. line = linecache.getline(fn, frame.f_lineno, frame.f_globals)
  769. print('+++', fn, frame.f_lineno, name, ':', line.strip())
  770. def user_return(self, frame, retval):
  771. print('+++ return', retval)
  772. def user_exception(self, frame, exc_stuff):
  773. print('+++ exception', exc_stuff)
  774. self.set_continue()
  775. def foo(n):
  776. print('foo(', n, ')')
  777. x = bar(n*10)
  778. print('bar returned', x)
  779. def bar(a):
  780. print('bar(', a, ')')
  781. return a/2
  782. def test():
  783. t = Tdb()
  784. t.run('import bdb; bdb.foo(10)')