##// END OF EJS Templates
Fix method special attributes...
Thomas Kluyver -
Show More
@@ -1,647 +1,647 b''
1 1 """Implementation of basic magic functions.
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 from __future__ import print_function
15 15
16 16 # Stdlib
17 17 import io
18 18 import json
19 19 import sys
20 20 from pprint import pformat
21 21
22 22 # Our own packages
23 23 from IPython.core import magic_arguments, page
24 24 from IPython.core.error import UsageError
25 25 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
26 26 from IPython.utils.text import format_screen, dedent, indent
27 27 from IPython.testing.skipdoctest import skip_doctest
28 28 from IPython.utils.ipstruct import Struct
29 29 from IPython.utils.path import unquote_filename
30 30 from IPython.utils.py3compat import unicode_type
31 31 from IPython.utils.warn import warn, error
32 32
33 33 #-----------------------------------------------------------------------------
34 34 # Magics class implementation
35 35 #-----------------------------------------------------------------------------
36 36
37 37 class MagicsDisplay(object):
38 38 def __init__(self, magics_manager):
39 39 self.magics_manager = magics_manager
40 40
41 41 def _lsmagic(self):
42 42 """The main implementation of the %lsmagic"""
43 43 mesc = magic_escapes['line']
44 44 cesc = magic_escapes['cell']
45 45 mman = self.magics_manager
46 46 magics = mman.lsmagic()
47 47 out = ['Available line magics:',
48 48 mesc + (' '+mesc).join(sorted(magics['line'])),
49 49 '',
50 50 'Available cell magics:',
51 51 cesc + (' '+cesc).join(sorted(magics['cell'])),
52 52 '',
53 53 mman.auto_status()]
54 54 return '\n'.join(out)
55 55
56 56 def _repr_pretty_(self, p, cycle):
57 57 p.text(self._lsmagic())
58 58
59 59 def __str__(self):
60 60 return self._lsmagic()
61 61
62 62 def _jsonable(self):
63 63 """turn magics dict into jsonable dict of the same structure
64 64
65 65 replaces object instances with their class names as strings
66 66 """
67 67 magic_dict = {}
68 68 mman = self.magics_manager
69 69 magics = mman.lsmagic()
70 70 for key, subdict in magics.items():
71 71 d = {}
72 72 magic_dict[key] = d
73 73 for name, obj in subdict.items():
74 74 try:
75 classname = obj.im_class.__name__
75 classname = obj.__self__.__class__.__name__
76 76 except AttributeError:
77 77 classname = 'Other'
78 78
79 79 d[name] = classname
80 80 return magic_dict
81 81
82 82 def _repr_json_(self):
83 83 return json.dumps(self._jsonable())
84 84
85 85
86 86 @magics_class
87 87 class BasicMagics(Magics):
88 88 """Magics that provide central IPython functionality.
89 89
90 90 These are various magics that don't fit into specific categories but that
91 91 are all part of the base 'IPython experience'."""
92 92
93 93 @magic_arguments.magic_arguments()
94 94 @magic_arguments.argument(
95 95 '-l', '--line', action='store_true',
96 96 help="""Create a line magic alias."""
97 97 )
98 98 @magic_arguments.argument(
99 99 '-c', '--cell', action='store_true',
100 100 help="""Create a cell magic alias."""
101 101 )
102 102 @magic_arguments.argument(
103 103 'name',
104 104 help="""Name of the magic to be created."""
105 105 )
106 106 @magic_arguments.argument(
107 107 'target',
108 108 help="""Name of the existing line or cell magic."""
109 109 )
110 110 @line_magic
111 111 def alias_magic(self, line=''):
112 112 """Create an alias for an existing line or cell magic.
113 113
114 114 Examples
115 115 --------
116 116 ::
117 117 In [1]: %alias_magic t timeit
118 118 Created `%t` as an alias for `%timeit`.
119 119 Created `%%t` as an alias for `%%timeit`.
120 120
121 121 In [2]: %t -n1 pass
122 122 1 loops, best of 3: 954 ns per loop
123 123
124 124 In [3]: %%t -n1
125 125 ...: pass
126 126 ...:
127 127 1 loops, best of 3: 954 ns per loop
128 128
129 129 In [4]: %alias_magic --cell whereami pwd
130 130 UsageError: Cell magic function `%%pwd` not found.
131 131 In [5]: %alias_magic --line whereami pwd
132 132 Created `%whereami` as an alias for `%pwd`.
133 133
134 134 In [6]: %whereami
135 135 Out[6]: u'/home/testuser'
136 136 """
137 137 args = magic_arguments.parse_argstring(self.alias_magic, line)
138 138 shell = self.shell
139 139 mman = self.shell.magics_manager
140 140 escs = ''.join(magic_escapes.values())
141 141
142 142 target = args.target.lstrip(escs)
143 143 name = args.name.lstrip(escs)
144 144
145 145 # Find the requested magics.
146 146 m_line = shell.find_magic(target, 'line')
147 147 m_cell = shell.find_magic(target, 'cell')
148 148 if args.line and m_line is None:
149 149 raise UsageError('Line magic function `%s%s` not found.' %
150 150 (magic_escapes['line'], target))
151 151 if args.cell and m_cell is None:
152 152 raise UsageError('Cell magic function `%s%s` not found.' %
153 153 (magic_escapes['cell'], target))
154 154
155 155 # If --line and --cell are not specified, default to the ones
156 156 # that are available.
157 157 if not args.line and not args.cell:
158 158 if not m_line and not m_cell:
159 159 raise UsageError(
160 160 'No line or cell magic with name `%s` found.' % target
161 161 )
162 162 args.line = bool(m_line)
163 163 args.cell = bool(m_cell)
164 164
165 165 if args.line:
166 166 mman.register_alias(name, target, 'line')
167 167 print('Created `%s%s` as an alias for `%s%s`.' % (
168 168 magic_escapes['line'], name,
169 169 magic_escapes['line'], target))
170 170
171 171 if args.cell:
172 172 mman.register_alias(name, target, 'cell')
173 173 print('Created `%s%s` as an alias for `%s%s`.' % (
174 174 magic_escapes['cell'], name,
175 175 magic_escapes['cell'], target))
176 176
177 177 @line_magic
178 178 def lsmagic(self, parameter_s=''):
179 179 """List currently available magic functions."""
180 180 return MagicsDisplay(self.shell.magics_manager)
181 181
182 182 def _magic_docs(self, brief=False, rest=False):
183 183 """Return docstrings from magic functions."""
184 184 mman = self.shell.magics_manager
185 185 docs = mman.lsmagic_docs(brief, missing='No documentation')
186 186
187 187 if rest:
188 188 format_string = '**%s%s**::\n\n%s\n\n'
189 189 else:
190 190 format_string = '%s%s:\n%s\n'
191 191
192 192 return ''.join(
193 193 [format_string % (magic_escapes['line'], fname,
194 194 indent(dedent(fndoc)))
195 195 for fname, fndoc in sorted(docs['line'].items())]
196 196 +
197 197 [format_string % (magic_escapes['cell'], fname,
198 198 indent(dedent(fndoc)))
199 199 for fname, fndoc in sorted(docs['cell'].items())]
200 200 )
201 201
202 202 @line_magic
203 203 def magic(self, parameter_s=''):
204 204 """Print information about the magic function system.
205 205
206 206 Supported formats: -latex, -brief, -rest
207 207 """
208 208
209 209 mode = ''
210 210 try:
211 211 mode = parameter_s.split()[0][1:]
212 212 if mode == 'rest':
213 213 rest_docs = []
214 214 except IndexError:
215 215 pass
216 216
217 217 brief = (mode == 'brief')
218 218 rest = (mode == 'rest')
219 219 magic_docs = self._magic_docs(brief, rest)
220 220
221 221 if mode == 'latex':
222 222 print(self.format_latex(magic_docs))
223 223 return
224 224 else:
225 225 magic_docs = format_screen(magic_docs)
226 226
227 227 out = ["""
228 228 IPython's 'magic' functions
229 229 ===========================
230 230
231 231 The magic function system provides a series of functions which allow you to
232 232 control the behavior of IPython itself, plus a lot of system-type
233 233 features. There are two kinds of magics, line-oriented and cell-oriented.
234 234
235 235 Line magics are prefixed with the % character and work much like OS
236 236 command-line calls: they get as an argument the rest of the line, where
237 237 arguments are passed without parentheses or quotes. For example, this will
238 238 time the given statement::
239 239
240 240 %timeit range(1000)
241 241
242 242 Cell magics are prefixed with a double %%, and they are functions that get as
243 243 an argument not only the rest of the line, but also the lines below it in a
244 244 separate argument. These magics are called with two arguments: the rest of the
245 245 call line and the body of the cell, consisting of the lines below the first.
246 246 For example::
247 247
248 248 %%timeit x = numpy.random.randn((100, 100))
249 249 numpy.linalg.svd(x)
250 250
251 251 will time the execution of the numpy svd routine, running the assignment of x
252 252 as part of the setup phase, which is not timed.
253 253
254 254 In a line-oriented client (the terminal or Qt console IPython), starting a new
255 255 input with %% will automatically enter cell mode, and IPython will continue
256 256 reading input until a blank line is given. In the notebook, simply type the
257 257 whole cell as one entity, but keep in mind that the %% escape can only be at
258 258 the very start of the cell.
259 259
260 260 NOTE: If you have 'automagic' enabled (via the command line option or with the
261 261 %automagic function), you don't need to type in the % explicitly for line
262 262 magics; cell magics always require an explicit '%%' escape. By default,
263 263 IPython ships with automagic on, so you should only rarely need the % escape.
264 264
265 265 Example: typing '%cd mydir' (without the quotes) changes you working directory
266 266 to 'mydir', if it exists.
267 267
268 268 For a list of the available magic functions, use %lsmagic. For a description
269 269 of any of them, type %magic_name?, e.g. '%cd?'.
270 270
271 271 Currently the magic system has the following functions:""",
272 272 magic_docs,
273 273 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
274 274 str(self.lsmagic()),
275 275 ]
276 276 page.page('\n'.join(out))
277 277
278 278
279 279 @line_magic
280 280 def page(self, parameter_s=''):
281 281 """Pretty print the object and display it through a pager.
282 282
283 283 %page [options] OBJECT
284 284
285 285 If no object is given, use _ (last output).
286 286
287 287 Options:
288 288
289 289 -r: page str(object), don't pretty-print it."""
290 290
291 291 # After a function contributed by Olivier Aubert, slightly modified.
292 292
293 293 # Process options/args
294 294 opts, args = self.parse_options(parameter_s, 'r')
295 295 raw = 'r' in opts
296 296
297 297 oname = args and args or '_'
298 298 info = self.shell._ofind(oname)
299 299 if info['found']:
300 300 txt = (raw and str or pformat)( info['obj'] )
301 301 page.page(txt)
302 302 else:
303 303 print('Object `%s` not found' % oname)
304 304
305 305 @line_magic
306 306 def profile(self, parameter_s=''):
307 307 """Print your currently active IPython profile."""
308 308 from IPython.core.application import BaseIPythonApplication
309 309 if BaseIPythonApplication.initialized():
310 310 print(BaseIPythonApplication.instance().profile)
311 311 else:
312 312 error("profile is an application-level value, but you don't appear to be in an IPython application")
313 313
314 314 @line_magic
315 315 def pprint(self, parameter_s=''):
316 316 """Toggle pretty printing on/off."""
317 317 ptformatter = self.shell.display_formatter.formatters['text/plain']
318 318 ptformatter.pprint = bool(1 - ptformatter.pprint)
319 319 print('Pretty printing has been turned',
320 320 ['OFF','ON'][ptformatter.pprint])
321 321
322 322 @line_magic
323 323 def colors(self, parameter_s=''):
324 324 """Switch color scheme for prompts, info system and exception handlers.
325 325
326 326 Currently implemented schemes: NoColor, Linux, LightBG.
327 327
328 328 Color scheme names are not case-sensitive.
329 329
330 330 Examples
331 331 --------
332 332 To get a plain black and white terminal::
333 333
334 334 %colors nocolor
335 335 """
336 336 def color_switch_err(name):
337 337 warn('Error changing %s color schemes.\n%s' %
338 338 (name, sys.exc_info()[1]))
339 339
340 340
341 341 new_scheme = parameter_s.strip()
342 342 if not new_scheme:
343 343 raise UsageError(
344 344 "%colors: you must specify a color scheme. See '%colors?'")
345 345 # local shortcut
346 346 shell = self.shell
347 347
348 348 import IPython.utils.rlineimpl as readline
349 349
350 350 if not shell.colors_force and \
351 351 not readline.have_readline and \
352 352 (sys.platform == "win32" or sys.platform == "cli"):
353 353 msg = """\
354 354 Proper color support under MS Windows requires the pyreadline library.
355 355 You can find it at:
356 356 http://ipython.org/pyreadline.html
357 357 Gary's readline needs the ctypes module, from:
358 358 http://starship.python.net/crew/theller/ctypes
359 359 (Note that ctypes is already part of Python versions 2.5 and newer).
360 360
361 361 Defaulting color scheme to 'NoColor'"""
362 362 new_scheme = 'NoColor'
363 363 warn(msg)
364 364
365 365 # readline option is 0
366 366 if not shell.colors_force and not shell.has_readline:
367 367 new_scheme = 'NoColor'
368 368
369 369 # Set prompt colors
370 370 try:
371 371 shell.prompt_manager.color_scheme = new_scheme
372 372 except:
373 373 color_switch_err('prompt')
374 374 else:
375 375 shell.colors = \
376 376 shell.prompt_manager.color_scheme_table.active_scheme_name
377 377 # Set exception colors
378 378 try:
379 379 shell.InteractiveTB.set_colors(scheme = new_scheme)
380 380 shell.SyntaxTB.set_colors(scheme = new_scheme)
381 381 except:
382 382 color_switch_err('exception')
383 383
384 384 # Set info (for 'object?') colors
385 385 if shell.color_info:
386 386 try:
387 387 shell.inspector.set_active_scheme(new_scheme)
388 388 except:
389 389 color_switch_err('object inspector')
390 390 else:
391 391 shell.inspector.set_active_scheme('NoColor')
392 392
393 393 @line_magic
394 394 def xmode(self, parameter_s=''):
395 395 """Switch modes for the exception handlers.
396 396
397 397 Valid modes: Plain, Context and Verbose.
398 398
399 399 If called without arguments, acts as a toggle."""
400 400
401 401 def xmode_switch_err(name):
402 402 warn('Error changing %s exception modes.\n%s' %
403 403 (name,sys.exc_info()[1]))
404 404
405 405 shell = self.shell
406 406 new_mode = parameter_s.strip().capitalize()
407 407 try:
408 408 shell.InteractiveTB.set_mode(mode=new_mode)
409 409 print('Exception reporting mode:',shell.InteractiveTB.mode)
410 410 except:
411 411 xmode_switch_err('user')
412 412
413 413 @line_magic
414 414 def quickref(self,arg):
415 415 """ Show a quick reference sheet """
416 416 from IPython.core.usage import quick_reference
417 417 qr = quick_reference + self._magic_docs(brief=True)
418 418 page.page(qr)
419 419
420 420 @line_magic
421 421 def doctest_mode(self, parameter_s=''):
422 422 """Toggle doctest mode on and off.
423 423
424 424 This mode is intended to make IPython behave as much as possible like a
425 425 plain Python shell, from the perspective of how its prompts, exceptions
426 426 and output look. This makes it easy to copy and paste parts of a
427 427 session into doctests. It does so by:
428 428
429 429 - Changing the prompts to the classic ``>>>`` ones.
430 430 - Changing the exception reporting mode to 'Plain'.
431 431 - Disabling pretty-printing of output.
432 432
433 433 Note that IPython also supports the pasting of code snippets that have
434 434 leading '>>>' and '...' prompts in them. This means that you can paste
435 435 doctests from files or docstrings (even if they have leading
436 436 whitespace), and the code will execute correctly. You can then use
437 437 '%history -t' to see the translated history; this will give you the
438 438 input after removal of all the leading prompts and whitespace, which
439 439 can be pasted back into an editor.
440 440
441 441 With these features, you can switch into this mode easily whenever you
442 442 need to do testing and changes to doctests, without having to leave
443 443 your existing IPython session.
444 444 """
445 445
446 446 # Shorthands
447 447 shell = self.shell
448 448 pm = shell.prompt_manager
449 449 meta = shell.meta
450 450 disp_formatter = self.shell.display_formatter
451 451 ptformatter = disp_formatter.formatters['text/plain']
452 452 # dstore is a data store kept in the instance metadata bag to track any
453 453 # changes we make, so we can undo them later.
454 454 dstore = meta.setdefault('doctest_mode',Struct())
455 455 save_dstore = dstore.setdefault
456 456
457 457 # save a few values we'll need to recover later
458 458 mode = save_dstore('mode',False)
459 459 save_dstore('rc_pprint',ptformatter.pprint)
460 460 save_dstore('xmode',shell.InteractiveTB.mode)
461 461 save_dstore('rc_separate_out',shell.separate_out)
462 462 save_dstore('rc_separate_out2',shell.separate_out2)
463 463 save_dstore('rc_prompts_pad_left',pm.justify)
464 464 save_dstore('rc_separate_in',shell.separate_in)
465 465 save_dstore('rc_active_types',disp_formatter.active_types)
466 466 save_dstore('prompt_templates',(pm.in_template, pm.in2_template, pm.out_template))
467 467
468 468 if mode == False:
469 469 # turn on
470 470 pm.in_template = '>>> '
471 471 pm.in2_template = '... '
472 472 pm.out_template = ''
473 473
474 474 # Prompt separators like plain python
475 475 shell.separate_in = ''
476 476 shell.separate_out = ''
477 477 shell.separate_out2 = ''
478 478
479 479 pm.justify = False
480 480
481 481 ptformatter.pprint = False
482 482 disp_formatter.active_types = ['text/plain']
483 483
484 484 shell.magic('xmode Plain')
485 485 else:
486 486 # turn off
487 487 pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates
488 488
489 489 shell.separate_in = dstore.rc_separate_in
490 490
491 491 shell.separate_out = dstore.rc_separate_out
492 492 shell.separate_out2 = dstore.rc_separate_out2
493 493
494 494 pm.justify = dstore.rc_prompts_pad_left
495 495
496 496 ptformatter.pprint = dstore.rc_pprint
497 497 disp_formatter.active_types = dstore.rc_active_types
498 498
499 499 shell.magic('xmode ' + dstore.xmode)
500 500
501 501 # Store new mode and inform
502 502 dstore.mode = bool(1-int(mode))
503 503 mode_label = ['OFF','ON'][dstore.mode]
504 504 print('Doctest mode is:', mode_label)
505 505
506 506 @line_magic
507 507 def gui(self, parameter_s=''):
508 508 """Enable or disable IPython GUI event loop integration.
509 509
510 510 %gui [GUINAME]
511 511
512 512 This magic replaces IPython's threaded shells that were activated
513 513 using the (pylab/wthread/etc.) command line flags. GUI toolkits
514 514 can now be enabled at runtime and keyboard
515 515 interrupts should work without any problems. The following toolkits
516 516 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
517 517
518 518 %gui wx # enable wxPython event loop integration
519 519 %gui qt4|qt # enable PyQt4 event loop integration
520 520 %gui gtk # enable PyGTK event loop integration
521 521 %gui gtk3 # enable Gtk3 event loop integration
522 522 %gui tk # enable Tk event loop integration
523 523 %gui osx # enable Cocoa event loop integration
524 524 # (requires %matplotlib 1.1)
525 525 %gui # disable all event loop integration
526 526
527 527 WARNING: after any of these has been called you can simply create
528 528 an application object, but DO NOT start the event loop yourself, as
529 529 we have already handled that.
530 530 """
531 531 opts, arg = self.parse_options(parameter_s, '')
532 532 if arg=='': arg = None
533 533 try:
534 534 return self.shell.enable_gui(arg)
535 535 except Exception as e:
536 536 # print simple error message, rather than traceback if we can't
537 537 # hook up the GUI
538 538 error(str(e))
539 539
540 540 @skip_doctest
541 541 @line_magic
542 542 def precision(self, s=''):
543 543 """Set floating point precision for pretty printing.
544 544
545 545 Can set either integer precision or a format string.
546 546
547 547 If numpy has been imported and precision is an int,
548 548 numpy display precision will also be set, via ``numpy.set_printoptions``.
549 549
550 550 If no argument is given, defaults will be restored.
551 551
552 552 Examples
553 553 --------
554 554 ::
555 555
556 556 In [1]: from math import pi
557 557
558 558 In [2]: %precision 3
559 559 Out[2]: u'%.3f'
560 560
561 561 In [3]: pi
562 562 Out[3]: 3.142
563 563
564 564 In [4]: %precision %i
565 565 Out[4]: u'%i'
566 566
567 567 In [5]: pi
568 568 Out[5]: 3
569 569
570 570 In [6]: %precision %e
571 571 Out[6]: u'%e'
572 572
573 573 In [7]: pi**10
574 574 Out[7]: 9.364805e+04
575 575
576 576 In [8]: %precision
577 577 Out[8]: u'%r'
578 578
579 579 In [9]: pi**10
580 580 Out[9]: 93648.047476082982
581 581 """
582 582 ptformatter = self.shell.display_formatter.formatters['text/plain']
583 583 ptformatter.float_precision = s
584 584 return ptformatter.float_format
585 585
586 586 @magic_arguments.magic_arguments()
587 587 @magic_arguments.argument(
588 588 '-e', '--export', action='store_true', default=False,
589 589 help='Export IPython history as a notebook. The filename argument '
590 590 'is used to specify the notebook name and format. For example '
591 591 'a filename of notebook.ipynb will result in a notebook name '
592 592 'of "notebook" and a format of "json". Likewise using a ".py" '
593 593 'file extension will write the notebook as a Python script'
594 594 )
595 595 @magic_arguments.argument(
596 596 '-f', '--format',
597 597 help='Convert an existing IPython notebook to a new format. This option '
598 598 'specifies the new format and can have the values: json, py. '
599 599 'The target filename is chosen automatically based on the new '
600 600 'format. The filename argument gives the name of the source file.'
601 601 )
602 602 @magic_arguments.argument(
603 603 'filename', type=unicode_type,
604 604 help='Notebook name or filename'
605 605 )
606 606 @line_magic
607 607 def notebook(self, s):
608 608 """Export and convert IPython notebooks.
609 609
610 610 This function can export the current IPython history to a notebook file
611 611 or can convert an existing notebook file into a different format. For
612 612 example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb".
613 613 To export the history to "foo.py" do "%notebook -e foo.py". To convert
614 614 "foo.ipynb" to "foo.json" do "%notebook -f json foo.ipynb". Possible
615 615 formats include (json/ipynb, py).
616 616 """
617 617 args = magic_arguments.parse_argstring(self.notebook, s)
618 618
619 619 from IPython.nbformat import current
620 620 args.filename = unquote_filename(args.filename)
621 621 if args.export:
622 622 fname, name, format = current.parse_filename(args.filename)
623 623 cells = []
624 624 hist = list(self.shell.history_manager.get_range())
625 625 for session, prompt_number, input in hist[:-1]:
626 626 cells.append(current.new_code_cell(prompt_number=prompt_number,
627 627 input=input))
628 628 worksheet = current.new_worksheet(cells=cells)
629 629 nb = current.new_notebook(name=name,worksheets=[worksheet])
630 630 with io.open(fname, 'w', encoding='utf-8') as f:
631 631 current.write(nb, f, format);
632 632 elif args.format is not None:
633 633 old_fname, old_name, old_format = current.parse_filename(args.filename)
634 634 new_format = args.format
635 635 if new_format == u'xml':
636 636 raise ValueError('Notebooks cannot be written as xml.')
637 637 elif new_format == u'ipynb' or new_format == u'json':
638 638 new_fname = old_name + u'.ipynb'
639 639 new_format = u'json'
640 640 elif new_format == u'py':
641 641 new_fname = old_name + u'.py'
642 642 else:
643 643 raise ValueError('Invalid notebook format: %s' % new_format)
644 644 with io.open(old_fname, 'r', encoding='utf-8') as f:
645 645 nb = current.read(f, old_format)
646 646 with io.open(new_fname, 'w', encoding='utf-8') as f:
647 647 current.write(nb, f, new_format)
@@ -1,873 +1,873 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tools for inspecting Python objects.
3 3
4 4 Uses syntax highlighting for presenting the various information elements.
5 5
6 6 Similar in spirit to the inspect module, but all calls take a name argument to
7 7 reference the name under which an object is being read.
8 8 """
9 9
10 10 #*****************************************************************************
11 11 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
12 12 #
13 13 # Distributed under the terms of the BSD License. The full license is in
14 14 # the file COPYING, distributed as part of this software.
15 15 #*****************************************************************************
16 16 from __future__ import print_function
17 17
18 18 __all__ = ['Inspector','InspectColors']
19 19
20 20 # stdlib modules
21 21 import inspect
22 22 import linecache
23 23 import os
24 24 import types
25 25 import io as stdlib_io
26 26
27 27 try:
28 28 from itertools import izip_longest
29 29 except ImportError:
30 30 from itertools import zip_longest as izip_longest
31 31
32 32 # IPython's own
33 33 from IPython.core import page
34 34 from IPython.testing.skipdoctest import skip_doctest_py3
35 35 from IPython.utils import PyColorize
36 36 from IPython.utils import io
37 37 from IPython.utils import openpy
38 38 from IPython.utils import py3compat
39 39 from IPython.utils.dir2 import safe_hasattr
40 40 from IPython.utils.text import indent
41 41 from IPython.utils.wildcard import list_namespace
42 42 from IPython.utils.coloransi import *
43 43 from IPython.utils.py3compat import cast_unicode, string_types
44 44
45 45 #****************************************************************************
46 46 # Builtin color schemes
47 47
48 48 Colors = TermColors # just a shorthand
49 49
50 50 # Build a few color schemes
51 51 NoColor = ColorScheme(
52 52 'NoColor',{
53 53 'header' : Colors.NoColor,
54 54 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
55 55 } )
56 56
57 57 LinuxColors = ColorScheme(
58 58 'Linux',{
59 59 'header' : Colors.LightRed,
60 60 'normal' : Colors.Normal # color off (usu. Colors.Normal)
61 61 } )
62 62
63 63 LightBGColors = ColorScheme(
64 64 'LightBG',{
65 65 'header' : Colors.Red,
66 66 'normal' : Colors.Normal # color off (usu. Colors.Normal)
67 67 } )
68 68
69 69 # Build table of color schemes (needed by the parser)
70 70 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
71 71 'Linux')
72 72
73 73 #****************************************************************************
74 74 # Auxiliary functions and objects
75 75
76 76 # See the messaging spec for the definition of all these fields. This list
77 77 # effectively defines the order of display
78 78 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
79 79 'length', 'file', 'definition', 'docstring', 'source',
80 80 'init_definition', 'class_docstring', 'init_docstring',
81 81 'call_def', 'call_docstring',
82 82 # These won't be printed but will be used to determine how to
83 83 # format the object
84 84 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
85 85 ]
86 86
87 87
88 88 def object_info(**kw):
89 89 """Make an object info dict with all fields present."""
90 90 infodict = dict(izip_longest(info_fields, [None]))
91 91 infodict.update(kw)
92 92 return infodict
93 93
94 94
95 95 def get_encoding(obj):
96 96 """Get encoding for python source file defining obj
97 97
98 98 Returns None if obj is not defined in a sourcefile.
99 99 """
100 100 ofile = find_file(obj)
101 101 # run contents of file through pager starting at line where the object
102 102 # is defined, as long as the file isn't binary and is actually on the
103 103 # filesystem.
104 104 if ofile is None:
105 105 return None
106 106 elif ofile.endswith(('.so', '.dll', '.pyd')):
107 107 return None
108 108 elif not os.path.isfile(ofile):
109 109 return None
110 110 else:
111 111 # Print only text files, not extension binaries. Note that
112 112 # getsourcelines returns lineno with 1-offset and page() uses
113 113 # 0-offset, so we must adjust.
114 114 buffer = stdlib_io.open(ofile, 'rb') # Tweaked to use io.open for Python 2
115 115 encoding, lines = openpy.detect_encoding(buffer.readline)
116 116 return encoding
117 117
118 118 def getdoc(obj):
119 119 """Stable wrapper around inspect.getdoc.
120 120
121 121 This can't crash because of attribute problems.
122 122
123 123 It also attempts to call a getdoc() method on the given object. This
124 124 allows objects which provide their docstrings via non-standard mechanisms
125 125 (like Pyro proxies) to still be inspected by ipython's ? system."""
126 126 # Allow objects to offer customized documentation via a getdoc method:
127 127 try:
128 128 ds = obj.getdoc()
129 129 except Exception:
130 130 pass
131 131 else:
132 132 # if we get extra info, we add it to the normal docstring.
133 133 if isinstance(ds, string_types):
134 134 return inspect.cleandoc(ds)
135 135
136 136 try:
137 137 docstr = inspect.getdoc(obj)
138 138 encoding = get_encoding(obj)
139 139 return py3compat.cast_unicode(docstr, encoding=encoding)
140 140 except Exception:
141 141 # Harden against an inspect failure, which can occur with
142 142 # SWIG-wrapped extensions.
143 143 raise
144 144 return None
145 145
146 146
147 147 def getsource(obj,is_binary=False):
148 148 """Wrapper around inspect.getsource.
149 149
150 150 This can be modified by other projects to provide customized source
151 151 extraction.
152 152
153 153 Inputs:
154 154
155 155 - obj: an object whose source code we will attempt to extract.
156 156
157 157 Optional inputs:
158 158
159 159 - is_binary: whether the object is known to come from a binary source.
160 160 This implementation will skip returning any output for binary objects, but
161 161 custom extractors may know how to meaningfully process them."""
162 162
163 163 if is_binary:
164 164 return None
165 165 else:
166 166 # get source if obj was decorated with @decorator
167 167 if hasattr(obj,"__wrapped__"):
168 168 obj = obj.__wrapped__
169 169 try:
170 170 src = inspect.getsource(obj)
171 171 except TypeError:
172 172 if hasattr(obj,'__class__'):
173 173 src = inspect.getsource(obj.__class__)
174 174 encoding = get_encoding(obj)
175 175 return cast_unicode(src, encoding=encoding)
176 176
177 177 def getargspec(obj):
178 178 """Get the names and default values of a function's arguments.
179 179
180 180 A tuple of four things is returned: (args, varargs, varkw, defaults).
181 181 'args' is a list of the argument names (it may contain nested lists).
182 182 'varargs' and 'varkw' are the names of the * and ** arguments or None.
183 183 'defaults' is an n-tuple of the default values of the last n arguments.
184 184
185 185 Modified version of inspect.getargspec from the Python Standard
186 186 Library."""
187 187
188 188 if inspect.isfunction(obj):
189 189 func_obj = obj
190 190 elif inspect.ismethod(obj):
191 func_obj = obj.im_func
191 func_obj = obj.__func__
192 192 elif hasattr(obj, '__call__'):
193 193 func_obj = obj.__call__
194 194 else:
195 195 raise TypeError('arg is not a Python function')
196 196 args, varargs, varkw = inspect.getargs(func_obj.__code__)
197 197 return args, varargs, varkw, func_obj.__defaults__
198 198
199 199
200 200 def format_argspec(argspec):
201 201 """Format argspect, convenience wrapper around inspect's.
202 202
203 203 This takes a dict instead of ordered arguments and calls
204 204 inspect.format_argspec with the arguments in the necessary order.
205 205 """
206 206 return inspect.formatargspec(argspec['args'], argspec['varargs'],
207 207 argspec['varkw'], argspec['defaults'])
208 208
209 209
210 210 def call_tip(oinfo, format_call=True):
211 211 """Extract call tip data from an oinfo dict.
212 212
213 213 Parameters
214 214 ----------
215 215 oinfo : dict
216 216
217 217 format_call : bool, optional
218 218 If True, the call line is formatted and returned as a string. If not, a
219 219 tuple of (name, argspec) is returned.
220 220
221 221 Returns
222 222 -------
223 223 call_info : None, str or (str, dict) tuple.
224 224 When format_call is True, the whole call information is formattted as a
225 225 single string. Otherwise, the object's name and its argspec dict are
226 226 returned. If no call information is available, None is returned.
227 227
228 228 docstring : str or None
229 229 The most relevant docstring for calling purposes is returned, if
230 230 available. The priority is: call docstring for callable instances, then
231 231 constructor docstring for classes, then main object's docstring otherwise
232 232 (regular functions).
233 233 """
234 234 # Get call definition
235 235 argspec = oinfo.get('argspec')
236 236 if argspec is None:
237 237 call_line = None
238 238 else:
239 239 # Callable objects will have 'self' as their first argument, prune
240 240 # it out if it's there for clarity (since users do *not* pass an
241 241 # extra first argument explicitly).
242 242 try:
243 243 has_self = argspec['args'][0] == 'self'
244 244 except (KeyError, IndexError):
245 245 pass
246 246 else:
247 247 if has_self:
248 248 argspec['args'] = argspec['args'][1:]
249 249
250 250 call_line = oinfo['name']+format_argspec(argspec)
251 251
252 252 # Now get docstring.
253 253 # The priority is: call docstring, constructor docstring, main one.
254 254 doc = oinfo.get('call_docstring')
255 255 if doc is None:
256 256 doc = oinfo.get('init_docstring')
257 257 if doc is None:
258 258 doc = oinfo.get('docstring','')
259 259
260 260 return call_line, doc
261 261
262 262
263 263 def find_file(obj):
264 264 """Find the absolute path to the file where an object was defined.
265 265
266 266 This is essentially a robust wrapper around `inspect.getabsfile`.
267 267
268 268 Returns None if no file can be found.
269 269
270 270 Parameters
271 271 ----------
272 272 obj : any Python object
273 273
274 274 Returns
275 275 -------
276 276 fname : str
277 277 The absolute path to the file where the object was defined.
278 278 """
279 279 # get source if obj was decorated with @decorator
280 280 if safe_hasattr(obj, '__wrapped__'):
281 281 obj = obj.__wrapped__
282 282
283 283 fname = None
284 284 try:
285 285 fname = inspect.getabsfile(obj)
286 286 except TypeError:
287 287 # For an instance, the file that matters is where its class was
288 288 # declared.
289 289 if hasattr(obj, '__class__'):
290 290 try:
291 291 fname = inspect.getabsfile(obj.__class__)
292 292 except TypeError:
293 293 # Can happen for builtins
294 294 pass
295 295 except:
296 296 pass
297 297 return cast_unicode(fname)
298 298
299 299
300 300 def find_source_lines(obj):
301 301 """Find the line number in a file where an object was defined.
302 302
303 303 This is essentially a robust wrapper around `inspect.getsourcelines`.
304 304
305 305 Returns None if no file can be found.
306 306
307 307 Parameters
308 308 ----------
309 309 obj : any Python object
310 310
311 311 Returns
312 312 -------
313 313 lineno : int
314 314 The line number where the object definition starts.
315 315 """
316 316 # get source if obj was decorated with @decorator
317 317 if safe_hasattr(obj, '__wrapped__'):
318 318 obj = obj.__wrapped__
319 319
320 320 try:
321 321 try:
322 322 lineno = inspect.getsourcelines(obj)[1]
323 323 except TypeError:
324 324 # For instances, try the class object like getsource() does
325 325 if hasattr(obj, '__class__'):
326 326 lineno = inspect.getsourcelines(obj.__class__)[1]
327 327 else:
328 328 lineno = None
329 329 except:
330 330 return None
331 331
332 332 return lineno
333 333
334 334
335 335 class Inspector:
336 336 def __init__(self, color_table=InspectColors,
337 337 code_color_table=PyColorize.ANSICodeColors,
338 338 scheme='NoColor',
339 339 str_detail_level=0):
340 340 self.color_table = color_table
341 341 self.parser = PyColorize.Parser(code_color_table,out='str')
342 342 self.format = self.parser.format
343 343 self.str_detail_level = str_detail_level
344 344 self.set_active_scheme(scheme)
345 345
346 346 def _getdef(self,obj,oname=''):
347 347 """Return the call signature for any callable object.
348 348
349 349 If any exception is generated, None is returned instead and the
350 350 exception is suppressed."""
351 351
352 352 try:
353 353 hdef = oname + inspect.formatargspec(*getargspec(obj))
354 354 return cast_unicode(hdef)
355 355 except:
356 356 return None
357 357
358 358 def __head(self,h):
359 359 """Return a header string with proper colors."""
360 360 return '%s%s%s' % (self.color_table.active_colors.header,h,
361 361 self.color_table.active_colors.normal)
362 362
363 363 def set_active_scheme(self, scheme):
364 364 self.color_table.set_active_scheme(scheme)
365 365 self.parser.color_table.set_active_scheme(scheme)
366 366
367 367 def noinfo(self, msg, oname):
368 368 """Generic message when no information is found."""
369 369 print('No %s found' % msg, end=' ')
370 370 if oname:
371 371 print('for %s' % oname)
372 372 else:
373 373 print()
374 374
375 375 def pdef(self, obj, oname=''):
376 376 """Print the call signature for any callable object.
377 377
378 378 If the object is a class, print the constructor information."""
379 379
380 380 if not callable(obj):
381 381 print('Object is not callable.')
382 382 return
383 383
384 384 header = ''
385 385
386 386 if inspect.isclass(obj):
387 387 header = self.__head('Class constructor information:\n')
388 388 obj = obj.__init__
389 389 elif (not py3compat.PY3) and type(obj) is types.InstanceType:
390 390 obj = obj.__call__
391 391
392 392 output = self._getdef(obj,oname)
393 393 if output is None:
394 394 self.noinfo('definition header',oname)
395 395 else:
396 396 print(header,self.format(output), end=' ', file=io.stdout)
397 397
398 398 # In Python 3, all classes are new-style, so they all have __init__.
399 399 @skip_doctest_py3
400 400 def pdoc(self,obj,oname='',formatter = None):
401 401 """Print the docstring for any object.
402 402
403 403 Optional:
404 404 -formatter: a function to run the docstring through for specially
405 405 formatted docstrings.
406 406
407 407 Examples
408 408 --------
409 409
410 410 In [1]: class NoInit:
411 411 ...: pass
412 412
413 413 In [2]: class NoDoc:
414 414 ...: def __init__(self):
415 415 ...: pass
416 416
417 417 In [3]: %pdoc NoDoc
418 418 No documentation found for NoDoc
419 419
420 420 In [4]: %pdoc NoInit
421 421 No documentation found for NoInit
422 422
423 423 In [5]: obj = NoInit()
424 424
425 425 In [6]: %pdoc obj
426 426 No documentation found for obj
427 427
428 428 In [5]: obj2 = NoDoc()
429 429
430 430 In [6]: %pdoc obj2
431 431 No documentation found for obj2
432 432 """
433 433
434 434 head = self.__head # For convenience
435 435 lines = []
436 436 ds = getdoc(obj)
437 437 if formatter:
438 438 ds = formatter(ds)
439 439 if ds:
440 440 lines.append(head("Class Docstring:"))
441 441 lines.append(indent(ds))
442 442 if inspect.isclass(obj) and hasattr(obj, '__init__'):
443 443 init_ds = getdoc(obj.__init__)
444 444 if init_ds is not None:
445 445 lines.append(head("Constructor Docstring:"))
446 446 lines.append(indent(init_ds))
447 447 elif hasattr(obj,'__call__'):
448 448 call_ds = getdoc(obj.__call__)
449 449 if call_ds:
450 450 lines.append(head("Calling Docstring:"))
451 451 lines.append(indent(call_ds))
452 452
453 453 if not lines:
454 454 self.noinfo('documentation',oname)
455 455 else:
456 456 page.page('\n'.join(lines))
457 457
458 458 def psource(self,obj,oname=''):
459 459 """Print the source code for an object."""
460 460
461 461 # Flush the source cache because inspect can return out-of-date source
462 462 linecache.checkcache()
463 463 try:
464 464 src = getsource(obj)
465 465 except:
466 466 self.noinfo('source',oname)
467 467 else:
468 468 page.page(self.format(src))
469 469
470 470 def pfile(self, obj, oname=''):
471 471 """Show the whole file where an object was defined."""
472 472
473 473 lineno = find_source_lines(obj)
474 474 if lineno is None:
475 475 self.noinfo('file', oname)
476 476 return
477 477
478 478 ofile = find_file(obj)
479 479 # run contents of file through pager starting at line where the object
480 480 # is defined, as long as the file isn't binary and is actually on the
481 481 # filesystem.
482 482 if ofile.endswith(('.so', '.dll', '.pyd')):
483 483 print('File %r is binary, not printing.' % ofile)
484 484 elif not os.path.isfile(ofile):
485 485 print('File %r does not exist, not printing.' % ofile)
486 486 else:
487 487 # Print only text files, not extension binaries. Note that
488 488 # getsourcelines returns lineno with 1-offset and page() uses
489 489 # 0-offset, so we must adjust.
490 490 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
491 491
492 492 def _format_fields(self, fields, title_width=12):
493 493 """Formats a list of fields for display.
494 494
495 495 Parameters
496 496 ----------
497 497 fields : list
498 498 A list of 2-tuples: (field_title, field_content)
499 499 title_width : int
500 500 How many characters to pad titles to. Default 12.
501 501 """
502 502 out = []
503 503 header = self.__head
504 504 for title, content in fields:
505 505 if len(content.splitlines()) > 1:
506 506 title = header(title + ":") + "\n"
507 507 else:
508 508 title = header((title+":").ljust(title_width))
509 509 out.append(cast_unicode(title) + cast_unicode(content))
510 510 return "\n".join(out)
511 511
512 512 # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict)
513 513 pinfo_fields1 = [("Type", "type_name"),
514 514 ]
515 515
516 516 pinfo_fields2 = [("String Form", "string_form"),
517 517 ]
518 518
519 519 pinfo_fields3 = [("Length", "length"),
520 520 ("File", "file"),
521 521 ("Definition", "definition"),
522 522 ]
523 523
524 524 pinfo_fields_obj = [("Class Docstring", "class_docstring"),
525 525 ("Constructor Docstring","init_docstring"),
526 526 ("Call def", "call_def"),
527 527 ("Call docstring", "call_docstring")]
528 528
529 529 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
530 530 """Show detailed information about an object.
531 531
532 532 Optional arguments:
533 533
534 534 - oname: name of the variable pointing to the object.
535 535
536 536 - formatter: special formatter for docstrings (see pdoc)
537 537
538 538 - info: a structure with some information fields which may have been
539 539 precomputed already.
540 540
541 541 - detail_level: if set to 1, more information is given.
542 542 """
543 543 info = self.info(obj, oname=oname, formatter=formatter,
544 544 info=info, detail_level=detail_level)
545 545 displayfields = []
546 546 def add_fields(fields):
547 547 for title, key in fields:
548 548 field = info[key]
549 549 if field is not None:
550 550 displayfields.append((title, field.rstrip()))
551 551
552 552 add_fields(self.pinfo_fields1)
553 553
554 554 # Base class for old-style instances
555 555 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
556 556 displayfields.append(("Base Class", info['base_class'].rstrip()))
557 557
558 558 add_fields(self.pinfo_fields2)
559 559
560 560 # Namespace
561 561 if info['namespace'] != 'Interactive':
562 562 displayfields.append(("Namespace", info['namespace'].rstrip()))
563 563
564 564 add_fields(self.pinfo_fields3)
565 565
566 566 # Source or docstring, depending on detail level and whether
567 567 # source found.
568 568 if detail_level > 0 and info['source'] is not None:
569 569 displayfields.append(("Source",
570 570 self.format(cast_unicode(info['source']))))
571 571 elif info['docstring'] is not None:
572 572 displayfields.append(("Docstring", info["docstring"]))
573 573
574 574 # Constructor info for classes
575 575 if info['isclass']:
576 576 if info['init_definition'] or info['init_docstring']:
577 577 displayfields.append(("Constructor information", ""))
578 578 if info['init_definition'] is not None:
579 579 displayfields.append((" Definition",
580 580 info['init_definition'].rstrip()))
581 581 if info['init_docstring'] is not None:
582 582 displayfields.append((" Docstring",
583 583 indent(info['init_docstring'])))
584 584
585 585 # Info for objects:
586 586 else:
587 587 add_fields(self.pinfo_fields_obj)
588 588
589 589 # Finally send to printer/pager:
590 590 if displayfields:
591 591 page.page(self._format_fields(displayfields))
592 592
593 593 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
594 594 """Compute a dict with detailed information about an object.
595 595
596 596 Optional arguments:
597 597
598 598 - oname: name of the variable pointing to the object.
599 599
600 600 - formatter: special formatter for docstrings (see pdoc)
601 601
602 602 - info: a structure with some information fields which may have been
603 603 precomputed already.
604 604
605 605 - detail_level: if set to 1, more information is given.
606 606 """
607 607
608 608 obj_type = type(obj)
609 609
610 610 header = self.__head
611 611 if info is None:
612 612 ismagic = 0
613 613 isalias = 0
614 614 ospace = ''
615 615 else:
616 616 ismagic = info.ismagic
617 617 isalias = info.isalias
618 618 ospace = info.namespace
619 619
620 620 # Get docstring, special-casing aliases:
621 621 if isalias:
622 622 if not callable(obj):
623 623 try:
624 624 ds = "Alias to the system command:\n %s" % obj[1]
625 625 except:
626 626 ds = "Alias: " + str(obj)
627 627 else:
628 628 ds = "Alias to " + str(obj)
629 629 if obj.__doc__:
630 630 ds += "\nDocstring:\n" + obj.__doc__
631 631 else:
632 632 ds = getdoc(obj)
633 633 if ds is None:
634 634 ds = '<no docstring>'
635 635 if formatter is not None:
636 636 ds = formatter(ds)
637 637
638 638 # store output in a dict, we initialize it here and fill it as we go
639 639 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
640 640
641 641 string_max = 200 # max size of strings to show (snipped if longer)
642 642 shalf = int((string_max -5)/2)
643 643
644 644 if ismagic:
645 645 obj_type_name = 'Magic function'
646 646 elif isalias:
647 647 obj_type_name = 'System alias'
648 648 else:
649 649 obj_type_name = obj_type.__name__
650 650 out['type_name'] = obj_type_name
651 651
652 652 try:
653 653 bclass = obj.__class__
654 654 out['base_class'] = str(bclass)
655 655 except: pass
656 656
657 657 # String form, but snip if too long in ? form (full in ??)
658 658 if detail_level >= self.str_detail_level:
659 659 try:
660 660 ostr = str(obj)
661 661 str_head = 'string_form'
662 662 if not detail_level and len(ostr)>string_max:
663 663 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
664 664 ostr = ("\n" + " " * len(str_head.expandtabs())).\
665 665 join(q.strip() for q in ostr.split("\n"))
666 666 out[str_head] = ostr
667 667 except:
668 668 pass
669 669
670 670 if ospace:
671 671 out['namespace'] = ospace
672 672
673 673 # Length (for strings and lists)
674 674 try:
675 675 out['length'] = str(len(obj))
676 676 except: pass
677 677
678 678 # Filename where object was defined
679 679 binary_file = False
680 680 fname = find_file(obj)
681 681 if fname is None:
682 682 # if anything goes wrong, we don't want to show source, so it's as
683 683 # if the file was binary
684 684 binary_file = True
685 685 else:
686 686 if fname.endswith(('.so', '.dll', '.pyd')):
687 687 binary_file = True
688 688 elif fname.endswith('<string>'):
689 689 fname = 'Dynamically generated function. No source code available.'
690 690 out['file'] = fname
691 691
692 692 # reconstruct the function definition and print it:
693 693 defln = self._getdef(obj, oname)
694 694 if defln:
695 695 out['definition'] = self.format(defln)
696 696
697 697 # Docstrings only in detail 0 mode, since source contains them (we
698 698 # avoid repetitions). If source fails, we add them back, see below.
699 699 if ds and detail_level == 0:
700 700 out['docstring'] = ds
701 701
702 702 # Original source code for any callable
703 703 if detail_level:
704 704 # Flush the source cache because inspect can return out-of-date
705 705 # source
706 706 linecache.checkcache()
707 707 source = None
708 708 try:
709 709 try:
710 710 source = getsource(obj, binary_file)
711 711 except TypeError:
712 712 if hasattr(obj, '__class__'):
713 713 source = getsource(obj.__class__, binary_file)
714 714 if source is not None:
715 715 out['source'] = source.rstrip()
716 716 except Exception:
717 717 pass
718 718
719 719 if ds and source is None:
720 720 out['docstring'] = ds
721 721
722 722
723 723 # Constructor docstring for classes
724 724 if inspect.isclass(obj):
725 725 out['isclass'] = True
726 726 # reconstruct the function definition and print it:
727 727 try:
728 728 obj_init = obj.__init__
729 729 except AttributeError:
730 730 init_def = init_ds = None
731 731 else:
732 732 init_def = self._getdef(obj_init,oname)
733 733 init_ds = getdoc(obj_init)
734 734 # Skip Python's auto-generated docstrings
735 735 if init_ds and \
736 736 init_ds.startswith('x.__init__(...) initializes'):
737 737 init_ds = None
738 738
739 739 if init_def or init_ds:
740 740 if init_def:
741 741 out['init_definition'] = self.format(init_def)
742 742 if init_ds:
743 743 out['init_docstring'] = init_ds
744 744
745 745 # and class docstring for instances:
746 746 else:
747 747 # First, check whether the instance docstring is identical to the
748 748 # class one, and print it separately if they don't coincide. In
749 749 # most cases they will, but it's nice to print all the info for
750 750 # objects which use instance-customized docstrings.
751 751 if ds:
752 752 try:
753 753 cls = getattr(obj,'__class__')
754 754 except:
755 755 class_ds = None
756 756 else:
757 757 class_ds = getdoc(cls)
758 758 # Skip Python's auto-generated docstrings
759 759 if class_ds and \
760 760 (class_ds.startswith('function(code, globals[,') or \
761 761 class_ds.startswith('instancemethod(function, instance,') or \
762 762 class_ds.startswith('module(name[,') ):
763 763 class_ds = None
764 764 if class_ds and ds != class_ds:
765 765 out['class_docstring'] = class_ds
766 766
767 767 # Next, try to show constructor docstrings
768 768 try:
769 769 init_ds = getdoc(obj.__init__)
770 770 # Skip Python's auto-generated docstrings
771 771 if init_ds and \
772 772 init_ds.startswith('x.__init__(...) initializes'):
773 773 init_ds = None
774 774 except AttributeError:
775 775 init_ds = None
776 776 if init_ds:
777 777 out['init_docstring'] = init_ds
778 778
779 779 # Call form docstring for callable instances
780 780 if safe_hasattr(obj, '__call__'):
781 781 call_def = self._getdef(obj.__call__, oname)
782 782 if call_def is not None:
783 783 out['call_def'] = self.format(call_def)
784 784 call_ds = getdoc(obj.__call__)
785 785 # Skip Python's auto-generated docstrings
786 786 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
787 787 call_ds = None
788 788 if call_ds:
789 789 out['call_docstring'] = call_ds
790 790
791 791 # Compute the object's argspec as a callable. The key is to decide
792 792 # whether to pull it from the object itself, from its __init__ or
793 793 # from its __call__ method.
794 794
795 795 if inspect.isclass(obj):
796 796 # Old-style classes need not have an __init__
797 797 callable_obj = getattr(obj, "__init__", None)
798 798 elif callable(obj):
799 799 callable_obj = obj
800 800 else:
801 801 callable_obj = None
802 802
803 803 if callable_obj:
804 804 try:
805 805 args, varargs, varkw, defaults = getargspec(callable_obj)
806 806 except (TypeError, AttributeError):
807 807 # For extensions/builtins we can't retrieve the argspec
808 808 pass
809 809 else:
810 810 out['argspec'] = dict(args=args, varargs=varargs,
811 811 varkw=varkw, defaults=defaults)
812 812
813 813 return object_info(**out)
814 814
815 815
816 816 def psearch(self,pattern,ns_table,ns_search=[],
817 817 ignore_case=False,show_all=False):
818 818 """Search namespaces with wildcards for objects.
819 819
820 820 Arguments:
821 821
822 822 - pattern: string containing shell-like wildcards to use in namespace
823 823 searches and optionally a type specification to narrow the search to
824 824 objects of that type.
825 825
826 826 - ns_table: dict of name->namespaces for search.
827 827
828 828 Optional arguments:
829 829
830 830 - ns_search: list of namespace names to include in search.
831 831
832 832 - ignore_case(False): make the search case-insensitive.
833 833
834 834 - show_all(False): show all names, including those starting with
835 835 underscores.
836 836 """
837 837 #print 'ps pattern:<%r>' % pattern # dbg
838 838
839 839 # defaults
840 840 type_pattern = 'all'
841 841 filter = ''
842 842
843 843 cmds = pattern.split()
844 844 len_cmds = len(cmds)
845 845 if len_cmds == 1:
846 846 # Only filter pattern given
847 847 filter = cmds[0]
848 848 elif len_cmds == 2:
849 849 # Both filter and type specified
850 850 filter,type_pattern = cmds
851 851 else:
852 852 raise ValueError('invalid argument string for psearch: <%s>' %
853 853 pattern)
854 854
855 855 # filter search namespaces
856 856 for name in ns_search:
857 857 if name not in ns_table:
858 858 raise ValueError('invalid namespace <%s>. Valid names: %s' %
859 859 (name,ns_table.keys()))
860 860
861 861 #print 'type_pattern:',type_pattern # dbg
862 862 search_result, namespaces_seen = set(), set()
863 863 for ns_name in ns_search:
864 864 ns = ns_table[ns_name]
865 865 # Normally, locals and globals are the same, so we just check one.
866 866 if id(ns) in namespaces_seen:
867 867 continue
868 868 namespaces_seen.add(id(ns))
869 869 tmp_res = list_namespace(ns, type_pattern, filter,
870 870 ignore_case=ignore_case, show_all=show_all)
871 871 search_result.update(tmp_res)
872 872
873 873 page.page('\n'.join(sorted(search_result)))
@@ -1,944 +1,944 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for various magic functions.
3 3
4 4 Needs to be run by nose (to make ipython session available).
5 5 """
6 6 from __future__ import absolute_import
7 7
8 8 #-----------------------------------------------------------------------------
9 9 # Imports
10 10 #-----------------------------------------------------------------------------
11 11
12 12 import io
13 13 import os
14 14 import sys
15 15 from unittest import TestCase
16 16
17 17 try:
18 18 from importlib import invalidate_caches # Required from Python 3.3
19 19 except ImportError:
20 20 def invalidate_caches():
21 21 pass
22 22
23 23 import nose.tools as nt
24 24
25 25 from IPython.core import magic
26 26 from IPython.core.magic import (Magics, magics_class, line_magic,
27 27 cell_magic, line_cell_magic,
28 28 register_line_magic, register_cell_magic,
29 29 register_line_cell_magic)
30 30 from IPython.core.magics import execution, script, code
31 31 from IPython.nbformat.v3.tests.nbexamples import nb0
32 32 from IPython.nbformat import current
33 33 from IPython.testing import decorators as dec
34 34 from IPython.testing import tools as tt
35 35 from IPython.utils import py3compat
36 36 from IPython.utils.io import capture_output
37 37 from IPython.utils.tempdir import TemporaryDirectory
38 38 from IPython.utils.process import find_cmd
39 39
40 40 if py3compat.PY3:
41 41 from io import StringIO
42 42 else:
43 43 from StringIO import StringIO
44 44
45 45 #-----------------------------------------------------------------------------
46 46 # Test functions begin
47 47 #-----------------------------------------------------------------------------
48 48
49 49 @magic.magics_class
50 50 class DummyMagics(magic.Magics): pass
51 51
52 52 def test_extract_code_ranges():
53 53 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
54 54 expected = [(0, 1),
55 55 (2, 3),
56 56 (4, 6),
57 57 (6, 9),
58 58 (9, 14),
59 59 (16, None),
60 60 (None, 9),
61 61 (9, None),
62 62 (None, 13),
63 63 (None, None)]
64 64 actual = list(code.extract_code_ranges(instr))
65 65 nt.assert_equal(actual, expected)
66 66
67 67 def test_extract_symbols():
68 68 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
69 69 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
70 70 expected = [([], ['a']),
71 71 (["def b():\n return 42\n"], []),
72 72 (["class A: pass\n"], []),
73 73 (["class A: pass\n", "def b():\n return 42\n"], []),
74 74 (["class A: pass\n"], ['a']),
75 75 ([], ['z'])]
76 76 for symbols, exp in zip(symbols_args, expected):
77 77 nt.assert_equal(code.extract_symbols(source, symbols), exp)
78 78
79 79
80 80 def test_extract_symbols_raises_exception_with_non_python_code():
81 81 source = ("=begin A Ruby program :)=end\n"
82 82 "def hello\n"
83 83 "puts 'Hello world'\n"
84 84 "end")
85 85 with nt.assert_raises(SyntaxError):
86 86 code.extract_symbols(source, "hello")
87 87
88 88 def test_config():
89 89 """ test that config magic does not raise
90 90 can happen if Configurable init is moved too early into
91 91 Magics.__init__ as then a Config object will be registerd as a
92 92 magic.
93 93 """
94 94 ## should not raise.
95 95 _ip.magic('config')
96 96
97 97 def test_rehashx():
98 98 # clear up everything
99 99 _ip = get_ipython()
100 100 _ip.alias_manager.clear_aliases()
101 101 del _ip.db['syscmdlist']
102 102
103 103 _ip.magic('rehashx')
104 104 # Practically ALL ipython development systems will have more than 10 aliases
105 105
106 106 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
107 107 for name, cmd in _ip.alias_manager.aliases:
108 108 # we must strip dots from alias names
109 109 nt.assert_not_in('.', name)
110 110
111 111 # rehashx must fill up syscmdlist
112 112 scoms = _ip.db['syscmdlist']
113 113 nt.assert_true(len(scoms) > 10)
114 114
115 115
116 116 def test_magic_parse_options():
117 117 """Test that we don't mangle paths when parsing magic options."""
118 118 ip = get_ipython()
119 119 path = 'c:\\x'
120 120 m = DummyMagics(ip)
121 121 opts = m.parse_options('-f %s' % path,'f:')[0]
122 122 # argv splitting is os-dependent
123 123 if os.name == 'posix':
124 124 expected = 'c:x'
125 125 else:
126 126 expected = path
127 127 nt.assert_equal(opts['f'], expected)
128 128
129 129 def test_magic_parse_long_options():
130 130 """Magic.parse_options can handle --foo=bar long options"""
131 131 ip = get_ipython()
132 132 m = DummyMagics(ip)
133 133 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
134 134 nt.assert_in('foo', opts)
135 135 nt.assert_in('bar', opts)
136 136 nt.assert_equal(opts['bar'], "bubble")
137 137
138 138
139 139 @dec.skip_without('sqlite3')
140 140 def doctest_hist_f():
141 141 """Test %hist -f with temporary filename.
142 142
143 143 In [9]: import tempfile
144 144
145 145 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
146 146
147 147 In [11]: %hist -nl -f $tfile 3
148 148
149 149 In [13]: import os; os.unlink(tfile)
150 150 """
151 151
152 152
153 153 @dec.skip_without('sqlite3')
154 154 def doctest_hist_r():
155 155 """Test %hist -r
156 156
157 157 XXX - This test is not recording the output correctly. For some reason, in
158 158 testing mode the raw history isn't getting populated. No idea why.
159 159 Disabling the output checking for now, though at least we do run it.
160 160
161 161 In [1]: 'hist' in _ip.lsmagic()
162 162 Out[1]: True
163 163
164 164 In [2]: x=1
165 165
166 166 In [3]: %hist -rl 2
167 167 x=1 # random
168 168 %hist -r 2
169 169 """
170 170
171 171
172 172 @dec.skip_without('sqlite3')
173 173 def doctest_hist_op():
174 174 """Test %hist -op
175 175
176 176 In [1]: class b(float):
177 177 ...: pass
178 178 ...:
179 179
180 180 In [2]: class s(object):
181 181 ...: def __str__(self):
182 182 ...: return 's'
183 183 ...:
184 184
185 185 In [3]:
186 186
187 187 In [4]: class r(b):
188 188 ...: def __repr__(self):
189 189 ...: return 'r'
190 190 ...:
191 191
192 192 In [5]: class sr(s,r): pass
193 193 ...:
194 194
195 195 In [6]:
196 196
197 197 In [7]: bb=b()
198 198
199 199 In [8]: ss=s()
200 200
201 201 In [9]: rr=r()
202 202
203 203 In [10]: ssrr=sr()
204 204
205 205 In [11]: 4.5
206 206 Out[11]: 4.5
207 207
208 208 In [12]: str(ss)
209 209 Out[12]: 's'
210 210
211 211 In [13]:
212 212
213 213 In [14]: %hist -op
214 214 >>> class b:
215 215 ... pass
216 216 ...
217 217 >>> class s(b):
218 218 ... def __str__(self):
219 219 ... return 's'
220 220 ...
221 221 >>>
222 222 >>> class r(b):
223 223 ... def __repr__(self):
224 224 ... return 'r'
225 225 ...
226 226 >>> class sr(s,r): pass
227 227 >>>
228 228 >>> bb=b()
229 229 >>> ss=s()
230 230 >>> rr=r()
231 231 >>> ssrr=sr()
232 232 >>> 4.5
233 233 4.5
234 234 >>> str(ss)
235 235 's'
236 236 >>>
237 237 """
238 238
239 239
240 240 @dec.skip_without('sqlite3')
241 241 def test_macro():
242 242 ip = get_ipython()
243 243 ip.history_manager.reset() # Clear any existing history.
244 244 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
245 245 for i, cmd in enumerate(cmds, start=1):
246 246 ip.history_manager.store_inputs(i, cmd)
247 247 ip.magic("macro test 1-3")
248 248 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
249 249
250 250 # List macros
251 251 nt.assert_in("test", ip.magic("macro"))
252 252
253 253
254 254 @dec.skip_without('sqlite3')
255 255 def test_macro_run():
256 256 """Test that we can run a multi-line macro successfully."""
257 257 ip = get_ipython()
258 258 ip.history_manager.reset()
259 259 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
260 260 "%macro test 2-3"]
261 261 for cmd in cmds:
262 262 ip.run_cell(cmd, store_history=True)
263 263 nt.assert_equal(ip.user_ns["test"].value,
264 264 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
265 265 with tt.AssertPrints("12"):
266 266 ip.run_cell("test")
267 267 with tt.AssertPrints("13"):
268 268 ip.run_cell("test")
269 269
270 270
271 271 def test_magic_magic():
272 272 """Test %magic"""
273 273 ip = get_ipython()
274 274 with capture_output() as captured:
275 275 ip.magic("magic")
276 276
277 277 stdout = captured.stdout
278 278 nt.assert_in('%magic', stdout)
279 279 nt.assert_in('IPython', stdout)
280 280 nt.assert_in('Available', stdout)
281 281
282 282
283 283 @dec.skipif_not_numpy
284 284 def test_numpy_reset_array_undec():
285 285 "Test '%reset array' functionality"
286 286 _ip.ex('import numpy as np')
287 287 _ip.ex('a = np.empty(2)')
288 288 nt.assert_in('a', _ip.user_ns)
289 289 _ip.magic('reset -f array')
290 290 nt.assert_not_in('a', _ip.user_ns)
291 291
292 292 def test_reset_out():
293 293 "Test '%reset out' magic"
294 294 _ip.run_cell("parrot = 'dead'", store_history=True)
295 295 # test '%reset -f out', make an Out prompt
296 296 _ip.run_cell("parrot", store_history=True)
297 297 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
298 298 _ip.magic('reset -f out')
299 299 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
300 300 nt.assert_equal(len(_ip.user_ns['Out']), 0)
301 301
302 302 def test_reset_in():
303 303 "Test '%reset in' magic"
304 304 # test '%reset -f in'
305 305 _ip.run_cell("parrot", store_history=True)
306 306 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
307 307 _ip.magic('%reset -f in')
308 308 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
309 309 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
310 310
311 311 def test_reset_dhist():
312 312 "Test '%reset dhist' magic"
313 313 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
314 314 _ip.magic('cd ' + os.path.dirname(nt.__file__))
315 315 _ip.magic('cd -')
316 316 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
317 317 _ip.magic('reset -f dhist')
318 318 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
319 319 _ip.run_cell("_dh = [d for d in tmp]") #restore
320 320
321 321 def test_reset_in_length():
322 322 "Test that '%reset in' preserves In[] length"
323 323 _ip.run_cell("print 'foo'")
324 324 _ip.run_cell("reset -f in")
325 325 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
326 326
327 327 def test_tb_syntaxerror():
328 328 """test %tb after a SyntaxError"""
329 329 ip = get_ipython()
330 330 ip.run_cell("for")
331 331
332 332 # trap and validate stdout
333 333 save_stdout = sys.stdout
334 334 try:
335 335 sys.stdout = StringIO()
336 336 ip.run_cell("%tb")
337 337 out = sys.stdout.getvalue()
338 338 finally:
339 339 sys.stdout = save_stdout
340 340 # trim output, and only check the last line
341 341 last_line = out.rstrip().splitlines()[-1].strip()
342 342 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
343 343
344 344
345 345 def test_time():
346 346 ip = get_ipython()
347 347
348 348 with tt.AssertPrints("Wall time: "):
349 349 ip.run_cell("%time None")
350 350
351 351 ip.run_cell("def f(kmjy):\n"
352 352 " %time print (2*kmjy)")
353 353
354 354 with tt.AssertPrints("Wall time: "):
355 355 with tt.AssertPrints("hihi", suppress=False):
356 356 ip.run_cell("f('hi')")
357 357
358 358
359 359 @dec.skip_win32
360 360 def test_time2():
361 361 ip = get_ipython()
362 362
363 363 with tt.AssertPrints("CPU times: user "):
364 364 ip.run_cell("%time None")
365 365
366 366 def test_time3():
367 367 """Erroneous magic function calls, issue gh-3334"""
368 368 ip = get_ipython()
369 369 ip.user_ns.pop('run', None)
370 370
371 371 with tt.AssertNotPrints("not found", channel='stderr'):
372 372 ip.run_cell("%%time\n"
373 373 "run = 0\n"
374 374 "run += 1")
375 375
376 376 def test_doctest_mode():
377 377 "Toggle doctest_mode twice, it should be a no-op and run without error"
378 378 _ip.magic('doctest_mode')
379 379 _ip.magic('doctest_mode')
380 380
381 381
382 382 def test_parse_options():
383 383 """Tests for basic options parsing in magics."""
384 384 # These are only the most minimal of tests, more should be added later. At
385 385 # the very least we check that basic text/unicode calls work OK.
386 386 m = DummyMagics(_ip)
387 387 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
388 388 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
389 389
390 390
391 391 def test_dirops():
392 392 """Test various directory handling operations."""
393 393 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
394 394 curpath = os.getcwdu
395 395 startdir = os.getcwdu()
396 396 ipdir = os.path.realpath(_ip.ipython_dir)
397 397 try:
398 398 _ip.magic('cd "%s"' % ipdir)
399 399 nt.assert_equal(curpath(), ipdir)
400 400 _ip.magic('cd -')
401 401 nt.assert_equal(curpath(), startdir)
402 402 _ip.magic('pushd "%s"' % ipdir)
403 403 nt.assert_equal(curpath(), ipdir)
404 404 _ip.magic('popd')
405 405 nt.assert_equal(curpath(), startdir)
406 406 finally:
407 407 os.chdir(startdir)
408 408
409 409
410 410 def test_xmode():
411 411 # Calling xmode three times should be a no-op
412 412 xmode = _ip.InteractiveTB.mode
413 413 for i in range(3):
414 414 _ip.magic("xmode")
415 415 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
416 416
417 417 def test_reset_hard():
418 418 monitor = []
419 419 class A(object):
420 420 def __del__(self):
421 421 monitor.append(1)
422 422 def __repr__(self):
423 423 return "<A instance>"
424 424
425 425 _ip.user_ns["a"] = A()
426 426 _ip.run_cell("a")
427 427
428 428 nt.assert_equal(monitor, [])
429 429 _ip.magic("reset -f")
430 430 nt.assert_equal(monitor, [1])
431 431
432 432 class TestXdel(tt.TempFileMixin):
433 433 def test_xdel(self):
434 434 """Test that references from %run are cleared by xdel."""
435 435 src = ("class A(object):\n"
436 436 " monitor = []\n"
437 437 " def __del__(self):\n"
438 438 " self.monitor.append(1)\n"
439 439 "a = A()\n")
440 440 self.mktmp(src)
441 441 # %run creates some hidden references...
442 442 _ip.magic("run %s" % self.fname)
443 443 # ... as does the displayhook.
444 444 _ip.run_cell("a")
445 445
446 446 monitor = _ip.user_ns["A"].monitor
447 447 nt.assert_equal(monitor, [])
448 448
449 449 _ip.magic("xdel a")
450 450
451 451 # Check that a's __del__ method has been called.
452 452 nt.assert_equal(monitor, [1])
453 453
454 454 def doctest_who():
455 455 """doctest for %who
456 456
457 457 In [1]: %reset -f
458 458
459 459 In [2]: alpha = 123
460 460
461 461 In [3]: beta = 'beta'
462 462
463 463 In [4]: %who int
464 464 alpha
465 465
466 466 In [5]: %who str
467 467 beta
468 468
469 469 In [6]: %whos
470 470 Variable Type Data/Info
471 471 ----------------------------
472 472 alpha int 123
473 473 beta str beta
474 474
475 475 In [7]: %who_ls
476 476 Out[7]: ['alpha', 'beta']
477 477 """
478 478
479 479 def test_whos():
480 480 """Check that whos is protected against objects where repr() fails."""
481 481 class A(object):
482 482 def __repr__(self):
483 483 raise Exception()
484 484 _ip.user_ns['a'] = A()
485 485 _ip.magic("whos")
486 486
487 487 @py3compat.u_format
488 488 def doctest_precision():
489 489 """doctest for %precision
490 490
491 491 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
492 492
493 493 In [2]: %precision 5
494 494 Out[2]: {u}'%.5f'
495 495
496 496 In [3]: f.float_format
497 497 Out[3]: {u}'%.5f'
498 498
499 499 In [4]: %precision %e
500 500 Out[4]: {u}'%e'
501 501
502 502 In [5]: f(3.1415927)
503 503 Out[5]: {u}'3.141593e+00'
504 504 """
505 505
506 506 def test_psearch():
507 507 with tt.AssertPrints("dict.fromkeys"):
508 508 _ip.run_cell("dict.fr*?")
509 509
510 510 def test_timeit_shlex():
511 511 """test shlex issues with timeit (#1109)"""
512 512 _ip.ex("def f(*a,**kw): pass")
513 513 _ip.magic('timeit -n1 "this is a bug".count(" ")')
514 514 _ip.magic('timeit -r1 -n1 f(" ", 1)')
515 515 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
516 516 _ip.magic('timeit -r1 -n1 ("a " + "b")')
517 517 _ip.magic('timeit -r1 -n1 f("a " + "b")')
518 518 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
519 519
520 520
521 521 def test_timeit_arguments():
522 522 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
523 523 _ip.magic("timeit ('#')")
524 524
525 525
526 526 def test_timeit_special_syntax():
527 527 "Test %%timeit with IPython special syntax"
528 528 @register_line_magic
529 529 def lmagic(line):
530 530 ip = get_ipython()
531 531 ip.user_ns['lmagic_out'] = line
532 532
533 533 # line mode test
534 534 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
535 535 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
536 536 # cell mode test
537 537 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
538 538 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
539 539
540 540 def test_timeit_return():
541 541 """
542 542 test wether timeit -o return object
543 543 """
544 544
545 545 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
546 546 assert(res is not None)
547 547
548 548 def test_timeit_quiet():
549 549 """
550 550 test quiet option of timeit magic
551 551 """
552 552 with tt.AssertNotPrints("loops"):
553 553 _ip.run_cell("%timeit -n1 -r1 -q 1")
554 554
555 555 @dec.skipif(execution.profile is None)
556 556 def test_prun_special_syntax():
557 557 "Test %%prun with IPython special syntax"
558 558 @register_line_magic
559 559 def lmagic(line):
560 560 ip = get_ipython()
561 561 ip.user_ns['lmagic_out'] = line
562 562
563 563 # line mode test
564 564 _ip.run_line_magic('prun', '-q %lmagic my line')
565 565 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
566 566 # cell mode test
567 567 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
568 568 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
569 569
570 570 @dec.skipif(execution.profile is None)
571 571 def test_prun_quotes():
572 572 "Test that prun does not clobber string escapes (GH #1302)"
573 573 _ip.magic(r"prun -q x = '\t'")
574 574 nt.assert_equal(_ip.user_ns['x'], '\t')
575 575
576 576 def test_extension():
577 577 tmpdir = TemporaryDirectory()
578 578 orig_ipython_dir = _ip.ipython_dir
579 579 try:
580 580 _ip.ipython_dir = tmpdir.name
581 581 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
582 582 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
583 583 _ip.magic("install_ext %s" % url)
584 584 _ip.user_ns.pop('arq', None)
585 585 invalidate_caches() # Clear import caches
586 586 _ip.magic("load_ext daft_extension")
587 587 nt.assert_equal(_ip.user_ns['arq'], 185)
588 588 _ip.magic("unload_ext daft_extension")
589 589 assert 'arq' not in _ip.user_ns
590 590 finally:
591 591 _ip.ipython_dir = orig_ipython_dir
592 592 tmpdir.cleanup()
593 593
594 594 def test_notebook_export_json():
595 595 with TemporaryDirectory() as td:
596 596 outfile = os.path.join(td, "nb.ipynb")
597 597 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
598 598 _ip.magic("notebook -e %s" % outfile)
599 599
600 600 def test_notebook_export_py():
601 601 with TemporaryDirectory() as td:
602 602 outfile = os.path.join(td, "nb.py")
603 603 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
604 604 _ip.magic("notebook -e %s" % outfile)
605 605
606 606 def test_notebook_reformat_py():
607 607 with TemporaryDirectory() as td:
608 608 infile = os.path.join(td, "nb.ipynb")
609 609 with io.open(infile, 'w', encoding='utf-8') as f:
610 610 current.write(nb0, f, 'json')
611 611
612 612 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
613 613 _ip.magic("notebook -f py %s" % infile)
614 614
615 615 def test_notebook_reformat_json():
616 616 with TemporaryDirectory() as td:
617 617 infile = os.path.join(td, "nb.py")
618 618 with io.open(infile, 'w', encoding='utf-8') as f:
619 619 current.write(nb0, f, 'py')
620 620
621 621 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
622 622 _ip.magic("notebook -f ipynb %s" % infile)
623 623 _ip.magic("notebook -f json %s" % infile)
624 624
625 625 def test_env():
626 626 env = _ip.magic("env")
627 627 assert isinstance(env, dict), type(env)
628 628
629 629
630 630 class CellMagicTestCase(TestCase):
631 631
632 632 def check_ident(self, magic):
633 633 # Manually called, we get the result
634 634 out = _ip.run_cell_magic(magic, 'a', 'b')
635 635 nt.assert_equal(out, ('a','b'))
636 636 # Via run_cell, it goes into the user's namespace via displayhook
637 637 _ip.run_cell('%%' + magic +' c\nd')
638 638 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
639 639
640 640 def test_cell_magic_func_deco(self):
641 641 "Cell magic using simple decorator"
642 642 @register_cell_magic
643 643 def cellm(line, cell):
644 644 return line, cell
645 645
646 646 self.check_ident('cellm')
647 647
648 648 def test_cell_magic_reg(self):
649 649 "Cell magic manually registered"
650 650 def cellm(line, cell):
651 651 return line, cell
652 652
653 653 _ip.register_magic_function(cellm, 'cell', 'cellm2')
654 654 self.check_ident('cellm2')
655 655
656 656 def test_cell_magic_class(self):
657 657 "Cell magics declared via a class"
658 658 @magics_class
659 659 class MyMagics(Magics):
660 660
661 661 @cell_magic
662 662 def cellm3(self, line, cell):
663 663 return line, cell
664 664
665 665 _ip.register_magics(MyMagics)
666 666 self.check_ident('cellm3')
667 667
668 668 def test_cell_magic_class2(self):
669 669 "Cell magics declared via a class, #2"
670 670 @magics_class
671 671 class MyMagics2(Magics):
672 672
673 673 @cell_magic('cellm4')
674 674 def cellm33(self, line, cell):
675 675 return line, cell
676 676
677 677 _ip.register_magics(MyMagics2)
678 678 self.check_ident('cellm4')
679 679 # Check that nothing is registered as 'cellm33'
680 680 c33 = _ip.find_cell_magic('cellm33')
681 681 nt.assert_equal(c33, None)
682 682
683 683 def test_file():
684 684 """Basic %%file"""
685 685 ip = get_ipython()
686 686 with TemporaryDirectory() as td:
687 687 fname = os.path.join(td, 'file1')
688 688 ip.run_cell_magic("file", fname, u'\n'.join([
689 689 'line1',
690 690 'line2',
691 691 ]))
692 692 with open(fname) as f:
693 693 s = f.read()
694 694 nt.assert_in('line1\n', s)
695 695 nt.assert_in('line2', s)
696 696
697 697 def test_file_var_expand():
698 698 """%%file $filename"""
699 699 ip = get_ipython()
700 700 with TemporaryDirectory() as td:
701 701 fname = os.path.join(td, 'file1')
702 702 ip.user_ns['filename'] = fname
703 703 ip.run_cell_magic("file", '$filename', u'\n'.join([
704 704 'line1',
705 705 'line2',
706 706 ]))
707 707 with open(fname) as f:
708 708 s = f.read()
709 709 nt.assert_in('line1\n', s)
710 710 nt.assert_in('line2', s)
711 711
712 712 def test_file_unicode():
713 713 """%%file with unicode cell"""
714 714 ip = get_ipython()
715 715 with TemporaryDirectory() as td:
716 716 fname = os.path.join(td, 'file1')
717 717 ip.run_cell_magic("file", fname, u'\n'.join([
718 718 u'linΓ©1',
719 719 u'linΓ©2',
720 720 ]))
721 721 with io.open(fname, encoding='utf-8') as f:
722 722 s = f.read()
723 723 nt.assert_in(u'linΓ©1\n', s)
724 724 nt.assert_in(u'linΓ©2', s)
725 725
726 726 def test_file_amend():
727 727 """%%file -a amends files"""
728 728 ip = get_ipython()
729 729 with TemporaryDirectory() as td:
730 730 fname = os.path.join(td, 'file2')
731 731 ip.run_cell_magic("file", fname, u'\n'.join([
732 732 'line1',
733 733 'line2',
734 734 ]))
735 735 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
736 736 'line3',
737 737 'line4',
738 738 ]))
739 739 with open(fname) as f:
740 740 s = f.read()
741 741 nt.assert_in('line1\n', s)
742 742 nt.assert_in('line3\n', s)
743 743
744 744
745 745 def test_script_config():
746 746 ip = get_ipython()
747 747 ip.config.ScriptMagics.script_magics = ['whoda']
748 748 sm = script.ScriptMagics(shell=ip)
749 749 nt.assert_in('whoda', sm.magics['cell'])
750 750
751 751 @dec.skip_win32
752 752 def test_script_out():
753 753 ip = get_ipython()
754 754 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
755 755 nt.assert_equal(ip.user_ns['output'], 'hi\n')
756 756
757 757 @dec.skip_win32
758 758 def test_script_err():
759 759 ip = get_ipython()
760 760 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
761 761 nt.assert_equal(ip.user_ns['error'], 'hello\n')
762 762
763 763 @dec.skip_win32
764 764 def test_script_out_err():
765 765 ip = get_ipython()
766 766 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
767 767 nt.assert_equal(ip.user_ns['output'], 'hi\n')
768 768 nt.assert_equal(ip.user_ns['error'], 'hello\n')
769 769
770 770 @dec.skip_win32
771 771 def test_script_bg_out():
772 772 ip = get_ipython()
773 773 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
774 774 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
775 775
776 776 @dec.skip_win32
777 777 def test_script_bg_err():
778 778 ip = get_ipython()
779 779 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
780 780 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
781 781
782 782 @dec.skip_win32
783 783 def test_script_bg_out_err():
784 784 ip = get_ipython()
785 785 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
786 786 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
787 787 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
788 788
789 789 def test_script_defaults():
790 790 ip = get_ipython()
791 791 for cmd in ['sh', 'bash', 'perl', 'ruby']:
792 792 try:
793 793 find_cmd(cmd)
794 794 except Exception:
795 795 pass
796 796 else:
797 797 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
798 798
799 799
800 800 @magics_class
801 801 class FooFoo(Magics):
802 802 """class with both %foo and %%foo magics"""
803 803 @line_magic('foo')
804 804 def line_foo(self, line):
805 805 "I am line foo"
806 806 pass
807 807
808 808 @cell_magic("foo")
809 809 def cell_foo(self, line, cell):
810 810 "I am cell foo, not line foo"
811 811 pass
812 812
813 813 def test_line_cell_info():
814 814 """%%foo and %foo magics are distinguishable to inspect"""
815 815 ip = get_ipython()
816 816 ip.magics_manager.register(FooFoo)
817 817 oinfo = ip.object_inspect('foo')
818 818 nt.assert_true(oinfo['found'])
819 819 nt.assert_true(oinfo['ismagic'])
820 820
821 821 oinfo = ip.object_inspect('%%foo')
822 822 nt.assert_true(oinfo['found'])
823 823 nt.assert_true(oinfo['ismagic'])
824 824 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
825 825
826 826 oinfo = ip.object_inspect('%foo')
827 827 nt.assert_true(oinfo['found'])
828 828 nt.assert_true(oinfo['ismagic'])
829 829 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
830 830
831 831 def test_multiple_magics():
832 832 ip = get_ipython()
833 833 foo1 = FooFoo(ip)
834 834 foo2 = FooFoo(ip)
835 835 mm = ip.magics_manager
836 836 mm.register(foo1)
837 nt.assert_true(mm.magics['line']['foo'].im_self is foo1)
837 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
838 838 mm.register(foo2)
839 nt.assert_true(mm.magics['line']['foo'].im_self is foo2)
839 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
840 840
841 841 def test_alias_magic():
842 842 """Test %alias_magic."""
843 843 ip = get_ipython()
844 844 mm = ip.magics_manager
845 845
846 846 # Basic operation: both cell and line magics are created, if possible.
847 847 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
848 848 nt.assert_in('timeit_alias', mm.magics['line'])
849 849 nt.assert_in('timeit_alias', mm.magics['cell'])
850 850
851 851 # --cell is specified, line magic not created.
852 852 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
853 853 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
854 854 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
855 855
856 856 # Test that line alias is created successfully.
857 857 ip.run_line_magic('alias_magic', '--line env_alias env')
858 858 nt.assert_equal(ip.run_line_magic('env', ''),
859 859 ip.run_line_magic('env_alias', ''))
860 860
861 861 def test_save():
862 862 """Test %save."""
863 863 ip = get_ipython()
864 864 ip.history_manager.reset() # Clear any existing history.
865 865 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
866 866 for i, cmd in enumerate(cmds, start=1):
867 867 ip.history_manager.store_inputs(i, cmd)
868 868 with TemporaryDirectory() as tmpdir:
869 869 file = os.path.join(tmpdir, "testsave.py")
870 870 ip.run_line_magic("save", "%s 1-10" % file)
871 871 with open(file) as f:
872 872 content = f.read()
873 873 nt.assert_equal(content.count(cmds[0]), 1)
874 874 nt.assert_in('coding: utf-8', content)
875 875 ip.run_line_magic("save", "-a %s 1-10" % file)
876 876 with open(file) as f:
877 877 content = f.read()
878 878 nt.assert_equal(content.count(cmds[0]), 2)
879 879 nt.assert_in('coding: utf-8', content)
880 880
881 881
882 882 def test_store():
883 883 """Test %store."""
884 884 ip = get_ipython()
885 885 ip.run_line_magic('load_ext', 'storemagic')
886 886
887 887 # make sure the storage is empty
888 888 ip.run_line_magic('store', '-z')
889 889 ip.user_ns['var'] = 42
890 890 ip.run_line_magic('store', 'var')
891 891 ip.user_ns['var'] = 39
892 892 ip.run_line_magic('store', '-r')
893 893 nt.assert_equal(ip.user_ns['var'], 42)
894 894
895 895 ip.run_line_magic('store', '-d var')
896 896 ip.user_ns['var'] = 39
897 897 ip.run_line_magic('store' , '-r')
898 898 nt.assert_equal(ip.user_ns['var'], 39)
899 899
900 900
901 901 def _run_edit_test(arg_s, exp_filename=None,
902 902 exp_lineno=-1,
903 903 exp_contents=None,
904 904 exp_is_temp=None):
905 905 ip = get_ipython()
906 906 M = code.CodeMagics(ip)
907 907 last_call = ['','']
908 908 opts,args = M.parse_options(arg_s,'prxn:')
909 909 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
910 910
911 911 if exp_filename is not None:
912 912 nt.assert_equal(exp_filename, filename)
913 913 if exp_contents is not None:
914 914 with io.open(filename, 'r') as f:
915 915 contents = f.read()
916 916 nt.assert_equal(exp_contents, contents)
917 917 if exp_lineno != -1:
918 918 nt.assert_equal(exp_lineno, lineno)
919 919 if exp_is_temp is not None:
920 920 nt.assert_equal(exp_is_temp, is_temp)
921 921
922 922
923 923 def test_edit_interactive():
924 924 """%edit on interactively defined objects"""
925 925 ip = get_ipython()
926 926 n = ip.execution_count
927 927 ip.run_cell(u"def foo(): return 1", store_history=True)
928 928
929 929 try:
930 930 _run_edit_test("foo")
931 931 except code.InteractivelyDefined as e:
932 932 nt.assert_equal(e.index, n)
933 933 else:
934 934 raise AssertionError("Should have raised InteractivelyDefined")
935 935
936 936
937 937 def test_edit_cell():
938 938 """%edit [cell id]"""
939 939 ip = get_ipython()
940 940
941 941 ip.run_cell(u"def foo(): return 1", store_history=True)
942 942
943 943 # test
944 944 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
@@ -1,1267 +1,1267 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 ultratb.py -- Spice up your tracebacks!
4 4
5 5 * ColorTB
6 6 I've always found it a bit hard to visually parse tracebacks in Python. The
7 7 ColorTB class is a solution to that problem. It colors the different parts of a
8 8 traceback in a manner similar to what you would expect from a syntax-highlighting
9 9 text editor.
10 10
11 11 Installation instructions for ColorTB::
12 12
13 13 import sys,ultratb
14 14 sys.excepthook = ultratb.ColorTB()
15 15
16 16 * VerboseTB
17 17 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
18 18 of useful info when a traceback occurs. Ping originally had it spit out HTML
19 19 and intended it for CGI programmers, but why should they have all the fun? I
20 20 altered it to spit out colored text to the terminal. It's a bit overwhelming,
21 21 but kind of neat, and maybe useful for long-running programs that you believe
22 22 are bug-free. If a crash *does* occur in that type of program you want details.
23 23 Give it a shot--you'll love it or you'll hate it.
24 24
25 25 .. note::
26 26
27 27 The Verbose mode prints the variables currently visible where the exception
28 28 happened (shortening their strings if too long). This can potentially be
29 29 very slow, if you happen to have a huge data structure whose string
30 30 representation is complex to compute. Your computer may appear to freeze for
31 31 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
32 32 with Ctrl-C (maybe hitting it more than once).
33 33
34 34 If you encounter this kind of situation often, you may want to use the
35 35 Verbose_novars mode instead of the regular Verbose, which avoids formatting
36 36 variables (but otherwise includes the information and context given by
37 37 Verbose).
38 38
39 39
40 40 Installation instructions for ColorTB::
41 41
42 42 import sys,ultratb
43 43 sys.excepthook = ultratb.VerboseTB()
44 44
45 45 Note: Much of the code in this module was lifted verbatim from the standard
46 46 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
47 47
48 48 Color schemes
49 49 -------------
50 50
51 51 The colors are defined in the class TBTools through the use of the
52 52 ColorSchemeTable class. Currently the following exist:
53 53
54 54 - NoColor: allows all of this module to be used in any terminal (the color
55 55 escapes are just dummy blank strings).
56 56
57 57 - Linux: is meant to look good in a terminal like the Linux console (black
58 58 or very dark background).
59 59
60 60 - LightBG: similar to Linux but swaps dark/light colors to be more readable
61 61 in light background terminals.
62 62
63 63 You can implement other color schemes easily, the syntax is fairly
64 64 self-explanatory. Please send back new schemes you develop to the author for
65 65 possible inclusion in future releases.
66 66
67 67 Inheritance diagram:
68 68
69 69 .. inheritance-diagram:: IPython.core.ultratb
70 70 :parts: 3
71 71 """
72 72
73 73 #*****************************************************************************
74 74 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
75 75 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
76 76 #
77 77 # Distributed under the terms of the BSD License. The full license is in
78 78 # the file COPYING, distributed as part of this software.
79 79 #*****************************************************************************
80 80
81 81 from __future__ import unicode_literals
82 82 from __future__ import print_function
83 83
84 84 import inspect
85 85 import keyword
86 86 import linecache
87 87 import os
88 88 import pydoc
89 89 import re
90 90 import sys
91 91 import time
92 92 import tokenize
93 93 import traceback
94 94 import types
95 95
96 96 try: # Python 2
97 97 generate_tokens = tokenize.generate_tokens
98 98 except AttributeError: # Python 3
99 99 generate_tokens = tokenize.tokenize
100 100
101 101 # For purposes of monkeypatching inspect to fix a bug in it.
102 102 from inspect import getsourcefile, getfile, getmodule,\
103 103 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
104 104
105 105 # IPython's own modules
106 106 # Modified pdb which doesn't damage IPython's readline handling
107 107 from IPython import get_ipython
108 108 from IPython.core import debugger
109 109 from IPython.core.display_trap import DisplayTrap
110 110 from IPython.core.excolors import exception_colors
111 111 from IPython.utils import PyColorize
112 112 from IPython.utils import io
113 113 from IPython.utils import openpy
114 114 from IPython.utils import path as util_path
115 115 from IPython.utils import py3compat
116 116 from IPython.utils import ulinecache
117 117 from IPython.utils.data import uniq_stable
118 118 from IPython.utils.warn import info, error
119 119
120 120 # Globals
121 121 # amount of space to put line numbers before verbose tracebacks
122 122 INDENT_SIZE = 8
123 123
124 124 # Default color scheme. This is used, for example, by the traceback
125 125 # formatter. When running in an actual IPython instance, the user's rc.colors
126 126 # value is used, but havinga module global makes this functionality available
127 127 # to users of ultratb who are NOT running inside ipython.
128 128 DEFAULT_SCHEME = 'NoColor'
129 129
130 130 #---------------------------------------------------------------------------
131 131 # Code begins
132 132
133 133 # Utility functions
134 134 def inspect_error():
135 135 """Print a message about internal inspect errors.
136 136
137 137 These are unfortunately quite common."""
138 138
139 139 error('Internal Python error in the inspect module.\n'
140 140 'Below is the traceback from this internal error.\n')
141 141
142 142 # This function is a monkeypatch we apply to the Python inspect module. We have
143 143 # now found when it's needed (see discussion on issue gh-1456), and we have a
144 144 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
145 145 # the monkeypatch is not applied. TK, Aug 2012.
146 146 def findsource(object):
147 147 """Return the entire source file and starting line number for an object.
148 148
149 149 The argument may be a module, class, method, function, traceback, frame,
150 150 or code object. The source code is returned as a list of all the lines
151 151 in the file and the line number indexes a line in that list. An IOError
152 152 is raised if the source code cannot be retrieved.
153 153
154 154 FIXED version with which we monkeypatch the stdlib to work around a bug."""
155 155
156 156 file = getsourcefile(object) or getfile(object)
157 157 # If the object is a frame, then trying to get the globals dict from its
158 158 # module won't work. Instead, the frame object itself has the globals
159 159 # dictionary.
160 160 globals_dict = None
161 161 if inspect.isframe(object):
162 162 # XXX: can this ever be false?
163 163 globals_dict = object.f_globals
164 164 else:
165 165 module = getmodule(object, file)
166 166 if module:
167 167 globals_dict = module.__dict__
168 168 lines = linecache.getlines(file, globals_dict)
169 169 if not lines:
170 170 raise IOError('could not get source code')
171 171
172 172 if ismodule(object):
173 173 return lines, 0
174 174
175 175 if isclass(object):
176 176 name = object.__name__
177 177 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
178 178 # make some effort to find the best matching class definition:
179 179 # use the one with the least indentation, which is the one
180 180 # that's most probably not inside a function definition.
181 181 candidates = []
182 182 for i in range(len(lines)):
183 183 match = pat.match(lines[i])
184 184 if match:
185 185 # if it's at toplevel, it's already the best one
186 186 if lines[i][0] == 'c':
187 187 return lines, i
188 188 # else add whitespace to candidate list
189 189 candidates.append((match.group(1), i))
190 190 if candidates:
191 191 # this will sort by whitespace, and by line number,
192 192 # less whitespace first
193 193 candidates.sort()
194 194 return lines, candidates[0][1]
195 195 else:
196 196 raise IOError('could not find class definition')
197 197
198 198 if ismethod(object):
199 object = object.im_func
199 object = object.__func__
200 200 if isfunction(object):
201 201 object = object.__code__
202 202 if istraceback(object):
203 203 object = object.tb_frame
204 204 if isframe(object):
205 205 object = object.f_code
206 206 if iscode(object):
207 207 if not hasattr(object, 'co_firstlineno'):
208 208 raise IOError('could not find function definition')
209 209 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
210 210 pmatch = pat.match
211 211 # fperez - fix: sometimes, co_firstlineno can give a number larger than
212 212 # the length of lines, which causes an error. Safeguard against that.
213 213 lnum = min(object.co_firstlineno,len(lines))-1
214 214 while lnum > 0:
215 215 if pmatch(lines[lnum]): break
216 216 lnum -= 1
217 217
218 218 return lines, lnum
219 219 raise IOError('could not find code object')
220 220
221 221 # Monkeypatch inspect to apply our bugfix. This code only works with Python >= 2.5
222 222 inspect.findsource = findsource
223 223
224 224 def fix_frame_records_filenames(records):
225 225 """Try to fix the filenames in each record from inspect.getinnerframes().
226 226
227 227 Particularly, modules loaded from within zip files have useless filenames
228 228 attached to their code object, and inspect.getinnerframes() just uses it.
229 229 """
230 230 fixed_records = []
231 231 for frame, filename, line_no, func_name, lines, index in records:
232 232 # Look inside the frame's globals dictionary for __file__, which should
233 233 # be better.
234 234 better_fn = frame.f_globals.get('__file__', None)
235 235 if isinstance(better_fn, str):
236 236 # Check the type just in case someone did something weird with
237 237 # __file__. It might also be None if the error occurred during
238 238 # import.
239 239 filename = better_fn
240 240 fixed_records.append((frame, filename, line_no, func_name, lines, index))
241 241 return fixed_records
242 242
243 243
244 244 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
245 245 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
246 246
247 247 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
248 248
249 249 # If the error is at the console, don't build any context, since it would
250 250 # otherwise produce 5 blank lines printed out (there is no file at the
251 251 # console)
252 252 rec_check = records[tb_offset:]
253 253 try:
254 254 rname = rec_check[0][1]
255 255 if rname == '<ipython console>' or rname.endswith('<string>'):
256 256 return rec_check
257 257 except IndexError:
258 258 pass
259 259
260 260 aux = traceback.extract_tb(etb)
261 261 assert len(records) == len(aux)
262 262 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
263 263 maybeStart = lnum-1 - context//2
264 264 start = max(maybeStart, 0)
265 265 end = start + context
266 266 lines = ulinecache.getlines(file)[start:end]
267 267 buf = list(records[i])
268 268 buf[LNUM_POS] = lnum
269 269 buf[INDEX_POS] = lnum - 1 - start
270 270 buf[LINES_POS] = lines
271 271 records[i] = tuple(buf)
272 272 return records[tb_offset:]
273 273
274 274 # Helper function -- largely belongs to VerboseTB, but we need the same
275 275 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
276 276 # can be recognized properly by ipython.el's py-traceback-line-re
277 277 # (SyntaxErrors have to be treated specially because they have no traceback)
278 278
279 279 _parser = PyColorize.Parser()
280 280
281 281 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):
282 282 numbers_width = INDENT_SIZE - 1
283 283 res = []
284 284 i = lnum - index
285 285
286 286 # This lets us get fully syntax-highlighted tracebacks.
287 287 if scheme is None:
288 288 ipinst = get_ipython()
289 289 if ipinst is not None:
290 290 scheme = ipinst.colors
291 291 else:
292 292 scheme = DEFAULT_SCHEME
293 293
294 294 _line_format = _parser.format2
295 295
296 296 for line in lines:
297 297 line = py3compat.cast_unicode(line)
298 298
299 299 new_line, err = _line_format(line, 'str', scheme)
300 300 if not err: line = new_line
301 301
302 302 if i == lnum:
303 303 # This is the line with the error
304 304 pad = numbers_width - len(str(i))
305 305 if pad >= 3:
306 306 marker = '-'*(pad-3) + '-> '
307 307 elif pad == 2:
308 308 marker = '> '
309 309 elif pad == 1:
310 310 marker = '>'
311 311 else:
312 312 marker = ''
313 313 num = marker + str(i)
314 314 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
315 315 Colors.line, line, Colors.Normal)
316 316 else:
317 317 num = '%*s' % (numbers_width,i)
318 318 line = '%s%s%s %s' %(Colors.lineno, num,
319 319 Colors.Normal, line)
320 320
321 321 res.append(line)
322 322 if lvals and i == lnum:
323 323 res.append(lvals + '\n')
324 324 i = i + 1
325 325 return res
326 326
327 327
328 328 #---------------------------------------------------------------------------
329 329 # Module classes
330 330 class TBTools(object):
331 331 """Basic tools used by all traceback printer classes."""
332 332
333 333 # Number of frames to skip when reporting tracebacks
334 334 tb_offset = 0
335 335
336 336 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
337 337 # Whether to call the interactive pdb debugger after printing
338 338 # tracebacks or not
339 339 self.call_pdb = call_pdb
340 340
341 341 # Output stream to write to. Note that we store the original value in
342 342 # a private attribute and then make the public ostream a property, so
343 343 # that we can delay accessing io.stdout until runtime. The way
344 344 # things are written now, the io.stdout object is dynamically managed
345 345 # so a reference to it should NEVER be stored statically. This
346 346 # property approach confines this detail to a single location, and all
347 347 # subclasses can simply access self.ostream for writing.
348 348 self._ostream = ostream
349 349
350 350 # Create color table
351 351 self.color_scheme_table = exception_colors()
352 352
353 353 self.set_colors(color_scheme)
354 354 self.old_scheme = color_scheme # save initial value for toggles
355 355
356 356 if call_pdb:
357 357 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
358 358 else:
359 359 self.pdb = None
360 360
361 361 def _get_ostream(self):
362 362 """Output stream that exceptions are written to.
363 363
364 364 Valid values are:
365 365
366 366 - None: the default, which means that IPython will dynamically resolve
367 367 to io.stdout. This ensures compatibility with most tools, including
368 368 Windows (where plain stdout doesn't recognize ANSI escapes).
369 369
370 370 - Any object with 'write' and 'flush' attributes.
371 371 """
372 372 return io.stdout if self._ostream is None else self._ostream
373 373
374 374 def _set_ostream(self, val):
375 375 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
376 376 self._ostream = val
377 377
378 378 ostream = property(_get_ostream, _set_ostream)
379 379
380 380 def set_colors(self,*args,**kw):
381 381 """Shorthand access to the color table scheme selector method."""
382 382
383 383 # Set own color table
384 384 self.color_scheme_table.set_active_scheme(*args,**kw)
385 385 # for convenience, set Colors to the active scheme
386 386 self.Colors = self.color_scheme_table.active_colors
387 387 # Also set colors of debugger
388 388 if hasattr(self,'pdb') and self.pdb is not None:
389 389 self.pdb.set_colors(*args,**kw)
390 390
391 391 def color_toggle(self):
392 392 """Toggle between the currently active color scheme and NoColor."""
393 393
394 394 if self.color_scheme_table.active_scheme_name == 'NoColor':
395 395 self.color_scheme_table.set_active_scheme(self.old_scheme)
396 396 self.Colors = self.color_scheme_table.active_colors
397 397 else:
398 398 self.old_scheme = self.color_scheme_table.active_scheme_name
399 399 self.color_scheme_table.set_active_scheme('NoColor')
400 400 self.Colors = self.color_scheme_table.active_colors
401 401
402 402 def stb2text(self, stb):
403 403 """Convert a structured traceback (a list) to a string."""
404 404 return '\n'.join(stb)
405 405
406 406 def text(self, etype, value, tb, tb_offset=None, context=5):
407 407 """Return formatted traceback.
408 408
409 409 Subclasses may override this if they add extra arguments.
410 410 """
411 411 tb_list = self.structured_traceback(etype, value, tb,
412 412 tb_offset, context)
413 413 return self.stb2text(tb_list)
414 414
415 415 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
416 416 context=5, mode=None):
417 417 """Return a list of traceback frames.
418 418
419 419 Must be implemented by each class.
420 420 """
421 421 raise NotImplementedError()
422 422
423 423
424 424 #---------------------------------------------------------------------------
425 425 class ListTB(TBTools):
426 426 """Print traceback information from a traceback list, with optional color.
427 427
428 428 Calling requires 3 arguments: (etype, evalue, elist)
429 429 as would be obtained by::
430 430
431 431 etype, evalue, tb = sys.exc_info()
432 432 if tb:
433 433 elist = traceback.extract_tb(tb)
434 434 else:
435 435 elist = None
436 436
437 437 It can thus be used by programs which need to process the traceback before
438 438 printing (such as console replacements based on the code module from the
439 439 standard library).
440 440
441 441 Because they are meant to be called without a full traceback (only a
442 442 list), instances of this class can't call the interactive pdb debugger."""
443 443
444 444 def __init__(self,color_scheme = 'NoColor', call_pdb=False, ostream=None):
445 445 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
446 446 ostream=ostream)
447 447
448 448 def __call__(self, etype, value, elist):
449 449 self.ostream.flush()
450 450 self.ostream.write(self.text(etype, value, elist))
451 451 self.ostream.write('\n')
452 452
453 453 def structured_traceback(self, etype, value, elist, tb_offset=None,
454 454 context=5):
455 455 """Return a color formatted string with the traceback info.
456 456
457 457 Parameters
458 458 ----------
459 459 etype : exception type
460 460 Type of the exception raised.
461 461
462 462 value : object
463 463 Data stored in the exception
464 464
465 465 elist : list
466 466 List of frames, see class docstring for details.
467 467
468 468 tb_offset : int, optional
469 469 Number of frames in the traceback to skip. If not given, the
470 470 instance value is used (set in constructor).
471 471
472 472 context : int, optional
473 473 Number of lines of context information to print.
474 474
475 475 Returns
476 476 -------
477 477 String with formatted exception.
478 478 """
479 479 tb_offset = self.tb_offset if tb_offset is None else tb_offset
480 480 Colors = self.Colors
481 481 out_list = []
482 482 if elist:
483 483
484 484 if tb_offset and len(elist) > tb_offset:
485 485 elist = elist[tb_offset:]
486 486
487 487 out_list.append('Traceback %s(most recent call last)%s:' %
488 488 (Colors.normalEm, Colors.Normal) + '\n')
489 489 out_list.extend(self._format_list(elist))
490 490 # The exception info should be a single entry in the list.
491 491 lines = ''.join(self._format_exception_only(etype, value))
492 492 out_list.append(lines)
493 493
494 494 # Note: this code originally read:
495 495
496 496 ## for line in lines[:-1]:
497 497 ## out_list.append(" "+line)
498 498 ## out_list.append(lines[-1])
499 499
500 500 # This means it was indenting everything but the last line by a little
501 501 # bit. I've disabled this for now, but if we see ugliness somewhre we
502 502 # can restore it.
503 503
504 504 return out_list
505 505
506 506 def _format_list(self, extracted_list):
507 507 """Format a list of traceback entry tuples for printing.
508 508
509 509 Given a list of tuples as returned by extract_tb() or
510 510 extract_stack(), return a list of strings ready for printing.
511 511 Each string in the resulting list corresponds to the item with the
512 512 same index in the argument list. Each string ends in a newline;
513 513 the strings may contain internal newlines as well, for those items
514 514 whose source text line is not None.
515 515
516 516 Lifted almost verbatim from traceback.py
517 517 """
518 518
519 519 Colors = self.Colors
520 520 list = []
521 521 for filename, lineno, name, line in extracted_list[:-1]:
522 522 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
523 523 (Colors.filename, filename, Colors.Normal,
524 524 Colors.lineno, lineno, Colors.Normal,
525 525 Colors.name, name, Colors.Normal)
526 526 if line:
527 527 item += ' %s\n' % line.strip()
528 528 list.append(item)
529 529 # Emphasize the last entry
530 530 filename, lineno, name, line = extracted_list[-1]
531 531 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
532 532 (Colors.normalEm,
533 533 Colors.filenameEm, filename, Colors.normalEm,
534 534 Colors.linenoEm, lineno, Colors.normalEm,
535 535 Colors.nameEm, name, Colors.normalEm,
536 536 Colors.Normal)
537 537 if line:
538 538 item += '%s %s%s\n' % (Colors.line, line.strip(),
539 539 Colors.Normal)
540 540 list.append(item)
541 541 #from pprint import pformat; print 'LISTTB', pformat(list) # dbg
542 542 return list
543 543
544 544 def _format_exception_only(self, etype, value):
545 545 """Format the exception part of a traceback.
546 546
547 547 The arguments are the exception type and value such as given by
548 548 sys.exc_info()[:2]. The return value is a list of strings, each ending
549 549 in a newline. Normally, the list contains a single string; however,
550 550 for SyntaxError exceptions, it contains several lines that (when
551 551 printed) display detailed information about where the syntax error
552 552 occurred. The message indicating which exception occurred is the
553 553 always last string in the list.
554 554
555 555 Also lifted nearly verbatim from traceback.py
556 556 """
557 557 have_filedata = False
558 558 Colors = self.Colors
559 559 list = []
560 560 stype = Colors.excName + etype.__name__ + Colors.Normal
561 561 if value is None:
562 562 # Not sure if this can still happen in Python 2.6 and above
563 563 list.append( py3compat.cast_unicode(stype) + '\n')
564 564 else:
565 565 if issubclass(etype, SyntaxError):
566 566 have_filedata = True
567 567 #print 'filename is',filename # dbg
568 568 if not value.filename: value.filename = "<string>"
569 569 if value.lineno:
570 570 lineno = value.lineno
571 571 textline = ulinecache.getline(value.filename, value.lineno)
572 572 else:
573 573 lineno = 'unknown'
574 574 textline = ''
575 575 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
576 576 (Colors.normalEm,
577 577 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
578 578 Colors.linenoEm, lineno, Colors.Normal ))
579 579 if textline == '':
580 580 textline = py3compat.cast_unicode(value.text, "utf-8")
581 581
582 582 if textline is not None:
583 583 i = 0
584 584 while i < len(textline) and textline[i].isspace():
585 585 i += 1
586 586 list.append('%s %s%s\n' % (Colors.line,
587 587 textline.strip(),
588 588 Colors.Normal))
589 589 if value.offset is not None:
590 590 s = ' '
591 591 for c in textline[i:value.offset-1]:
592 592 if c.isspace():
593 593 s += c
594 594 else:
595 595 s += ' '
596 596 list.append('%s%s^%s\n' % (Colors.caret, s,
597 597 Colors.Normal) )
598 598
599 599 try:
600 600 s = value.msg
601 601 except Exception:
602 602 s = self._some_str(value)
603 603 if s:
604 604 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
605 605 Colors.Normal, s))
606 606 else:
607 607 list.append('%s\n' % str(stype))
608 608
609 609 # sync with user hooks
610 610 if have_filedata:
611 611 ipinst = get_ipython()
612 612 if ipinst is not None:
613 613 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
614 614
615 615 return list
616 616
617 617 def get_exception_only(self, etype, value):
618 618 """Only print the exception type and message, without a traceback.
619 619
620 620 Parameters
621 621 ----------
622 622 etype : exception type
623 623 value : exception value
624 624 """
625 625 return ListTB.structured_traceback(self, etype, value, [])
626 626
627 627
628 628 def show_exception_only(self, etype, evalue):
629 629 """Only print the exception type and message, without a traceback.
630 630
631 631 Parameters
632 632 ----------
633 633 etype : exception type
634 634 value : exception value
635 635 """
636 636 # This method needs to use __call__ from *this* class, not the one from
637 637 # a subclass whose signature or behavior may be different
638 638 ostream = self.ostream
639 639 ostream.flush()
640 640 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
641 641 ostream.flush()
642 642
643 643 def _some_str(self, value):
644 644 # Lifted from traceback.py
645 645 try:
646 646 return str(value)
647 647 except:
648 648 return '<unprintable %s object>' % type(value).__name__
649 649
650 650 #----------------------------------------------------------------------------
651 651 class VerboseTB(TBTools):
652 652 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
653 653 of HTML. Requires inspect and pydoc. Crazy, man.
654 654
655 655 Modified version which optionally strips the topmost entries from the
656 656 traceback, to be used with alternate interpreters (because their own code
657 657 would appear in the traceback)."""
658 658
659 659 def __init__(self,color_scheme = 'Linux', call_pdb=False, ostream=None,
660 660 tb_offset=0, long_header=False, include_vars=True,
661 661 check_cache=None):
662 662 """Specify traceback offset, headers and color scheme.
663 663
664 664 Define how many frames to drop from the tracebacks. Calling it with
665 665 tb_offset=1 allows use of this handler in interpreters which will have
666 666 their own code at the top of the traceback (VerboseTB will first
667 667 remove that frame before printing the traceback info)."""
668 668 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
669 669 ostream=ostream)
670 670 self.tb_offset = tb_offset
671 671 self.long_header = long_header
672 672 self.include_vars = include_vars
673 673 # By default we use linecache.checkcache, but the user can provide a
674 674 # different check_cache implementation. This is used by the IPython
675 675 # kernel to provide tracebacks for interactive code that is cached,
676 676 # by a compiler instance that flushes the linecache but preserves its
677 677 # own code cache.
678 678 if check_cache is None:
679 679 check_cache = linecache.checkcache
680 680 self.check_cache = check_cache
681 681
682 682 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
683 683 context=5):
684 684 """Return a nice text document describing the traceback."""
685 685
686 686 tb_offset = self.tb_offset if tb_offset is None else tb_offset
687 687
688 688 # some locals
689 689 try:
690 690 etype = etype.__name__
691 691 except AttributeError:
692 692 pass
693 693 Colors = self.Colors # just a shorthand + quicker name lookup
694 694 ColorsNormal = Colors.Normal # used a lot
695 695 col_scheme = self.color_scheme_table.active_scheme_name
696 696 indent = ' '*INDENT_SIZE
697 697 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
698 698 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
699 699 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
700 700
701 701 # some internal-use functions
702 702 def text_repr(value):
703 703 """Hopefully pretty robust repr equivalent."""
704 704 # this is pretty horrible but should always return *something*
705 705 try:
706 706 return pydoc.text.repr(value)
707 707 except KeyboardInterrupt:
708 708 raise
709 709 except:
710 710 try:
711 711 return repr(value)
712 712 except KeyboardInterrupt:
713 713 raise
714 714 except:
715 715 try:
716 716 # all still in an except block so we catch
717 717 # getattr raising
718 718 name = getattr(value, '__name__', None)
719 719 if name:
720 720 # ick, recursion
721 721 return text_repr(name)
722 722 klass = getattr(value, '__class__', None)
723 723 if klass:
724 724 return '%s instance' % text_repr(klass)
725 725 except KeyboardInterrupt:
726 726 raise
727 727 except:
728 728 return 'UNRECOVERABLE REPR FAILURE'
729 729 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
730 730 def nullrepr(value, repr=text_repr): return ''
731 731
732 732 # meat of the code begins
733 733 try:
734 734 etype = etype.__name__
735 735 except AttributeError:
736 736 pass
737 737
738 738 if self.long_header:
739 739 # Header with the exception type, python version, and date
740 740 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
741 741 date = time.ctime(time.time())
742 742
743 743 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
744 744 exc, ' '*(75-len(str(etype))-len(pyver)),
745 745 pyver, date.rjust(75) )
746 746 head += "\nA problem occured executing Python code. Here is the sequence of function"\
747 747 "\ncalls leading up to the error, with the most recent (innermost) call last."
748 748 else:
749 749 # Simplified header
750 750 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
751 751 'Traceback (most recent call last)'.\
752 752 rjust(75 - len(str(etype)) ) )
753 753 frames = []
754 754 # Flush cache before calling inspect. This helps alleviate some of the
755 755 # problems with python 2.3's inspect.py.
756 756 ##self.check_cache()
757 757 # Drop topmost frames if requested
758 758 try:
759 759 # Try the default getinnerframes and Alex's: Alex's fixes some
760 760 # problems, but it generates empty tracebacks for console errors
761 761 # (5 blanks lines) where none should be returned.
762 762 #records = inspect.getinnerframes(etb, context)[tb_offset:]
763 763 #print 'python records:', records # dbg
764 764 records = _fixed_getinnerframes(etb, context, tb_offset)
765 765 #print 'alex records:', records # dbg
766 766 except:
767 767
768 768 # FIXME: I've been getting many crash reports from python 2.3
769 769 # users, traceable to inspect.py. If I can find a small test-case
770 770 # to reproduce this, I should either write a better workaround or
771 771 # file a bug report against inspect (if that's the real problem).
772 772 # So far, I haven't been able to find an isolated example to
773 773 # reproduce the problem.
774 774 inspect_error()
775 775 traceback.print_exc(file=self.ostream)
776 776 info('\nUnfortunately, your original traceback can not be constructed.\n')
777 777 return ''
778 778
779 779 # build some color string templates outside these nested loops
780 780 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
781 781 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
782 782 ColorsNormal)
783 783 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
784 784 (Colors.vName, Colors.valEm, ColorsNormal)
785 785 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
786 786 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
787 787 Colors.vName, ColorsNormal)
788 788 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
789 789 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
790 790 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
791 791 ColorsNormal)
792 792
793 793 # now, loop over all records printing context and info
794 794 abspath = os.path.abspath
795 795 for frame, file, lnum, func, lines, index in records:
796 796 #print '*** record:',file,lnum,func,lines,index # dbg
797 797 if not file:
798 798 file = '?'
799 799 elif not(file.startswith(str("<")) and file.endswith(str(">"))):
800 800 # Guess that filenames like <string> aren't real filenames, so
801 801 # don't call abspath on them.
802 802 try:
803 803 file = abspath(file)
804 804 except OSError:
805 805 # Not sure if this can still happen: abspath now works with
806 806 # file names like <string>
807 807 pass
808 808 file = py3compat.cast_unicode(file, util_path.fs_encoding)
809 809 link = tpl_link % file
810 810 args, varargs, varkw, locals = inspect.getargvalues(frame)
811 811
812 812 if func == '?':
813 813 call = ''
814 814 else:
815 815 # Decide whether to include variable details or not
816 816 var_repr = self.include_vars and eqrepr or nullrepr
817 817 try:
818 818 call = tpl_call % (func,inspect.formatargvalues(args,
819 819 varargs, varkw,
820 820 locals,formatvalue=var_repr))
821 821 except KeyError:
822 822 # This happens in situations like errors inside generator
823 823 # expressions, where local variables are listed in the
824 824 # line, but can't be extracted from the frame. I'm not
825 825 # 100% sure this isn't actually a bug in inspect itself,
826 826 # but since there's no info for us to compute with, the
827 827 # best we can do is report the failure and move on. Here
828 828 # we must *not* call any traceback construction again,
829 829 # because that would mess up use of %debug later on. So we
830 830 # simply report the failure and move on. The only
831 831 # limitation will be that this frame won't have locals
832 832 # listed in the call signature. Quite subtle problem...
833 833 # I can't think of a good way to validate this in a unit
834 834 # test, but running a script consisting of:
835 835 # dict( (k,v.strip()) for (k,v) in range(10) )
836 836 # will illustrate the error, if this exception catch is
837 837 # disabled.
838 838 call = tpl_call_fail % func
839 839
840 840 # Don't attempt to tokenize binary files.
841 841 if file.endswith(('.so', '.pyd', '.dll')):
842 842 frames.append('%s %s\n' % (link,call))
843 843 continue
844 844 elif file.endswith(('.pyc','.pyo')):
845 845 # Look up the corresponding source file.
846 846 file = openpy.source_from_cache(file)
847 847
848 848 def linereader(file=file, lnum=[lnum], getline=ulinecache.getline):
849 849 line = getline(file, lnum[0])
850 850 lnum[0] += 1
851 851 return line
852 852
853 853 # Build the list of names on this line of code where the exception
854 854 # occurred.
855 855 try:
856 856 names = []
857 857 name_cont = False
858 858
859 859 for token_type, token, start, end, line in generate_tokens(linereader):
860 860 # build composite names
861 861 if token_type == tokenize.NAME and token not in keyword.kwlist:
862 862 if name_cont:
863 863 # Continuation of a dotted name
864 864 try:
865 865 names[-1].append(token)
866 866 except IndexError:
867 867 names.append([token])
868 868 name_cont = False
869 869 else:
870 870 # Regular new names. We append everything, the caller
871 871 # will be responsible for pruning the list later. It's
872 872 # very tricky to try to prune as we go, b/c composite
873 873 # names can fool us. The pruning at the end is easy
874 874 # to do (or the caller can print a list with repeated
875 875 # names if so desired.
876 876 names.append([token])
877 877 elif token == '.':
878 878 name_cont = True
879 879 elif token_type == tokenize.NEWLINE:
880 880 break
881 881
882 882 except (IndexError, UnicodeDecodeError):
883 883 # signals exit of tokenizer
884 884 pass
885 885 except tokenize.TokenError as msg:
886 886 _m = ("An unexpected error occurred while tokenizing input\n"
887 887 "The following traceback may be corrupted or invalid\n"
888 888 "The error message is: %s\n" % msg)
889 889 error(_m)
890 890
891 891 # Join composite names (e.g. "dict.fromkeys")
892 892 names = ['.'.join(n) for n in names]
893 893 # prune names list of duplicates, but keep the right order
894 894 unique_names = uniq_stable(names)
895 895
896 896 # Start loop over vars
897 897 lvals = []
898 898 if self.include_vars:
899 899 for name_full in unique_names:
900 900 name_base = name_full.split('.',1)[0]
901 901 if name_base in frame.f_code.co_varnames:
902 902 if name_base in locals:
903 903 try:
904 904 value = repr(eval(name_full,locals))
905 905 except:
906 906 value = undefined
907 907 else:
908 908 value = undefined
909 909 name = tpl_local_var % name_full
910 910 else:
911 911 if name_base in frame.f_globals:
912 912 try:
913 913 value = repr(eval(name_full,frame.f_globals))
914 914 except:
915 915 value = undefined
916 916 else:
917 917 value = undefined
918 918 name = tpl_global_var % name_full
919 919 lvals.append(tpl_name_val % (name,value))
920 920 if lvals:
921 921 lvals = '%s%s' % (indent,em_normal.join(lvals))
922 922 else:
923 923 lvals = ''
924 924
925 925 level = '%s %s\n' % (link,call)
926 926
927 927 if index is None:
928 928 frames.append(level)
929 929 else:
930 930 frames.append('%s%s' % (level,''.join(
931 931 _format_traceback_lines(lnum,index,lines,Colors,lvals,
932 932 col_scheme))))
933 933
934 934 # Get (safely) a string form of the exception info
935 935 try:
936 936 etype_str,evalue_str = map(str,(etype,evalue))
937 937 except:
938 938 # User exception is improperly defined.
939 939 etype,evalue = str,sys.exc_info()[:2]
940 940 etype_str,evalue_str = map(str,(etype,evalue))
941 941 # ... and format it
942 942 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
943 943 ColorsNormal, py3compat.cast_unicode(evalue_str))]
944 944 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
945 945 try:
946 946 names = [w for w in dir(evalue) if isinstance(w, py3compat.string_types)]
947 947 except:
948 948 # Every now and then, an object with funny inernals blows up
949 949 # when dir() is called on it. We do the best we can to report
950 950 # the problem and continue
951 951 _m = '%sException reporting error (object with broken dir())%s:'
952 952 exception.append(_m % (Colors.excName,ColorsNormal))
953 953 etype_str,evalue_str = map(str,sys.exc_info()[:2])
954 954 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
955 955 ColorsNormal, py3compat.cast_unicode(evalue_str)))
956 956 names = []
957 957 for name in names:
958 958 value = text_repr(getattr(evalue, name))
959 959 exception.append('\n%s%s = %s' % (indent, name, value))
960 960
961 961 # vds: >>
962 962 if records:
963 963 filepath, lnum = records[-1][1:3]
964 964 #print "file:", str(file), "linenb", str(lnum) # dbg
965 965 filepath = os.path.abspath(filepath)
966 966 ipinst = get_ipython()
967 967 if ipinst is not None:
968 968 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
969 969 # vds: <<
970 970
971 971 # return all our info assembled as a single string
972 972 # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
973 973 return [head] + frames + [''.join(exception[0])]
974 974
975 975 def debugger(self,force=False):
976 976 """Call up the pdb debugger if desired, always clean up the tb
977 977 reference.
978 978
979 979 Keywords:
980 980
981 981 - force(False): by default, this routine checks the instance call_pdb
982 982 flag and does not actually invoke the debugger if the flag is false.
983 983 The 'force' option forces the debugger to activate even if the flag
984 984 is false.
985 985
986 986 If the call_pdb flag is set, the pdb interactive debugger is
987 987 invoked. In all cases, the self.tb reference to the current traceback
988 988 is deleted to prevent lingering references which hamper memory
989 989 management.
990 990
991 991 Note that each call to pdb() does an 'import readline', so if your app
992 992 requires a special setup for the readline completers, you'll have to
993 993 fix that by hand after invoking the exception handler."""
994 994
995 995 if force or self.call_pdb:
996 996 if self.pdb is None:
997 997 self.pdb = debugger.Pdb(
998 998 self.color_scheme_table.active_scheme_name)
999 999 # the system displayhook may have changed, restore the original
1000 1000 # for pdb
1001 1001 display_trap = DisplayTrap(hook=sys.__displayhook__)
1002 1002 with display_trap:
1003 1003 self.pdb.reset()
1004 1004 # Find the right frame so we don't pop up inside ipython itself
1005 1005 if hasattr(self,'tb') and self.tb is not None:
1006 1006 etb = self.tb
1007 1007 else:
1008 1008 etb = self.tb = sys.last_traceback
1009 1009 while self.tb is not None and self.tb.tb_next is not None:
1010 1010 self.tb = self.tb.tb_next
1011 1011 if etb and etb.tb_next:
1012 1012 etb = etb.tb_next
1013 1013 self.pdb.botframe = etb.tb_frame
1014 1014 self.pdb.interaction(self.tb.tb_frame, self.tb)
1015 1015
1016 1016 if hasattr(self,'tb'):
1017 1017 del self.tb
1018 1018
1019 1019 def handler(self, info=None):
1020 1020 (etype, evalue, etb) = info or sys.exc_info()
1021 1021 self.tb = etb
1022 1022 ostream = self.ostream
1023 1023 ostream.flush()
1024 1024 ostream.write(self.text(etype, evalue, etb))
1025 1025 ostream.write('\n')
1026 1026 ostream.flush()
1027 1027
1028 1028 # Changed so an instance can just be called as VerboseTB_inst() and print
1029 1029 # out the right info on its own.
1030 1030 def __call__(self, etype=None, evalue=None, etb=None):
1031 1031 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1032 1032 if etb is None:
1033 1033 self.handler()
1034 1034 else:
1035 1035 self.handler((etype, evalue, etb))
1036 1036 try:
1037 1037 self.debugger()
1038 1038 except KeyboardInterrupt:
1039 1039 print("\nKeyboardInterrupt")
1040 1040
1041 1041 #----------------------------------------------------------------------------
1042 1042 class FormattedTB(VerboseTB, ListTB):
1043 1043 """Subclass ListTB but allow calling with a traceback.
1044 1044
1045 1045 It can thus be used as a sys.excepthook for Python > 2.1.
1046 1046
1047 1047 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1048 1048
1049 1049 Allows a tb_offset to be specified. This is useful for situations where
1050 1050 one needs to remove a number of topmost frames from the traceback (such as
1051 1051 occurs with python programs that themselves execute other python code,
1052 1052 like Python shells). """
1053 1053
1054 1054 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1055 1055 ostream=None,
1056 1056 tb_offset=0, long_header=False, include_vars=False,
1057 1057 check_cache=None):
1058 1058
1059 1059 # NEVER change the order of this list. Put new modes at the end:
1060 1060 self.valid_modes = ['Plain','Context','Verbose']
1061 1061 self.verbose_modes = self.valid_modes[1:3]
1062 1062
1063 1063 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1064 1064 ostream=ostream, tb_offset=tb_offset,
1065 1065 long_header=long_header, include_vars=include_vars,
1066 1066 check_cache=check_cache)
1067 1067
1068 1068 # Different types of tracebacks are joined with different separators to
1069 1069 # form a single string. They are taken from this dict
1070 1070 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1071 1071 # set_mode also sets the tb_join_char attribute
1072 1072 self.set_mode(mode)
1073 1073
1074 1074 def _extract_tb(self,tb):
1075 1075 if tb:
1076 1076 return traceback.extract_tb(tb)
1077 1077 else:
1078 1078 return None
1079 1079
1080 1080 def structured_traceback(self, etype, value, tb, tb_offset=None, context=5):
1081 1081 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1082 1082 mode = self.mode
1083 1083 if mode in self.verbose_modes:
1084 1084 # Verbose modes need a full traceback
1085 1085 return VerboseTB.structured_traceback(
1086 1086 self, etype, value, tb, tb_offset, context
1087 1087 )
1088 1088 else:
1089 1089 # We must check the source cache because otherwise we can print
1090 1090 # out-of-date source code.
1091 1091 self.check_cache()
1092 1092 # Now we can extract and format the exception
1093 1093 elist = self._extract_tb(tb)
1094 1094 return ListTB.structured_traceback(
1095 1095 self, etype, value, elist, tb_offset, context
1096 1096 )
1097 1097
1098 1098 def stb2text(self, stb):
1099 1099 """Convert a structured traceback (a list) to a string."""
1100 1100 return self.tb_join_char.join(stb)
1101 1101
1102 1102
1103 1103 def set_mode(self,mode=None):
1104 1104 """Switch to the desired mode.
1105 1105
1106 1106 If mode is not specified, cycles through the available modes."""
1107 1107
1108 1108 if not mode:
1109 1109 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
1110 1110 len(self.valid_modes)
1111 1111 self.mode = self.valid_modes[new_idx]
1112 1112 elif mode not in self.valid_modes:
1113 1113 raise ValueError('Unrecognized mode in FormattedTB: <'+mode+'>\n'
1114 1114 'Valid modes: '+str(self.valid_modes))
1115 1115 else:
1116 1116 self.mode = mode
1117 1117 # include variable details only in 'Verbose' mode
1118 1118 self.include_vars = (self.mode == self.valid_modes[2])
1119 1119 # Set the join character for generating text tracebacks
1120 1120 self.tb_join_char = self._join_chars[self.mode]
1121 1121
1122 1122 # some convenient shorcuts
1123 1123 def plain(self):
1124 1124 self.set_mode(self.valid_modes[0])
1125 1125
1126 1126 def context(self):
1127 1127 self.set_mode(self.valid_modes[1])
1128 1128
1129 1129 def verbose(self):
1130 1130 self.set_mode(self.valid_modes[2])
1131 1131
1132 1132 #----------------------------------------------------------------------------
1133 1133 class AutoFormattedTB(FormattedTB):
1134 1134 """A traceback printer which can be called on the fly.
1135 1135
1136 1136 It will find out about exceptions by itself.
1137 1137
1138 1138 A brief example::
1139 1139
1140 1140 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1141 1141 try:
1142 1142 ...
1143 1143 except:
1144 1144 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1145 1145 """
1146 1146
1147 1147 def __call__(self,etype=None,evalue=None,etb=None,
1148 1148 out=None,tb_offset=None):
1149 1149 """Print out a formatted exception traceback.
1150 1150
1151 1151 Optional arguments:
1152 1152 - out: an open file-like object to direct output to.
1153 1153
1154 1154 - tb_offset: the number of frames to skip over in the stack, on a
1155 1155 per-call basis (this overrides temporarily the instance's tb_offset
1156 1156 given at initialization time. """
1157 1157
1158 1158
1159 1159 if out is None:
1160 1160 out = self.ostream
1161 1161 out.flush()
1162 1162 out.write(self.text(etype, evalue, etb, tb_offset))
1163 1163 out.write('\n')
1164 1164 out.flush()
1165 1165 # FIXME: we should remove the auto pdb behavior from here and leave
1166 1166 # that to the clients.
1167 1167 try:
1168 1168 self.debugger()
1169 1169 except KeyboardInterrupt:
1170 1170 print("\nKeyboardInterrupt")
1171 1171
1172 1172 def structured_traceback(self, etype=None, value=None, tb=None,
1173 1173 tb_offset=None, context=5):
1174 1174 if etype is None:
1175 1175 etype,value,tb = sys.exc_info()
1176 1176 self.tb = tb
1177 1177 return FormattedTB.structured_traceback(
1178 1178 self, etype, value, tb, tb_offset, context)
1179 1179
1180 1180 #---------------------------------------------------------------------------
1181 1181
1182 1182 # A simple class to preserve Nathan's original functionality.
1183 1183 class ColorTB(FormattedTB):
1184 1184 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1185 1185 def __init__(self,color_scheme='Linux',call_pdb=0):
1186 1186 FormattedTB.__init__(self,color_scheme=color_scheme,
1187 1187 call_pdb=call_pdb)
1188 1188
1189 1189
1190 1190 class SyntaxTB(ListTB):
1191 1191 """Extension which holds some state: the last exception value"""
1192 1192
1193 1193 def __init__(self,color_scheme = 'NoColor'):
1194 1194 ListTB.__init__(self,color_scheme)
1195 1195 self.last_syntax_error = None
1196 1196
1197 1197 def __call__(self, etype, value, elist):
1198 1198 self.last_syntax_error = value
1199 1199 ListTB.__call__(self,etype,value,elist)
1200 1200
1201 1201 def structured_traceback(self, etype, value, elist, tb_offset=None,
1202 1202 context=5):
1203 1203 # If the source file has been edited, the line in the syntax error can
1204 1204 # be wrong (retrieved from an outdated cache). This replaces it with
1205 1205 # the current value.
1206 1206 if isinstance(value, SyntaxError) \
1207 1207 and isinstance(value.filename, py3compat.string_types) \
1208 1208 and isinstance(value.lineno, int):
1209 1209 linecache.checkcache(value.filename)
1210 1210 newtext = ulinecache.getline(value.filename, value.lineno)
1211 1211 if newtext:
1212 1212 value.text = newtext
1213 1213 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1214 1214 tb_offset=tb_offset, context=context)
1215 1215
1216 1216 def clear_err_state(self):
1217 1217 """Return the current error state and clear it"""
1218 1218 e = self.last_syntax_error
1219 1219 self.last_syntax_error = None
1220 1220 return e
1221 1221
1222 1222 def stb2text(self, stb):
1223 1223 """Convert a structured traceback (a list) to a string."""
1224 1224 return ''.join(stb)
1225 1225
1226 1226
1227 1227 #----------------------------------------------------------------------------
1228 1228 # module testing (minimal)
1229 1229 if __name__ == "__main__":
1230 1230 def spam(c, d_e):
1231 1231 (d, e) = d_e
1232 1232 x = c + d
1233 1233 y = c * d
1234 1234 foo(x, y)
1235 1235
1236 1236 def foo(a, b, bar=1):
1237 1237 eggs(a, b + bar)
1238 1238
1239 1239 def eggs(f, g, z=globals()):
1240 1240 h = f + g
1241 1241 i = f - g
1242 1242 return h / i
1243 1243
1244 1244 print('')
1245 1245 print('*** Before ***')
1246 1246 try:
1247 1247 print(spam(1, (2, 3)))
1248 1248 except:
1249 1249 traceback.print_exc()
1250 1250 print('')
1251 1251
1252 1252 handler = ColorTB()
1253 1253 print('*** ColorTB ***')
1254 1254 try:
1255 1255 print(spam(1, (2, 3)))
1256 1256 except:
1257 1257 handler(*sys.exc_info())
1258 1258 print('')
1259 1259
1260 1260 handler = VerboseTB()
1261 1261 print('*** VerboseTB ***')
1262 1262 try:
1263 1263 print(spam(1, (2, 3)))
1264 1264 except:
1265 1265 handler(*sys.exc_info())
1266 1266 print('')
1267 1267
@@ -1,509 +1,509 b''
1 1 """IPython extension to reload modules before executing user code.
2 2
3 3 ``autoreload`` reloads modules automatically before entering the execution of
4 4 code typed at the IPython prompt.
5 5
6 6 This makes for example the following workflow possible:
7 7
8 8 .. sourcecode:: ipython
9 9
10 10 In [1]: %load_ext autoreload
11 11
12 12 In [2]: %autoreload 2
13 13
14 14 In [3]: from foo import some_function
15 15
16 16 In [4]: some_function()
17 17 Out[4]: 42
18 18
19 19 In [5]: # open foo.py in an editor and change some_function to return 43
20 20
21 21 In [6]: some_function()
22 22 Out[6]: 43
23 23
24 24 The module was reloaded without reloading it explicitly, and the object
25 25 imported with ``from foo import ...`` was also updated.
26 26
27 27 Usage
28 28 =====
29 29
30 30 The following magic commands are provided:
31 31
32 32 ``%autoreload``
33 33
34 34 Reload all modules (except those excluded by ``%aimport``)
35 35 automatically now.
36 36
37 37 ``%autoreload 0``
38 38
39 39 Disable automatic reloading.
40 40
41 41 ``%autoreload 1``
42 42
43 43 Reload all modules imported with ``%aimport`` every time before
44 44 executing the Python code typed.
45 45
46 46 ``%autoreload 2``
47 47
48 48 Reload all modules (except those excluded by ``%aimport``) every
49 49 time before executing the Python code typed.
50 50
51 51 ``%aimport``
52 52
53 53 List modules which are to be automatically imported or not to be imported.
54 54
55 55 ``%aimport foo``
56 56
57 57 Import module 'foo' and mark it to be autoreloaded for ``%autoreload 1``
58 58
59 59 ``%aimport -foo``
60 60
61 61 Mark module 'foo' to not be autoreloaded.
62 62
63 63 Caveats
64 64 =======
65 65
66 66 Reloading Python modules in a reliable way is in general difficult,
67 67 and unexpected things may occur. ``%autoreload`` tries to work around
68 68 common pitfalls by replacing function code objects and parts of
69 69 classes previously in the module with new versions. This makes the
70 70 following things to work:
71 71
72 72 - Functions and classes imported via 'from xxx import foo' are upgraded
73 73 to new versions when 'xxx' is reloaded.
74 74
75 75 - Methods and properties of classes are upgraded on reload, so that
76 76 calling 'c.foo()' on an object 'c' created before the reload causes
77 77 the new code for 'foo' to be executed.
78 78
79 79 Some of the known remaining caveats are:
80 80
81 81 - Replacing code objects does not always succeed: changing a @property
82 82 in a class to an ordinary method or a method to a member variable
83 83 can cause problems (but in old objects only).
84 84
85 85 - Functions that are removed (eg. via monkey-patching) from a module
86 86 before it is reloaded are not upgraded.
87 87
88 88 - C extension modules cannot be reloaded, and so cannot be autoreloaded.
89 89 """
90 90 from __future__ import print_function
91 91
92 92 skip_doctest = True
93 93
94 94 #-----------------------------------------------------------------------------
95 95 # Copyright (C) 2000 Thomas Heller
96 96 # Copyright (C) 2008 Pauli Virtanen <pav@iki.fi>
97 97 # Copyright (C) 2012 The IPython Development Team
98 98 #
99 99 # Distributed under the terms of the BSD License. The full license is in
100 100 # the file COPYING, distributed as part of this software.
101 101 #-----------------------------------------------------------------------------
102 102 #
103 103 # This IPython module is written by Pauli Virtanen, based on the autoreload
104 104 # code by Thomas Heller.
105 105
106 106 #-----------------------------------------------------------------------------
107 107 # Imports
108 108 #-----------------------------------------------------------------------------
109 109
110 110 import os
111 111 import sys
112 112 import traceback
113 113 import types
114 114 import weakref
115 115
116 116 try:
117 117 # Reload is not defined by default in Python3.
118 118 reload
119 119 except NameError:
120 120 from imp import reload
121 121
122 122 from IPython.utils import openpy
123 123 from IPython.utils.py3compat import PY3
124 124
125 125 #------------------------------------------------------------------------------
126 126 # Autoreload functionality
127 127 #------------------------------------------------------------------------------
128 128
129 129 class ModuleReloader(object):
130 130 enabled = False
131 131 """Whether this reloader is enabled"""
132 132
133 133 failed = {}
134 134 """Modules that failed to reload: {module: mtime-on-failed-reload, ...}"""
135 135
136 136 modules = {}
137 137 """Modules specially marked as autoreloadable."""
138 138
139 139 skip_modules = {}
140 140 """Modules specially marked as not autoreloadable."""
141 141
142 142 check_all = True
143 143 """Autoreload all modules, not just those listed in 'modules'"""
144 144
145 145 old_objects = {}
146 146 """(module-name, name) -> weakref, for replacing old code objects"""
147 147
148 148 def mark_module_skipped(self, module_name):
149 149 """Skip reloading the named module in the future"""
150 150 try:
151 151 del self.modules[module_name]
152 152 except KeyError:
153 153 pass
154 154 self.skip_modules[module_name] = True
155 155
156 156 def mark_module_reloadable(self, module_name):
157 157 """Reload the named module in the future (if it is imported)"""
158 158 try:
159 159 del self.skip_modules[module_name]
160 160 except KeyError:
161 161 pass
162 162 self.modules[module_name] = True
163 163
164 164 def aimport_module(self, module_name):
165 165 """Import a module, and mark it reloadable
166 166
167 167 Returns
168 168 -------
169 169 top_module : module
170 170 The imported module if it is top-level, or the top-level
171 171 top_name : module
172 172 Name of top_module
173 173
174 174 """
175 175 self.mark_module_reloadable(module_name)
176 176
177 177 __import__(module_name)
178 178 top_name = module_name.split('.')[0]
179 179 top_module = sys.modules[top_name]
180 180 return top_module, top_name
181 181
182 182 def check(self, check_all=False):
183 183 """Check whether some modules need to be reloaded."""
184 184
185 185 if not self.enabled and not check_all:
186 186 return
187 187
188 188 if check_all or self.check_all:
189 189 modules = sys.modules.keys()
190 190 else:
191 191 modules = self.modules.keys()
192 192
193 193 for modname in modules:
194 194 m = sys.modules.get(modname, None)
195 195
196 196 if modname in self.skip_modules:
197 197 continue
198 198
199 199 if not hasattr(m, '__file__'):
200 200 continue
201 201
202 202 if m.__name__ == '__main__':
203 203 # we cannot reload(__main__)
204 204 continue
205 205
206 206 filename = m.__file__
207 207 path, ext = os.path.splitext(filename)
208 208
209 209 if ext.lower() == '.py':
210 210 pyc_filename = openpy.cache_from_source(filename)
211 211 py_filename = filename
212 212 else:
213 213 pyc_filename = filename
214 214 try:
215 215 py_filename = openpy.source_from_cache(filename)
216 216 except ValueError:
217 217 continue
218 218
219 219 try:
220 220 pymtime = os.stat(py_filename).st_mtime
221 221 if pymtime <= os.stat(pyc_filename).st_mtime:
222 222 continue
223 223 if self.failed.get(py_filename, None) == pymtime:
224 224 continue
225 225 except OSError:
226 226 continue
227 227
228 228 try:
229 229 superreload(m, reload, self.old_objects)
230 230 if py_filename in self.failed:
231 231 del self.failed[py_filename]
232 232 except:
233 233 print("[autoreload of %s failed: %s]" % (
234 234 modname, traceback.format_exc(1)), file=sys.stderr)
235 235 self.failed[py_filename] = pymtime
236 236
237 237 #------------------------------------------------------------------------------
238 238 # superreload
239 239 #------------------------------------------------------------------------------
240 240
241 241 if PY3:
242 242 func_attrs = ['__code__', '__defaults__', '__doc__',
243 243 '__closure__', '__globals__', '__dict__']
244 244 else:
245 245 func_attrs = ['func_code', 'func_defaults', 'func_doc',
246 246 'func_closure', 'func_globals', 'func_dict']
247 247
248 248
249 249 def update_function(old, new):
250 250 """Upgrade the code object of a function"""
251 251 for name in func_attrs:
252 252 try:
253 253 setattr(old, name, getattr(new, name))
254 254 except (AttributeError, TypeError):
255 255 pass
256 256
257 257
258 258 def update_class(old, new):
259 259 """Replace stuff in the __dict__ of a class, and upgrade
260 260 method code objects"""
261 261 for key in old.__dict__.keys():
262 262 old_obj = getattr(old, key)
263 263
264 264 try:
265 265 new_obj = getattr(new, key)
266 266 except AttributeError:
267 267 # obsolete attribute: remove it
268 268 try:
269 269 delattr(old, key)
270 270 except (AttributeError, TypeError):
271 271 pass
272 272 continue
273 273
274 274 if update_generic(old_obj, new_obj): continue
275 275
276 276 try:
277 277 setattr(old, key, getattr(new, key))
278 278 except (AttributeError, TypeError):
279 279 pass # skip non-writable attributes
280 280
281 281
282 282 def update_property(old, new):
283 283 """Replace get/set/del functions of a property"""
284 284 update_generic(old.fdel, new.fdel)
285 285 update_generic(old.fget, new.fget)
286 286 update_generic(old.fset, new.fset)
287 287
288 288
289 289 def isinstance2(a, b, typ):
290 290 return isinstance(a, typ) and isinstance(b, typ)
291 291
292 292
293 293 UPDATE_RULES = [
294 294 (lambda a, b: isinstance2(a, b, type),
295 295 update_class),
296 296 (lambda a, b: isinstance2(a, b, types.FunctionType),
297 297 update_function),
298 298 (lambda a, b: isinstance2(a, b, property),
299 299 update_property),
300 300 ]
301 301
302 302
303 303 if PY3:
304 304 UPDATE_RULES.extend([(lambda a, b: isinstance2(a, b, types.MethodType),
305 305 lambda a, b: update_function(a.__func__, b.__func__)),
306 306 ])
307 307 else:
308 308 UPDATE_RULES.extend([(lambda a, b: isinstance2(a, b, types.ClassType),
309 309 update_class),
310 310 (lambda a, b: isinstance2(a, b, types.MethodType),
311 lambda a, b: update_function(a.im_func, b.im_func)),
311 lambda a, b: update_function(a.__func__, b.__func__)),
312 312 ])
313 313
314 314
315 315 def update_generic(a, b):
316 316 for type_check, update in UPDATE_RULES:
317 317 if type_check(a, b):
318 318 update(a, b)
319 319 return True
320 320 return False
321 321
322 322
323 323 class StrongRef(object):
324 324 def __init__(self, obj):
325 325 self.obj = obj
326 326 def __call__(self):
327 327 return self.obj
328 328
329 329
330 330 def superreload(module, reload=reload, old_objects={}):
331 331 """Enhanced version of the builtin reload function.
332 332
333 333 superreload remembers objects previously in the module, and
334 334
335 335 - upgrades the class dictionary of every old class in the module
336 336 - upgrades the code object of every old function and method
337 337 - clears the module's namespace before reloading
338 338
339 339 """
340 340
341 341 # collect old objects in the module
342 342 for name, obj in module.__dict__.items():
343 343 if not hasattr(obj, '__module__') or obj.__module__ != module.__name__:
344 344 continue
345 345 key = (module.__name__, name)
346 346 try:
347 347 old_objects.setdefault(key, []).append(weakref.ref(obj))
348 348 except TypeError:
349 349 # weakref doesn't work for all types;
350 350 # create strong references for 'important' cases
351 351 if not PY3 and isinstance(obj, types.ClassType):
352 352 old_objects.setdefault(key, []).append(StrongRef(obj))
353 353
354 354 # reload module
355 355 try:
356 356 # clear namespace first from old cruft
357 357 old_dict = module.__dict__.copy()
358 358 old_name = module.__name__
359 359 module.__dict__.clear()
360 360 module.__dict__['__name__'] = old_name
361 361 module.__dict__['__loader__'] = old_dict['__loader__']
362 362 except (TypeError, AttributeError, KeyError):
363 363 pass
364 364
365 365 try:
366 366 module = reload(module)
367 367 except:
368 368 # restore module dictionary on failed reload
369 369 module.__dict__.update(old_dict)
370 370 raise
371 371
372 372 # iterate over all objects and update functions & classes
373 373 for name, new_obj in module.__dict__.items():
374 374 key = (module.__name__, name)
375 375 if key not in old_objects: continue
376 376
377 377 new_refs = []
378 378 for old_ref in old_objects[key]:
379 379 old_obj = old_ref()
380 380 if old_obj is None: continue
381 381 new_refs.append(old_ref)
382 382 update_generic(old_obj, new_obj)
383 383
384 384 if new_refs:
385 385 old_objects[key] = new_refs
386 386 else:
387 387 del old_objects[key]
388 388
389 389 return module
390 390
391 391 #------------------------------------------------------------------------------
392 392 # IPython connectivity
393 393 #------------------------------------------------------------------------------
394 394
395 395 from IPython.core.hooks import TryNext
396 396 from IPython.core.magic import Magics, magics_class, line_magic
397 397
398 398 @magics_class
399 399 class AutoreloadMagics(Magics):
400 400 def __init__(self, *a, **kw):
401 401 super(AutoreloadMagics, self).__init__(*a, **kw)
402 402 self._reloader = ModuleReloader()
403 403 self._reloader.check_all = False
404 404
405 405 @line_magic
406 406 def autoreload(self, parameter_s=''):
407 407 r"""%autoreload => Reload modules automatically
408 408
409 409 %autoreload
410 410 Reload all modules (except those excluded by %aimport) automatically
411 411 now.
412 412
413 413 %autoreload 0
414 414 Disable automatic reloading.
415 415
416 416 %autoreload 1
417 417 Reload all modules imported with %aimport every time before executing
418 418 the Python code typed.
419 419
420 420 %autoreload 2
421 421 Reload all modules (except those excluded by %aimport) every time
422 422 before executing the Python code typed.
423 423
424 424 Reloading Python modules in a reliable way is in general
425 425 difficult, and unexpected things may occur. %autoreload tries to
426 426 work around common pitfalls by replacing function code objects and
427 427 parts of classes previously in the module with new versions. This
428 428 makes the following things to work:
429 429
430 430 - Functions and classes imported via 'from xxx import foo' are upgraded
431 431 to new versions when 'xxx' is reloaded.
432 432
433 433 - Methods and properties of classes are upgraded on reload, so that
434 434 calling 'c.foo()' on an object 'c' created before the reload causes
435 435 the new code for 'foo' to be executed.
436 436
437 437 Some of the known remaining caveats are:
438 438
439 439 - Replacing code objects does not always succeed: changing a @property
440 440 in a class to an ordinary method or a method to a member variable
441 441 can cause problems (but in old objects only).
442 442
443 443 - Functions that are removed (eg. via monkey-patching) from a module
444 444 before it is reloaded are not upgraded.
445 445
446 446 - C extension modules cannot be reloaded, and so cannot be
447 447 autoreloaded.
448 448
449 449 """
450 450 if parameter_s == '':
451 451 self._reloader.check(True)
452 452 elif parameter_s == '0':
453 453 self._reloader.enabled = False
454 454 elif parameter_s == '1':
455 455 self._reloader.check_all = False
456 456 self._reloader.enabled = True
457 457 elif parameter_s == '2':
458 458 self._reloader.check_all = True
459 459 self._reloader.enabled = True
460 460
461 461 @line_magic
462 462 def aimport(self, parameter_s='', stream=None):
463 463 """%aimport => Import modules for automatic reloading.
464 464
465 465 %aimport
466 466 List modules to automatically import and not to import.
467 467
468 468 %aimport foo
469 469 Import module 'foo' and mark it to be autoreloaded for %autoreload 1
470 470
471 471 %aimport -foo
472 472 Mark module 'foo' to not be autoreloaded for %autoreload 1
473 473 """
474 474 modname = parameter_s
475 475 if not modname:
476 476 to_reload = self._reloader.modules.keys()
477 477 to_reload.sort()
478 478 to_skip = self._reloader.skip_modules.keys()
479 479 to_skip.sort()
480 480 if stream is None:
481 481 stream = sys.stdout
482 482 if self._reloader.check_all:
483 483 stream.write("Modules to reload:\nall-except-skipped\n")
484 484 else:
485 485 stream.write("Modules to reload:\n%s\n" % ' '.join(to_reload))
486 486 stream.write("\nModules to skip:\n%s\n" % ' '.join(to_skip))
487 487 elif modname.startswith('-'):
488 488 modname = modname[1:]
489 489 self._reloader.mark_module_skipped(modname)
490 490 else:
491 491 top_module, top_name = self._reloader.aimport_module(modname)
492 492
493 493 # Inject module to user namespace
494 494 self.shell.push({top_name: top_module})
495 495
496 496 def pre_run_code_hook(self, ip):
497 497 if not self._reloader.enabled:
498 498 raise TryNext
499 499 try:
500 500 self._reloader.check()
501 501 except:
502 502 pass
503 503
504 504
505 505 def load_ipython_extension(ip):
506 506 """Load the extension in IPython."""
507 507 auto_reload = AutoreloadMagics(ip)
508 508 ip.register_magics(auto_reload)
509 509 ip.set_hook('pre_run_code_hook', auto_reload.pre_run_code_hook)
@@ -1,764 +1,764 b''
1 1 """Nose Plugin that supports IPython doctests.
2 2
3 3 Limitations:
4 4
5 5 - When generating examples for use as doctests, make sure that you have
6 6 pretty-printing OFF. This can be done either by setting the
7 7 ``PlainTextFormatter.pprint`` option in your configuration file to False, or
8 8 by interactively disabling it with %Pprint. This is required so that IPython
9 9 output matches that of normal Python, which is used by doctest for internal
10 10 execution.
11 11
12 12 - Do not rely on specific prompt numbers for results (such as using
13 13 '_34==True', for example). For IPython tests run via an external process the
14 14 prompt numbers may be different, and IPython tests run as normal python code
15 15 won't even have these special _NN variables set at all.
16 16 """
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Module imports
20 20
21 21 # From the standard library
22 22 import doctest
23 23 import inspect
24 24 import logging
25 25 import os
26 26 import re
27 27 import sys
28 28 import traceback
29 29 import unittest
30 30
31 31 from inspect import getmodule
32 32
33 33 # We are overriding the default doctest runner, so we need to import a few
34 34 # things from doctest directly
35 35 from doctest import (REPORTING_FLAGS, REPORT_ONLY_FIRST_FAILURE,
36 36 _unittest_reportflags, DocTestRunner,
37 37 _extract_future_flags, pdb, _OutputRedirectingPdb,
38 38 _exception_traceback,
39 39 linecache)
40 40
41 41 # Third-party modules
42 42 import nose.core
43 43
44 44 from nose.plugins import doctests, Plugin
45 45 from nose.util import anyp, getpackage, test_address, resolve_name, tolist
46 46
47 47 # Our own imports
48 48 from IPython.utils.py3compat import builtin_mod, PY3
49 49
50 50 if PY3:
51 51 from io import StringIO
52 52 else:
53 53 from StringIO import StringIO
54 54
55 55 #-----------------------------------------------------------------------------
56 56 # Module globals and other constants
57 57 #-----------------------------------------------------------------------------
58 58
59 59 log = logging.getLogger(__name__)
60 60
61 61
62 62 #-----------------------------------------------------------------------------
63 63 # Classes and functions
64 64 #-----------------------------------------------------------------------------
65 65
66 66 def is_extension_module(filename):
67 67 """Return whether the given filename is an extension module.
68 68
69 69 This simply checks that the extension is either .so or .pyd.
70 70 """
71 71 return os.path.splitext(filename)[1].lower() in ('.so','.pyd')
72 72
73 73
74 74 class DocTestSkip(object):
75 75 """Object wrapper for doctests to be skipped."""
76 76
77 77 ds_skip = """Doctest to skip.
78 78 >>> 1 #doctest: +SKIP
79 79 """
80 80
81 81 def __init__(self,obj):
82 82 self.obj = obj
83 83
84 84 def __getattribute__(self,key):
85 85 if key == '__doc__':
86 86 return DocTestSkip.ds_skip
87 87 else:
88 88 return getattr(object.__getattribute__(self,'obj'),key)
89 89
90 90 # Modified version of the one in the stdlib, that fixes a python bug (doctests
91 91 # not found in extension modules, http://bugs.python.org/issue3158)
92 92 class DocTestFinder(doctest.DocTestFinder):
93 93
94 94 def _from_module(self, module, object):
95 95 """
96 96 Return true if the given object is defined in the given
97 97 module.
98 98 """
99 99 if module is None:
100 100 return True
101 101 elif inspect.isfunction(object):
102 102 return module.__dict__ is object.__globals__
103 103 elif inspect.isbuiltin(object):
104 104 return module.__name__ == object.__module__
105 105 elif inspect.isclass(object):
106 106 return module.__name__ == object.__module__
107 107 elif inspect.ismethod(object):
108 108 # This one may be a bug in cython that fails to correctly set the
109 109 # __module__ attribute of methods, but since the same error is easy
110 110 # to make by extension code writers, having this safety in place
111 111 # isn't such a bad idea
112 return module.__name__ == object.im_class.__module__
112 return module.__name__ == object.__self__.__class__.__module__
113 113 elif inspect.getmodule(object) is not None:
114 114 return module is inspect.getmodule(object)
115 115 elif hasattr(object, '__module__'):
116 116 return module.__name__ == object.__module__
117 117 elif isinstance(object, property):
118 118 return True # [XX] no way not be sure.
119 119 else:
120 120 raise ValueError("object must be a class or function")
121 121
122 122 def _find(self, tests, obj, name, module, source_lines, globs, seen):
123 123 """
124 124 Find tests for the given object and any contained objects, and
125 125 add them to `tests`.
126 126 """
127 127 #print '_find for:', obj, name, module # dbg
128 128 if hasattr(obj,"skip_doctest"):
129 129 #print 'SKIPPING DOCTEST FOR:',obj # dbg
130 130 obj = DocTestSkip(obj)
131 131
132 132 doctest.DocTestFinder._find(self,tests, obj, name, module,
133 133 source_lines, globs, seen)
134 134
135 135 # Below we re-run pieces of the above method with manual modifications,
136 136 # because the original code is buggy and fails to correctly identify
137 137 # doctests in extension modules.
138 138
139 139 # Local shorthands
140 140 from inspect import isroutine, isclass, ismodule
141 141
142 142 # Look for tests in a module's contained objects.
143 143 if inspect.ismodule(obj) and self._recurse:
144 144 for valname, val in obj.__dict__.items():
145 145 valname1 = '%s.%s' % (name, valname)
146 146 if ( (isroutine(val) or isclass(val))
147 147 and self._from_module(module, val) ):
148 148
149 149 self._find(tests, val, valname1, module, source_lines,
150 150 globs, seen)
151 151
152 152 # Look for tests in a class's contained objects.
153 153 if inspect.isclass(obj) and self._recurse:
154 154 #print 'RECURSE into class:',obj # dbg
155 155 for valname, val in obj.__dict__.items():
156 156 # Special handling for staticmethod/classmethod.
157 157 if isinstance(val, staticmethod):
158 158 val = getattr(obj, valname)
159 159 if isinstance(val, classmethod):
160 val = getattr(obj, valname).im_func
160 val = getattr(obj, valname).__func__
161 161
162 162 # Recurse to methods, properties, and nested classes.
163 163 if ((inspect.isfunction(val) or inspect.isclass(val) or
164 164 inspect.ismethod(val) or
165 165 isinstance(val, property)) and
166 166 self._from_module(module, val)):
167 167 valname = '%s.%s' % (name, valname)
168 168 self._find(tests, val, valname, module, source_lines,
169 169 globs, seen)
170 170
171 171
172 172 class IPDoctestOutputChecker(doctest.OutputChecker):
173 173 """Second-chance checker with support for random tests.
174 174
175 175 If the default comparison doesn't pass, this checker looks in the expected
176 176 output string for flags that tell us to ignore the output.
177 177 """
178 178
179 179 random_re = re.compile(r'#\s*random\s+')
180 180
181 181 def check_output(self, want, got, optionflags):
182 182 """Check output, accepting special markers embedded in the output.
183 183
184 184 If the output didn't pass the default validation but the special string
185 185 '#random' is included, we accept it."""
186 186
187 187 # Let the original tester verify first, in case people have valid tests
188 188 # that happen to have a comment saying '#random' embedded in.
189 189 ret = doctest.OutputChecker.check_output(self, want, got,
190 190 optionflags)
191 191 if not ret and self.random_re.search(want):
192 192 #print >> sys.stderr, 'RANDOM OK:',want # dbg
193 193 return True
194 194
195 195 return ret
196 196
197 197
198 198 class DocTestCase(doctests.DocTestCase):
199 199 """Proxy for DocTestCase: provides an address() method that
200 200 returns the correct address for the doctest case. Otherwise
201 201 acts as a proxy to the test case. To provide hints for address(),
202 202 an obj may also be passed -- this will be used as the test object
203 203 for purposes of determining the test address, if it is provided.
204 204 """
205 205
206 206 # Note: this method was taken from numpy's nosetester module.
207 207
208 208 # Subclass nose.plugins.doctests.DocTestCase to work around a bug in
209 209 # its constructor that blocks non-default arguments from being passed
210 210 # down into doctest.DocTestCase
211 211
212 212 def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
213 213 checker=None, obj=None, result_var='_'):
214 214 self._result_var = result_var
215 215 doctests.DocTestCase.__init__(self, test,
216 216 optionflags=optionflags,
217 217 setUp=setUp, tearDown=tearDown,
218 218 checker=checker)
219 219 # Now we must actually copy the original constructor from the stdlib
220 220 # doctest class, because we can't call it directly and a bug in nose
221 221 # means it never gets passed the right arguments.
222 222
223 223 self._dt_optionflags = optionflags
224 224 self._dt_checker = checker
225 225 self._dt_test = test
226 226 self._dt_test_globs_ori = test.globs
227 227 self._dt_setUp = setUp
228 228 self._dt_tearDown = tearDown
229 229
230 230 # XXX - store this runner once in the object!
231 231 runner = IPDocTestRunner(optionflags=optionflags,
232 232 checker=checker, verbose=False)
233 233 self._dt_runner = runner
234 234
235 235
236 236 # Each doctest should remember the directory it was loaded from, so
237 237 # things like %run work without too many contortions
238 238 self._ori_dir = os.path.dirname(test.filename)
239 239
240 240 # Modified runTest from the default stdlib
241 241 def runTest(self):
242 242 test = self._dt_test
243 243 runner = self._dt_runner
244 244
245 245 old = sys.stdout
246 246 new = StringIO()
247 247 optionflags = self._dt_optionflags
248 248
249 249 if not (optionflags & REPORTING_FLAGS):
250 250 # The option flags don't include any reporting flags,
251 251 # so add the default reporting flags
252 252 optionflags |= _unittest_reportflags
253 253
254 254 try:
255 255 # Save our current directory and switch out to the one where the
256 256 # test was originally created, in case another doctest did a
257 257 # directory change. We'll restore this in the finally clause.
258 258 curdir = os.getcwdu()
259 259 #print 'runTest in dir:', self._ori_dir # dbg
260 260 os.chdir(self._ori_dir)
261 261
262 262 runner.DIVIDER = "-"*70
263 263 failures, tries = runner.run(test,out=new.write,
264 264 clear_globs=False)
265 265 finally:
266 266 sys.stdout = old
267 267 os.chdir(curdir)
268 268
269 269 if failures:
270 270 raise self.failureException(self.format_failure(new.getvalue()))
271 271
272 272 def setUp(self):
273 273 """Modified test setup that syncs with ipython namespace"""
274 274 #print "setUp test", self._dt_test.examples # dbg
275 275 if isinstance(self._dt_test.examples[0], IPExample):
276 276 # for IPython examples *only*, we swap the globals with the ipython
277 277 # namespace, after updating it with the globals (which doctest
278 278 # fills with the necessary info from the module being tested).
279 279 self.user_ns_orig = {}
280 280 self.user_ns_orig.update(_ip.user_ns)
281 281 _ip.user_ns.update(self._dt_test.globs)
282 282 # We must remove the _ key in the namespace, so that Python's
283 283 # doctest code sets it naturally
284 284 _ip.user_ns.pop('_', None)
285 285 _ip.user_ns['__builtins__'] = builtin_mod
286 286 self._dt_test.globs = _ip.user_ns
287 287
288 288 super(DocTestCase, self).setUp()
289 289
290 290 def tearDown(self):
291 291
292 292 # Undo the test.globs reassignment we made, so that the parent class
293 293 # teardown doesn't destroy the ipython namespace
294 294 if isinstance(self._dt_test.examples[0], IPExample):
295 295 self._dt_test.globs = self._dt_test_globs_ori
296 296 _ip.user_ns.clear()
297 297 _ip.user_ns.update(self.user_ns_orig)
298 298
299 299 # XXX - fperez: I am not sure if this is truly a bug in nose 0.11, but
300 300 # it does look like one to me: its tearDown method tries to run
301 301 #
302 302 # delattr(builtin_mod, self._result_var)
303 303 #
304 304 # without checking that the attribute really is there; it implicitly
305 305 # assumes it should have been set via displayhook. But if the
306 306 # displayhook was never called, this doesn't necessarily happen. I
307 307 # haven't been able to find a little self-contained example outside of
308 308 # ipython that would show the problem so I can report it to the nose
309 309 # team, but it does happen a lot in our code.
310 310 #
311 311 # So here, we just protect as narrowly as possible by trapping an
312 312 # attribute error whose message would be the name of self._result_var,
313 313 # and letting any other error propagate.
314 314 try:
315 315 super(DocTestCase, self).tearDown()
316 316 except AttributeError as exc:
317 317 if exc.args[0] != self._result_var:
318 318 raise
319 319
320 320
321 321 # A simple subclassing of the original with a different class name, so we can
322 322 # distinguish and treat differently IPython examples from pure python ones.
323 323 class IPExample(doctest.Example): pass
324 324
325 325
326 326 class IPExternalExample(doctest.Example):
327 327 """Doctest examples to be run in an external process."""
328 328
329 329 def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
330 330 options=None):
331 331 # Parent constructor
332 332 doctest.Example.__init__(self,source,want,exc_msg,lineno,indent,options)
333 333
334 334 # An EXTRA newline is needed to prevent pexpect hangs
335 335 self.source += '\n'
336 336
337 337
338 338 class IPDocTestParser(doctest.DocTestParser):
339 339 """
340 340 A class used to parse strings containing doctest examples.
341 341
342 342 Note: This is a version modified to properly recognize IPython input and
343 343 convert any IPython examples into valid Python ones.
344 344 """
345 345 # This regular expression is used to find doctest examples in a
346 346 # string. It defines three groups: `source` is the source code
347 347 # (including leading indentation and prompts); `indent` is the
348 348 # indentation of the first (PS1) line of the source code; and
349 349 # `want` is the expected output (including leading indentation).
350 350
351 351 # Classic Python prompts or default IPython ones
352 352 _PS1_PY = r'>>>'
353 353 _PS2_PY = r'\.\.\.'
354 354
355 355 _PS1_IP = r'In\ \[\d+\]:'
356 356 _PS2_IP = r'\ \ \ \.\.\.+:'
357 357
358 358 _RE_TPL = r'''
359 359 # Source consists of a PS1 line followed by zero or more PS2 lines.
360 360 (?P<source>
361 361 (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line
362 362 (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines
363 363 \n? # a newline
364 364 # Want consists of any non-blank lines that do not start with PS1.
365 365 (?P<want> (?:(?![ ]*$) # Not a blank line
366 366 (?![ ]*%s) # Not a line starting with PS1
367 367 (?![ ]*%s) # Not a line starting with PS2
368 368 .*$\n? # But any other line
369 369 )*)
370 370 '''
371 371
372 372 _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY),
373 373 re.MULTILINE | re.VERBOSE)
374 374
375 375 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
376 376 re.MULTILINE | re.VERBOSE)
377 377
378 378 # Mark a test as being fully random. In this case, we simply append the
379 379 # random marker ('#random') to each individual example's output. This way
380 380 # we don't need to modify any other code.
381 381 _RANDOM_TEST = re.compile(r'#\s*all-random\s+')
382 382
383 383 # Mark tests to be executed in an external process - currently unsupported.
384 384 _EXTERNAL_IP = re.compile(r'#\s*ipdoctest:\s*EXTERNAL')
385 385
386 386 def ip2py(self,source):
387 387 """Convert input IPython source into valid Python."""
388 388 block = _ip.input_transformer_manager.transform_cell(source)
389 389 if len(block.splitlines()) == 1:
390 390 return _ip.prefilter(block)
391 391 else:
392 392 return block
393 393
394 394 def parse(self, string, name='<string>'):
395 395 """
396 396 Divide the given string into examples and intervening text,
397 397 and return them as a list of alternating Examples and strings.
398 398 Line numbers for the Examples are 0-based. The optional
399 399 argument `name` is a name identifying this string, and is only
400 400 used for error messages.
401 401 """
402 402
403 403 #print 'Parse string:\n',string # dbg
404 404
405 405 string = string.expandtabs()
406 406 # If all lines begin with the same indentation, then strip it.
407 407 min_indent = self._min_indent(string)
408 408 if min_indent > 0:
409 409 string = '\n'.join([l[min_indent:] for l in string.split('\n')])
410 410
411 411 output = []
412 412 charno, lineno = 0, 0
413 413
414 414 # We make 'all random' tests by adding the '# random' mark to every
415 415 # block of output in the test.
416 416 if self._RANDOM_TEST.search(string):
417 417 random_marker = '\n# random'
418 418 else:
419 419 random_marker = ''
420 420
421 421 # Whether to convert the input from ipython to python syntax
422 422 ip2py = False
423 423 # Find all doctest examples in the string. First, try them as Python
424 424 # examples, then as IPython ones
425 425 terms = list(self._EXAMPLE_RE_PY.finditer(string))
426 426 if terms:
427 427 # Normal Python example
428 428 #print '-'*70 # dbg
429 429 #print 'PyExample, Source:\n',string # dbg
430 430 #print '-'*70 # dbg
431 431 Example = doctest.Example
432 432 else:
433 433 # It's an ipython example. Note that IPExamples are run
434 434 # in-process, so their syntax must be turned into valid python.
435 435 # IPExternalExamples are run out-of-process (via pexpect) so they
436 436 # don't need any filtering (a real ipython will be executing them).
437 437 terms = list(self._EXAMPLE_RE_IP.finditer(string))
438 438 if self._EXTERNAL_IP.search(string):
439 439 #print '-'*70 # dbg
440 440 #print 'IPExternalExample, Source:\n',string # dbg
441 441 #print '-'*70 # dbg
442 442 Example = IPExternalExample
443 443 else:
444 444 #print '-'*70 # dbg
445 445 #print 'IPExample, Source:\n',string # dbg
446 446 #print '-'*70 # dbg
447 447 Example = IPExample
448 448 ip2py = True
449 449
450 450 for m in terms:
451 451 # Add the pre-example text to `output`.
452 452 output.append(string[charno:m.start()])
453 453 # Update lineno (lines before this example)
454 454 lineno += string.count('\n', charno, m.start())
455 455 # Extract info from the regexp match.
456 456 (source, options, want, exc_msg) = \
457 457 self._parse_example(m, name, lineno,ip2py)
458 458
459 459 # Append the random-output marker (it defaults to empty in most
460 460 # cases, it's only non-empty for 'all-random' tests):
461 461 want += random_marker
462 462
463 463 if Example is IPExternalExample:
464 464 options[doctest.NORMALIZE_WHITESPACE] = True
465 465 want += '\n'
466 466
467 467 # Create an Example, and add it to the list.
468 468 if not self._IS_BLANK_OR_COMMENT(source):
469 469 output.append(Example(source, want, exc_msg,
470 470 lineno=lineno,
471 471 indent=min_indent+len(m.group('indent')),
472 472 options=options))
473 473 # Update lineno (lines inside this example)
474 474 lineno += string.count('\n', m.start(), m.end())
475 475 # Update charno.
476 476 charno = m.end()
477 477 # Add any remaining post-example text to `output`.
478 478 output.append(string[charno:])
479 479 return output
480 480
481 481 def _parse_example(self, m, name, lineno,ip2py=False):
482 482 """
483 483 Given a regular expression match from `_EXAMPLE_RE` (`m`),
484 484 return a pair `(source, want)`, where `source` is the matched
485 485 example's source code (with prompts and indentation stripped);
486 486 and `want` is the example's expected output (with indentation
487 487 stripped).
488 488
489 489 `name` is the string's name, and `lineno` is the line number
490 490 where the example starts; both are used for error messages.
491 491
492 492 Optional:
493 493 `ip2py`: if true, filter the input via IPython to convert the syntax
494 494 into valid python.
495 495 """
496 496
497 497 # Get the example's indentation level.
498 498 indent = len(m.group('indent'))
499 499
500 500 # Divide source into lines; check that they're properly
501 501 # indented; and then strip their indentation & prompts.
502 502 source_lines = m.group('source').split('\n')
503 503
504 504 # We're using variable-length input prompts
505 505 ps1 = m.group('ps1')
506 506 ps2 = m.group('ps2')
507 507 ps1_len = len(ps1)
508 508
509 509 self._check_prompt_blank(source_lines, indent, name, lineno,ps1_len)
510 510 if ps2:
511 511 self._check_prefix(source_lines[1:], ' '*indent + ps2, name, lineno)
512 512
513 513 source = '\n'.join([sl[indent+ps1_len+1:] for sl in source_lines])
514 514
515 515 if ip2py:
516 516 # Convert source input from IPython into valid Python syntax
517 517 source = self.ip2py(source)
518 518
519 519 # Divide want into lines; check that it's properly indented; and
520 520 # then strip the indentation. Spaces before the last newline should
521 521 # be preserved, so plain rstrip() isn't good enough.
522 522 want = m.group('want')
523 523 want_lines = want.split('\n')
524 524 if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
525 525 del want_lines[-1] # forget final newline & spaces after it
526 526 self._check_prefix(want_lines, ' '*indent, name,
527 527 lineno + len(source_lines))
528 528
529 529 # Remove ipython output prompt that might be present in the first line
530 530 want_lines[0] = re.sub(r'Out\[\d+\]: \s*?\n?','',want_lines[0])
531 531
532 532 want = '\n'.join([wl[indent:] for wl in want_lines])
533 533
534 534 # If `want` contains a traceback message, then extract it.
535 535 m = self._EXCEPTION_RE.match(want)
536 536 if m:
537 537 exc_msg = m.group('msg')
538 538 else:
539 539 exc_msg = None
540 540
541 541 # Extract options from the source.
542 542 options = self._find_options(source, name, lineno)
543 543
544 544 return source, options, want, exc_msg
545 545
546 546 def _check_prompt_blank(self, lines, indent, name, lineno, ps1_len):
547 547 """
548 548 Given the lines of a source string (including prompts and
549 549 leading indentation), check to make sure that every prompt is
550 550 followed by a space character. If any line is not followed by
551 551 a space character, then raise ValueError.
552 552
553 553 Note: IPython-modified version which takes the input prompt length as a
554 554 parameter, so that prompts of variable length can be dealt with.
555 555 """
556 556 space_idx = indent+ps1_len
557 557 min_len = space_idx+1
558 558 for i, line in enumerate(lines):
559 559 if len(line) >= min_len and line[space_idx] != ' ':
560 560 raise ValueError('line %r of the docstring for %s '
561 561 'lacks blank after %s: %r' %
562 562 (lineno+i+1, name,
563 563 line[indent:space_idx], line))
564 564
565 565
566 566 SKIP = doctest.register_optionflag('SKIP')
567 567
568 568
569 569 class IPDocTestRunner(doctest.DocTestRunner,object):
570 570 """Test runner that synchronizes the IPython namespace with test globals.
571 571 """
572 572
573 573 def run(self, test, compileflags=None, out=None, clear_globs=True):
574 574
575 575 # Hack: ipython needs access to the execution context of the example,
576 576 # so that it can propagate user variables loaded by %run into
577 577 # test.globs. We put them here into our modified %run as a function
578 578 # attribute. Our new %run will then only make the namespace update
579 579 # when called (rather than unconconditionally updating test.globs here
580 580 # for all examples, most of which won't be calling %run anyway).
581 581 #_ip._ipdoctest_test_globs = test.globs
582 582 #_ip._ipdoctest_test_filename = test.filename
583 583
584 584 test.globs.update(_ip.user_ns)
585 585
586 586 return super(IPDocTestRunner,self).run(test,
587 587 compileflags,out,clear_globs)
588 588
589 589
590 590 class DocFileCase(doctest.DocFileCase):
591 591 """Overrides to provide filename
592 592 """
593 593 def address(self):
594 594 return (self._dt_test.filename, None, None)
595 595
596 596
597 597 class ExtensionDoctest(doctests.Doctest):
598 598 """Nose Plugin that supports doctests in extension modules.
599 599 """
600 600 name = 'extdoctest' # call nosetests with --with-extdoctest
601 601 enabled = True
602 602
603 603 def options(self, parser, env=os.environ):
604 604 Plugin.options(self, parser, env)
605 605 parser.add_option('--doctest-tests', action='store_true',
606 606 dest='doctest_tests',
607 607 default=env.get('NOSE_DOCTEST_TESTS',True),
608 608 help="Also look for doctests in test modules. "
609 609 "Note that classes, methods and functions should "
610 610 "have either doctests or non-doctest tests, "
611 611 "not both. [NOSE_DOCTEST_TESTS]")
612 612 parser.add_option('--doctest-extension', action="append",
613 613 dest="doctestExtension",
614 614 help="Also look for doctests in files with "
615 615 "this extension [NOSE_DOCTEST_EXTENSION]")
616 616 # Set the default as a list, if given in env; otherwise
617 617 # an additional value set on the command line will cause
618 618 # an error.
619 619 env_setting = env.get('NOSE_DOCTEST_EXTENSION')
620 620 if env_setting is not None:
621 621 parser.set_defaults(doctestExtension=tolist(env_setting))
622 622
623 623
624 624 def configure(self, options, config):
625 625 Plugin.configure(self, options, config)
626 626 # Pull standard doctest plugin out of config; we will do doctesting
627 627 config.plugins.plugins = [p for p in config.plugins.plugins
628 628 if p.name != 'doctest']
629 629 self.doctest_tests = options.doctest_tests
630 630 self.extension = tolist(options.doctestExtension)
631 631
632 632 self.parser = doctest.DocTestParser()
633 633 self.finder = DocTestFinder()
634 634 self.checker = IPDoctestOutputChecker()
635 635 self.globs = None
636 636 self.extraglobs = None
637 637
638 638
639 639 def loadTestsFromExtensionModule(self,filename):
640 640 bpath,mod = os.path.split(filename)
641 641 modname = os.path.splitext(mod)[0]
642 642 try:
643 643 sys.path.append(bpath)
644 644 module = __import__(modname)
645 645 tests = list(self.loadTestsFromModule(module))
646 646 finally:
647 647 sys.path.pop()
648 648 return tests
649 649
650 650 # NOTE: the method below is almost a copy of the original one in nose, with
651 651 # a few modifications to control output checking.
652 652
653 653 def loadTestsFromModule(self, module):
654 654 #print '*** ipdoctest - lTM',module # dbg
655 655
656 656 if not self.matches(module.__name__):
657 657 log.debug("Doctest doesn't want module %s", module)
658 658 return
659 659
660 660 tests = self.finder.find(module,globs=self.globs,
661 661 extraglobs=self.extraglobs)
662 662 if not tests:
663 663 return
664 664
665 665 # always use whitespace and ellipsis options
666 666 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
667 667
668 668 tests.sort()
669 669 module_file = module.__file__
670 670 if module_file[-4:] in ('.pyc', '.pyo'):
671 671 module_file = module_file[:-1]
672 672 for test in tests:
673 673 if not test.examples:
674 674 continue
675 675 if not test.filename:
676 676 test.filename = module_file
677 677
678 678 yield DocTestCase(test,
679 679 optionflags=optionflags,
680 680 checker=self.checker)
681 681
682 682
683 683 def loadTestsFromFile(self, filename):
684 684 #print "ipdoctest - from file", filename # dbg
685 685 if is_extension_module(filename):
686 686 for t in self.loadTestsFromExtensionModule(filename):
687 687 yield t
688 688 else:
689 689 if self.extension and anyp(filename.endswith, self.extension):
690 690 name = os.path.basename(filename)
691 691 dh = open(filename)
692 692 try:
693 693 doc = dh.read()
694 694 finally:
695 695 dh.close()
696 696 test = self.parser.get_doctest(
697 697 doc, globs={'__file__': filename}, name=name,
698 698 filename=filename, lineno=0)
699 699 if test.examples:
700 700 #print 'FileCase:',test.examples # dbg
701 701 yield DocFileCase(test)
702 702 else:
703 703 yield False # no tests to load
704 704
705 705
706 706 class IPythonDoctest(ExtensionDoctest):
707 707 """Nose Plugin that supports doctests in extension modules.
708 708 """
709 709 name = 'ipdoctest' # call nosetests with --with-ipdoctest
710 710 enabled = True
711 711
712 712 def makeTest(self, obj, parent):
713 713 """Look for doctests in the given object, which will be a
714 714 function, method or class.
715 715 """
716 716 #print 'Plugin analyzing:', obj, parent # dbg
717 717 # always use whitespace and ellipsis options
718 718 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
719 719
720 720 doctests = self.finder.find(obj, module=getmodule(parent))
721 721 if doctests:
722 722 for test in doctests:
723 723 if len(test.examples) == 0:
724 724 continue
725 725
726 726 yield DocTestCase(test, obj=obj,
727 727 optionflags=optionflags,
728 728 checker=self.checker)
729 729
730 730 def options(self, parser, env=os.environ):
731 731 #print "Options for nose plugin:", self.name # dbg
732 732 Plugin.options(self, parser, env)
733 733 parser.add_option('--ipdoctest-tests', action='store_true',
734 734 dest='ipdoctest_tests',
735 735 default=env.get('NOSE_IPDOCTEST_TESTS',True),
736 736 help="Also look for doctests in test modules. "
737 737 "Note that classes, methods and functions should "
738 738 "have either doctests or non-doctest tests, "
739 739 "not both. [NOSE_IPDOCTEST_TESTS]")
740 740 parser.add_option('--ipdoctest-extension', action="append",
741 741 dest="ipdoctest_extension",
742 742 help="Also look for doctests in files with "
743 743 "this extension [NOSE_IPDOCTEST_EXTENSION]")
744 744 # Set the default as a list, if given in env; otherwise
745 745 # an additional value set on the command line will cause
746 746 # an error.
747 747 env_setting = env.get('NOSE_IPDOCTEST_EXTENSION')
748 748 if env_setting is not None:
749 749 parser.set_defaults(ipdoctest_extension=tolist(env_setting))
750 750
751 751 def configure(self, options, config):
752 752 #print "Configuring nose plugin:", self.name # dbg
753 753 Plugin.configure(self, options, config)
754 754 # Pull standard doctest plugin out of config; we will do doctesting
755 755 config.plugins.plugins = [p for p in config.plugins.plugins
756 756 if p.name != 'doctest']
757 757 self.doctest_tests = options.ipdoctest_tests
758 758 self.extension = tolist(options.ipdoctest_extension)
759 759
760 760 self.parser = IPDocTestParser()
761 761 self.finder = DocTestFinder(parser=self.parser)
762 762 self.checker = IPDoctestOutputChecker()
763 763 self.globs = None
764 764 self.extraglobs = None
@@ -1,169 +1,169 b''
1 1 """Tests for the decorators we've created for IPython.
2 2 """
3 3 from __future__ import print_function
4 4
5 5 # Module imports
6 6 # Std lib
7 7 import inspect
8 8 import sys
9 9
10 10 # Third party
11 11 import nose.tools as nt
12 12
13 13 # Our own
14 14 from IPython.testing import decorators as dec
15 15 from IPython.testing.skipdoctest import skip_doctest
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Utilities
19 19
20 20 # Note: copied from OInspect, kept here so the testing stuff doesn't create
21 21 # circular dependencies and is easier to reuse.
22 22 def getargspec(obj):
23 23 """Get the names and default values of a function's arguments.
24 24
25 25 A tuple of four things is returned: (args, varargs, varkw, defaults).
26 26 'args' is a list of the argument names (it may contain nested lists).
27 27 'varargs' and 'varkw' are the names of the * and ** arguments or None.
28 28 'defaults' is an n-tuple of the default values of the last n arguments.
29 29
30 30 Modified version of inspect.getargspec from the Python Standard
31 31 Library."""
32 32
33 33 if inspect.isfunction(obj):
34 34 func_obj = obj
35 35 elif inspect.ismethod(obj):
36 func_obj = obj.im_func
36 func_obj = obj.__func__
37 37 else:
38 38 raise TypeError('arg is not a Python function')
39 39 args, varargs, varkw = inspect.getargs(func_obj.__code__)
40 40 return args, varargs, varkw, func_obj.__defaults__
41 41
42 42 #-----------------------------------------------------------------------------
43 43 # Testing functions
44 44
45 45 @dec.as_unittest
46 46 def trivial():
47 47 """A trivial test"""
48 48 pass
49 49
50 50
51 51 @dec.skip
52 52 def test_deliberately_broken():
53 53 """A deliberately broken test - we want to skip this one."""
54 54 1/0
55 55
56 56 @dec.skip('Testing the skip decorator')
57 57 def test_deliberately_broken2():
58 58 """Another deliberately broken test - we want to skip this one."""
59 59 1/0
60 60
61 61
62 62 # Verify that we can correctly skip the doctest for a function at will, but
63 63 # that the docstring itself is NOT destroyed by the decorator.
64 64 @skip_doctest
65 65 def doctest_bad(x,y=1,**k):
66 66 """A function whose doctest we need to skip.
67 67
68 68 >>> 1+1
69 69 3
70 70 """
71 71 print('x:',x)
72 72 print('y:',y)
73 73 print('k:',k)
74 74
75 75
76 76 def call_doctest_bad():
77 77 """Check that we can still call the decorated functions.
78 78
79 79 >>> doctest_bad(3,y=4)
80 80 x: 3
81 81 y: 4
82 82 k: {}
83 83 """
84 84 pass
85 85
86 86
87 87 def test_skip_dt_decorator():
88 88 """Doctest-skipping decorator should preserve the docstring.
89 89 """
90 90 # Careful: 'check' must be a *verbatim* copy of the doctest_bad docstring!
91 91 check = """A function whose doctest we need to skip.
92 92
93 93 >>> 1+1
94 94 3
95 95 """
96 96 # Fetch the docstring from doctest_bad after decoration.
97 97 val = doctest_bad.__doc__
98 98
99 99 nt.assert_equal(check,val,"doctest_bad docstrings don't match")
100 100
101 101
102 102 # Doctest skipping should work for class methods too
103 103 class FooClass(object):
104 104 """FooClass
105 105
106 106 Example:
107 107
108 108 >>> 1+1
109 109 2
110 110 """
111 111
112 112 @skip_doctest
113 113 def __init__(self,x):
114 114 """Make a FooClass.
115 115
116 116 Example:
117 117
118 118 >>> f = FooClass(3)
119 119 junk
120 120 """
121 121 print('Making a FooClass.')
122 122 self.x = x
123 123
124 124 @skip_doctest
125 125 def bar(self,y):
126 126 """Example:
127 127
128 128 >>> ff = FooClass(3)
129 129 >>> ff.bar(0)
130 130 boom!
131 131 >>> 1/0
132 132 bam!
133 133 """
134 134 return 1/y
135 135
136 136 def baz(self,y):
137 137 """Example:
138 138
139 139 >>> ff2 = FooClass(3)
140 140 Making a FooClass.
141 141 >>> ff2.baz(3)
142 142 True
143 143 """
144 144 return self.x==y
145 145
146 146
147 147 def test_skip_dt_decorator2():
148 148 """Doctest-skipping decorator should preserve function signature.
149 149 """
150 150 # Hardcoded correct answer
151 151 dtargs = (['x', 'y'], None, 'k', (1,))
152 152 # Introspect out the value
153 153 dtargsr = getargspec(doctest_bad)
154 154 assert dtargsr==dtargs, \
155 155 "Incorrectly reconstructed args for doctest_bad: %s" % (dtargsr,)
156 156
157 157
158 158 @dec.skip_linux
159 159 def test_linux():
160 160 nt.assert_false(sys.platform.startswith('linux'),"This test can't run under linux")
161 161
162 162 @dec.skip_win32
163 163 def test_win32():
164 164 nt.assert_not_equal(sys.platform,'win32',"This test can't run under windows")
165 165
166 166 @dec.skip_osx
167 167 def test_osx():
168 168 nt.assert_not_equal(sys.platform,'darwin',"This test can't run under osx")
169 169
General Comments 0
You need to be logged in to leave comments. Login now