##// END OF EJS Templates
merge functionality in io and openpy relating to encoding...
Jörgen Stenarson -
Show More
@@ -1,529 +1,535 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Pdb debugger class.
4 4
5 5 Modified from the standard pdb.Pdb class to avoid including readline, so that
6 6 the command line completion of other programs which include this isn't
7 7 damaged.
8 8
9 9 In the future, this class will be expanded with improvements over the standard
10 10 pdb.
11 11
12 12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
13 13 changes. Licensing should therefore be under the standard Python terms. For
14 14 details on the PSF (Python Software Foundation) standard license, see:
15 15
16 16 http://www.python.org/2.2.3/license.html"""
17 17
18 18 #*****************************************************************************
19 19 #
20 20 # This file is licensed under the PSF license.
21 21 #
22 22 # Copyright (C) 2001 Python Software Foundation, www.python.org
23 23 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
24 24 #
25 25 #
26 26 #*****************************************************************************
27 27 from __future__ import print_function
28 28
29 29 import bdb
30 30 import linecache
31 31 import sys
32 32
33 33 from IPython.utils import PyColorize
34 34 from IPython.core import ipapi
35 from IPython.utils import coloransi, io
35 from IPython.utils import coloransi, io, openpy
36 36 from IPython.core.excolors import exception_colors
37 37
38 38 # See if we can use pydb.
39 39 has_pydb = False
40 40 prompt = 'ipdb> '
41 41 #We have to check this directly from sys.argv, config struct not yet available
42 42 if '--pydb' in sys.argv:
43 43 try:
44 44 import pydb
45 45 if hasattr(pydb.pydb, "runl") and pydb.version>'1.17':
46 46 # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we
47 47 # better protect against it.
48 48 has_pydb = True
49 49 except ImportError:
50 50 print("Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available")
51 51
52 52 if has_pydb:
53 53 from pydb import Pdb as OldPdb
54 54 #print "Using pydb for %run -d and post-mortem" #dbg
55 55 prompt = 'ipydb> '
56 56 else:
57 57 from pdb import Pdb as OldPdb
58 58
59 59 # Allow the set_trace code to operate outside of an ipython instance, even if
60 60 # it does so with some limitations. The rest of this support is implemented in
61 61 # the Tracer constructor.
62 62 def BdbQuit_excepthook(et,ev,tb):
63 63 if et==bdb.BdbQuit:
64 64 print('Exiting Debugger.')
65 65 else:
66 66 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
67 67
68 68 def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None):
69 69 print('Exiting Debugger.')
70 70
71 71
72 72 class Tracer(object):
73 73 """Class for local debugging, similar to pdb.set_trace.
74 74
75 75 Instances of this class, when called, behave like pdb.set_trace, but
76 76 providing IPython's enhanced capabilities.
77 77
78 78 This is implemented as a class which must be initialized in your own code
79 79 and not as a standalone function because we need to detect at runtime
80 80 whether IPython is already active or not. That detection is done in the
81 81 constructor, ensuring that this code plays nicely with a running IPython,
82 82 while functioning acceptably (though with limitations) if outside of it.
83 83 """
84 84
85 85 def __init__(self,colors=None):
86 86 """Create a local debugger instance.
87 87
88 88 :Parameters:
89 89
90 90 - `colors` (None): a string containing the name of the color scheme to
91 91 use, it must be one of IPython's valid color schemes. If not given, the
92 92 function will default to the current IPython scheme when running inside
93 93 IPython, and to 'NoColor' otherwise.
94 94
95 95 Usage example:
96 96
97 97 from IPython.core.debugger import Tracer; debug_here = Tracer()
98 98
99 99 ... later in your code
100 100 debug_here() # -> will open up the debugger at that point.
101 101
102 102 Once the debugger activates, you can use all of its regular commands to
103 103 step through code, set breakpoints, etc. See the pdb documentation
104 104 from the Python standard library for usage details.
105 105 """
106 106
107 107 try:
108 108 ip = get_ipython()
109 109 except NameError:
110 110 # Outside of ipython, we set our own exception hook manually
111 111 BdbQuit_excepthook.excepthook_ori = sys.excepthook
112 112 sys.excepthook = BdbQuit_excepthook
113 113 def_colors = 'NoColor'
114 114 try:
115 115 # Limited tab completion support
116 116 import readline
117 117 readline.parse_and_bind('tab: complete')
118 118 except ImportError:
119 119 pass
120 120 else:
121 121 # In ipython, we use its custom exception handler mechanism
122 122 def_colors = ip.colors
123 123 ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook)
124 124
125 125 if colors is None:
126 126 colors = def_colors
127 127
128 128 # The stdlib debugger internally uses a modified repr from the `repr`
129 129 # module, that limits the length of printed strings to a hardcoded
130 130 # limit of 30 characters. That much trimming is too aggressive, let's
131 131 # at least raise that limit to 80 chars, which should be enough for
132 132 # most interactive uses.
133 133 try:
134 134 from repr import aRepr
135 135 aRepr.maxstring = 80
136 136 except:
137 137 # This is only a user-facing convenience, so any error we encounter
138 138 # here can be warned about but can be otherwise ignored. These
139 139 # printouts will tell us about problems if this API changes
140 140 import traceback
141 141 traceback.print_exc()
142 142
143 143 self.debugger = Pdb(colors)
144 144
145 145 def __call__(self):
146 146 """Starts an interactive debugger at the point where called.
147 147
148 148 This is similar to the pdb.set_trace() function from the std lib, but
149 149 using IPython's enhanced debugger."""
150 150
151 151 self.debugger.set_trace(sys._getframe().f_back)
152 152
153 153
154 154 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
155 155 """Make new_fn have old_fn's doc string. This is particularly useful
156 156 for the do_... commands that hook into the help system.
157 157 Adapted from from a comp.lang.python posting
158 158 by Duncan Booth."""
159 159 def wrapper(*args, **kw):
160 160 return new_fn(*args, **kw)
161 161 if old_fn.__doc__:
162 162 wrapper.__doc__ = old_fn.__doc__ + additional_text
163 163 return wrapper
164 164
165 165
166 166 def _file_lines(fname):
167 167 """Return the contents of a named file as a list of lines.
168 168
169 169 This function never raises an IOError exception: if the file can't be
170 170 read, it simply returns an empty list."""
171 171
172 172 try:
173 173 outfile = open(fname)
174 174 except IOError:
175 175 return []
176 176 else:
177 177 out = outfile.readlines()
178 178 outfile.close()
179 179 return out
180 180
181 181
182 182 class Pdb(OldPdb):
183 183 """Modified Pdb class, does not load readline."""
184 184
185 185 def __init__(self,color_scheme='NoColor',completekey=None,
186 186 stdin=None, stdout=None):
187 187
188 188 # Parent constructor:
189 189 if has_pydb and completekey is None:
190 190 OldPdb.__init__(self,stdin=stdin,stdout=io.stdout)
191 191 else:
192 192 OldPdb.__init__(self,completekey,stdin,stdout)
193 193
194 194 self.prompt = prompt # The default prompt is '(Pdb)'
195 195
196 196 # IPython changes...
197 197 self.is_pydb = has_pydb
198 198
199 199 self.shell = ipapi.get()
200 200
201 201 if self.is_pydb:
202 202
203 203 # interactiveshell.py's ipalias seems to want pdb's checkline
204 204 # which located in pydb.fn
205 205 import pydb.fns
206 206 self.checkline = lambda filename, lineno: \
207 207 pydb.fns.checkline(self, filename, lineno)
208 208
209 209 self.curframe = None
210 210 self.do_restart = self.new_do_restart
211 211
212 212 self.old_all_completions = self.shell.Completer.all_completions
213 213 self.shell.Completer.all_completions=self.all_completions
214 214
215 215 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
216 216 OldPdb.do_list)
217 217 self.do_l = self.do_list
218 218 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
219 219 OldPdb.do_frame)
220 220
221 221 self.aliases = {}
222 222
223 223 # Create color table: we copy the default one from the traceback
224 224 # module and add a few attributes needed for debugging
225 225 self.color_scheme_table = exception_colors()
226 226
227 227 # shorthands
228 228 C = coloransi.TermColors
229 229 cst = self.color_scheme_table
230 230
231 231 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
232 232 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
233 233
234 234 cst['Linux'].colors.breakpoint_enabled = C.LightRed
235 235 cst['Linux'].colors.breakpoint_disabled = C.Red
236 236
237 237 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
238 238 cst['LightBG'].colors.breakpoint_disabled = C.Red
239 239
240 240 self.set_colors(color_scheme)
241 241
242 242 # Add a python parser so we can syntax highlight source while
243 243 # debugging.
244 244 self.parser = PyColorize.Parser()
245 245
246 246 def set_colors(self, scheme):
247 247 """Shorthand access to the color table scheme selector method."""
248 248 self.color_scheme_table.set_active_scheme(scheme)
249 249
250 250 def interaction(self, frame, traceback):
251 251 self.shell.set_completer_frame(frame)
252 252 OldPdb.interaction(self, frame, traceback)
253 253
254 254 def new_do_up(self, arg):
255 255 OldPdb.do_up(self, arg)
256 256 self.shell.set_completer_frame(self.curframe)
257 257 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
258 258
259 259 def new_do_down(self, arg):
260 260 OldPdb.do_down(self, arg)
261 261 self.shell.set_completer_frame(self.curframe)
262 262
263 263 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
264 264
265 265 def new_do_frame(self, arg):
266 266 OldPdb.do_frame(self, arg)
267 267 self.shell.set_completer_frame(self.curframe)
268 268
269 269 def new_do_quit(self, arg):
270 270
271 271 if hasattr(self, 'old_all_completions'):
272 272 self.shell.Completer.all_completions=self.old_all_completions
273 273
274 274
275 275 return OldPdb.do_quit(self, arg)
276 276
277 277 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
278 278
279 279 def new_do_restart(self, arg):
280 280 """Restart command. In the context of ipython this is exactly the same
281 281 thing as 'quit'."""
282 282 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
283 283 return self.do_quit(arg)
284 284
285 285 def postloop(self):
286 286 self.shell.set_completer_frame(None)
287 287
288 288 def print_stack_trace(self):
289 289 try:
290 290 for frame_lineno in self.stack:
291 291 self.print_stack_entry(frame_lineno, context = 5)
292 292 except KeyboardInterrupt:
293 293 pass
294 294
295 295 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
296 296 context = 3):
297 297 #frame, lineno = frame_lineno
298 298 print(self.format_stack_entry(frame_lineno, '', context), file=io.stdout)
299 299
300 300 # vds: >>
301 301 frame, lineno = frame_lineno
302 302 filename = frame.f_code.co_filename
303 303 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
304 304 # vds: <<
305 305
306 306 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
307 307 import linecache, repr
308 308
309 309 ret = []
310 310
311 311 Colors = self.color_scheme_table.active_colors
312 312 ColorsNormal = Colors.Normal
313 313 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
314 314 tpl_call = '%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
315 315 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
316 316 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
317 317 ColorsNormal)
318 318
319 319 frame, lineno = frame_lineno
320 320
321 321 return_value = ''
322 322 if '__return__' in frame.f_locals:
323 323 rv = frame.f_locals['__return__']
324 324 #return_value += '->'
325 325 return_value += repr.repr(rv) + '\n'
326 326 ret.append(return_value)
327 327
328 328 #s = filename + '(' + `lineno` + ')'
329 329 filename = self.canonic(frame.f_code.co_filename)
330 330 link = tpl_link % filename
331 331
332 332 if frame.f_code.co_name:
333 333 func = frame.f_code.co_name
334 334 else:
335 335 func = "<lambda>"
336 336
337 337 call = ''
338 338 if func != '?':
339 339 if '__args__' in frame.f_locals:
340 340 args = repr.repr(frame.f_locals['__args__'])
341 341 else:
342 342 args = '()'
343 343 call = tpl_call % (func, args)
344 344
345 345 # The level info should be generated in the same format pdb uses, to
346 346 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
347 347 if frame is self.curframe:
348 348 ret.append('> ')
349 349 else:
350 350 ret.append(' ')
351 351 ret.append('%s(%s)%s\n' % (link,lineno,call))
352 352
353 353 start = lineno - 1 - context//2
354 354 lines = linecache.getlines(filename)
355 encoding = io.guess_encoding(lines)
355 try:
356 encoding, _ = openpy.detect_encoding(lambda :lines[:2].pop(0))
357 except SyntaxError:
358 encoding = "ascii"
356 359 start = max(start, 0)
357 360 start = min(start, len(lines) - context)
358 361 lines = lines[start : start + context]
359 362
360 363 for i,line in enumerate(lines):
361 364 show_arrow = (start + 1 + i == lineno)
362 365 linetpl = (frame is self.curframe or show_arrow) \
363 366 and tpl_line_em \
364 367 or tpl_line
365 368 ret.append(self.__format_line(linetpl, filename,
366 start + 1 + i, line.decode(encoding),
369 start + 1 + i, line.decode(encoding, errors="replace"),
367 370 arrow = show_arrow) )
368 371 return ''.join(ret)
369 372
370 373 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
371 374 bp_mark = ""
372 375 bp_mark_color = ""
373 376
374 377 scheme = self.color_scheme_table.active_scheme_name
375 378 new_line, err = self.parser.format2(line, 'str', scheme)
376 379 if not err: line = new_line
377 380
378 381 bp = None
379 382 if lineno in self.get_file_breaks(filename):
380 383 bps = self.get_breaks(filename, lineno)
381 384 bp = bps[-1]
382 385
383 386 if bp:
384 387 Colors = self.color_scheme_table.active_colors
385 388 bp_mark = str(bp.number)
386 389 bp_mark_color = Colors.breakpoint_enabled
387 390 if not bp.enabled:
388 391 bp_mark_color = Colors.breakpoint_disabled
389 392
390 393 numbers_width = 7
391 394 if arrow:
392 395 # This is the line with the error
393 396 pad = numbers_width - len(str(lineno)) - len(bp_mark)
394 397 if pad >= 3:
395 398 marker = '-'*(pad-3) + '-> '
396 399 elif pad == 2:
397 400 marker = '> '
398 401 elif pad == 1:
399 402 marker = '>'
400 403 else:
401 404 marker = ''
402 405 num = '%s%s' % (marker, str(lineno))
403 406 line = tpl_line % (bp_mark_color + bp_mark, num, line)
404 407 else:
405 408 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
406 409 line = tpl_line % (bp_mark_color + bp_mark, num, line)
407 410
408 411 return line
409 412
410 413 def list_command_pydb(self, arg):
411 414 """List command to use if we have a newer pydb installed"""
412 415 filename, first, last = OldPdb.parse_list_cmd(self, arg)
413 416 if filename is not None:
414 417 self.print_list_lines(filename, first, last)
415 418
416 419 def print_list_lines(self, filename, first, last):
417 420 """The printing (as opposed to the parsing part of a 'list'
418 421 command."""
419 422 try:
420 423 Colors = self.color_scheme_table.active_colors
421 424 ColorsNormal = Colors.Normal
422 425 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
423 426 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
424 427 src = []
425 428 lines = linecache.getlines(filename)
426 encoding = io.guess_encoding(lines)
429 try:
430 encoding, _ = openpy.detect_encoding(lambda :lines[:2].pop(0))
431 except SyntaxError:
432 encoding = "ascii"
427 433 for lineno in range(first, last+1):
428 line = lines[lineno].decode(encoding)
434 line = lines[lineno].decode(encoding, errors="replace")
429 435 if not line:
430 436 break
431 437
432 438 if lineno == self.curframe.f_lineno:
433 439 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
434 440 else:
435 441 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
436 442
437 443 src.append(line)
438 444 self.lineno = lineno
439 445
440 446 print(''.join(src), file=io.stdout)
441 447
442 448 except KeyboardInterrupt:
443 449 pass
444 450
445 451 def do_list(self, arg):
446 452 self.lastcmd = 'list'
447 453 last = None
448 454 if arg:
449 455 try:
450 456 x = eval(arg, {}, {})
451 457 if type(x) == type(()):
452 458 first, last = x
453 459 first = int(first)
454 460 last = int(last)
455 461 if last < first:
456 462 # Assume it's a count
457 463 last = first + last
458 464 else:
459 465 first = max(1, int(x) - 5)
460 466 except:
461 467 print('*** Error in argument:', repr(arg))
462 468 return
463 469 elif self.lineno is None:
464 470 first = max(1, self.curframe.f_lineno - 5)
465 471 else:
466 472 first = self.lineno + 1
467 473 if last is None:
468 474 last = first + 10
469 475 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
470 476
471 477 # vds: >>
472 478 lineno = first
473 479 filename = self.curframe.f_code.co_filename
474 480 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
475 481 # vds: <<
476 482
477 483 do_l = do_list
478 484
479 485 def do_pdef(self, arg):
480 486 """The debugger interface to magic_pdef"""
481 487 namespaces = [('Locals', self.curframe.f_locals),
482 488 ('Globals', self.curframe.f_globals)]
483 489 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
484 490
485 491 def do_pdoc(self, arg):
486 492 """The debugger interface to magic_pdoc"""
487 493 namespaces = [('Locals', self.curframe.f_locals),
488 494 ('Globals', self.curframe.f_globals)]
489 495 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
490 496
491 497 def do_pinfo(self, arg):
492 498 """The debugger equivalant of ?obj"""
493 499 namespaces = [('Locals', self.curframe.f_locals),
494 500 ('Globals', self.curframe.f_globals)]
495 501 self.shell.find_line_magic('pinfo')("pinfo %s" % arg,
496 502 namespaces=namespaces)
497 503
498 504 def checkline(self, filename, lineno):
499 505 """Check whether specified line seems to be executable.
500 506
501 507 Return `lineno` if it is, 0 if not (e.g. a docstring, comment, blank
502 508 line or EOF). Warning: testing is not comprehensive.
503 509 """
504 510 #######################################################################
505 511 # XXX Hack! Use python-2.5 compatible code for this call, because with
506 512 # all of our changes, we've drifted from the pdb api in 2.6. For now,
507 513 # changing:
508 514 #
509 515 #line = linecache.getline(filename, lineno, self.curframe.f_globals)
510 516 # to:
511 517 #
512 518 line = linecache.getline(filename, lineno)
513 519 #
514 520 # does the trick. But in reality, we need to fix this by reconciling
515 521 # our updates with the new Pdb APIs in Python 2.6.
516 522 #
517 523 # End hack. The rest of this method is copied verbatim from 2.6 pdb.py
518 524 #######################################################################
519 525
520 526 if not line:
521 527 print('End of file', file=self.stdout)
522 528 return 0
523 529 line = line.strip()
524 530 # Don't allow setting breakpoint at a blank line
525 531 if (not line or (line[0] == '#') or
526 532 (line[:3] == '"""') or line[:3] == "'''"):
527 533 print('*** Blank or comment', file=self.stdout)
528 534 return 0
529 535 return lineno
@@ -1,842 +1,843 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 __builtin__
22 22 import inspect
23 23 import linecache
24 24 import os
25 25 import sys
26 26 import types
27 27 from collections import namedtuple
28 28 try:
29 29 from itertools import izip_longest
30 30 except ImportError:
31 31 from itertools import zip_longest as izip_longest
32 32
33 33 # IPython's own
34 34 from IPython.core import page
35 35 from IPython.testing.skipdoctest import skip_doctest_py3
36 36 from IPython.utils import PyColorize
37 37 from IPython.utils import io
38 from IPython.utils import openpy
38 39 from IPython.utils import py3compat
39 40 from IPython.utils.text import indent
40 41 from IPython.utils.wildcard import list_namespace
41 42 from IPython.utils.coloransi import *
42 43
43 44 #****************************************************************************
44 45 # Builtin color schemes
45 46
46 47 Colors = TermColors # just a shorthand
47 48
48 49 # Build a few color schemes
49 50 NoColor = ColorScheme(
50 51 'NoColor',{
51 52 'header' : Colors.NoColor,
52 53 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
53 54 } )
54 55
55 56 LinuxColors = ColorScheme(
56 57 'Linux',{
57 58 'header' : Colors.LightRed,
58 59 'normal' : Colors.Normal # color off (usu. Colors.Normal)
59 60 } )
60 61
61 62 LightBGColors = ColorScheme(
62 63 'LightBG',{
63 64 'header' : Colors.Red,
64 65 'normal' : Colors.Normal # color off (usu. Colors.Normal)
65 66 } )
66 67
67 68 # Build table of color schemes (needed by the parser)
68 69 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
69 70 'Linux')
70 71
71 72 #****************************************************************************
72 73 # Auxiliary functions and objects
73 74
74 75 # See the messaging spec for the definition of all these fields. This list
75 76 # effectively defines the order of display
76 77 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
77 78 'length', 'file', 'definition', 'docstring', 'source',
78 79 'init_definition', 'class_docstring', 'init_docstring',
79 80 'call_def', 'call_docstring',
80 81 # These won't be printed but will be used to determine how to
81 82 # format the object
82 83 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
83 84 ]
84 85
85 86
86 87 def object_info(**kw):
87 88 """Make an object info dict with all fields present."""
88 89 infodict = dict(izip_longest(info_fields, [None]))
89 90 infodict.update(kw)
90 91 return infodict
91 92
92 93
93 94 def getdoc(obj):
94 95 """Stable wrapper around inspect.getdoc.
95 96
96 97 This can't crash because of attribute problems.
97 98
98 99 It also attempts to call a getdoc() method on the given object. This
99 100 allows objects which provide their docstrings via non-standard mechanisms
100 101 (like Pyro proxies) to still be inspected by ipython's ? system."""
101 102 # Allow objects to offer customized documentation via a getdoc method:
102 103 try:
103 104 ds = obj.getdoc()
104 105 except Exception:
105 106 pass
106 107 else:
107 108 # if we get extra info, we add it to the normal docstring.
108 109 if isinstance(ds, basestring):
109 110 return inspect.cleandoc(ds)
110 111
111 112 try:
112 113 return inspect.getdoc(obj)
113 114 except Exception:
114 115 # Harden against an inspect failure, which can occur with
115 116 # SWIG-wrapped extensions.
116 117 return None
117 118
118 119
119 120 def getsource(obj,is_binary=False):
120 121 """Wrapper around inspect.getsource.
121 122
122 123 This can be modified by other projects to provide customized source
123 124 extraction.
124 125
125 126 Inputs:
126 127
127 128 - obj: an object whose source code we will attempt to extract.
128 129
129 130 Optional inputs:
130 131
131 132 - is_binary: whether the object is known to come from a binary source.
132 133 This implementation will skip returning any output for binary objects, but
133 134 custom extractors may know how to meaningfully process them."""
134 135
135 136 if is_binary:
136 137 return None
137 138 else:
138 139 # get source if obj was decorated with @decorator
139 140 if hasattr(obj,"__wrapped__"):
140 141 obj = obj.__wrapped__
141 142 try:
142 143 src = inspect.getsource(obj)
143 144 except TypeError:
144 145 if hasattr(obj,'__class__'):
145 146 src = inspect.getsource(obj.__class__)
146 147 return src
147 148
148 149 def getargspec(obj):
149 150 """Get the names and default values of a function's arguments.
150 151
151 152 A tuple of four things is returned: (args, varargs, varkw, defaults).
152 153 'args' is a list of the argument names (it may contain nested lists).
153 154 'varargs' and 'varkw' are the names of the * and ** arguments or None.
154 155 'defaults' is an n-tuple of the default values of the last n arguments.
155 156
156 157 Modified version of inspect.getargspec from the Python Standard
157 158 Library."""
158 159
159 160 if inspect.isfunction(obj):
160 161 func_obj = obj
161 162 elif inspect.ismethod(obj):
162 163 func_obj = obj.im_func
163 164 elif hasattr(obj, '__call__'):
164 165 func_obj = obj.__call__
165 166 else:
166 167 raise TypeError('arg is not a Python function')
167 168 args, varargs, varkw = inspect.getargs(func_obj.func_code)
168 169 return args, varargs, varkw, func_obj.func_defaults
169 170
170 171
171 172 def format_argspec(argspec):
172 173 """Format argspect, convenience wrapper around inspect's.
173 174
174 175 This takes a dict instead of ordered arguments and calls
175 176 inspect.format_argspec with the arguments in the necessary order.
176 177 """
177 178 return inspect.formatargspec(argspec['args'], argspec['varargs'],
178 179 argspec['varkw'], argspec['defaults'])
179 180
180 181
181 182 def call_tip(oinfo, format_call=True):
182 183 """Extract call tip data from an oinfo dict.
183 184
184 185 Parameters
185 186 ----------
186 187 oinfo : dict
187 188
188 189 format_call : bool, optional
189 190 If True, the call line is formatted and returned as a string. If not, a
190 191 tuple of (name, argspec) is returned.
191 192
192 193 Returns
193 194 -------
194 195 call_info : None, str or (str, dict) tuple.
195 196 When format_call is True, the whole call information is formattted as a
196 197 single string. Otherwise, the object's name and its argspec dict are
197 198 returned. If no call information is available, None is returned.
198 199
199 200 docstring : str or None
200 201 The most relevant docstring for calling purposes is returned, if
201 202 available. The priority is: call docstring for callable instances, then
202 203 constructor docstring for classes, then main object's docstring otherwise
203 204 (regular functions).
204 205 """
205 206 # Get call definition
206 207 argspec = oinfo.get('argspec')
207 208 if argspec is None:
208 209 call_line = None
209 210 else:
210 211 # Callable objects will have 'self' as their first argument, prune
211 212 # it out if it's there for clarity (since users do *not* pass an
212 213 # extra first argument explicitly).
213 214 try:
214 215 has_self = argspec['args'][0] == 'self'
215 216 except (KeyError, IndexError):
216 217 pass
217 218 else:
218 219 if has_self:
219 220 argspec['args'] = argspec['args'][1:]
220 221
221 222 call_line = oinfo['name']+format_argspec(argspec)
222 223
223 224 # Now get docstring.
224 225 # The priority is: call docstring, constructor docstring, main one.
225 226 doc = oinfo.get('call_docstring')
226 227 if doc is None:
227 228 doc = oinfo.get('init_docstring')
228 229 if doc is None:
229 230 doc = oinfo.get('docstring','')
230 231
231 232 return call_line, doc
232 233
233 234
234 235 def find_file(obj):
235 236 """Find the absolute path to the file where an object was defined.
236 237
237 238 This is essentially a robust wrapper around `inspect.getabsfile`.
238 239
239 240 Returns None if no file can be found.
240 241
241 242 Parameters
242 243 ----------
243 244 obj : any Python object
244 245
245 246 Returns
246 247 -------
247 248 fname : str
248 249 The absolute path to the file where the object was defined.
249 250 """
250 251 # get source if obj was decorated with @decorator
251 252 if hasattr(obj, '__wrapped__'):
252 253 obj = obj.__wrapped__
253 254
254 255 fname = None
255 256 try:
256 257 fname = inspect.getabsfile(obj)
257 258 except TypeError:
258 259 # For an instance, the file that matters is where its class was
259 260 # declared.
260 261 if hasattr(obj, '__class__'):
261 262 try:
262 263 fname = inspect.getabsfile(obj.__class__)
263 264 except TypeError:
264 265 # Can happen for builtins
265 266 pass
266 267 except:
267 268 pass
268 269 return fname
269 270
270 271
271 272 def find_source_lines(obj):
272 273 """Find the line number in a file where an object was defined.
273 274
274 275 This is essentially a robust wrapper around `inspect.getsourcelines`.
275 276
276 277 Returns None if no file can be found.
277 278
278 279 Parameters
279 280 ----------
280 281 obj : any Python object
281 282
282 283 Returns
283 284 -------
284 285 lineno : int
285 286 The line number where the object definition starts.
286 287 """
287 288 # get source if obj was decorated with @decorator
288 289 if hasattr(obj, '__wrapped__'):
289 290 obj = obj.__wrapped__
290 291
291 292 try:
292 293 try:
293 294 lineno = inspect.getsourcelines(obj)[1]
294 295 except TypeError:
295 296 # For instances, try the class object like getsource() does
296 297 if hasattr(obj, '__class__'):
297 298 lineno = inspect.getsourcelines(obj.__class__)[1]
298 299 except:
299 300 return None
300 301
301 302 return lineno
302 303
303 304
304 305 class Inspector:
305 306 def __init__(self, color_table=InspectColors,
306 307 code_color_table=PyColorize.ANSICodeColors,
307 308 scheme='NoColor',
308 309 str_detail_level=0):
309 310 self.color_table = color_table
310 311 self.parser = PyColorize.Parser(code_color_table,out='str')
311 312 self.format = self.parser.format
312 313 self.str_detail_level = str_detail_level
313 314 self.set_active_scheme(scheme)
314 315
315 316 def _getdef(self,obj,oname=''):
316 317 """Return the definition header for any callable object.
317 318
318 319 If any exception is generated, None is returned instead and the
319 320 exception is suppressed."""
320 321
321 322 try:
322 323 # We need a plain string here, NOT unicode!
323 324 hdef = oname + inspect.formatargspec(*getargspec(obj))
324 325 return py3compat.unicode_to_str(hdef, 'ascii')
325 326 except:
326 327 return None
327 328
328 329 def __head(self,h):
329 330 """Return a header string with proper colors."""
330 331 return '%s%s%s' % (self.color_table.active_colors.header,h,
331 332 self.color_table.active_colors.normal)
332 333
333 334 def set_active_scheme(self, scheme):
334 335 self.color_table.set_active_scheme(scheme)
335 336 self.parser.color_table.set_active_scheme(scheme)
336 337
337 338 def noinfo(self, msg, oname):
338 339 """Generic message when no information is found."""
339 340 print('No %s found' % msg, end=' ')
340 341 if oname:
341 342 print('for %s' % oname)
342 343 else:
343 344 print()
344 345
345 346 def pdef(self, obj, oname=''):
346 347 """Print the definition header for any callable object.
347 348
348 349 If the object is a class, print the constructor information."""
349 350
350 351 if not callable(obj):
351 352 print('Object is not callable.')
352 353 return
353 354
354 355 header = ''
355 356
356 357 if inspect.isclass(obj):
357 358 header = self.__head('Class constructor information:\n')
358 359 obj = obj.__init__
359 360 elif (not py3compat.PY3) and type(obj) is types.InstanceType:
360 361 obj = obj.__call__
361 362
362 363 output = self._getdef(obj,oname)
363 364 if output is None:
364 365 self.noinfo('definition header',oname)
365 366 else:
366 367 print(header,self.format(output), end=' ', file=io.stdout)
367 368
368 369 # In Python 3, all classes are new-style, so they all have __init__.
369 370 @skip_doctest_py3
370 371 def pdoc(self,obj,oname='',formatter = None):
371 372 """Print the docstring for any object.
372 373
373 374 Optional:
374 375 -formatter: a function to run the docstring through for specially
375 376 formatted docstrings.
376 377
377 378 Examples
378 379 --------
379 380
380 381 In [1]: class NoInit:
381 382 ...: pass
382 383
383 384 In [2]: class NoDoc:
384 385 ...: def __init__(self):
385 386 ...: pass
386 387
387 388 In [3]: %pdoc NoDoc
388 389 No documentation found for NoDoc
389 390
390 391 In [4]: %pdoc NoInit
391 392 No documentation found for NoInit
392 393
393 394 In [5]: obj = NoInit()
394 395
395 396 In [6]: %pdoc obj
396 397 No documentation found for obj
397 398
398 399 In [5]: obj2 = NoDoc()
399 400
400 401 In [6]: %pdoc obj2
401 402 No documentation found for obj2
402 403 """
403 404
404 405 head = self.__head # For convenience
405 406 lines = []
406 407 ds = getdoc(obj)
407 408 if formatter:
408 409 ds = formatter(ds)
409 410 if ds:
410 411 lines.append(head("Class Docstring:"))
411 412 lines.append(indent(ds))
412 413 if inspect.isclass(obj) and hasattr(obj, '__init__'):
413 414 init_ds = getdoc(obj.__init__)
414 415 if init_ds is not None:
415 416 lines.append(head("Constructor Docstring:"))
416 417 lines.append(indent(init_ds))
417 418 elif hasattr(obj,'__call__'):
418 419 call_ds = getdoc(obj.__call__)
419 420 if call_ds:
420 421 lines.append(head("Calling Docstring:"))
421 422 lines.append(indent(call_ds))
422 423
423 424 if not lines:
424 425 self.noinfo('documentation',oname)
425 426 else:
426 427 page.page('\n'.join(lines))
427 428
428 429 def psource(self,obj,oname=''):
429 430 """Print the source code for an object."""
430 431
431 432 # Flush the source cache because inspect can return out-of-date source
432 433 linecache.checkcache()
433 434 try:
434 435 src = getsource(obj)
435 436 except:
436 437 self.noinfo('source',oname)
437 438 else:
438 439 page.page(self.format(py3compat.unicode_to_str(src)))
439 440
440 441 def pfile(self, obj, oname=''):
441 442 """Show the whole file where an object was defined."""
442 443
443 444 lineno = find_source_lines(obj)
444 445 if lineno is None:
445 446 self.noinfo('file', oname)
446 447 return
447 448
448 449 ofile = find_file(obj)
449 450 # run contents of file through pager starting at line where the object
450 451 # is defined, as long as the file isn't binary and is actually on the
451 452 # filesystem.
452 453 if ofile.endswith(('.so', '.dll', '.pyd')):
453 454 print('File %r is binary, not printing.' % ofile)
454 455 elif not os.path.isfile(ofile):
455 456 print('File %r does not exist, not printing.' % ofile)
456 457 else:
457 458 # Print only text files, not extension binaries. Note that
458 459 # getsourcelines returns lineno with 1-offset and page() uses
459 460 # 0-offset, so we must adjust.
460 page.page(self.format(io.source_to_unicode(open(ofile).read())), lineno-1)
461 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
461 462
462 463 def _format_fields(self, fields, title_width=12):
463 464 """Formats a list of fields for display.
464 465
465 466 Parameters
466 467 ----------
467 468 fields : list
468 469 A list of 2-tuples: (field_title, field_content)
469 470 title_width : int
470 471 How many characters to pad titles to. Default 12.
471 472 """
472 473 out = []
473 474 header = self.__head
474 475 for title, content in fields:
475 476 if len(content.splitlines()) > 1:
476 477 title = header(title + ":") + "\n"
477 478 else:
478 479 title = header((title+":").ljust(title_width))
479 480 out.append(title + content)
480 481 return "\n".join(out)
481 482
482 483 # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict)
483 484 pinfo_fields1 = [("Type", "type_name"),
484 485 ]
485 486
486 487 pinfo_fields2 = [("String Form", "string_form"),
487 488 ]
488 489
489 490 pinfo_fields3 = [("Length", "length"),
490 491 ("File", "file"),
491 492 ("Definition", "definition"),
492 493 ]
493 494
494 495 pinfo_fields_obj = [("Class Docstring", "class_docstring"),
495 496 ("Constructor Docstring","init_docstring"),
496 497 ("Call def", "call_def"),
497 498 ("Call docstring", "call_docstring")]
498 499
499 500 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
500 501 """Show detailed information about an object.
501 502
502 503 Optional arguments:
503 504
504 505 - oname: name of the variable pointing to the object.
505 506
506 507 - formatter: special formatter for docstrings (see pdoc)
507 508
508 509 - info: a structure with some information fields which may have been
509 510 precomputed already.
510 511
511 512 - detail_level: if set to 1, more information is given.
512 513 """
513 514 info = self.info(obj, oname=oname, formatter=formatter,
514 515 info=info, detail_level=detail_level)
515 516 displayfields = []
516 517 def add_fields(fields):
517 518 for title, key in fields:
518 519 field = info[key]
519 520 if field is not None:
520 521 displayfields.append((title, field.rstrip()))
521 522
522 523 add_fields(self.pinfo_fields1)
523 524
524 525 # Base class for old-style instances
525 526 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
526 527 displayfields.append(("Base Class", info['base_class'].rstrip()))
527 528
528 529 add_fields(self.pinfo_fields2)
529 530
530 531 # Namespace
531 532 if info['namespace'] != 'Interactive':
532 533 displayfields.append(("Namespace", info['namespace'].rstrip()))
533 534
534 535 add_fields(self.pinfo_fields3)
535 536
536 537 # Source or docstring, depending on detail level and whether
537 538 # source found.
538 539 if detail_level > 0 and info['source'] is not None:
539 540 displayfields.append(("Source", self.format(py3compat.cast_bytes_py2(info['source']))))
540 541 elif info['docstring'] is not None:
541 542 displayfields.append(("Docstring", info["docstring"]))
542 543
543 544 # Constructor info for classes
544 545 if info['isclass']:
545 546 if info['init_definition'] or info['init_docstring']:
546 547 displayfields.append(("Constructor information", ""))
547 548 if info['init_definition'] is not None:
548 549 displayfields.append((" Definition",
549 550 info['init_definition'].rstrip()))
550 551 if info['init_docstring'] is not None:
551 552 displayfields.append((" Docstring",
552 553 indent(info['init_docstring'])))
553 554
554 555 # Info for objects:
555 556 else:
556 557 add_fields(self.pinfo_fields_obj)
557 558
558 559 # Finally send to printer/pager:
559 560 if displayfields:
560 561 page.page(self._format_fields(displayfields))
561 562
562 563 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
563 564 """Compute a dict with detailed information about an object.
564 565
565 566 Optional arguments:
566 567
567 568 - oname: name of the variable pointing to the object.
568 569
569 570 - formatter: special formatter for docstrings (see pdoc)
570 571
571 572 - info: a structure with some information fields which may have been
572 573 precomputed already.
573 574
574 575 - detail_level: if set to 1, more information is given.
575 576 """
576 577
577 578 obj_type = type(obj)
578 579
579 580 header = self.__head
580 581 if info is None:
581 582 ismagic = 0
582 583 isalias = 0
583 584 ospace = ''
584 585 else:
585 586 ismagic = info.ismagic
586 587 isalias = info.isalias
587 588 ospace = info.namespace
588 589
589 590 # Get docstring, special-casing aliases:
590 591 if isalias:
591 592 if not callable(obj):
592 593 try:
593 594 ds = "Alias to the system command:\n %s" % obj[1]
594 595 except:
595 596 ds = "Alias: " + str(obj)
596 597 else:
597 598 ds = "Alias to " + str(obj)
598 599 if obj.__doc__:
599 600 ds += "\nDocstring:\n" + obj.__doc__
600 601 else:
601 602 ds = getdoc(obj)
602 603 if ds is None:
603 604 ds = '<no docstring>'
604 605 if formatter is not None:
605 606 ds = formatter(ds)
606 607
607 608 # store output in a dict, we initialize it here and fill it as we go
608 609 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
609 610
610 611 string_max = 200 # max size of strings to show (snipped if longer)
611 612 shalf = int((string_max -5)/2)
612 613
613 614 if ismagic:
614 615 obj_type_name = 'Magic function'
615 616 elif isalias:
616 617 obj_type_name = 'System alias'
617 618 else:
618 619 obj_type_name = obj_type.__name__
619 620 out['type_name'] = obj_type_name
620 621
621 622 try:
622 623 bclass = obj.__class__
623 624 out['base_class'] = str(bclass)
624 625 except: pass
625 626
626 627 # String form, but snip if too long in ? form (full in ??)
627 628 if detail_level >= self.str_detail_level:
628 629 try:
629 630 ostr = str(obj)
630 631 str_head = 'string_form'
631 632 if not detail_level and len(ostr)>string_max:
632 633 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
633 634 ostr = ("\n" + " " * len(str_head.expandtabs())).\
634 635 join(q.strip() for q in ostr.split("\n"))
635 636 out[str_head] = ostr
636 637 except:
637 638 pass
638 639
639 640 if ospace:
640 641 out['namespace'] = ospace
641 642
642 643 # Length (for strings and lists)
643 644 try:
644 645 out['length'] = str(len(obj))
645 646 except: pass
646 647
647 648 # Filename where object was defined
648 649 binary_file = False
649 650 fname = find_file(obj)
650 651 if fname is None:
651 652 # if anything goes wrong, we don't want to show source, so it's as
652 653 # if the file was binary
653 654 binary_file = True
654 655 else:
655 656 if fname.endswith(('.so', '.dll', '.pyd')):
656 657 binary_file = True
657 658 elif fname.endswith('<string>'):
658 659 fname = 'Dynamically generated function. No source code available.'
659 660 out['file'] = fname
660 661
661 662 # reconstruct the function definition and print it:
662 663 defln = self._getdef(obj, oname)
663 664 if defln:
664 665 out['definition'] = self.format(defln)
665 666
666 667 # Docstrings only in detail 0 mode, since source contains them (we
667 668 # avoid repetitions). If source fails, we add them back, see below.
668 669 if ds and detail_level == 0:
669 670 out['docstring'] = ds
670 671
671 672 # Original source code for any callable
672 673 if detail_level:
673 674 # Flush the source cache because inspect can return out-of-date
674 675 # source
675 676 linecache.checkcache()
676 677 source = None
677 678 try:
678 679 try:
679 680 source = getsource(obj, binary_file)
680 681 except TypeError:
681 682 if hasattr(obj, '__class__'):
682 683 source = getsource(obj.__class__, binary_file)
683 684 if source is not None:
684 685 out['source'] = source.rstrip()
685 686 except Exception:
686 687 pass
687 688
688 689 if ds and source is None:
689 690 out['docstring'] = ds
690 691
691 692
692 693 # Constructor docstring for classes
693 694 if inspect.isclass(obj):
694 695 out['isclass'] = True
695 696 # reconstruct the function definition and print it:
696 697 try:
697 698 obj_init = obj.__init__
698 699 except AttributeError:
699 700 init_def = init_ds = None
700 701 else:
701 702 init_def = self._getdef(obj_init,oname)
702 703 init_ds = getdoc(obj_init)
703 704 # Skip Python's auto-generated docstrings
704 705 if init_ds and \
705 706 init_ds.startswith('x.__init__(...) initializes'):
706 707 init_ds = None
707 708
708 709 if init_def or init_ds:
709 710 if init_def:
710 711 out['init_definition'] = self.format(init_def)
711 712 if init_ds:
712 713 out['init_docstring'] = init_ds
713 714
714 715 # and class docstring for instances:
715 716 else:
716 717 # First, check whether the instance docstring is identical to the
717 718 # class one, and print it separately if they don't coincide. In
718 719 # most cases they will, but it's nice to print all the info for
719 720 # objects which use instance-customized docstrings.
720 721 if ds:
721 722 try:
722 723 cls = getattr(obj,'__class__')
723 724 except:
724 725 class_ds = None
725 726 else:
726 727 class_ds = getdoc(cls)
727 728 # Skip Python's auto-generated docstrings
728 729 if class_ds and \
729 730 (class_ds.startswith('function(code, globals[,') or \
730 731 class_ds.startswith('instancemethod(function, instance,') or \
731 732 class_ds.startswith('module(name[,') ):
732 733 class_ds = None
733 734 if class_ds and ds != class_ds:
734 735 out['class_docstring'] = class_ds
735 736
736 737 # Next, try to show constructor docstrings
737 738 try:
738 739 init_ds = getdoc(obj.__init__)
739 740 # Skip Python's auto-generated docstrings
740 741 if init_ds and \
741 742 init_ds.startswith('x.__init__(...) initializes'):
742 743 init_ds = None
743 744 except AttributeError:
744 745 init_ds = None
745 746 if init_ds:
746 747 out['init_docstring'] = init_ds
747 748
748 749 # Call form docstring for callable instances
749 750 if hasattr(obj, '__call__'):
750 751 call_def = self._getdef(obj.__call__, oname)
751 752 if call_def is not None:
752 753 out['call_def'] = self.format(call_def)
753 754 call_ds = getdoc(obj.__call__)
754 755 # Skip Python's auto-generated docstrings
755 756 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
756 757 call_ds = None
757 758 if call_ds:
758 759 out['call_docstring'] = call_ds
759 760
760 761 # Compute the object's argspec as a callable. The key is to decide
761 762 # whether to pull it from the object itself, from its __init__ or
762 763 # from its __call__ method.
763 764
764 765 if inspect.isclass(obj):
765 766 # Old-style classes need not have an __init__
766 767 callable_obj = getattr(obj, "__init__", None)
767 768 elif callable(obj):
768 769 callable_obj = obj
769 770 else:
770 771 callable_obj = None
771 772
772 773 if callable_obj:
773 774 try:
774 775 args, varargs, varkw, defaults = getargspec(callable_obj)
775 776 except (TypeError, AttributeError):
776 777 # For extensions/builtins we can't retrieve the argspec
777 778 pass
778 779 else:
779 780 out['argspec'] = dict(args=args, varargs=varargs,
780 781 varkw=varkw, defaults=defaults)
781 782
782 783 return object_info(**out)
783 784
784 785
785 786 def psearch(self,pattern,ns_table,ns_search=[],
786 787 ignore_case=False,show_all=False):
787 788 """Search namespaces with wildcards for objects.
788 789
789 790 Arguments:
790 791
791 792 - pattern: string containing shell-like wildcards to use in namespace
792 793 searches and optionally a type specification to narrow the search to
793 794 objects of that type.
794 795
795 796 - ns_table: dict of name->namespaces for search.
796 797
797 798 Optional arguments:
798 799
799 800 - ns_search: list of namespace names to include in search.
800 801
801 802 - ignore_case(False): make the search case-insensitive.
802 803
803 804 - show_all(False): show all names, including those starting with
804 805 underscores.
805 806 """
806 807 #print 'ps pattern:<%r>' % pattern # dbg
807 808
808 809 # defaults
809 810 type_pattern = 'all'
810 811 filter = ''
811 812
812 813 cmds = pattern.split()
813 814 len_cmds = len(cmds)
814 815 if len_cmds == 1:
815 816 # Only filter pattern given
816 817 filter = cmds[0]
817 818 elif len_cmds == 2:
818 819 # Both filter and type specified
819 820 filter,type_pattern = cmds
820 821 else:
821 822 raise ValueError('invalid argument string for psearch: <%s>' %
822 823 pattern)
823 824
824 825 # filter search namespaces
825 826 for name in ns_search:
826 827 if name not in ns_table:
827 828 raise ValueError('invalid namespace <%s>. Valid names: %s' %
828 829 (name,ns_table.keys()))
829 830
830 831 #print 'type_pattern:',type_pattern # dbg
831 832 search_result, namespaces_seen = set(), set()
832 833 for ns_name in ns_search:
833 834 ns = ns_table[ns_name]
834 835 # Normally, locals and globals are the same, so we just check one.
835 836 if id(ns) in namespaces_seen:
836 837 continue
837 838 namespaces_seen.add(id(ns))
838 839 tmp_res = list_namespace(ns, type_pattern, filter,
839 840 ignore_case=ignore_case, show_all=show_all)
840 841 search_result.update(tmp_res)
841 842
842 843 page.page('\n'.join(sorted(search_result)))
@@ -1,409 +1,385 b''
1 1 # encoding: utf-8
2 2 """
3 3 IO related utilities.
4 4 """
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2008-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12 from __future__ import print_function
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17 import re
18 18 import os
19 19 import sys
20 20 import tempfile
21 21 from StringIO import StringIO
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Code
25 25 #-----------------------------------------------------------------------------
26 26
27 27
28 28 class IOStream:
29 29
30 30 def __init__(self,stream, fallback=None):
31 31 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
32 32 if fallback is not None:
33 33 stream = fallback
34 34 else:
35 35 raise ValueError("fallback required, but not specified")
36 36 self.stream = stream
37 37 self._swrite = stream.write
38 38
39 39 # clone all methods not overridden:
40 40 def clone(meth):
41 41 return not hasattr(self, meth) and not meth.startswith('_')
42 42 for meth in filter(clone, dir(stream)):
43 43 setattr(self, meth, getattr(stream, meth))
44 44
45 45 def write(self,data):
46 46 try:
47 47 self._swrite(data)
48 48 except:
49 49 try:
50 50 # print handles some unicode issues which may trip a plain
51 51 # write() call. Emulate write() by using an empty end
52 52 # argument.
53 53 print(data, end='', file=self.stream)
54 54 except:
55 55 # if we get here, something is seriously broken.
56 56 print('ERROR - failed to write data to stream:', self.stream,
57 57 file=sys.stderr)
58 58
59 59 def writelines(self, lines):
60 60 if isinstance(lines, basestring):
61 61 lines = [lines]
62 62 for line in lines:
63 63 self.write(line)
64 64
65 65 # This class used to have a writeln method, but regular files and streams
66 66 # in Python don't have this method. We need to keep this completely
67 67 # compatible so we removed it.
68 68
69 69 @property
70 70 def closed(self):
71 71 return self.stream.closed
72 72
73 73 def close(self):
74 74 pass
75 75
76 76 # setup stdin/stdout/stderr to sys.stdin/sys.stdout/sys.stderr
77 77 devnull = open(os.devnull, 'a')
78 78 stdin = IOStream(sys.stdin, fallback=devnull)
79 79 stdout = IOStream(sys.stdout, fallback=devnull)
80 80 stderr = IOStream(sys.stderr, fallback=devnull)
81 81
82 82 class IOTerm:
83 83 """ Term holds the file or file-like objects for handling I/O operations.
84 84
85 85 These are normally just sys.stdin, sys.stdout and sys.stderr but for
86 86 Windows they can can replaced to allow editing the strings before they are
87 87 displayed."""
88 88
89 89 # In the future, having IPython channel all its I/O operations through
90 90 # this class will make it easier to embed it into other environments which
91 91 # are not a normal terminal (such as a GUI-based shell)
92 92 def __init__(self, stdin=None, stdout=None, stderr=None):
93 93 mymodule = sys.modules[__name__]
94 94 self.stdin = IOStream(stdin, mymodule.stdin)
95 95 self.stdout = IOStream(stdout, mymodule.stdout)
96 96 self.stderr = IOStream(stderr, mymodule.stderr)
97 97
98 98
99 99 class Tee(object):
100 100 """A class to duplicate an output stream to stdout/err.
101 101
102 102 This works in a manner very similar to the Unix 'tee' command.
103 103
104 104 When the object is closed or deleted, it closes the original file given to
105 105 it for duplication.
106 106 """
107 107 # Inspired by:
108 108 # http://mail.python.org/pipermail/python-list/2007-May/442737.html
109 109
110 110 def __init__(self, file_or_name, mode="w", channel='stdout'):
111 111 """Construct a new Tee object.
112 112
113 113 Parameters
114 114 ----------
115 115 file_or_name : filename or open filehandle (writable)
116 116 File that will be duplicated
117 117
118 118 mode : optional, valid mode for open().
119 119 If a filename was give, open with this mode.
120 120
121 121 channel : str, one of ['stdout', 'stderr']
122 122 """
123 123 if channel not in ['stdout', 'stderr']:
124 124 raise ValueError('Invalid channel spec %s' % channel)
125 125
126 126 if hasattr(file_or_name, 'write') and hasattr(file_or_name, 'seek'):
127 127 self.file = file_or_name
128 128 else:
129 129 self.file = open(file_or_name, mode)
130 130 self.channel = channel
131 131 self.ostream = getattr(sys, channel)
132 132 setattr(sys, channel, self)
133 133 self._closed = False
134 134
135 135 def close(self):
136 136 """Close the file and restore the channel."""
137 137 self.flush()
138 138 setattr(sys, self.channel, self.ostream)
139 139 self.file.close()
140 140 self._closed = True
141 141
142 142 def write(self, data):
143 143 """Write data to both channels."""
144 144 self.file.write(data)
145 145 self.ostream.write(data)
146 146 self.ostream.flush()
147 147
148 148 def flush(self):
149 149 """Flush both channels."""
150 150 self.file.flush()
151 151 self.ostream.flush()
152 152
153 153 def __del__(self):
154 154 if not self._closed:
155 155 self.close()
156 156
157 157
158 def guess_encoding(lines):
159 """check list of lines for line matching the source code encoding pattern
160
161 Only check first two lines
162 """
163 reg = re.compile("#.*coding[:=]\s*([-\w.]+)")
164 for row in lines[:2]: #We only need to check the first two lines
165 result = reg.match(row)
166 if result:
167 coding = result.groups()[0]
168 break
169 else:
170 coding = "ascii"
171 return coding
172
173 def source_to_unicode(txt):
174 """Converts string with python source code to unicode
175 """
176 if isinstance(txt, unicode):
177 return txt
178 coding = guess_encoding(txt.split("\n", 2))
179 return txt.decode(coding, errors="replace")
180
181
182 158 def file_read(filename):
183 159 """Read a file and close it. Returns the file source."""
184 160 fobj = open(filename,'r');
185 161 source = fobj.read();
186 162 fobj.close()
187 163 return source
188 164
189 165
190 166 def file_readlines(filename):
191 167 """Read a file and close it. Returns the file source using readlines()."""
192 168 fobj = open(filename,'r');
193 169 lines = fobj.readlines();
194 170 fobj.close()
195 171 return lines
196 172
197 173
198 174 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
199 175 """Take multiple lines of input.
200 176
201 177 A list with each line of input as a separate element is returned when a
202 178 termination string is entered (defaults to a single '.'). Input can also
203 179 terminate via EOF (^D in Unix, ^Z-RET in Windows).
204 180
205 181 Lines of input which end in \\ are joined into single entries (and a
206 182 secondary continuation prompt is issued as long as the user terminates
207 183 lines with \\). This allows entering very long strings which are still
208 184 meant to be treated as single entities.
209 185 """
210 186
211 187 try:
212 188 if header:
213 189 header += '\n'
214 190 lines = [raw_input(header + ps1)]
215 191 except EOFError:
216 192 return []
217 193 terminate = [terminate_str]
218 194 try:
219 195 while lines[-1:] != terminate:
220 196 new_line = raw_input(ps1)
221 197 while new_line.endswith('\\'):
222 198 new_line = new_line[:-1] + raw_input(ps2)
223 199 lines.append(new_line)
224 200
225 201 return lines[:-1] # don't return the termination command
226 202 except EOFError:
227 203 print()
228 204 return lines
229 205
230 206
231 207 def raw_input_ext(prompt='', ps2='... '):
232 208 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
233 209
234 210 line = raw_input(prompt)
235 211 while line.endswith('\\'):
236 212 line = line[:-1] + raw_input(ps2)
237 213 return line
238 214
239 215
240 216 def ask_yes_no(prompt,default=None):
241 217 """Asks a question and returns a boolean (y/n) answer.
242 218
243 219 If default is given (one of 'y','n'), it is used if the user input is
244 220 empty. Otherwise the question is repeated until an answer is given.
245 221
246 222 An EOF is treated as the default answer. If there is no default, an
247 223 exception is raised to prevent infinite loops.
248 224
249 225 Valid answers are: y/yes/n/no (match is not case sensitive)."""
250 226
251 227 answers = {'y':True,'n':False,'yes':True,'no':False}
252 228 ans = None
253 229 while ans not in answers.keys():
254 230 try:
255 231 ans = raw_input(prompt+' ').lower()
256 232 if not ans: # response was an empty string
257 233 ans = default
258 234 except KeyboardInterrupt:
259 235 pass
260 236 except EOFError:
261 237 if default in answers.keys():
262 238 ans = default
263 239 print()
264 240 else:
265 241 raise
266 242
267 243 return answers[ans]
268 244
269 245
270 246 class NLprinter:
271 247 """Print an arbitrarily nested list, indicating index numbers.
272 248
273 249 An instance of this class called nlprint is available and callable as a
274 250 function.
275 251
276 252 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
277 253 and using 'sep' to separate the index from the value. """
278 254
279 255 def __init__(self):
280 256 self.depth = 0
281 257
282 258 def __call__(self,lst,pos='',**kw):
283 259 """Prints the nested list numbering levels."""
284 260 kw.setdefault('indent',' ')
285 261 kw.setdefault('sep',': ')
286 262 kw.setdefault('start',0)
287 263 kw.setdefault('stop',len(lst))
288 264 # we need to remove start and stop from kw so they don't propagate
289 265 # into a recursive call for a nested list.
290 266 start = kw['start']; del kw['start']
291 267 stop = kw['stop']; del kw['stop']
292 268 if self.depth == 0 and 'header' in kw.keys():
293 269 print(kw['header'])
294 270
295 271 for idx in range(start,stop):
296 272 elem = lst[idx]
297 273 newpos = pos + str(idx)
298 274 if type(elem)==type([]):
299 275 self.depth += 1
300 276 self.__call__(elem, newpos+",", **kw)
301 277 self.depth -= 1
302 278 else:
303 279 print(kw['indent']*self.depth + newpos + kw["sep"] + repr(elem))
304 280
305 281 nlprint = NLprinter()
306 282
307 283
308 284 def temp_pyfile(src, ext='.py'):
309 285 """Make a temporary python file, return filename and filehandle.
310 286
311 287 Parameters
312 288 ----------
313 289 src : string or list of strings (no need for ending newlines if list)
314 290 Source code to be written to the file.
315 291
316 292 ext : optional, string
317 293 Extension for the generated file.
318 294
319 295 Returns
320 296 -------
321 297 (filename, open filehandle)
322 298 It is the caller's responsibility to close the open file and unlink it.
323 299 """
324 300 fname = tempfile.mkstemp(ext)[1]
325 301 f = open(fname,'w')
326 302 f.write(src)
327 303 f.flush()
328 304 return fname, f
329 305
330 306
331 307 def raw_print(*args, **kw):
332 308 """Raw print to sys.__stdout__, otherwise identical interface to print()."""
333 309
334 310 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
335 311 file=sys.__stdout__)
336 312 sys.__stdout__.flush()
337 313
338 314
339 315 def raw_print_err(*args, **kw):
340 316 """Raw print to sys.__stderr__, otherwise identical interface to print()."""
341 317
342 318 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
343 319 file=sys.__stderr__)
344 320 sys.__stderr__.flush()
345 321
346 322
347 323 # Short aliases for quick debugging, do NOT use these in production code.
348 324 rprint = raw_print
349 325 rprinte = raw_print_err
350 326
351 327
352 328 class CapturedIO(object):
353 329 """Simple object for containing captured stdout/err StringIO objects"""
354 330
355 331 def __init__(self, stdout, stderr):
356 332 self._stdout = stdout
357 333 self._stderr = stderr
358 334
359 335 def __str__(self):
360 336 return self.stdout
361 337
362 338 @property
363 339 def stdout(self):
364 340 if not self._stdout:
365 341 return ''
366 342 return self._stdout.getvalue()
367 343
368 344 @property
369 345 def stderr(self):
370 346 if not self._stderr:
371 347 return ''
372 348 return self._stderr.getvalue()
373 349
374 350 def show(self):
375 351 """write my output to sys.stdout/err as appropriate"""
376 352 sys.stdout.write(self.stdout)
377 353 sys.stderr.write(self.stderr)
378 354 sys.stdout.flush()
379 355 sys.stderr.flush()
380 356
381 357 __call__ = show
382 358
383 359
384 360 class capture_output(object):
385 361 """context manager for capturing stdout/err"""
386 362 stdout = True
387 363 stderr = True
388 364
389 365 def __init__(self, stdout=True, stderr=True):
390 366 self.stdout = stdout
391 367 self.stderr = stderr
392 368
393 369 def __enter__(self):
394 370 self.sys_stdout = sys.stdout
395 371 self.sys_stderr = sys.stderr
396 372
397 373 stdout = stderr = False
398 374 if self.stdout:
399 375 stdout = sys.stdout = StringIO()
400 376 if self.stderr:
401 377 stderr = sys.stderr = StringIO()
402 378
403 379 return CapturedIO(stdout, stderr)
404 380
405 381 def __exit__(self, exc_type, exc_value, traceback):
406 382 sys.stdout = self.sys_stdout
407 383 sys.stderr = self.sys_stderr
408 384
409 385
@@ -1,192 +1,204 b''
1 1 """
2 2 Tools to open .py files as Unicode, using the encoding specified within the file,
3 3 as per PEP 263.
4 4
5 5 Much of the code is taken from the tokenize module in Python 3.2.
6 6 """
7 7 from __future__ import absolute_import
8 8
9 9 import io
10 10 from io import TextIOWrapper
11 11 import re
12 from StringIO import StringIO
12 13 import urllib
13 14
14 15 cookie_re = re.compile(ur"coding[:=]\s*([-\w.]+)", re.UNICODE)
15 16 cookie_comment_re = re.compile(ur"^\s*#.*coding[:=]\s*([-\w.]+)", re.UNICODE)
16 17
17 18 try:
18 19 # Available in Python 3
19 20 from tokenize import detect_encoding
20 21 except ImportError:
21 22 from codecs import lookup, BOM_UTF8
22 23
23 24 # Copied from Python 3.2 tokenize
24 25 def _get_normal_name(orig_enc):
25 26 """Imitates get_normal_name in tokenizer.c."""
26 27 # Only care about the first 12 characters.
27 28 enc = orig_enc[:12].lower().replace("_", "-")
28 29 if enc == "utf-8" or enc.startswith("utf-8-"):
29 30 return "utf-8"
30 31 if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \
31 32 enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")):
32 33 return "iso-8859-1"
33 34 return orig_enc
34 35
35 36 # Copied from Python 3.2 tokenize
36 37 def detect_encoding(readline):
37 38 """
38 39 The detect_encoding() function is used to detect the encoding that should
39 40 be used to decode a Python source file. It requires one argment, readline,
40 41 in the same way as the tokenize() generator.
41 42
42 43 It will call readline a maximum of twice, and return the encoding used
43 44 (as a string) and a list of any lines (left as bytes) it has read in.
44 45
45 46 It detects the encoding from the presence of a utf-8 bom or an encoding
46 47 cookie as specified in pep-0263. If both a bom and a cookie are present,
47 48 but disagree, a SyntaxError will be raised. If the encoding cookie is an
48 49 invalid charset, raise a SyntaxError. Note that if a utf-8 bom is found,
49 50 'utf-8-sig' is returned.
50 51
51 52 If no encoding is specified, then the default of 'utf-8' will be returned.
52 53 """
53 54 bom_found = False
54 55 encoding = None
55 56 default = 'utf-8'
56 57 def read_or_stop():
57 58 try:
58 59 return readline()
59 60 except StopIteration:
60 61 return b''
61 62
62 63 def find_cookie(line):
63 64 try:
64 65 line_string = line.decode('ascii')
65 66 except UnicodeDecodeError:
66 67 return None
67 68
68 69 matches = cookie_re.findall(line_string)
69 70 if not matches:
70 71 return None
71 72 encoding = _get_normal_name(matches[0])
72 73 try:
73 74 codec = lookup(encoding)
74 75 except LookupError:
75 76 # This behaviour mimics the Python interpreter
76 77 raise SyntaxError("unknown encoding: " + encoding)
77 78
78 79 if bom_found:
79 80 if codec.name != 'utf-8':
80 81 # This behaviour mimics the Python interpreter
81 82 raise SyntaxError('encoding problem: utf-8')
82 83 encoding += '-sig'
83 84 return encoding
84 85
85 86 first = read_or_stop()
86 87 if first.startswith(BOM_UTF8):
87 88 bom_found = True
88 89 first = first[3:]
89 90 default = 'utf-8-sig'
90 91 if not first:
91 92 return default, []
92 93
93 94 encoding = find_cookie(first)
94 95 if encoding:
95 96 return encoding, [first]
96 97
97 98 second = read_or_stop()
98 99 if not second:
99 100 return default, [first]
100 101
101 102 encoding = find_cookie(second)
102 103 if encoding:
103 104 return encoding, [first, second]
104 105
105 106 return default, [first, second]
106 107
107 108 try:
108 109 # Available in Python 3.2 and above.
109 110 from tokenize import open
110 111 except ImportError:
111 112 # Copied from Python 3.2 tokenize
112 113 def open(filename):
113 114 """Open a file in read only mode using the encoding detected by
114 115 detect_encoding().
115 116 """
116 117 buffer = io.open(filename, 'rb') # Tweaked to use io.open for Python 2
117 118 encoding, lines = detect_encoding(buffer.readline)
118 119 buffer.seek(0)
119 120 text = TextIOWrapper(buffer, encoding, line_buffering=True)
120 121 text.mode = 'r'
121 122 return text
122 123
124 def source_to_unicode(txt):
125 """Converts string with python source code to unicode
126 """
127 if isinstance(txt, unicode):
128 return txt
129 try:
130 coding, _ = detect_encoding(StringIO(txt).readline)
131 except SyntaxError:
132 coding = "ascii"
133 return txt.decode(coding, errors="replace")
134
123 135 def strip_encoding_cookie(filelike):
124 136 """Generator to pull lines from a text-mode file, skipping the encoding
125 137 cookie if it is found in the first two lines.
126 138 """
127 139 it = iter(filelike)
128 140 try:
129 141 first = next(it)
130 142 if not cookie_comment_re.match(first):
131 143 yield first
132 144 second = next(it)
133 145 if not cookie_comment_re.match(second):
134 146 yield second
135 147 except StopIteration:
136 148 return
137 149
138 150 for line in it:
139 151 yield line
140 152
141 153 def read_py_file(filename, skip_encoding_cookie=True):
142 154 """Read a Python file, using the encoding declared inside the file.
143 155
144 156 Parameters
145 157 ----------
146 158 filename : str
147 159 The path to the file to read.
148 160 skip_encoding_cookie : bool
149 161 If True (the default), and the encoding declaration is found in the first
150 162 two lines, that line will be excluded from the output - compiling a
151 163 unicode string with an encoding declaration is a SyntaxError in Python 2.
152 164
153 165 Returns
154 166 -------
155 167 A unicode string containing the contents of the file.
156 168 """
157 169 with open(filename) as f: # the open function defined in this module.
158 170 if skip_encoding_cookie:
159 171 return "".join(strip_encoding_cookie(f))
160 172 else:
161 173 return f.read()
162 174
163 175 def read_py_url(url, errors='replace', skip_encoding_cookie=True):
164 176 """Read a Python file from a URL, using the encoding declared inside the file.
165 177
166 178 Parameters
167 179 ----------
168 180 url : str
169 181 The URL from which to fetch the file.
170 182 errors : str
171 183 How to handle decoding errors in the file. Options are the same as for
172 184 bytes.decode(), but here 'replace' is the default.
173 185 skip_encoding_cookie : bool
174 186 If True (the default), and the encoding declaration is found in the first
175 187 two lines, that line will be excluded from the output - compiling a
176 188 unicode string with an encoding declaration is a SyntaxError in Python 2.
177 189
178 190 Returns
179 191 -------
180 192 A unicode string containing the contents of the file.
181 193 """
182 194 response = urllib.urlopen(url)
183 195 buffer = io.BytesIO(response.read())
184 196 encoding, lines = detect_encoding(buffer.readline)
185 197 buffer.seek(0)
186 198 text = TextIOWrapper(buffer, encoding, errors=errors, line_buffering=True)
187 199 text.mode = 'r'
188 200 if skip_encoding_cookie:
189 201 return "".join(strip_encoding_cookie(text))
190 202 else:
191 203 return text.read()
192 204
@@ -1,588 +1,590 b''
1 1 """A ZMQ-based subclass of InteractiveShell.
2 2
3 3 This code is meant to ease the refactoring of the base InteractiveShell into
4 4 something with a cleaner architecture for 2-process use, without actually
5 5 breaking InteractiveShell itself. So we're doing something a bit ugly, where
6 6 we subclass and override what we want to fix. Once this is working well, we
7 7 can go back to the base class and refactor the code for a cleaner inheritance
8 8 implementation that doesn't rely on so much monkeypatching.
9 9
10 10 But this lets us maintain a fully working IPython as we develop the new
11 11 machinery. This should thus be thought of as scaffolding.
12 12 """
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 from __future__ import print_function
17 17
18 18 # Stdlib
19 19 import os
20 20 import sys
21 21 import time
22 22
23 23 # System library imports
24 24 from zmq.eventloop import ioloop
25 25
26 26 # Our own
27 27 from IPython.core.interactiveshell import (
28 28 InteractiveShell, InteractiveShellABC
29 29 )
30 30 from IPython.core import page
31 31 from IPython.core.autocall import ZMQExitAutocall
32 32 from IPython.core.displaypub import DisplayPublisher
33 33 from IPython.core.error import UsageError
34 34 from IPython.core.magics import MacroToEdit, CodeMagics
35 35 from IPython.core.magic import magics_class, line_magic, Magics
36 36 from IPython.core.payloadpage import install_payload_page
37 37 from IPython.lib.kernel import (
38 38 get_connection_file, get_connection_info, connect_qtconsole
39 39 )
40 40 from IPython.testing.skipdoctest import skip_doctest
41 from IPython.utils import io
41 from IPython.utils import io, openpy
42 42 from IPython.utils.jsonutil import json_clean, encode_images
43 43 from IPython.utils.process import arg_split
44 44 from IPython.utils import py3compat
45 45 from IPython.utils.traitlets import Instance, Type, Dict, CBool, CBytes
46 46 from IPython.utils.warn import warn, error
47 47 from IPython.zmq.displayhook import ZMQShellDisplayHook
48 48 from IPython.zmq.datapub import ZMQDataPublisher
49 49 from IPython.zmq.session import extract_header
50 50 from session import Session
51 51
52 52 #-----------------------------------------------------------------------------
53 53 # Functions and classes
54 54 #-----------------------------------------------------------------------------
55 55
56 56 class ZMQDisplayPublisher(DisplayPublisher):
57 57 """A display publisher that publishes data using a ZeroMQ PUB socket."""
58 58
59 59 session = Instance(Session)
60 60 pub_socket = Instance('zmq.Socket')
61 61 parent_header = Dict({})
62 62 topic = CBytes(b'displaypub')
63 63
64 64 def set_parent(self, parent):
65 65 """Set the parent for outbound messages."""
66 66 self.parent_header = extract_header(parent)
67 67
68 68 def _flush_streams(self):
69 69 """flush IO Streams prior to display"""
70 70 sys.stdout.flush()
71 71 sys.stderr.flush()
72 72
73 73 def publish(self, source, data, metadata=None):
74 74 self._flush_streams()
75 75 if metadata is None:
76 76 metadata = {}
77 77 self._validate_data(source, data, metadata)
78 78 content = {}
79 79 content['source'] = source
80 80 content['data'] = encode_images(data)
81 81 content['metadata'] = metadata
82 82 self.session.send(
83 83 self.pub_socket, u'display_data', json_clean(content),
84 84 parent=self.parent_header, ident=self.topic,
85 85 )
86 86
87 87 def clear_output(self, stdout=True, stderr=True, other=True):
88 88 content = dict(stdout=stdout, stderr=stderr, other=other)
89 89
90 90 if stdout:
91 91 print('\r', file=sys.stdout, end='')
92 92 if stderr:
93 93 print('\r', file=sys.stderr, end='')
94 94
95 95 self._flush_streams()
96 96
97 97 self.session.send(
98 98 self.pub_socket, u'clear_output', content,
99 99 parent=self.parent_header, ident=self.topic,
100 100 )
101 101
102 102 @magics_class
103 103 class KernelMagics(Magics):
104 104 #------------------------------------------------------------------------
105 105 # Magic overrides
106 106 #------------------------------------------------------------------------
107 107 # Once the base class stops inheriting from magic, this code needs to be
108 108 # moved into a separate machinery as well. For now, at least isolate here
109 109 # the magics which this class needs to implement differently from the base
110 110 # class, or that are unique to it.
111 111
112 112 @line_magic
113 113 def doctest_mode(self, parameter_s=''):
114 114 """Toggle doctest mode on and off.
115 115
116 116 This mode is intended to make IPython behave as much as possible like a
117 117 plain Python shell, from the perspective of how its prompts, exceptions
118 118 and output look. This makes it easy to copy and paste parts of a
119 119 session into doctests. It does so by:
120 120
121 121 - Changing the prompts to the classic ``>>>`` ones.
122 122 - Changing the exception reporting mode to 'Plain'.
123 123 - Disabling pretty-printing of output.
124 124
125 125 Note that IPython also supports the pasting of code snippets that have
126 126 leading '>>>' and '...' prompts in them. This means that you can paste
127 127 doctests from files or docstrings (even if they have leading
128 128 whitespace), and the code will execute correctly. You can then use
129 129 '%history -t' to see the translated history; this will give you the
130 130 input after removal of all the leading prompts and whitespace, which
131 131 can be pasted back into an editor.
132 132
133 133 With these features, you can switch into this mode easily whenever you
134 134 need to do testing and changes to doctests, without having to leave
135 135 your existing IPython session.
136 136 """
137 137
138 138 from IPython.utils.ipstruct import Struct
139 139
140 140 # Shorthands
141 141 shell = self.shell
142 142 disp_formatter = self.shell.display_formatter
143 143 ptformatter = disp_formatter.formatters['text/plain']
144 144 # dstore is a data store kept in the instance metadata bag to track any
145 145 # changes we make, so we can undo them later.
146 146 dstore = shell.meta.setdefault('doctest_mode', Struct())
147 147 save_dstore = dstore.setdefault
148 148
149 149 # save a few values we'll need to recover later
150 150 mode = save_dstore('mode', False)
151 151 save_dstore('rc_pprint', ptformatter.pprint)
152 152 save_dstore('rc_plain_text_only',disp_formatter.plain_text_only)
153 153 save_dstore('xmode', shell.InteractiveTB.mode)
154 154
155 155 if mode == False:
156 156 # turn on
157 157 ptformatter.pprint = False
158 158 disp_formatter.plain_text_only = True
159 159 shell.magic('xmode Plain')
160 160 else:
161 161 # turn off
162 162 ptformatter.pprint = dstore.rc_pprint
163 163 disp_formatter.plain_text_only = dstore.rc_plain_text_only
164 164 shell.magic("xmode " + dstore.xmode)
165 165
166 166 # Store new mode and inform on console
167 167 dstore.mode = bool(1-int(mode))
168 168 mode_label = ['OFF','ON'][dstore.mode]
169 169 print('Doctest mode is:', mode_label)
170 170
171 171 # Send the payload back so that clients can modify their prompt display
172 172 payload = dict(
173 173 source='IPython.zmq.zmqshell.ZMQInteractiveShell.doctest_mode',
174 174 mode=dstore.mode)
175 175 shell.payload_manager.write_payload(payload)
176 176
177 177
178 178 _find_edit_target = CodeMagics._find_edit_target
179 179
180 180 @skip_doctest
181 181 @line_magic
182 182 def edit(self, parameter_s='', last_call=['','']):
183 183 """Bring up an editor and execute the resulting code.
184 184
185 185 Usage:
186 186 %edit [options] [args]
187 187
188 188 %edit runs an external text editor. You will need to set the command for
189 189 this editor via the ``TerminalInteractiveShell.editor`` option in your
190 190 configuration file before it will work.
191 191
192 192 This command allows you to conveniently edit multi-line code right in
193 193 your IPython session.
194 194
195 195 If called without arguments, %edit opens up an empty editor with a
196 196 temporary file and will execute the contents of this file when you
197 197 close it (don't forget to save it!).
198 198
199 199
200 200 Options:
201 201
202 202 -n <number>: open the editor at a specified line number. By default,
203 203 the IPython editor hook uses the unix syntax 'editor +N filename', but
204 204 you can configure this by providing your own modified hook if your
205 205 favorite editor supports line-number specifications with a different
206 206 syntax.
207 207
208 208 -p: this will call the editor with the same data as the previous time
209 209 it was used, regardless of how long ago (in your current session) it
210 210 was.
211 211
212 212 -r: use 'raw' input. This option only applies to input taken from the
213 213 user's history. By default, the 'processed' history is used, so that
214 214 magics are loaded in their transformed version to valid Python. If
215 215 this option is given, the raw input as typed as the command line is
216 216 used instead. When you exit the editor, it will be executed by
217 217 IPython's own processor.
218 218
219 219 -x: do not execute the edited code immediately upon exit. This is
220 220 mainly useful if you are editing programs which need to be called with
221 221 command line arguments, which you can then do using %run.
222 222
223 223
224 224 Arguments:
225 225
226 226 If arguments are given, the following possibilites exist:
227 227
228 228 - The arguments are numbers or pairs of colon-separated numbers (like
229 229 1 4:8 9). These are interpreted as lines of previous input to be
230 230 loaded into the editor. The syntax is the same of the %macro command.
231 231
232 232 - If the argument doesn't start with a number, it is evaluated as a
233 233 variable and its contents loaded into the editor. You can thus edit
234 234 any string which contains python code (including the result of
235 235 previous edits).
236 236
237 237 - If the argument is the name of an object (other than a string),
238 238 IPython will try to locate the file where it was defined and open the
239 239 editor at the point where it is defined. You can use `%edit function`
240 240 to load an editor exactly at the point where 'function' is defined,
241 241 edit it and have the file be executed automatically.
242 242
243 243 If the object is a macro (see %macro for details), this opens up your
244 244 specified editor with a temporary file containing the macro's data.
245 245 Upon exit, the macro is reloaded with the contents of the file.
246 246
247 247 Note: opening at an exact line is only supported under Unix, and some
248 248 editors (like kedit and gedit up to Gnome 2.8) do not understand the
249 249 '+NUMBER' parameter necessary for this feature. Good editors like
250 250 (X)Emacs, vi, jed, pico and joe all do.
251 251
252 252 - If the argument is not found as a variable, IPython will look for a
253 253 file with that name (adding .py if necessary) and load it into the
254 254 editor. It will execute its contents with execfile() when you exit,
255 255 loading any code in the file into your interactive namespace.
256 256
257 257 After executing your code, %edit will return as output the code you
258 258 typed in the editor (except when it was an existing file). This way
259 259 you can reload the code in further invocations of %edit as a variable,
260 260 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
261 261 the output.
262 262
263 263 Note that %edit is also available through the alias %ed.
264 264
265 265 This is an example of creating a simple function inside the editor and
266 266 then modifying it. First, start up the editor:
267 267
268 268 In [1]: ed
269 269 Editing... done. Executing edited code...
270 270 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
271 271
272 272 We can then call the function foo():
273 273
274 274 In [2]: foo()
275 275 foo() was defined in an editing session
276 276
277 277 Now we edit foo. IPython automatically loads the editor with the
278 278 (temporary) file where foo() was previously defined:
279 279
280 280 In [3]: ed foo
281 281 Editing... done. Executing edited code...
282 282
283 283 And if we call foo() again we get the modified version:
284 284
285 285 In [4]: foo()
286 286 foo() has now been changed!
287 287
288 288 Here is an example of how to edit a code snippet successive
289 289 times. First we call the editor:
290 290
291 291 In [5]: ed
292 292 Editing... done. Executing edited code...
293 293 hello
294 294 Out[5]: "print 'hello'n"
295 295
296 296 Now we call it again with the previous output (stored in _):
297 297
298 298 In [6]: ed _
299 299 Editing... done. Executing edited code...
300 300 hello world
301 301 Out[6]: "print 'hello world'n"
302 302
303 303 Now we call it with the output #8 (stored in _8, also as Out[8]):
304 304
305 305 In [7]: ed _8
306 306 Editing... done. Executing edited code...
307 307 hello again
308 308 Out[7]: "print 'hello again'n"
309 309 """
310 310
311 311 opts,args = self.parse_options(parameter_s,'prn:')
312 312
313 313 try:
314 314 filename, lineno, _ = CodeMagics._find_edit_target(self.shell, args, opts, last_call)
315 315 except MacroToEdit as e:
316 316 # TODO: Implement macro editing over 2 processes.
317 317 print("Macro editing not yet implemented in 2-process model.")
318 318 return
319 319
320 320 # Make sure we send to the client an absolute path, in case the working
321 321 # directory of client and kernel don't match
322 322 filename = os.path.abspath(filename)
323 323
324 324 payload = {
325 325 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
326 326 'filename' : filename,
327 327 'line_number' : lineno
328 328 }
329 329 self.shell.payload_manager.write_payload(payload)
330 330
331 331 # A few magics that are adapted to the specifics of using pexpect and a
332 332 # remote terminal
333 333
334 334 @line_magic
335 335 def clear(self, arg_s):
336 336 """Clear the terminal."""
337 337 if os.name == 'posix':
338 338 self.shell.system("clear")
339 339 else:
340 340 self.shell.system("cls")
341 341
342 342 if os.name == 'nt':
343 343 # This is the usual name in windows
344 344 cls = line_magic('cls')(clear)
345 345
346 346 # Terminal pagers won't work over pexpect, but we do have our own pager
347 347
348 348 @line_magic
349 349 def less(self, arg_s):
350 350 """Show a file through the pager.
351 351
352 352 Files ending in .py are syntax-highlighted."""
353 353 if not arg_s:
354 354 raise UsageError('Missing filename.')
355 355
356 356 cont = open(arg_s).read()
357 357 if arg_s.endswith('.py'):
358 cont = self.shell.pycolorize(io.source_to_unicode(cont))
358 cont = self.shell.pycolorize(openpy.read_py_file(arg_s, skip_encoding_cookie=False))
359 else:
360 cont = open(arg_s).read()
359 361 page.page(cont)
360 362
361 363 more = line_magic('more')(less)
362 364
363 365 # Man calls a pager, so we also need to redefine it
364 366 if os.name == 'posix':
365 367 @line_magic
366 368 def man(self, arg_s):
367 369 """Find the man page for the given command and display in pager."""
368 370 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
369 371 split=False))
370 372
371 373 @line_magic
372 374 def connect_info(self, arg_s):
373 375 """Print information for connecting other clients to this kernel
374 376
375 377 It will print the contents of this session's connection file, as well as
376 378 shortcuts for local clients.
377 379
378 380 In the simplest case, when called from the most recently launched kernel,
379 381 secondary clients can be connected, simply with:
380 382
381 383 $> ipython <app> --existing
382 384
383 385 """
384 386
385 387 from IPython.core.application import BaseIPythonApplication as BaseIPApp
386 388
387 389 if BaseIPApp.initialized():
388 390 app = BaseIPApp.instance()
389 391 security_dir = app.profile_dir.security_dir
390 392 profile = app.profile
391 393 else:
392 394 profile = 'default'
393 395 security_dir = ''
394 396
395 397 try:
396 398 connection_file = get_connection_file()
397 399 info = get_connection_info(unpack=False)
398 400 except Exception as e:
399 401 error("Could not get connection info: %r" % e)
400 402 return
401 403
402 404 # add profile flag for non-default profile
403 405 profile_flag = "--profile %s" % profile if profile != 'default' else ""
404 406
405 407 # if it's in the security dir, truncate to basename
406 408 if security_dir == os.path.dirname(connection_file):
407 409 connection_file = os.path.basename(connection_file)
408 410
409 411
410 412 print (info + '\n')
411 413 print ("Paste the above JSON into a file, and connect with:\n"
412 414 " $> ipython <app> --existing <file>\n"
413 415 "or, if you are local, you can connect with just:\n"
414 416 " $> ipython <app> --existing {0} {1}\n"
415 417 "or even just:\n"
416 418 " $> ipython <app> --existing {1}\n"
417 419 "if this is the most recent IPython session you have started.".format(
418 420 connection_file, profile_flag
419 421 )
420 422 )
421 423
422 424 @line_magic
423 425 def qtconsole(self, arg_s):
424 426 """Open a qtconsole connected to this kernel.
425 427
426 428 Useful for connecting a qtconsole to running notebooks, for better
427 429 debugging.
428 430 """
429 431
430 432 # %qtconsole should imply bind_kernel for engines:
431 433 try:
432 434 from IPython.parallel import bind_kernel
433 435 except ImportError:
434 436 # technically possible, because parallel has higher pyzmq min-version
435 437 pass
436 438 else:
437 439 bind_kernel()
438 440
439 441 try:
440 442 p = connect_qtconsole(argv=arg_split(arg_s, os.name=='posix'))
441 443 except Exception as e:
442 444 error("Could not start qtconsole: %r" % e)
443 445 return
444 446
445 447 def safe_unicode(e):
446 448 """unicode(e) with various fallbacks. Used for exceptions, which may not be
447 449 safe to call unicode() on.
448 450 """
449 451 try:
450 452 return unicode(e)
451 453 except UnicodeError:
452 454 pass
453 455
454 456 try:
455 457 return py3compat.str_to_unicode(str(e))
456 458 except UnicodeError:
457 459 pass
458 460
459 461 try:
460 462 return py3compat.str_to_unicode(repr(e))
461 463 except UnicodeError:
462 464 pass
463 465
464 466 return u'Unrecoverably corrupt evalue'
465 467
466 468
467 469 class ZMQInteractiveShell(InteractiveShell):
468 470 """A subclass of InteractiveShell for ZMQ."""
469 471
470 472 displayhook_class = Type(ZMQShellDisplayHook)
471 473 display_pub_class = Type(ZMQDisplayPublisher)
472 474 data_pub_class = Type(ZMQDataPublisher)
473 475
474 476 # Override the traitlet in the parent class, because there's no point using
475 477 # readline for the kernel. Can be removed when the readline code is moved
476 478 # to the terminal frontend.
477 479 colors_force = CBool(True)
478 480 readline_use = CBool(False)
479 481 # autoindent has no meaning in a zmqshell, and attempting to enable it
480 482 # will print a warning in the absence of readline.
481 483 autoindent = CBool(False)
482 484
483 485 exiter = Instance(ZMQExitAutocall)
484 486 def _exiter_default(self):
485 487 return ZMQExitAutocall(self)
486 488
487 489 def _exit_now_changed(self, name, old, new):
488 490 """stop eventloop when exit_now fires"""
489 491 if new:
490 492 loop = ioloop.IOLoop.instance()
491 493 loop.add_timeout(time.time()+0.1, loop.stop)
492 494
493 495 keepkernel_on_exit = None
494 496
495 497 # Over ZeroMQ, GUI control isn't done with PyOS_InputHook as there is no
496 498 # interactive input being read; we provide event loop support in ipkernel
497 499 from .eventloops import enable_gui
498 500 enable_gui = staticmethod(enable_gui)
499 501
500 502 def init_environment(self):
501 503 """Configure the user's environment.
502 504
503 505 """
504 506 env = os.environ
505 507 # These two ensure 'ls' produces nice coloring on BSD-derived systems
506 508 env['TERM'] = 'xterm-color'
507 509 env['CLICOLOR'] = '1'
508 510 # Since normal pagers don't work at all (over pexpect we don't have
509 511 # single-key control of the subprocess), try to disable paging in
510 512 # subprocesses as much as possible.
511 513 env['PAGER'] = 'cat'
512 514 env['GIT_PAGER'] = 'cat'
513 515
514 516 # And install the payload version of page.
515 517 install_payload_page()
516 518
517 519 def auto_rewrite_input(self, cmd):
518 520 """Called to show the auto-rewritten input for autocall and friends.
519 521
520 522 FIXME: this payload is currently not correctly processed by the
521 523 frontend.
522 524 """
523 525 new = self.prompt_manager.render('rewrite') + cmd
524 526 payload = dict(
525 527 source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input',
526 528 transformed_input=new,
527 529 )
528 530 self.payload_manager.write_payload(payload)
529 531
530 532 def ask_exit(self):
531 533 """Engage the exit actions."""
532 534 self.exit_now = True
533 535 payload = dict(
534 536 source='IPython.zmq.zmqshell.ZMQInteractiveShell.ask_exit',
535 537 exit=True,
536 538 keepkernel=self.keepkernel_on_exit,
537 539 )
538 540 self.payload_manager.write_payload(payload)
539 541
540 542 def _showtraceback(self, etype, evalue, stb):
541 543
542 544 exc_content = {
543 545 u'traceback' : stb,
544 546 u'ename' : unicode(etype.__name__),
545 547 u'evalue' : safe_unicode(evalue)
546 548 }
547 549
548 550 dh = self.displayhook
549 551 # Send exception info over pub socket for other clients than the caller
550 552 # to pick up
551 553 topic = None
552 554 if dh.topic:
553 555 topic = dh.topic.replace(b'pyout', b'pyerr')
554 556
555 557 exc_msg = dh.session.send(dh.pub_socket, u'pyerr', json_clean(exc_content), dh.parent_header, ident=topic)
556 558
557 559 # FIXME - Hack: store exception info in shell object. Right now, the
558 560 # caller is reading this info after the fact, we need to fix this logic
559 561 # to remove this hack. Even uglier, we need to store the error status
560 562 # here, because in the main loop, the logic that sets it is being
561 563 # skipped because runlines swallows the exceptions.
562 564 exc_content[u'status'] = u'error'
563 565 self._reply_content = exc_content
564 566 # /FIXME
565 567
566 568 return exc_content
567 569
568 570 def set_next_input(self, text):
569 571 """Send the specified text to the frontend to be presented at the next
570 572 input cell."""
571 573 payload = dict(
572 574 source='IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input',
573 575 text=text
574 576 )
575 577 self.payload_manager.write_payload(payload)
576 578
577 579 #-------------------------------------------------------------------------
578 580 # Things related to magics
579 581 #-------------------------------------------------------------------------
580 582
581 583 def init_magics(self):
582 584 super(ZMQInteractiveShell, self).init_magics()
583 585 self.register_magics(KernelMagics)
584 586 self.magics_manager.register_alias('ed', 'edit')
585 587
586 588
587 589
588 590 InteractiveShellABC.register(ZMQInteractiveShell)
General Comments 0
You need to be logged in to leave comments. Login now