##// END OF EJS Templates
Fix clashes between debugger tests and coverage.py...
Thomas Kluyver -
Show More
@@ -1,577 +1,579 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Pdb debugger class.
4 4
5 5 Modified from the standard pdb.Pdb class to avoid including readline, so that
6 6 the command line completion of other programs which include this isn't
7 7 damaged.
8 8
9 9 In the future, this class will be expanded with improvements over the standard
10 10 pdb.
11 11
12 12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
13 13 changes. Licensing should therefore be under the standard Python terms. For
14 14 details on the PSF (Python Software Foundation) standard license, see:
15 15
16 16 http://www.python.org/2.2.3/license.html"""
17 17
18 18 #*****************************************************************************
19 19 #
20 20 # This file is licensed under the PSF license.
21 21 #
22 22 # Copyright (C) 2001 Python Software Foundation, www.python.org
23 23 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
24 24 #
25 25 #
26 26 #*****************************************************************************
27 27 from __future__ import print_function
28 28
29 29 import bdb
30 30 import functools
31 31 import linecache
32 32 import sys
33 33
34 34 from IPython import get_ipython
35 35 from IPython.utils import PyColorize, ulinecache
36 36 from IPython.utils import coloransi, io, py3compat
37 37 from IPython.core.excolors import exception_colors
38 from IPython.testing.skipdoctest import skip_doctest
38 39
39 40 # See if we can use pydb.
40 41 has_pydb = False
41 42 prompt = 'ipdb> '
42 43 #We have to check this directly from sys.argv, config struct not yet available
43 44 if '--pydb' in sys.argv:
44 45 try:
45 46 import pydb
46 47 if hasattr(pydb.pydb, "runl") and pydb.version>'1.17':
47 48 # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we
48 49 # better protect against it.
49 50 has_pydb = True
50 51 except ImportError:
51 52 print("Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available")
52 53
53 54 if has_pydb:
54 55 from pydb import Pdb as OldPdb
55 56 #print "Using pydb for %run -d and post-mortem" #dbg
56 57 prompt = 'ipydb> '
57 58 else:
58 59 from pdb import Pdb as OldPdb
59 60
60 61 # Allow the set_trace code to operate outside of an ipython instance, even if
61 62 # it does so with some limitations. The rest of this support is implemented in
62 63 # the Tracer constructor.
63 64 def BdbQuit_excepthook(et, ev, tb, excepthook=None):
64 65 """Exception hook which handles `BdbQuit` exceptions.
65 66
66 67 All other exceptions are processed using the `excepthook`
67 68 parameter.
68 69 """
69 70 if et==bdb.BdbQuit:
70 71 print('Exiting Debugger.')
71 72 elif excepthook is not None:
72 73 excepthook(et, ev, tb)
73 74 else:
74 75 # Backwards compatibility. Raise deprecation warning?
75 76 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
76 77
77 78 def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None):
78 79 print('Exiting Debugger.')
79 80
80 81
81 82 class Tracer(object):
82 83 """Class for local debugging, similar to pdb.set_trace.
83 84
84 85 Instances of this class, when called, behave like pdb.set_trace, but
85 86 providing IPython's enhanced capabilities.
86 87
87 88 This is implemented as a class which must be initialized in your own code
88 89 and not as a standalone function because we need to detect at runtime
89 90 whether IPython is already active or not. That detection is done in the
90 91 constructor, ensuring that this code plays nicely with a running IPython,
91 92 while functioning acceptably (though with limitations) if outside of it.
92 93 """
93 94
95 @skip_doctest
94 96 def __init__(self,colors=None):
95 97 """Create a local debugger instance.
96 98
97 99 :Parameters:
98 100
99 101 - `colors` (None): a string containing the name of the color scheme to
100 102 use, it must be one of IPython's valid color schemes. If not given, the
101 103 function will default to the current IPython scheme when running inside
102 104 IPython, and to 'NoColor' otherwise.
103 105
104 106 Usage example:
105 107
106 108 from IPython.core.debugger import Tracer; debug_here = Tracer()
107 109
108 110 ... later in your code
109 111 debug_here() # -> will open up the debugger at that point.
110 112
111 113 Once the debugger activates, you can use all of its regular commands to
112 114 step through code, set breakpoints, etc. See the pdb documentation
113 115 from the Python standard library for usage details.
114 116 """
115 117
116 118 ip = get_ipython()
117 119 if ip is None:
118 120 # Outside of ipython, we set our own exception hook manually
119 121 sys.excepthook = functools.partial(BdbQuit_excepthook,
120 122 excepthook=sys.excepthook)
121 123 def_colors = 'NoColor'
122 124 try:
123 125 # Limited tab completion support
124 126 import readline
125 127 readline.parse_and_bind('tab: complete')
126 128 except ImportError:
127 129 pass
128 130 else:
129 131 # In ipython, we use its custom exception handler mechanism
130 132 def_colors = ip.colors
131 133 ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook)
132 134
133 135 if colors is None:
134 136 colors = def_colors
135 137
136 138 # The stdlib debugger internally uses a modified repr from the `repr`
137 139 # module, that limits the length of printed strings to a hardcoded
138 140 # limit of 30 characters. That much trimming is too aggressive, let's
139 141 # at least raise that limit to 80 chars, which should be enough for
140 142 # most interactive uses.
141 143 try:
142 144 from repr import aRepr
143 145 aRepr.maxstring = 80
144 146 except:
145 147 # This is only a user-facing convenience, so any error we encounter
146 148 # here can be warned about but can be otherwise ignored. These
147 149 # printouts will tell us about problems if this API changes
148 150 import traceback
149 151 traceback.print_exc()
150 152
151 153 self.debugger = Pdb(colors)
152 154
153 155 def __call__(self):
154 156 """Starts an interactive debugger at the point where called.
155 157
156 158 This is similar to the pdb.set_trace() function from the std lib, but
157 159 using IPython's enhanced debugger."""
158 160
159 161 self.debugger.set_trace(sys._getframe().f_back)
160 162
161 163
162 164 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
163 165 """Make new_fn have old_fn's doc string. This is particularly useful
164 166 for the ``do_...`` commands that hook into the help system.
165 167 Adapted from from a comp.lang.python posting
166 168 by Duncan Booth."""
167 169 def wrapper(*args, **kw):
168 170 return new_fn(*args, **kw)
169 171 if old_fn.__doc__:
170 172 wrapper.__doc__ = old_fn.__doc__ + additional_text
171 173 return wrapper
172 174
173 175
174 176 def _file_lines(fname):
175 177 """Return the contents of a named file as a list of lines.
176 178
177 179 This function never raises an IOError exception: if the file can't be
178 180 read, it simply returns an empty list."""
179 181
180 182 try:
181 183 outfile = open(fname)
182 184 except IOError:
183 185 return []
184 186 else:
185 187 out = outfile.readlines()
186 188 outfile.close()
187 189 return out
188 190
189 191
190 192 class Pdb(OldPdb):
191 193 """Modified Pdb class, does not load readline."""
192 194
193 195 def __init__(self,color_scheme='NoColor',completekey=None,
194 196 stdin=None, stdout=None):
195 197
196 198 # Parent constructor:
197 199 if has_pydb and completekey is None:
198 200 OldPdb.__init__(self,stdin=stdin,stdout=io.stdout)
199 201 else:
200 202 OldPdb.__init__(self,completekey,stdin,stdout)
201 203
202 204 self.prompt = prompt # The default prompt is '(Pdb)'
203 205
204 206 # IPython changes...
205 207 self.is_pydb = has_pydb
206 208
207 209 self.shell = get_ipython()
208 210
209 211 if self.shell is None:
210 212 # No IPython instance running, we must create one
211 213 from IPython.terminal.interactiveshell import \
212 214 TerminalInteractiveShell
213 215 self.shell = TerminalInteractiveShell.instance()
214 216
215 217 if self.is_pydb:
216 218
217 219 # interactiveshell.py's ipalias seems to want pdb's checkline
218 220 # which located in pydb.fn
219 221 import pydb.fns
220 222 self.checkline = lambda filename, lineno: \
221 223 pydb.fns.checkline(self, filename, lineno)
222 224
223 225 self.curframe = None
224 226 self.do_restart = self.new_do_restart
225 227
226 228 self.old_all_completions = self.shell.Completer.all_completions
227 229 self.shell.Completer.all_completions=self.all_completions
228 230
229 231 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
230 232 OldPdb.do_list)
231 233 self.do_l = self.do_list
232 234 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
233 235 OldPdb.do_frame)
234 236
235 237 self.aliases = {}
236 238
237 239 # Create color table: we copy the default one from the traceback
238 240 # module and add a few attributes needed for debugging
239 241 self.color_scheme_table = exception_colors()
240 242
241 243 # shorthands
242 244 C = coloransi.TermColors
243 245 cst = self.color_scheme_table
244 246
245 247 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
246 248 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
247 249
248 250 cst['Linux'].colors.breakpoint_enabled = C.LightRed
249 251 cst['Linux'].colors.breakpoint_disabled = C.Red
250 252
251 253 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
252 254 cst['LightBG'].colors.breakpoint_disabled = C.Red
253 255
254 256 self.set_colors(color_scheme)
255 257
256 258 # Add a python parser so we can syntax highlight source while
257 259 # debugging.
258 260 self.parser = PyColorize.Parser()
259 261
260 262 def set_colors(self, scheme):
261 263 """Shorthand access to the color table scheme selector method."""
262 264 self.color_scheme_table.set_active_scheme(scheme)
263 265
264 266 def interaction(self, frame, traceback):
265 267 self.shell.set_completer_frame(frame)
266 268 while True:
267 269 try:
268 270 OldPdb.interaction(self, frame, traceback)
269 271 except KeyboardInterrupt:
270 272 self.shell.write("\nKeyboardInterrupt\n")
271 273 else:
272 274 break
273 275
274 276 def new_do_up(self, arg):
275 277 OldPdb.do_up(self, arg)
276 278 self.shell.set_completer_frame(self.curframe)
277 279 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
278 280
279 281 def new_do_down(self, arg):
280 282 OldPdb.do_down(self, arg)
281 283 self.shell.set_completer_frame(self.curframe)
282 284
283 285 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
284 286
285 287 def new_do_frame(self, arg):
286 288 OldPdb.do_frame(self, arg)
287 289 self.shell.set_completer_frame(self.curframe)
288 290
289 291 def new_do_quit(self, arg):
290 292
291 293 if hasattr(self, 'old_all_completions'):
292 294 self.shell.Completer.all_completions=self.old_all_completions
293 295
294 296
295 297 return OldPdb.do_quit(self, arg)
296 298
297 299 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
298 300
299 301 def new_do_restart(self, arg):
300 302 """Restart command. In the context of ipython this is exactly the same
301 303 thing as 'quit'."""
302 304 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
303 305 return self.do_quit(arg)
304 306
305 307 def postloop(self):
306 308 self.shell.set_completer_frame(None)
307 309
308 310 def print_stack_trace(self):
309 311 try:
310 312 for frame_lineno in self.stack:
311 313 self.print_stack_entry(frame_lineno, context = 5)
312 314 except KeyboardInterrupt:
313 315 pass
314 316
315 317 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
316 318 context = 3):
317 319 #frame, lineno = frame_lineno
318 320 print(self.format_stack_entry(frame_lineno, '', context), file=io.stdout)
319 321
320 322 # vds: >>
321 323 frame, lineno = frame_lineno
322 324 filename = frame.f_code.co_filename
323 325 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
324 326 # vds: <<
325 327
326 328 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
327 329 import repr
328 330
329 331 ret = []
330 332
331 333 Colors = self.color_scheme_table.active_colors
332 334 ColorsNormal = Colors.Normal
333 335 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
334 336 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
335 337 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
336 338 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
337 339 ColorsNormal)
338 340
339 341 frame, lineno = frame_lineno
340 342
341 343 return_value = ''
342 344 if '__return__' in frame.f_locals:
343 345 rv = frame.f_locals['__return__']
344 346 #return_value += '->'
345 347 return_value += repr.repr(rv) + '\n'
346 348 ret.append(return_value)
347 349
348 350 #s = filename + '(' + `lineno` + ')'
349 351 filename = self.canonic(frame.f_code.co_filename)
350 352 link = tpl_link % py3compat.cast_unicode(filename)
351 353
352 354 if frame.f_code.co_name:
353 355 func = frame.f_code.co_name
354 356 else:
355 357 func = "<lambda>"
356 358
357 359 call = ''
358 360 if func != '?':
359 361 if '__args__' in frame.f_locals:
360 362 args = repr.repr(frame.f_locals['__args__'])
361 363 else:
362 364 args = '()'
363 365 call = tpl_call % (func, args)
364 366
365 367 # The level info should be generated in the same format pdb uses, to
366 368 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
367 369 if frame is self.curframe:
368 370 ret.append('> ')
369 371 else:
370 372 ret.append(' ')
371 373 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
372 374
373 375 start = lineno - 1 - context//2
374 376 lines = ulinecache.getlines(filename)
375 377 start = min(start, len(lines) - context)
376 378 start = max(start, 0)
377 379 lines = lines[start : start + context]
378 380
379 381 for i,line in enumerate(lines):
380 382 show_arrow = (start + 1 + i == lineno)
381 383 linetpl = (frame is self.curframe or show_arrow) \
382 384 and tpl_line_em \
383 385 or tpl_line
384 386 ret.append(self.__format_line(linetpl, filename,
385 387 start + 1 + i, line,
386 388 arrow = show_arrow) )
387 389 return ''.join(ret)
388 390
389 391 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
390 392 bp_mark = ""
391 393 bp_mark_color = ""
392 394
393 395 scheme = self.color_scheme_table.active_scheme_name
394 396 new_line, err = self.parser.format2(line, 'str', scheme)
395 397 if not err: line = new_line
396 398
397 399 bp = None
398 400 if lineno in self.get_file_breaks(filename):
399 401 bps = self.get_breaks(filename, lineno)
400 402 bp = bps[-1]
401 403
402 404 if bp:
403 405 Colors = self.color_scheme_table.active_colors
404 406 bp_mark = str(bp.number)
405 407 bp_mark_color = Colors.breakpoint_enabled
406 408 if not bp.enabled:
407 409 bp_mark_color = Colors.breakpoint_disabled
408 410
409 411 numbers_width = 7
410 412 if arrow:
411 413 # This is the line with the error
412 414 pad = numbers_width - len(str(lineno)) - len(bp_mark)
413 415 if pad >= 3:
414 416 marker = '-'*(pad-3) + '-> '
415 417 elif pad == 2:
416 418 marker = '> '
417 419 elif pad == 1:
418 420 marker = '>'
419 421 else:
420 422 marker = ''
421 423 num = '%s%s' % (marker, str(lineno))
422 424 line = tpl_line % (bp_mark_color + bp_mark, num, line)
423 425 else:
424 426 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
425 427 line = tpl_line % (bp_mark_color + bp_mark, num, line)
426 428
427 429 return line
428 430
429 431 def list_command_pydb(self, arg):
430 432 """List command to use if we have a newer pydb installed"""
431 433 filename, first, last = OldPdb.parse_list_cmd(self, arg)
432 434 if filename is not None:
433 435 self.print_list_lines(filename, first, last)
434 436
435 437 def print_list_lines(self, filename, first, last):
436 438 """The printing (as opposed to the parsing part of a 'list'
437 439 command."""
438 440 try:
439 441 Colors = self.color_scheme_table.active_colors
440 442 ColorsNormal = Colors.Normal
441 443 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
442 444 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
443 445 src = []
444 446 if filename == "<string>" and hasattr(self, "_exec_filename"):
445 447 filename = self._exec_filename
446 448
447 449 for lineno in range(first, last+1):
448 450 line = ulinecache.getline(filename, lineno)
449 451 if not line:
450 452 break
451 453
452 454 if lineno == self.curframe.f_lineno:
453 455 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
454 456 else:
455 457 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
456 458
457 459 src.append(line)
458 460 self.lineno = lineno
459 461
460 462 print(''.join(src), file=io.stdout)
461 463
462 464 except KeyboardInterrupt:
463 465 pass
464 466
465 467 def do_list(self, arg):
466 468 self.lastcmd = 'list'
467 469 last = None
468 470 if arg:
469 471 try:
470 472 x = eval(arg, {}, {})
471 473 if type(x) == type(()):
472 474 first, last = x
473 475 first = int(first)
474 476 last = int(last)
475 477 if last < first:
476 478 # Assume it's a count
477 479 last = first + last
478 480 else:
479 481 first = max(1, int(x) - 5)
480 482 except:
481 483 print('*** Error in argument:', repr(arg))
482 484 return
483 485 elif self.lineno is None:
484 486 first = max(1, self.curframe.f_lineno - 5)
485 487 else:
486 488 first = self.lineno + 1
487 489 if last is None:
488 490 last = first + 10
489 491 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
490 492
491 493 # vds: >>
492 494 lineno = first
493 495 filename = self.curframe.f_code.co_filename
494 496 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
495 497 # vds: <<
496 498
497 499 do_l = do_list
498 500
499 501 def do_pdef(self, arg):
500 502 """Print the call signature for any callable object.
501 503
502 504 The debugger interface to %pdef"""
503 505 namespaces = [('Locals', self.curframe.f_locals),
504 506 ('Globals', self.curframe.f_globals)]
505 507 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
506 508
507 509 def do_pdoc(self, arg):
508 510 """Print the docstring for an object.
509 511
510 512 The debugger interface to %pdoc."""
511 513 namespaces = [('Locals', self.curframe.f_locals),
512 514 ('Globals', self.curframe.f_globals)]
513 515 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
514 516
515 517 def do_pfile(self, arg):
516 518 """Print (or run through pager) the file where an object is defined.
517 519
518 520 The debugger interface to %pfile.
519 521 """
520 522 namespaces = [('Locals', self.curframe.f_locals),
521 523 ('Globals', self.curframe.f_globals)]
522 524 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
523 525
524 526 def do_pinfo(self, arg):
525 527 """Provide detailed information about an object.
526 528
527 529 The debugger interface to %pinfo, i.e., obj?."""
528 530 namespaces = [('Locals', self.curframe.f_locals),
529 531 ('Globals', self.curframe.f_globals)]
530 532 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
531 533
532 534 def do_pinfo2(self, arg):
533 535 """Provide extra detailed information about an object.
534 536
535 537 The debugger interface to %pinfo2, i.e., obj??."""
536 538 namespaces = [('Locals', self.curframe.f_locals),
537 539 ('Globals', self.curframe.f_globals)]
538 540 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
539 541
540 542 def do_psource(self, arg):
541 543 """Print (or run through pager) the source code for an object."""
542 544 namespaces = [('Locals', self.curframe.f_locals),
543 545 ('Globals', self.curframe.f_globals)]
544 546 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
545 547
546 548 def checkline(self, filename, lineno):
547 549 """Check whether specified line seems to be executable.
548 550
549 551 Return `lineno` if it is, 0 if not (e.g. a docstring, comment, blank
550 552 line or EOF). Warning: testing is not comprehensive.
551 553 """
552 554 #######################################################################
553 555 # XXX Hack! Use python-2.5 compatible code for this call, because with
554 556 # all of our changes, we've drifted from the pdb api in 2.6. For now,
555 557 # changing:
556 558 #
557 559 #line = linecache.getline(filename, lineno, self.curframe.f_globals)
558 560 # to:
559 561 #
560 562 line = linecache.getline(filename, lineno)
561 563 #
562 564 # does the trick. But in reality, we need to fix this by reconciling
563 565 # our updates with the new Pdb APIs in Python 2.6.
564 566 #
565 567 # End hack. The rest of this method is copied verbatim from 2.6 pdb.py
566 568 #######################################################################
567 569
568 570 if not line:
569 571 print('End of file', file=self.stdout)
570 572 return 0
571 573 line = line.strip()
572 574 # Don't allow setting breakpoint at a blank line
573 575 if (not line or (line[0] == '#') or
574 576 (line[:3] == '"""') or line[:3] == "'''"):
575 577 print('*** Blank or comment', file=self.stdout)
576 578 return 0
577 579 return lineno
@@ -1,142 +1,154 b''
1 1 """Tests for debugging machinery.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (c) 2012, The IPython Development Team.
5 5 #
6 6 # Distributed under the terms of the Modified BSD License.
7 7 #
8 8 # The full license is in the file COPYING.txt, distributed with this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14
15 15 import sys
16 16
17 17 # third-party
18 18 import nose.tools as nt
19 19
20 20 # Our own
21 21 from IPython.core import debugger
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Helper classes, from CPython's Pdb test suite
25 25 #-----------------------------------------------------------------------------
26 26
27 27 class _FakeInput(object):
28 28 """
29 29 A fake input stream for pdb's interactive debugger. Whenever a
30 30 line is read, print it (to simulate the user typing it), and then
31 31 return it. The set of lines to return is specified in the
32 32 constructor; they should not have trailing newlines.
33 33 """
34 34 def __init__(self, lines):
35 35 self.lines = iter(lines)
36 36
37 37 def readline(self):
38 38 line = next(self.lines)
39 39 print line
40 40 return line+'\n'
41 41
42 42 class PdbTestInput(object):
43 43 """Context manager that makes testing Pdb in doctests easier."""
44 44
45 45 def __init__(self, input):
46 46 self.input = input
47 47
48 48 def __enter__(self):
49 49 self.real_stdin = sys.stdin
50 50 sys.stdin = _FakeInput(self.input)
51 51
52 52 def __exit__(self, *exc):
53 53 sys.stdin = self.real_stdin
54 54
55 55 #-----------------------------------------------------------------------------
56 56 # Tests
57 57 #-----------------------------------------------------------------------------
58 58
59 59 def test_longer_repr():
60 60 from repr import repr as trepr
61 61
62 62 a = '1234567890'* 7
63 63 ar = "'1234567890123456789012345678901234567890123456789012345678901234567890'"
64 64 a_trunc = "'123456789012...8901234567890'"
65 65 nt.assert_equal(trepr(a), a_trunc)
66 66 # The creation of our tracer modifies the repr module's repr function
67 67 # in-place, since that global is used directly by the stdlib's pdb module.
68 68 t = debugger.Tracer()
69 69 nt.assert_equal(trepr(a), ar)
70 70
71 71 def test_ipdb_magics():
72 72 '''Test calling some IPython magics from ipdb.
73 73
74 74 First, set up some test functions and classes which we can inspect.
75 75
76 76 >>> class ExampleClass(object):
77 77 ... """Docstring for ExampleClass."""
78 78 ... def __init__(self):
79 79 ... """Docstring for ExampleClass.__init__"""
80 80 ... pass
81 81 ... def __str__(self):
82 82 ... return "ExampleClass()"
83 83
84 84 >>> def example_function(x, y, z="hello"):
85 85 ... """Docstring for example_function."""
86 86 ... pass
87 87
88 >>> old_trace = sys.gettrace()
89
88 90 Create a function which triggers ipdb.
89 91
90 92 >>> def trigger_ipdb():
91 93 ... a = ExampleClass()
92 94 ... debugger.Pdb().set_trace()
93 95
94 96 >>> with PdbTestInput([
95 97 ... 'pdef example_function',
96 98 ... 'pdoc ExampleClass',
97 99 ... 'pinfo a',
98 100 ... 'continue',
99 101 ... ]):
100 102 ... trigger_ipdb()
101 103 --Return--
102 104 None
103 105 > <doctest ...>(3)trigger_ipdb()
104 106 1 def trigger_ipdb():
105 107 2 a = ExampleClass()
106 108 ----> 3 debugger.Pdb().set_trace()
107 109 <BLANKLINE>
108 110 ipdb> pdef example_function
109 111 example_function(x, y, z='hello')
110 112 ipdb> pdoc ExampleClass
111 113 Class Docstring:
112 114 Docstring for ExampleClass.
113 115 Constructor Docstring:
114 116 Docstring for ExampleClass.__init__
115 117 ipdb> pinfo a
116 118 Type: ExampleClass
117 119 String Form:ExampleClass()
118 120 Namespace: Locals
119 121 File: ...
120 122 Docstring: Docstring for ExampleClass.
121 123 Constructor Docstring:Docstring for ExampleClass.__init__
122 124 ipdb> continue
125
126 Restore previous trace function, e.g. for coverage.py
127
128 >>> sys.settrace(old_trace)
123 129 '''
124 130
125 131 def test_ipdb_magics2():
126 132 '''Test ipdb with a very short function.
127 133
134 >>> old_trace = sys.gettrace()
135
128 136 >>> def bar():
129 137 ... pass
130 138
131 139 Run ipdb.
132 140
133 141 >>> with PdbTestInput([
134 142 ... 'continue',
135 143 ... ]):
136 144 ... debugger.Pdb().runcall(bar)
137 145 > <doctest ...>(2)bar()
138 146 1 def bar():
139 147 ----> 2 pass
140 148 <BLANKLINE>
141 149 ipdb> continue
150
151 Restore previous trace function, e.g. for coverage.py
152
153 >>> sys.settrace(old_trace)
142 154 '''
General Comments 0
You need to be logged in to leave comments. Login now