##// END OF EJS Templates
Merge pull request #1707 from bfroehle/_1532_qtconsole_gui_switch...
Min RK -
r7101:bd1da13c merge
parent child Browse files
Show More
@@ -1,538 +1,538 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 sys
19 19 from pprint import pformat
20 20
21 21 # Our own packages
22 22 from IPython.core.error import UsageError
23 23 from IPython.core.magic import Magics, magics_class, line_magic
24 24 from IPython.core.prefilter import ESC_MAGIC
25 25 from IPython.utils.text import format_screen
26 26 from IPython.core import magic_arguments, page
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.warn import warn, error
31 31
32 32 #-----------------------------------------------------------------------------
33 33 # Magics class implementation
34 34 #-----------------------------------------------------------------------------
35 35
36 36 @magics_class
37 37 class BasicMagics(Magics):
38 38 """Magics that provide central IPython functionality.
39 39
40 40 These are various magics that don't fit into specific categories but that
41 41 are all part of the base 'IPython experience'."""
42 42
43 43 def _lsmagic(self):
44 44 mesc = ESC_MAGIC
45 45 cesc = mesc*2
46 46 mman = self.shell.magics_manager
47 47 magics = mman.lsmagic()
48 48 out = ['Available line magics:',
49 49 mesc + (' '+mesc).join(magics['line']),
50 50 '',
51 51 'Available cell magics:',
52 52 cesc + (' '+cesc).join(magics['cell']),
53 53 '',
54 54 mman.auto_status()]
55 55 return '\n'.join(out)
56 56
57 57 @line_magic
58 58 def lsmagic(self, parameter_s=''):
59 59 """List currently available magic functions."""
60 60 print(self._lsmagic())
61 61
62 62 @line_magic
63 63 def magic(self, parameter_s=''):
64 64 """Print information about the magic function system.
65 65
66 66 Supported formats: -latex, -brief, -rest
67 67 """
68 68
69 69 mode = ''
70 70 try:
71 71 mode = parameter_s.split()[0][1:]
72 72 if mode == 'rest':
73 73 rest_docs = []
74 74 except IndexError:
75 75 pass
76 76
77 77 magic_docs = []
78 78 escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC*2)
79 79 magics = self.shell.magics_manager.magics
80 80
81 81 for mtype in ('line', 'cell'):
82 82 escape = escapes[mtype]
83 83 for fname, fn in magics[mtype].iteritems():
84 84
85 85 if mode == 'brief':
86 86 # only first line
87 87 if fn.__doc__:
88 88 fndoc = fn.__doc__.split('\n',1)[0]
89 89 else:
90 90 fndoc = 'No documentation'
91 91 else:
92 92 if fn.__doc__:
93 93 fndoc = fn.__doc__.rstrip()
94 94 else:
95 95 fndoc = 'No documentation'
96 96
97 97 if mode == 'rest':
98 98 rest_docs.append('**%s%s**::\n\n\t%s\n\n' %
99 99 (escape, fname, fndoc))
100 100 else:
101 101 magic_docs.append('%s%s:\n\t%s\n' %
102 102 (escape, fname, fndoc))
103 103
104 104 magic_docs = ''.join(magic_docs)
105 105
106 106 if mode == 'rest':
107 107 return "".join(rest_docs)
108 108
109 109 if mode == 'latex':
110 110 print(self.format_latex(magic_docs))
111 111 return
112 112 else:
113 113 magic_docs = format_screen(magic_docs)
114 114 if mode == 'brief':
115 115 return magic_docs
116 116
117 117 out = ["""
118 118 IPython's 'magic' functions
119 119 ===========================
120 120
121 121 The magic function system provides a series of functions which allow you to
122 122 control the behavior of IPython itself, plus a lot of system-type
123 123 features. There are two kinds of magics, line-oriented and cell-oriented.
124 124
125 125 Line magics are prefixed with the % character and work much like OS
126 126 command-line calls: they get as an argument the rest of the line, where
127 127 arguments are passed without parentheses or quotes. For example, this will
128 128 time the given statement::
129 129
130 130 %timeit range(1000)
131 131
132 132 Cell magics are prefixed with a double %%, and they are functions that get as
133 133 an argument not only the rest of the line, but also the lines below it in a
134 134 separate argument. These magics are called with two arguments: the rest of the
135 135 call line and the body of the cell, consisting of the lines below the first.
136 136 For example::
137 137
138 138 %%timeit x = numpy.random.randn((100, 100))
139 139 numpy.linalg.svd(x)
140 140
141 141 will time the execution of the numpy svd routine, running the assignment of x
142 142 as part of the setup phase, which is not timed.
143 143
144 144 In a line-oriented client (the terminal or Qt console IPython), starting a new
145 145 input with %% will automatically enter cell mode, and IPython will continue
146 146 reading input until a blank line is given. In the notebook, simply type the
147 147 whole cell as one entity, but keep in mind that the %% escape can only be at
148 148 the very start of the cell.
149 149
150 150 NOTE: If you have 'automagic' enabled (via the command line option or with the
151 151 %automagic function), you don't need to type in the % explicitly for line
152 152 magics; cell magics always require an explicit '%%' escape. By default,
153 153 IPython ships with automagic on, so you should only rarely need the % escape.
154 154
155 155 Example: typing '%cd mydir' (without the quotes) changes you working directory
156 156 to 'mydir', if it exists.
157 157
158 158 For a list of the available magic functions, use %lsmagic. For a description
159 159 of any of them, type %magic_name?, e.g. '%cd?'.
160 160
161 161 Currently the magic system has the following functions:""",
162 162 magic_docs,
163 163 "Summary of magic functions (from %slsmagic):",
164 164 self._lsmagic(),
165 165 ]
166 166 page.page('\n'.join(out))
167 167
168 168
169 169 @line_magic
170 170 def page(self, parameter_s=''):
171 171 """Pretty print the object and display it through a pager.
172 172
173 173 %page [options] OBJECT
174 174
175 175 If no object is given, use _ (last output).
176 176
177 177 Options:
178 178
179 179 -r: page str(object), don't pretty-print it."""
180 180
181 181 # After a function contributed by Olivier Aubert, slightly modified.
182 182
183 183 # Process options/args
184 184 opts, args = self.parse_options(parameter_s, 'r')
185 185 raw = 'r' in opts
186 186
187 187 oname = args and args or '_'
188 188 info = self._ofind(oname)
189 189 if info['found']:
190 190 txt = (raw and str or pformat)( info['obj'] )
191 191 page.page(txt)
192 192 else:
193 193 print('Object `%s` not found' % oname)
194 194
195 195 @line_magic
196 196 def profile(self, parameter_s=''):
197 197 """Print your currently active IPython profile."""
198 198 from IPython.core.application import BaseIPythonApplication
199 199 if BaseIPythonApplication.initialized():
200 200 print(BaseIPythonApplication.instance().profile)
201 201 else:
202 202 error("profile is an application-level value, but you don't appear to be in an IPython application")
203 203
204 204 @line_magic
205 205 def pprint(self, parameter_s=''):
206 206 """Toggle pretty printing on/off."""
207 207 ptformatter = self.shell.display_formatter.formatters['text/plain']
208 208 ptformatter.pprint = bool(1 - ptformatter.pprint)
209 209 print('Pretty printing has been turned',
210 210 ['OFF','ON'][ptformatter.pprint])
211 211
212 212 @line_magic
213 213 def colors(self, parameter_s=''):
214 214 """Switch color scheme for prompts, info system and exception handlers.
215 215
216 216 Currently implemented schemes: NoColor, Linux, LightBG.
217 217
218 218 Color scheme names are not case-sensitive.
219 219
220 220 Examples
221 221 --------
222 222 To get a plain black and white terminal::
223 223
224 224 %colors nocolor
225 225 """
226 226 def color_switch_err(name):
227 227 warn('Error changing %s color schemes.\n%s' %
228 228 (name, sys.exc_info()[1]))
229 229
230 230
231 231 new_scheme = parameter_s.strip()
232 232 if not new_scheme:
233 233 raise UsageError(
234 234 "%colors: you must specify a color scheme. See '%colors?'")
235 235 return
236 236 # local shortcut
237 237 shell = self.shell
238 238
239 239 import IPython.utils.rlineimpl as readline
240 240
241 241 if not shell.colors_force and \
242 242 not readline.have_readline and sys.platform == "win32":
243 243 msg = """\
244 244 Proper color support under MS Windows requires the pyreadline library.
245 245 You can find it at:
246 246 http://ipython.org/pyreadline.html
247 247 Gary's readline needs the ctypes module, from:
248 248 http://starship.python.net/crew/theller/ctypes
249 249 (Note that ctypes is already part of Python versions 2.5 and newer).
250 250
251 251 Defaulting color scheme to 'NoColor'"""
252 252 new_scheme = 'NoColor'
253 253 warn(msg)
254 254
255 255 # readline option is 0
256 256 if not shell.colors_force and not shell.has_readline:
257 257 new_scheme = 'NoColor'
258 258
259 259 # Set prompt colors
260 260 try:
261 261 shell.prompt_manager.color_scheme = new_scheme
262 262 except:
263 263 color_switch_err('prompt')
264 264 else:
265 265 shell.colors = \
266 266 shell.prompt_manager.color_scheme_table.active_scheme_name
267 267 # Set exception colors
268 268 try:
269 269 shell.InteractiveTB.set_colors(scheme = new_scheme)
270 270 shell.SyntaxTB.set_colors(scheme = new_scheme)
271 271 except:
272 272 color_switch_err('exception')
273 273
274 274 # Set info (for 'object?') colors
275 275 if shell.color_info:
276 276 try:
277 277 shell.inspector.set_active_scheme(new_scheme)
278 278 except:
279 279 color_switch_err('object inspector')
280 280 else:
281 281 shell.inspector.set_active_scheme('NoColor')
282 282
283 283 @line_magic
284 284 def xmode(self, parameter_s=''):
285 285 """Switch modes for the exception handlers.
286 286
287 287 Valid modes: Plain, Context and Verbose.
288 288
289 289 If called without arguments, acts as a toggle."""
290 290
291 291 def xmode_switch_err(name):
292 292 warn('Error changing %s exception modes.\n%s' %
293 293 (name,sys.exc_info()[1]))
294 294
295 295 shell = self.shell
296 296 new_mode = parameter_s.strip().capitalize()
297 297 try:
298 298 shell.InteractiveTB.set_mode(mode=new_mode)
299 299 print('Exception reporting mode:',shell.InteractiveTB.mode)
300 300 except:
301 301 xmode_switch_err('user')
302 302
303 303 @line_magic
304 304 def quickref(self,arg):
305 305 """ Show a quick reference sheet """
306 306 from IPython.core.usage import quick_reference
307 307 qr = quick_reference + self.magic('-brief')
308 308 page.page(qr)
309 309
310 310 @line_magic
311 311 def doctest_mode(self, parameter_s=''):
312 312 """Toggle doctest mode on and off.
313 313
314 314 This mode is intended to make IPython behave as much as possible like a
315 315 plain Python shell, from the perspective of how its prompts, exceptions
316 316 and output look. This makes it easy to copy and paste parts of a
317 317 session into doctests. It does so by:
318 318
319 319 - Changing the prompts to the classic ``>>>`` ones.
320 320 - Changing the exception reporting mode to 'Plain'.
321 321 - Disabling pretty-printing of output.
322 322
323 323 Note that IPython also supports the pasting of code snippets that have
324 324 leading '>>>' and '...' prompts in them. This means that you can paste
325 325 doctests from files or docstrings (even if they have leading
326 326 whitespace), and the code will execute correctly. You can then use
327 327 '%history -t' to see the translated history; this will give you the
328 328 input after removal of all the leading prompts and whitespace, which
329 329 can be pasted back into an editor.
330 330
331 331 With these features, you can switch into this mode easily whenever you
332 332 need to do testing and changes to doctests, without having to leave
333 333 your existing IPython session.
334 334 """
335 335
336 336 # Shorthands
337 337 shell = self.shell
338 338 pm = shell.prompt_manager
339 339 meta = shell.meta
340 340 disp_formatter = self.shell.display_formatter
341 341 ptformatter = disp_formatter.formatters['text/plain']
342 342 # dstore is a data store kept in the instance metadata bag to track any
343 343 # changes we make, so we can undo them later.
344 344 dstore = meta.setdefault('doctest_mode',Struct())
345 345 save_dstore = dstore.setdefault
346 346
347 347 # save a few values we'll need to recover later
348 348 mode = save_dstore('mode',False)
349 349 save_dstore('rc_pprint',ptformatter.pprint)
350 350 save_dstore('xmode',shell.InteractiveTB.mode)
351 351 save_dstore('rc_separate_out',shell.separate_out)
352 352 save_dstore('rc_separate_out2',shell.separate_out2)
353 353 save_dstore('rc_prompts_pad_left',pm.justify)
354 354 save_dstore('rc_separate_in',shell.separate_in)
355 355 save_dstore('rc_plain_text_only',disp_formatter.plain_text_only)
356 356 save_dstore('prompt_templates',(pm.in_template, pm.in2_template, pm.out_template))
357 357
358 358 if mode == False:
359 359 # turn on
360 360 pm.in_template = '>>> '
361 361 pm.in2_template = '... '
362 362 pm.out_template = ''
363 363
364 364 # Prompt separators like plain python
365 365 shell.separate_in = ''
366 366 shell.separate_out = ''
367 367 shell.separate_out2 = ''
368 368
369 369 pm.justify = False
370 370
371 371 ptformatter.pprint = False
372 372 disp_formatter.plain_text_only = True
373 373
374 374 shell.magic('xmode Plain')
375 375 else:
376 376 # turn off
377 377 pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates
378 378
379 379 shell.separate_in = dstore.rc_separate_in
380 380
381 381 shell.separate_out = dstore.rc_separate_out
382 382 shell.separate_out2 = dstore.rc_separate_out2
383 383
384 384 pm.justify = dstore.rc_prompts_pad_left
385 385
386 386 ptformatter.pprint = dstore.rc_pprint
387 387 disp_formatter.plain_text_only = dstore.rc_plain_text_only
388 388
389 389 shell.magic('xmode ' + dstore.xmode)
390 390
391 391 # Store new mode and inform
392 392 dstore.mode = bool(1-int(mode))
393 393 mode_label = ['OFF','ON'][dstore.mode]
394 394 print('Doctest mode is:', mode_label)
395 395
396 396 @line_magic
397 397 def gui(self, parameter_s=''):
398 398 """Enable or disable IPython GUI event loop integration.
399 399
400 400 %gui [GUINAME]
401 401
402 402 This magic replaces IPython's threaded shells that were activated
403 403 using the (pylab/wthread/etc.) command line flags. GUI toolkits
404 404 can now be enabled at runtime and keyboard
405 405 interrupts should work without any problems. The following toolkits
406 406 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
407 407
408 408 %gui wx # enable wxPython event loop integration
409 409 %gui qt4|qt # enable PyQt4 event loop integration
410 410 %gui gtk # enable PyGTK event loop integration
411 411 %gui gtk3 # enable Gtk3 event loop integration
412 412 %gui tk # enable Tk event loop integration
413 %gui OSX # enable Cocoa event loop integration
413 %gui osx # enable Cocoa event loop integration
414 414 # (requires %matplotlib 1.1)
415 415 %gui # disable all event loop integration
416 416
417 417 WARNING: after any of these has been called you can simply create
418 418 an application object, but DO NOT start the event loop yourself, as
419 419 we have already handled that.
420 420 """
421 421 opts, arg = self.parse_options(parameter_s, '')
422 422 if arg=='': arg = None
423 423 try:
424 424 return self.shell.enable_gui(arg)
425 425 except Exception as e:
426 426 # print simple error message, rather than traceback if we can't
427 427 # hook up the GUI
428 428 error(str(e))
429 429
430 430 @skip_doctest
431 431 @line_magic
432 432 def precision(self, s=''):
433 433 """Set floating point precision for pretty printing.
434 434
435 435 Can set either integer precision or a format string.
436 436
437 437 If numpy has been imported and precision is an int,
438 438 numpy display precision will also be set, via ``numpy.set_printoptions``.
439 439
440 440 If no argument is given, defaults will be restored.
441 441
442 442 Examples
443 443 --------
444 444 ::
445 445
446 446 In [1]: from math import pi
447 447
448 448 In [2]: %precision 3
449 449 Out[2]: u'%.3f'
450 450
451 451 In [3]: pi
452 452 Out[3]: 3.142
453 453
454 454 In [4]: %precision %i
455 455 Out[4]: u'%i'
456 456
457 457 In [5]: pi
458 458 Out[5]: 3
459 459
460 460 In [6]: %precision %e
461 461 Out[6]: u'%e'
462 462
463 463 In [7]: pi**10
464 464 Out[7]: 9.364805e+04
465 465
466 466 In [8]: %precision
467 467 Out[8]: u'%r'
468 468
469 469 In [9]: pi**10
470 470 Out[9]: 93648.047476082982
471 471 """
472 472 ptformatter = self.shell.display_formatter.formatters['text/plain']
473 473 ptformatter.float_precision = s
474 474 return ptformatter.float_format
475 475
476 476 @magic_arguments.magic_arguments()
477 477 @magic_arguments.argument(
478 478 '-e', '--export', action='store_true', default=False,
479 479 help='Export IPython history as a notebook. The filename argument '
480 480 'is used to specify the notebook name and format. For example '
481 481 'a filename of notebook.ipynb will result in a notebook name '
482 482 'of "notebook" and a format of "xml". Likewise using a ".json" '
483 483 'or ".py" file extension will write the notebook in the json '
484 484 'or py formats.'
485 485 )
486 486 @magic_arguments.argument(
487 487 '-f', '--format',
488 488 help='Convert an existing IPython notebook to a new format. This option '
489 489 'specifies the new format and can have the values: xml, json, py. '
490 490 'The target filename is chosen automatically based on the new '
491 491 'format. The filename argument gives the name of the source file.'
492 492 )
493 493 @magic_arguments.argument(
494 494 'filename', type=unicode,
495 495 help='Notebook name or filename'
496 496 )
497 497 @line_magic
498 498 def notebook(self, s):
499 499 """Export and convert IPython notebooks.
500 500
501 501 This function can export the current IPython history to a notebook file
502 502 or can convert an existing notebook file into a different format. For
503 503 example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb".
504 504 To export the history to "foo.py" do "%notebook -e foo.py". To convert
505 505 "foo.ipynb" to "foo.json" do "%notebook -f json foo.ipynb". Possible
506 506 formats include (json/ipynb, py).
507 507 """
508 508 args = magic_arguments.parse_argstring(self.notebook, s)
509 509
510 510 from IPython.nbformat import current
511 511 args.filename = unquote_filename(args.filename)
512 512 if args.export:
513 513 fname, name, format = current.parse_filename(args.filename)
514 514 cells = []
515 515 hist = list(self.shell.history_manager.get_range())
516 516 for session, prompt_number, input in hist[:-1]:
517 517 cells.append(current.new_code_cell(prompt_number=prompt_number,
518 518 input=input))
519 519 worksheet = current.new_worksheet(cells=cells)
520 520 nb = current.new_notebook(name=name,worksheets=[worksheet])
521 521 with io.open(fname, 'w', encoding='utf-8') as f:
522 522 current.write(nb, f, format);
523 523 elif args.format is not None:
524 524 old_fname, old_name, old_format = current.parse_filename(args.filename)
525 525 new_format = args.format
526 526 if new_format == u'xml':
527 527 raise ValueError('Notebooks cannot be written as xml.')
528 528 elif new_format == u'ipynb' or new_format == u'json':
529 529 new_fname = old_name + u'.ipynb'
530 530 new_format = u'json'
531 531 elif new_format == u'py':
532 532 new_fname = old_name + u'.py'
533 533 else:
534 534 raise ValueError('Invalid notebook format: %s' % new_format)
535 535 with io.open(old_fname, 'r', encoding='utf-8') as f:
536 536 nb = current.read(f, old_format)
537 537 with io.open(new_fname, 'w', encoding='utf-8') as f:
538 538 current.write(nb, f, new_format)
@@ -1,319 +1,360 b''
1 1 # encoding: utf-8
2 2 """
3 3 A mixin for :class:`~IPython.core.application.Application` classes that
4 4 launch InteractiveShell instances, load extensions, etc.
5 5
6 6 Authors
7 7 -------
8 8
9 9 * Min Ragan-Kelley
10 10 """
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Copyright (C) 2008-2011 The IPython Development Team
14 14 #
15 15 # Distributed under the terms of the BSD License. The full license is in
16 16 # the file COPYING, distributed as part of this software.
17 17 #-----------------------------------------------------------------------------
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Imports
21 21 #-----------------------------------------------------------------------------
22 22
23 23 from __future__ import absolute_import
24 24
25 25 import glob
26 26 import os
27 27 import sys
28 28
29 29 from IPython.config.application import boolean_flag
30 30 from IPython.config.configurable import Configurable
31 31 from IPython.config.loader import Config
32 from IPython.core import pylabtools
32 33 from IPython.utils import py3compat
33 34 from IPython.utils.path import filefind
34 from IPython.utils.traitlets import Unicode, Instance, List, Bool
35 from IPython.utils.traitlets import (
36 Unicode, Instance, List, Bool, CaselessStrEnum
37 )
35 38
36 39 #-----------------------------------------------------------------------------
37 40 # Aliases and Flags
38 41 #-----------------------------------------------------------------------------
39 42
40 43 shell_flags = {}
41 44
42 45 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
43 46 addflag('autoindent', 'InteractiveShell.autoindent',
44 47 'Turn on autoindenting.', 'Turn off autoindenting.'
45 48 )
46 49 addflag('automagic', 'InteractiveShell.automagic',
47 50 """Turn on the auto calling of magic commands. Type %%magic at the
48 51 IPython prompt for more information.""",
49 52 'Turn off the auto calling of magic commands.'
50 53 )
51 54 addflag('pdb', 'InteractiveShell.pdb',
52 55 "Enable auto calling the pdb debugger after every exception.",
53 56 "Disable auto calling the pdb debugger after every exception."
54 57 )
55 58 # pydb flag doesn't do any config, as core.debugger switches on import,
56 59 # which is before parsing. This just allows the flag to be passed.
57 60 shell_flags.update(dict(
58 61 pydb = ({},
59 62 """Use the third party 'pydb' package as debugger, instead of pdb.
60 63 Requires that pydb is installed."""
61 64 )
62 65 ))
63 66 addflag('pprint', 'PlainTextFormatter.pprint',
64 67 "Enable auto pretty printing of results.",
65 68 "Disable auto auto pretty printing of results."
66 69 )
67 70 addflag('color-info', 'InteractiveShell.color_info',
68 71 """IPython can display information about objects via a set of func-
69 72 tions, and optionally can use colors for this, syntax highlighting
70 73 source code and various other elements. However, because this
71 74 information is passed through a pager (like 'less') and many pagers get
72 75 confused with color codes, this option is off by default. You can test
73 76 it and turn it on permanently in your ipython_config.py file if it
74 77 works for you. Test it and turn it on permanently if it works with
75 78 your system. The magic function %%color_info allows you to toggle this
76 79 interactively for testing.""",
77 80 "Disable using colors for info related things."
78 81 )
79 82 addflag('deep-reload', 'InteractiveShell.deep_reload',
80 83 """Enable deep (recursive) reloading by default. IPython can use the
81 84 deep_reload module which reloads changes in modules recursively (it
82 85 replaces the reload() function, so you don't need to change anything to
83 86 use it). deep_reload() forces a full reload of modules whose code may
84 87 have changed, which the default reload() function does not. When
85 88 deep_reload is off, IPython will use the normal reload(), but
86 89 deep_reload will still be available as dreload(). This feature is off
87 90 by default [which means that you have both normal reload() and
88 91 dreload()].""",
89 92 "Disable deep (recursive) reloading by default."
90 93 )
91 94 nosep_config = Config()
92 95 nosep_config.InteractiveShell.separate_in = ''
93 96 nosep_config.InteractiveShell.separate_out = ''
94 97 nosep_config.InteractiveShell.separate_out2 = ''
95 98
96 99 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
97
100 shell_flags['pylab'] = (
101 {'InteractiveShellApp' : {'pylab' : 'auto'}},
102 """Pre-load matplotlib and numpy for interactive use with
103 the default matplotlib backend."""
104 )
98 105
99 106 # it's possible we don't want short aliases for *all* of these:
100 107 shell_aliases = dict(
101 108 autocall='InteractiveShell.autocall',
102 109 colors='InteractiveShell.colors',
103 110 logfile='InteractiveShell.logfile',
104 111 logappend='InteractiveShell.logappend',
105 112 c='InteractiveShellApp.code_to_run',
106 113 m='InteractiveShellApp.module_to_run',
107 114 ext='InteractiveShellApp.extra_extension',
115 gui='InteractiveShellApp.gui',
116 pylab='InteractiveShellApp.pylab',
108 117 )
109 118 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
110 119
111 120 #-----------------------------------------------------------------------------
112 121 # Main classes and functions
113 122 #-----------------------------------------------------------------------------
114 123
115 124 class InteractiveShellApp(Configurable):
116 125 """A Mixin for applications that start InteractiveShell instances.
117 126
118 127 Provides configurables for loading extensions and executing files
119 128 as part of configuring a Shell environment.
120 129
121 Provides init_path(), to be called before, and init_extensions() and
122 init_code() methods, to be called after init_shell(), which must be
123 implemented by subclasses.
130 The following methods should be called by the :meth:`initialize` method
131 of the subclass:
132
133 - :meth:`init_path`
134 - :meth:`init_shell` (to be implemented by the subclass)
135 - :meth:`init_gui_pylab`
136 - :meth:`init_extensions`
137 - :meth:`init_code`
124 138 """
125 139 extensions = List(Unicode, config=True,
126 140 help="A list of dotted module names of IPython extensions to load."
127 141 )
128 142 extra_extension = Unicode('', config=True,
129 143 help="dotted module name of an IPython extension to load."
130 144 )
131 145 def _extra_extension_changed(self, name, old, new):
132 146 if new:
133 147 # add to self.extensions
134 148 self.extensions.append(new)
135 149
136 150 # Extensions that are always loaded (not configurable)
137 151 default_extensions = List(Unicode, [u'storemagic'], config=False)
138 152
139 153 exec_files = List(Unicode, config=True,
140 154 help="""List of files to run at IPython startup."""
141 155 )
142 156 file_to_run = Unicode('', config=True,
143 157 help="""A file to be run""")
144 158
145 159 exec_lines = List(Unicode, config=True,
146 160 help="""lines of code to run at IPython startup."""
147 161 )
148 162 code_to_run = Unicode('', config=True,
149 163 help="Execute the given command string."
150 164 )
151 165 module_to_run = Unicode('', config=True,
152 166 help="Run the module as a script."
153 167 )
168 gui = CaselessStrEnum(('qt', 'wx', 'gtk', 'glut', 'pyglet', 'osx'), config=True,
169 help="Enable GUI event loop integration ('qt', 'wx', 'gtk', 'glut', 'pyglet', 'osx')."
170 )
171 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
172 config=True,
173 help="""Pre-load matplotlib and numpy for interactive use,
174 selecting a particular matplotlib backend and loop integration.
175 """
176 )
154 177 pylab_import_all = Bool(True, config=True,
155 178 help="""If true, an 'import *' is done from numpy and pylab,
156 179 when using pylab"""
157 180 )
158 181 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
159 182
160 183 def init_path(self):
161 184 """Add current working directory, '', to sys.path"""
162 185 if sys.path[0] != '':
163 186 sys.path.insert(0, '')
164 187
165 188 def init_shell(self):
166 189 raise NotImplementedError("Override in subclasses")
167
190
191 def init_gui_pylab(self):
192 """Enable GUI event loop integration, taking pylab into account."""
193 if self.gui or self.pylab:
194 shell = self.shell
195 try:
196 if self.pylab:
197 gui, backend = pylabtools.find_gui_and_backend(self.pylab)
198 self.log.info("Enabling GUI event loop integration, "
199 "toolkit=%s, pylab=%s" % (gui, self.pylab))
200 shell.enable_pylab(gui, import_all=self.pylab_import_all)
201 else:
202 self.log.info("Enabling GUI event loop integration, "
203 "toolkit=%s" % self.gui)
204 shell.enable_gui(self.gui)
205 except Exception:
206 self.log.warn("GUI event loop or pylab initialization failed")
207 self.shell.showtraceback()
208
168 209 def init_extensions(self):
169 210 """Load all IPython extensions in IPythonApp.extensions.
170 211
171 212 This uses the :meth:`ExtensionManager.load_extensions` to load all
172 213 the extensions listed in ``self.extensions``.
173 214 """
174 215 try:
175 216 self.log.debug("Loading IPython extensions...")
176 217 extensions = self.default_extensions + self.extensions
177 218 for ext in extensions:
178 219 try:
179 220 self.log.info("Loading IPython extension: %s" % ext)
180 221 self.shell.extension_manager.load_extension(ext)
181 222 except:
182 223 self.log.warn("Error in loading extension: %s" % ext +
183 224 "\nCheck your config files in %s" % self.profile_dir.location
184 225 )
185 226 self.shell.showtraceback()
186 227 except:
187 228 self.log.warn("Unknown error in loading extensions:")
188 229 self.shell.showtraceback()
189 230
190 231 def init_code(self):
191 232 """run the pre-flight code, specified via exec_lines"""
192 233 self._run_startup_files()
193 234 self._run_exec_lines()
194 235 self._run_exec_files()
195 236 self._run_cmd_line_code()
196 237 self._run_module()
197 238
198 239 # flush output, so itwon't be attached to the first cell
199 240 sys.stdout.flush()
200 241 sys.stderr.flush()
201 242
202 243 # Hide variables defined here from %who etc.
203 244 self.shell.user_ns_hidden.update(self.shell.user_ns)
204 245
205 246 def _run_exec_lines(self):
206 247 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
207 248 if not self.exec_lines:
208 249 return
209 250 try:
210 251 self.log.debug("Running code from IPythonApp.exec_lines...")
211 252 for line in self.exec_lines:
212 253 try:
213 254 self.log.info("Running code in user namespace: %s" %
214 255 line)
215 256 self.shell.run_cell(line, store_history=False)
216 257 except:
217 258 self.log.warn("Error in executing line in user "
218 259 "namespace: %s" % line)
219 260 self.shell.showtraceback()
220 261 except:
221 262 self.log.warn("Unknown error in handling IPythonApp.exec_lines:")
222 263 self.shell.showtraceback()
223 264
224 265 def _exec_file(self, fname):
225 266 try:
226 267 full_filename = filefind(fname, [u'.', self.ipython_dir])
227 268 except IOError as e:
228 269 self.log.warn("File not found: %r"%fname)
229 270 return
230 271 # Make sure that the running script gets a proper sys.argv as if it
231 272 # were run from a system shell.
232 273 save_argv = sys.argv
233 274 sys.argv = [full_filename] + self.extra_args[1:]
234 275 # protect sys.argv from potential unicode strings on Python 2:
235 276 if not py3compat.PY3:
236 277 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
237 278 try:
238 279 if os.path.isfile(full_filename):
239 280 if full_filename.endswith('.ipy'):
240 281 self.log.info("Running file in user namespace: %s" %
241 282 full_filename)
242 283 self.shell.safe_execfile_ipy(full_filename)
243 284 else:
244 285 # default to python, even without extension
245 286 self.log.info("Running file in user namespace: %s" %
246 287 full_filename)
247 288 # Ensure that __file__ is always defined to match Python behavior
248 289 self.shell.user_ns['__file__'] = fname
249 290 try:
250 291 self.shell.safe_execfile(full_filename, self.shell.user_ns)
251 292 finally:
252 293 del self.shell.user_ns['__file__']
253 294 finally:
254 295 sys.argv = save_argv
255 296
256 297 def _run_startup_files(self):
257 298 """Run files from profile startup directory"""
258 299 startup_dir = self.profile_dir.startup_dir
259 300 startup_files = glob.glob(os.path.join(startup_dir, '*.py'))
260 301 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
261 302 if not startup_files:
262 303 return
263 304
264 305 self.log.debug("Running startup files from %s...", startup_dir)
265 306 try:
266 307 for fname in sorted(startup_files):
267 308 self._exec_file(fname)
268 309 except:
269 310 self.log.warn("Unknown error in handling startup files:")
270 311 self.shell.showtraceback()
271 312
272 313 def _run_exec_files(self):
273 314 """Run files from IPythonApp.exec_files"""
274 315 if not self.exec_files:
275 316 return
276 317
277 318 self.log.debug("Running files in IPythonApp.exec_files...")
278 319 try:
279 320 for fname in self.exec_files:
280 321 self._exec_file(fname)
281 322 except:
282 323 self.log.warn("Unknown error in handling IPythonApp.exec_files:")
283 324 self.shell.showtraceback()
284 325
285 326 def _run_cmd_line_code(self):
286 327 """Run code or file specified at the command-line"""
287 328 if self.code_to_run:
288 329 line = self.code_to_run
289 330 try:
290 331 self.log.info("Running code given at command line (c=): %s" %
291 332 line)
292 333 self.shell.run_cell(line, store_history=False)
293 334 except:
294 335 self.log.warn("Error in executing line in user namespace: %s" %
295 336 line)
296 337 self.shell.showtraceback()
297 338
298 339 # Like Python itself, ignore the second if the first of these is present
299 340 elif self.file_to_run:
300 341 fname = self.file_to_run
301 342 try:
302 343 self._exec_file(fname)
303 344 except:
304 345 self.log.warn("Error in executing file in user namespace: %s" %
305 346 fname)
306 347 self.shell.showtraceback()
307 348
308 349 def _run_module(self):
309 350 """Run module specified at the command-line."""
310 351 if self.module_to_run:
311 352 # Make sure that the module gets a proper sys.argv as if it were
312 353 # run using `python -m`.
313 354 save_argv = sys.argv
314 355 sys.argv = [sys.executable] + self.extra_args
315 356 try:
316 357 self.shell.safe_run_module(self.module_to_run,
317 358 self.shell.user_ns)
318 359 finally:
319 360 sys.argv = save_argv
@@ -1,156 +1,154 b''
1 1 """ A minimal application using the ZMQ-based terminal IPython frontend.
2 2
3 3 This is not a complete console app, as subprocess will not be able to receive
4 4 input, there is no real readline support, among other limitations.
5 5
6 6 Authors:
7 7
8 8 * Min RK
9 9 * Paul Ivanov
10 10
11 11 """
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 import signal
17 17 import sys
18 18 import time
19 19
20 20 from IPython.frontend.terminal.ipapp import TerminalIPythonApp, frontend_flags as term_flags
21 21
22 22 from IPython.utils.traitlets import (
23 23 Dict, List, Unicode, Int, CaselessStrEnum, CBool, Any
24 24 )
25 25 from IPython.utils.warn import warn,error
26 26
27 27 from IPython.zmq.ipkernel import IPKernelApp
28 28 from IPython.zmq.session import Session, default_secure
29 29 from IPython.zmq.zmqshell import ZMQInteractiveShell
30 30 from IPython.frontend.consoleapp import (
31 31 IPythonConsoleApp, app_aliases, app_flags, aliases, app_aliases, flags
32 32 )
33 33
34 34 from IPython.frontend.terminal.console.interactiveshell import ZMQTerminalInteractiveShell
35 35
36 36 #-----------------------------------------------------------------------------
37 37 # Globals
38 38 #-----------------------------------------------------------------------------
39 39
40 40 _examples = """
41 41 ipython console # start the ZMQ-based console
42 42 ipython console --existing # connect to an existing ipython session
43 43 """
44 44
45 45 #-----------------------------------------------------------------------------
46 46 # Flags and Aliases
47 47 #-----------------------------------------------------------------------------
48 48
49 49 # copy flags from mixin:
50 50 flags = dict(flags)
51 51 # start with mixin frontend flags:
52 52 frontend_flags = dict(app_flags)
53 53 # add TerminalIPApp flags:
54 54 frontend_flags.update(term_flags)
55 # pylab is not frontend-specific in two-process IPython
56 frontend_flags.pop('pylab')
57 55 # disable quick startup, as it won't propagate to the kernel anyway
58 56 frontend_flags.pop('quick')
59 57 # update full dict with frontend flags:
60 58 flags.update(frontend_flags)
61 59
62 60 # copy flags from mixin
63 61 aliases = dict(aliases)
64 62 # start with mixin frontend flags
65 63 frontend_aliases = dict(app_aliases)
66 64 # load updated frontend flags into full dict
67 65 aliases.update(frontend_aliases)
68 66
69 67 # get flags&aliases into sets, and remove a couple that
70 68 # shouldn't be scrubbed from backend flags:
71 69 frontend_aliases = set(frontend_aliases.keys())
72 70 frontend_flags = set(frontend_flags.keys())
73 71
74 72
75 73 #-----------------------------------------------------------------------------
76 74 # Classes
77 75 #-----------------------------------------------------------------------------
78 76
79 77
80 78 class ZMQTerminalIPythonApp(TerminalIPythonApp, IPythonConsoleApp):
81 79 name = "ipython-console"
82 80 """Start a terminal frontend to the IPython zmq kernel."""
83 81
84 82 description = """
85 83 The IPython terminal-based Console.
86 84
87 85 This launches a Console application inside a terminal.
88 86
89 87 The Console supports various extra features beyond the traditional
90 88 single-process Terminal IPython shell, such as connecting to an
91 89 existing ipython session, via:
92 90
93 91 ipython console --existing
94 92
95 93 where the previous session could have been created by another ipython
96 94 console, an ipython qtconsole, or by opening an ipython notebook.
97 95
98 96 """
99 97 examples = _examples
100 98
101 99 classes = List([IPKernelApp, ZMQTerminalInteractiveShell, Session])
102 100 flags = Dict(flags)
103 101 aliases = Dict(aliases)
104 102 frontend_aliases = Any(frontend_aliases)
105 103 frontend_flags = Any(frontend_flags)
106 104
107 105 subcommands = Dict()
108 106
109 107 def parse_command_line(self, argv=None):
110 108 super(ZMQTerminalIPythonApp, self).parse_command_line(argv)
111 109 self.build_kernel_argv(argv)
112 110
113 111 def init_shell(self):
114 112 IPythonConsoleApp.initialize(self)
115 113 # relay sigint to kernel
116 114 signal.signal(signal.SIGINT, self.handle_sigint)
117 115 self.shell = ZMQTerminalInteractiveShell.instance(config=self.config,
118 116 display_banner=False, profile_dir=self.profile_dir,
119 117 ipython_dir=self.ipython_dir, kernel_manager=self.kernel_manager)
120 118
121 119 def init_gui_pylab(self):
122 120 # no-op, because we don't want to import matplotlib in the frontend.
123 121 pass
124 122
125 123 def handle_sigint(self, *args):
126 124 if self.shell._executing:
127 125 if self.kernel_manager.has_kernel:
128 126 # interrupt already gets passed to subprocess by signal handler.
129 127 # Only if we prevent that should we need to explicitly call
130 128 # interrupt_kernel, until which time, this would result in a
131 129 # double-interrupt:
132 130 # self.kernel_manager.interrupt_kernel()
133 131 pass
134 132 else:
135 133 self.shell.write_err('\n')
136 134 error("Cannot interrupt kernels we didn't start.\n")
137 135 else:
138 136 # raise the KeyboardInterrupt if we aren't waiting for execution,
139 137 # so that the interact loop advances, and prompt is redrawn, etc.
140 138 raise KeyboardInterrupt
141 139
142 140
143 141 def init_code(self):
144 142 # no-op in the frontend, code gets run in the backend
145 143 pass
146 144
147 145 def launch_new_instance():
148 146 """Create and run a full blown IPython instance"""
149 147 app = ZMQTerminalIPythonApp.instance()
150 148 app.initialize()
151 149 app.start()
152 150
153 151
154 152 if __name__ == '__main__':
155 153 launch_new_instance()
156 154
@@ -1,412 +1,370 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 The :class:`~IPython.core.application.Application` object for the command
5 5 line :command:`ipython` program.
6 6
7 7 Authors
8 8 -------
9 9
10 10 * Brian Granger
11 11 * Fernando Perez
12 12 * Min Ragan-Kelley
13 13 """
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Copyright (C) 2008-2011 The IPython Development Team
17 17 #
18 18 # Distributed under the terms of the BSD License. The full license is in
19 19 # the file COPYING, distributed as part of this software.
20 20 #-----------------------------------------------------------------------------
21 21
22 22 #-----------------------------------------------------------------------------
23 23 # Imports
24 24 #-----------------------------------------------------------------------------
25 25
26 26 from __future__ import absolute_import
27 27
28 28 import logging
29 29 import os
30 30 import sys
31 31
32 32 from IPython.config.loader import (
33 33 Config, PyFileConfigLoader, ConfigFileNotFound
34 34 )
35 35 from IPython.config.application import boolean_flag, catch_config_error
36 36 from IPython.core import release
37 37 from IPython.core import usage
38 38 from IPython.core.completer import IPCompleter
39 39 from IPython.core.crashhandler import CrashHandler
40 40 from IPython.core.formatters import PlainTextFormatter
41 41 from IPython.core.history import HistoryManager
42 42 from IPython.core.prompts import PromptManager
43 43 from IPython.core.application import (
44 44 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
45 45 )
46 46 from IPython.core.shellapp import (
47 47 InteractiveShellApp, shell_flags, shell_aliases
48 48 )
49 49 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
50 50 from IPython.lib import inputhook
51 51 from IPython.utils import warn
52 52 from IPython.utils.path import get_ipython_dir, check_for_old_config
53 53 from IPython.utils.traitlets import (
54 54 Bool, List, Dict, CaselessStrEnum
55 55 )
56 56
57 57 #-----------------------------------------------------------------------------
58 58 # Globals, utilities and helpers
59 59 #-----------------------------------------------------------------------------
60 60
61 61 #: The default config file name for this application.
62 62 default_config_file_name = u'ipython_config.py'
63 63
64 64 _examples = """
65 65 ipython --pylab # start in pylab mode
66 66 ipython --pylab=qt # start in pylab mode with the qt4 backend
67 67 ipython --log-level=DEBUG # set logging to DEBUG
68 68 ipython --profile=foo # start with profile foo
69 69
70 70 ipython qtconsole # start the qtconsole GUI application
71 71 ipython help qtconsole # show the help for the qtconsole subcmd
72 72
73 73 ipython console # start the terminal-based console application
74 74 ipython help console # show the help for the console subcmd
75 75
76 76 ipython notebook # start the IPython notebook
77 77 ipython help notebook # show the help for the notebook subcmd
78 78
79 79 ipython profile create foo # create profile foo w/ default config files
80 80 ipython help profile # show the help for the profile subcmd
81 81 """
82 82
83 83 #-----------------------------------------------------------------------------
84 84 # Crash handler for this application
85 85 #-----------------------------------------------------------------------------
86 86
87 87 class IPAppCrashHandler(CrashHandler):
88 88 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
89 89
90 90 def __init__(self, app):
91 91 contact_name = release.authors['Fernando'][0]
92 92 contact_email = release.author_email
93 93 bug_tracker = 'https://github.com/ipython/ipython/issues'
94 94 super(IPAppCrashHandler,self).__init__(
95 95 app, contact_name, contact_email, bug_tracker
96 96 )
97 97
98 98 def make_report(self,traceback):
99 99 """Return a string containing a crash report."""
100 100
101 101 sec_sep = self.section_sep
102 102 # Start with parent report
103 103 report = [super(IPAppCrashHandler, self).make_report(traceback)]
104 104 # Add interactive-specific info we may have
105 105 rpt_add = report.append
106 106 try:
107 107 rpt_add(sec_sep+"History of session input:")
108 108 for line in self.app.shell.user_ns['_ih']:
109 109 rpt_add(line)
110 110 rpt_add('\n*** Last line of input (may not be in above history):\n')
111 111 rpt_add(self.app.shell._last_input_line+'\n')
112 112 except:
113 113 pass
114 114
115 115 return ''.join(report)
116 116
117 117 #-----------------------------------------------------------------------------
118 118 # Aliases and Flags
119 119 #-----------------------------------------------------------------------------
120 120 flags = dict(base_flags)
121 121 flags.update(shell_flags)
122 122 frontend_flags = {}
123 123 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
124 124 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
125 125 'Turn on auto editing of files with syntax errors.',
126 126 'Turn off auto editing of files with syntax errors.'
127 127 )
128 128 addflag('banner', 'TerminalIPythonApp.display_banner',
129 129 "Display a banner upon starting IPython.",
130 130 "Don't display a banner upon starting IPython."
131 131 )
132 132 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
133 133 """Set to confirm when you try to exit IPython with an EOF (Control-D
134 134 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
135 135 you can force a direct exit without any confirmation.""",
136 136 "Don't prompt the user when exiting."
137 137 )
138 138 addflag('term-title', 'TerminalInteractiveShell.term_title',
139 139 "Enable auto setting the terminal title.",
140 140 "Disable auto setting the terminal title."
141 141 )
142 142 classic_config = Config()
143 143 classic_config.InteractiveShell.cache_size = 0
144 144 classic_config.PlainTextFormatter.pprint = False
145 145 classic_config.PromptManager.in_template = '>>> '
146 146 classic_config.PromptManager.in2_template = '... '
147 147 classic_config.PromptManager.out_template = ''
148 148 classic_config.InteractiveShell.separate_in = ''
149 149 classic_config.InteractiveShell.separate_out = ''
150 150 classic_config.InteractiveShell.separate_out2 = ''
151 151 classic_config.InteractiveShell.colors = 'NoColor'
152 152 classic_config.InteractiveShell.xmode = 'Plain'
153 153
154 154 frontend_flags['classic']=(
155 155 classic_config,
156 156 "Gives IPython a similar feel to the classic Python prompt."
157 157 )
158 158 # # log doesn't make so much sense this way anymore
159 159 # paa('--log','-l',
160 160 # action='store_true', dest='InteractiveShell.logstart',
161 161 # help="Start logging to the default log file (./ipython_log.py).")
162 162 #
163 163 # # quick is harder to implement
164 164 frontend_flags['quick']=(
165 165 {'TerminalIPythonApp' : {'quick' : True}},
166 166 "Enable quick startup with no config files."
167 167 )
168 168
169 169 frontend_flags['i'] = (
170 170 {'TerminalIPythonApp' : {'force_interact' : True}},
171 171 """If running code from the command line, become interactive afterwards.
172 172 Note: can also be given simply as '-i.'"""
173 173 )
174 frontend_flags['pylab'] = (
175 {'TerminalIPythonApp' : {'pylab' : 'auto'}},
176 """Pre-load matplotlib and numpy for interactive use with
177 the default matplotlib backend."""
178 )
179 174 flags.update(frontend_flags)
180 175
181 176 aliases = dict(base_aliases)
182 177 aliases.update(shell_aliases)
183 178
184 # it's possible we don't want short aliases for *all* of these:
185 aliases.update(dict(
186 gui='TerminalIPythonApp.gui',
187 pylab='TerminalIPythonApp.pylab',
188 ))
189
190 179 #-----------------------------------------------------------------------------
191 180 # Main classes and functions
192 181 #-----------------------------------------------------------------------------
193 182
194 183 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
195 184 name = u'ipython'
196 185 description = usage.cl_usage
197 186 default_config_file_name = default_config_file_name
198 187 crash_handler_class = IPAppCrashHandler
199 188 examples = _examples
200 189
201 190 flags = Dict(flags)
202 191 aliases = Dict(aliases)
203 192 classes = List()
204 193 def _classes_default(self):
205 194 """This has to be in a method, for TerminalIPythonApp to be available."""
206 195 return [
207 196 InteractiveShellApp, # ShellApp comes before TerminalApp, because
208 197 self.__class__, # it will also affect subclasses (e.g. QtConsole)
209 198 TerminalInteractiveShell,
210 199 PromptManager,
211 200 HistoryManager,
212 201 ProfileDir,
213 202 PlainTextFormatter,
214 203 IPCompleter,
215 204 ]
216 205
217 206 subcommands = Dict(dict(
218 207 qtconsole=('IPython.frontend.qt.console.qtconsoleapp.IPythonQtConsoleApp',
219 208 """Launch the IPython Qt Console."""
220 209 ),
221 210 notebook=('IPython.frontend.html.notebook.notebookapp.NotebookApp',
222 211 """Launch the IPython HTML Notebook Server."""
223 212 ),
224 213 profile = ("IPython.core.profileapp.ProfileApp",
225 214 "Create and manage IPython profiles."
226 215 ),
227 216 kernel = ("IPython.zmq.ipkernel.IPKernelApp",
228 217 "Start a kernel without an attached frontend."
229 218 ),
230 219 console=('IPython.frontend.terminal.console.app.ZMQTerminalIPythonApp',
231 220 """Launch the IPython terminal-based Console."""
232 221 ),
233 222 ))
234 223
235 224 # *do* autocreate requested profile, but don't create the config file.
236 225 auto_create=Bool(True)
237 226 # configurables
238 227 ignore_old_config=Bool(False, config=True,
239 228 help="Suppress warning messages about legacy config files"
240 229 )
241 230 quick = Bool(False, config=True,
242 231 help="""Start IPython quickly by skipping the loading of config files."""
243 232 )
244 233 def _quick_changed(self, name, old, new):
245 234 if new:
246 235 self.load_config_file = lambda *a, **kw: None
247 236 self.ignore_old_config=True
248 237
249 gui = CaselessStrEnum(('qt', 'wx', 'gtk', 'glut', 'pyglet'), config=True,
250 help="Enable GUI event loop integration ('qt', 'wx', 'gtk', 'glut', 'pyglet')."
251 )
252 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'auto'],
253 config=True,
254 help="""Pre-load matplotlib and numpy for interactive use,
255 selecting a particular matplotlib backend and loop integration.
256 """
257 )
258 238 display_banner = Bool(True, config=True,
259 239 help="Whether to display a banner upon starting IPython."
260 240 )
261 241
262 242 # if there is code of files to run from the cmd line, don't interact
263 243 # unless the --i flag (App.force_interact) is true.
264 244 force_interact = Bool(False, config=True,
265 245 help="""If a command or file is given via the command-line,
266 246 e.g. 'ipython foo.py"""
267 247 )
268 248 def _force_interact_changed(self, name, old, new):
269 249 if new:
270 250 self.interact = True
271 251
272 252 def _file_to_run_changed(self, name, old, new):
273 253 if new:
274 254 self.something_to_run = True
275 255 if new and not self.force_interact:
276 256 self.interact = False
277 257 _code_to_run_changed = _file_to_run_changed
278 258 _module_to_run_changed = _file_to_run_changed
279 259
280 260 # internal, not-configurable
281 261 interact=Bool(True)
282 262 something_to_run=Bool(False)
283 263
284 264 def parse_command_line(self, argv=None):
285 265 """override to allow old '-pylab' flag with deprecation warning"""
286 266
287 267 argv = sys.argv[1:] if argv is None else argv
288 268
289 269 if '-pylab' in argv:
290 270 # deprecated `-pylab` given,
291 271 # warn and transform into current syntax
292 272 argv = argv[:] # copy, don't clobber
293 273 idx = argv.index('-pylab')
294 274 warn.warn("`-pylab` flag has been deprecated.\n"
295 275 " Use `--pylab` instead, or `--pylab=foo` to specify a backend.")
296 276 sub = '--pylab'
297 277 if len(argv) > idx+1:
298 278 # check for gui arg, as in '-pylab qt'
299 279 gui = argv[idx+1]
300 280 if gui in ('wx', 'qt', 'qt4', 'gtk', 'auto'):
301 281 sub = '--pylab='+gui
302 282 argv.pop(idx+1)
303 283 argv[idx] = sub
304 284
305 285 return super(TerminalIPythonApp, self).parse_command_line(argv)
306 286
307 287 @catch_config_error
308 288 def initialize(self, argv=None):
309 289 """Do actions after construct, but before starting the app."""
310 290 super(TerminalIPythonApp, self).initialize(argv)
311 291 if self.subapp is not None:
312 292 # don't bother initializing further, starting subapp
313 293 return
314 294 if not self.ignore_old_config:
315 295 check_for_old_config(self.ipython_dir)
316 296 # print self.extra_args
317 297 if self.extra_args and not self.something_to_run:
318 298 self.file_to_run = self.extra_args[0]
319 299 self.init_path()
320 300 # create the shell
321 301 self.init_shell()
322 302 # and draw the banner
323 303 self.init_banner()
324 304 # Now a variety of things that happen after the banner is printed.
325 305 self.init_gui_pylab()
326 306 self.init_extensions()
327 307 self.init_code()
328 308
329 309 def init_shell(self):
330 310 """initialize the InteractiveShell instance"""
331 311 # Create an InteractiveShell instance.
332 312 # shell.display_banner should always be False for the terminal
333 313 # based app, because we call shell.show_banner() by hand below
334 314 # so the banner shows *before* all extension loading stuff.
335 315 self.shell = TerminalInteractiveShell.instance(config=self.config,
336 316 display_banner=False, profile_dir=self.profile_dir,
337 317 ipython_dir=self.ipython_dir)
338 318 self.shell.configurables.append(self)
339 319
340 320 def init_banner(self):
341 321 """optionally display the banner"""
342 322 if self.display_banner and self.interact:
343 323 self.shell.show_banner()
344 324 # Make sure there is a space below the banner.
345 325 if self.log_level <= logging.INFO: print
346 326
347
348 def init_gui_pylab(self):
349 """Enable GUI event loop integration, taking pylab into account."""
350 gui = self.gui
351
352 # Using `pylab` will also require gui activation, though which toolkit
353 # to use may be chosen automatically based on mpl configuration.
354 if self.pylab:
355 activate = self.shell.enable_pylab
356 if self.pylab == 'auto':
357 gui = None
358 else:
359 gui = self.pylab
360 else:
361 # Enable only GUI integration, no pylab
362 activate = inputhook.enable_gui
363
364 if gui or self.pylab:
365 try:
366 self.log.info("Enabling GUI event loop integration, "
367 "toolkit=%s, pylab=%s" % (gui, self.pylab) )
368 if self.pylab:
369 activate(gui, import_all=self.pylab_import_all)
370 else:
371 activate(gui)
372 except:
373 self.log.warn("Error in enabling GUI event loop integration:")
374 self.shell.showtraceback()
327 def _pylab_changed(self, name, old, new):
328 """Replace --pylab='inline' with --pylab='auto'"""
329 if new == 'inline':
330 warn.warn("'inline' not available as pylab backend, "
331 "using 'auto' instead.\n")
332 self.pylab = 'auto'
375 333
376 334 def start(self):
377 335 if self.subapp is not None:
378 336 return self.subapp.start()
379 337 # perform any prexec steps:
380 338 if self.interact:
381 339 self.log.debug("Starting IPython's mainloop...")
382 340 self.shell.mainloop()
383 341 else:
384 342 self.log.debug("IPython not interactive...")
385 343
386 344
387 345 def load_default_config(ipython_dir=None):
388 346 """Load the default config file from the default ipython_dir.
389 347
390 348 This is useful for embedded shells.
391 349 """
392 350 if ipython_dir is None:
393 351 ipython_dir = get_ipython_dir()
394 352 profile_dir = os.path.join(ipython_dir, 'profile_default')
395 353 cl = PyFileConfigLoader(default_config_file_name, profile_dir)
396 354 try:
397 355 config = cl.load_config()
398 356 except ConfigFileNotFound:
399 357 # no config found
400 358 config = Config()
401 359 return config
402 360
403 361
404 362 def launch_new_instance():
405 363 """Create and run a full blown IPython instance"""
406 364 app = TerminalIPythonApp.instance()
407 365 app.initialize()
408 366 app.start()
409 367
410 368
411 369 if __name__ == '__main__':
412 370 launch_new_instance()
@@ -1,921 +1,905 b''
1 1 #!/usr/bin/env python
2 2 """A simple interactive kernel that talks to a frontend over 0MQ.
3 3
4 4 Things to do:
5 5
6 6 * Implement `set_parent` logic. Right before doing exec, the Kernel should
7 7 call set_parent on all the PUB objects with the message about to be executed.
8 8 * Implement random port and security key logic.
9 9 * Implement control messages.
10 10 * Implement event loop and poll version.
11 11 """
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 from __future__ import print_function
17 17
18 18 # Standard library imports
19 19 import __builtin__
20 20 import atexit
21 21 import sys
22 22 import time
23 23 import traceback
24 24 import logging
25 25 import uuid
26 26
27 27 from datetime import datetime
28 28 from signal import (
29 29 signal, getsignal, default_int_handler, SIGINT, SIG_IGN
30 30 )
31 31
32 32 # System library imports
33 33 import zmq
34 34 from zmq.eventloop import ioloop
35 35 from zmq.eventloop.zmqstream import ZMQStream
36 36
37 37 # Local imports
38 from IPython.core import pylabtools
39 38 from IPython.config.configurable import Configurable
40 39 from IPython.config.application import boolean_flag, catch_config_error
41 40 from IPython.core.application import ProfileDir
42 41 from IPython.core.error import StdinNotImplementedError
43 42 from IPython.core.shellapp import (
44 43 InteractiveShellApp, shell_flags, shell_aliases
45 44 )
46 45 from IPython.utils import io
47 46 from IPython.utils import py3compat
48 47 from IPython.utils.frame import extract_module_locals
49 48 from IPython.utils.jsonutil import json_clean
50 49 from IPython.utils.traitlets import (
51 50 Any, Instance, Float, Dict, CaselessStrEnum, List, Set, Integer, Unicode
52 51 )
53 52
54 53 from entry_point import base_launch_kernel
55 54 from kernelapp import KernelApp, kernel_flags, kernel_aliases
56 55 from serialize import serialize_object, unpack_apply_message
57 56 from session import Session, Message
58 57 from zmqshell import ZMQInteractiveShell
59 58
60 59
61 60 #-----------------------------------------------------------------------------
62 61 # Main kernel class
63 62 #-----------------------------------------------------------------------------
64 63
65 64 class Kernel(Configurable):
66 65
67 66 #---------------------------------------------------------------------------
68 67 # Kernel interface
69 68 #---------------------------------------------------------------------------
70 69
71 70 # attribute to override with a GUI
72 71 eventloop = Any(None)
73 72 def _eventloop_changed(self, name, old, new):
74 73 """schedule call to eventloop from IOLoop"""
75 74 loop = ioloop.IOLoop.instance()
76 75 loop.add_timeout(time.time()+0.1, self.enter_eventloop)
77 76
78 77 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
79 78 session = Instance(Session)
80 79 profile_dir = Instance('IPython.core.profiledir.ProfileDir')
81 80 shell_streams = List()
82 81 control_stream = Instance(ZMQStream)
83 82 iopub_socket = Instance(zmq.Socket)
84 83 stdin_socket = Instance(zmq.Socket)
85 84 log = Instance(logging.Logger)
86 85
87 86 user_module = Any()
88 87 def _user_module_changed(self, name, old, new):
89 88 if self.shell is not None:
90 89 self.shell.user_module = new
91 90
92 91 user_ns = Dict(default_value=None)
93 92 def _user_ns_changed(self, name, old, new):
94 93 if self.shell is not None:
95 94 self.shell.user_ns = new
96 95 self.shell.init_user_ns()
97 96
98 97 # identities:
99 98 int_id = Integer(-1)
100 99 ident = Unicode()
101 100
102 101 def _ident_default(self):
103 102 return unicode(uuid.uuid4())
104 103
105 104
106 105 # Private interface
107 106
108 107 # Time to sleep after flushing the stdout/err buffers in each execute
109 108 # cycle. While this introduces a hard limit on the minimal latency of the
110 109 # execute cycle, it helps prevent output synchronization problems for
111 110 # clients.
112 111 # Units are in seconds. The minimum zmq latency on local host is probably
113 112 # ~150 microseconds, set this to 500us for now. We may need to increase it
114 113 # a little if it's not enough after more interactive testing.
115 114 _execute_sleep = Float(0.0005, config=True)
116 115
117 116 # Frequency of the kernel's event loop.
118 117 # Units are in seconds, kernel subclasses for GUI toolkits may need to
119 118 # adapt to milliseconds.
120 119 _poll_interval = Float(0.05, config=True)
121 120
122 121 # If the shutdown was requested over the network, we leave here the
123 122 # necessary reply message so it can be sent by our registered atexit
124 123 # handler. This ensures that the reply is only sent to clients truly at
125 124 # the end of our shutdown process (which happens after the underlying
126 125 # IPython shell's own shutdown).
127 126 _shutdown_message = None
128 127
129 128 # This is a dict of port number that the kernel is listening on. It is set
130 129 # by record_ports and used by connect_request.
131 130 _recorded_ports = Dict()
132 131
133 132 # set of aborted msg_ids
134 133 aborted = Set()
135 134
136 135
137 136 def __init__(self, **kwargs):
138 137 super(Kernel, self).__init__(**kwargs)
139 138
140 139 # Initialize the InteractiveShell subclass
141 140 self.shell = ZMQInteractiveShell.instance(config=self.config,
142 141 profile_dir = self.profile_dir,
143 142 user_module = self.user_module,
144 143 user_ns = self.user_ns,
145 144 )
146 145 self.shell.displayhook.session = self.session
147 146 self.shell.displayhook.pub_socket = self.iopub_socket
148 147 self.shell.displayhook.topic = self._topic('pyout')
149 148 self.shell.display_pub.session = self.session
150 149 self.shell.display_pub.pub_socket = self.iopub_socket
151 150
152 151 # TMP - hack while developing
153 152 self.shell._reply_content = None
154 153
155 154 # Build dict of handlers for message types
156 155 msg_types = [ 'execute_request', 'complete_request',
157 156 'object_info_request', 'history_request',
158 157 'connect_request', 'shutdown_request',
159 158 'apply_request',
160 159 ]
161 160 self.shell_handlers = {}
162 161 for msg_type in msg_types:
163 162 self.shell_handlers[msg_type] = getattr(self, msg_type)
164 163
165 164 control_msg_types = msg_types + [ 'clear_request', 'abort_request' ]
166 165 self.control_handlers = {}
167 166 for msg_type in control_msg_types:
168 167 self.control_handlers[msg_type] = getattr(self, msg_type)
169 168
170 169 def dispatch_control(self, msg):
171 170 """dispatch control requests"""
172 171 idents,msg = self.session.feed_identities(msg, copy=False)
173 172 try:
174 173 msg = self.session.unserialize(msg, content=True, copy=False)
175 174 except:
176 175 self.log.error("Invalid Control Message", exc_info=True)
177 176 return
178 177
179 178 self.log.debug("Control received: %s", msg)
180 179
181 180 header = msg['header']
182 181 msg_id = header['msg_id']
183 182 msg_type = header['msg_type']
184 183
185 184 handler = self.control_handlers.get(msg_type, None)
186 185 if handler is None:
187 186 self.log.error("UNKNOWN CONTROL MESSAGE TYPE: %r", msg_type)
188 187 else:
189 188 try:
190 189 handler(self.control_stream, idents, msg)
191 190 except Exception:
192 191 self.log.error("Exception in control handler:", exc_info=True)
193 192
194 193 def dispatch_shell(self, stream, msg):
195 194 """dispatch shell requests"""
196 195 # flush control requests first
197 196 if self.control_stream:
198 197 self.control_stream.flush()
199 198
200 199 idents,msg = self.session.feed_identities(msg, copy=False)
201 200 try:
202 201 msg = self.session.unserialize(msg, content=True, copy=False)
203 202 except:
204 203 self.log.error("Invalid Message", exc_info=True)
205 204 return
206 205
207 206 header = msg['header']
208 207 msg_id = header['msg_id']
209 208 msg_type = msg['header']['msg_type']
210 209
211 210 # Print some info about this message and leave a '--->' marker, so it's
212 211 # easier to trace visually the message chain when debugging. Each
213 212 # handler prints its message at the end.
214 213 self.log.debug('\n*** MESSAGE TYPE:%s***', msg_type)
215 214 self.log.debug(' Content: %s\n --->\n ', msg['content'])
216 215
217 216 if msg_id in self.aborted:
218 217 self.aborted.remove(msg_id)
219 218 # is it safe to assume a msg_id will not be resubmitted?
220 219 reply_type = msg_type.split('_')[0] + '_reply'
221 220 status = {'status' : 'aborted'}
222 221 sub = {'engine' : self.ident}
223 222 sub.update(status)
224 223 reply_msg = self.session.send(stream, reply_type, subheader=sub,
225 224 content=status, parent=msg, ident=idents)
226 225 return
227 226
228 227 handler = self.shell_handlers.get(msg_type, None)
229 228 if handler is None:
230 229 self.log.error("UNKNOWN MESSAGE TYPE: %r", msg_type)
231 230 else:
232 231 # ensure default_int_handler during handler call
233 232 sig = signal(SIGINT, default_int_handler)
234 233 try:
235 234 handler(stream, idents, msg)
236 235 except Exception:
237 236 self.log.error("Exception in message handler:", exc_info=True)
238 237 finally:
239 238 signal(SIGINT, sig)
240 239
241 240 def enter_eventloop(self):
242 241 """enter eventloop"""
243 242 self.log.info("entering eventloop")
244 243 # restore default_int_handler
245 244 signal(SIGINT, default_int_handler)
246 245 while self.eventloop is not None:
247 246 try:
248 247 self.eventloop(self)
249 248 except KeyboardInterrupt:
250 249 # Ctrl-C shouldn't crash the kernel
251 250 self.log.error("KeyboardInterrupt caught in kernel")
252 251 continue
253 252 else:
254 253 # eventloop exited cleanly, this means we should stop (right?)
255 254 self.eventloop = None
256 255 break
257 256 self.log.info("exiting eventloop")
258 257 # if eventloop exits, IOLoop should stop
259 258 ioloop.IOLoop.instance().stop()
260 259
261 260 def start(self):
262 261 """register dispatchers for streams"""
263 262 self.shell.exit_now = False
264 263 if self.control_stream:
265 264 self.control_stream.on_recv(self.dispatch_control, copy=False)
266 265
267 266 def make_dispatcher(stream):
268 267 def dispatcher(msg):
269 268 return self.dispatch_shell(stream, msg)
270 269 return dispatcher
271 270
272 271 for s in self.shell_streams:
273 272 s.on_recv(make_dispatcher(s), copy=False)
274 273
275 274 def do_one_iteration(self):
276 275 """step eventloop just once"""
277 276 if self.control_stream:
278 277 self.control_stream.flush()
279 278 for stream in self.shell_streams:
280 279 # handle at most one request per iteration
281 280 stream.flush(zmq.POLLIN, 1)
282 281 stream.flush(zmq.POLLOUT)
283 282
284 283
285 284 def record_ports(self, ports):
286 285 """Record the ports that this kernel is using.
287 286
288 287 The creator of the Kernel instance must call this methods if they
289 288 want the :meth:`connect_request` method to return the port numbers.
290 289 """
291 290 self._recorded_ports = ports
292 291
293 292 #---------------------------------------------------------------------------
294 293 # Kernel request handlers
295 294 #---------------------------------------------------------------------------
296 295
297 296 def _make_subheader(self):
298 297 """init subheader dict, for execute/apply_reply"""
299 298 return {
300 299 'dependencies_met' : True,
301 300 'engine' : self.ident,
302 301 'started': datetime.now(),
303 302 }
304 303
305 304 def _publish_pyin(self, code, parent, execution_count):
306 305 """Publish the code request on the pyin stream."""
307 306
308 307 self.session.send(self.iopub_socket, u'pyin',
309 308 {u'code':code, u'execution_count': execution_count},
310 309 parent=parent, ident=self._topic('pyin')
311 310 )
312 311
313 312 def execute_request(self, stream, ident, parent):
314 313
315 314 self.session.send(self.iopub_socket,
316 315 u'status',
317 316 {u'execution_state':u'busy'},
318 317 parent=parent,
319 318 ident=self._topic('status'),
320 319 )
321 320
322 321 try:
323 322 content = parent[u'content']
324 323 code = content[u'code']
325 324 silent = content[u'silent']
326 325 except:
327 326 self.log.error("Got bad msg: ")
328 327 self.log.error("%s", parent)
329 328 return
330 329
331 330 sub = self._make_subheader()
332 331
333 332 shell = self.shell # we'll need this a lot here
334 333
335 334 # Replace raw_input. Note that is not sufficient to replace
336 335 # raw_input in the user namespace.
337 336 if content.get('allow_stdin', False):
338 337 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
339 338 else:
340 339 raw_input = lambda prompt='' : self._no_raw_input()
341 340
342 341 if py3compat.PY3:
343 342 __builtin__.input = raw_input
344 343 else:
345 344 __builtin__.raw_input = raw_input
346 345
347 346 # Set the parent message of the display hook and out streams.
348 347 shell.displayhook.set_parent(parent)
349 348 shell.display_pub.set_parent(parent)
350 349 sys.stdout.set_parent(parent)
351 350 sys.stderr.set_parent(parent)
352 351
353 352 # Re-broadcast our input for the benefit of listening clients, and
354 353 # start computing output
355 354 if not silent:
356 355 self._publish_pyin(code, parent, shell.execution_count)
357 356
358 357 reply_content = {}
359 358 try:
360 359 # FIXME: the shell calls the exception handler itself.
361 360 shell.run_cell(code, store_history=not silent, silent=silent)
362 361 except:
363 362 status = u'error'
364 363 # FIXME: this code right now isn't being used yet by default,
365 364 # because the run_cell() call above directly fires off exception
366 365 # reporting. This code, therefore, is only active in the scenario
367 366 # where runlines itself has an unhandled exception. We need to
368 367 # uniformize this, for all exception construction to come from a
369 368 # single location in the codbase.
370 369 etype, evalue, tb = sys.exc_info()
371 370 tb_list = traceback.format_exception(etype, evalue, tb)
372 371 reply_content.update(shell._showtraceback(etype, evalue, tb_list))
373 372 else:
374 373 status = u'ok'
375 374
376 375 reply_content[u'status'] = status
377 376
378 377 # Return the execution counter so clients can display prompts
379 378 reply_content['execution_count'] = shell.execution_count - 1
380 379
381 380 # FIXME - fish exception info out of shell, possibly left there by
382 381 # runlines. We'll need to clean up this logic later.
383 382 if shell._reply_content is not None:
384 383 reply_content.update(shell._reply_content)
385 384 e_info = dict(engine_uuid=self.ident, engine_id=self.int_id, method='execute')
386 385 reply_content['engine_info'] = e_info
387 386 # reset after use
388 387 shell._reply_content = None
389 388
390 389 # At this point, we can tell whether the main code execution succeeded
391 390 # or not. If it did, we proceed to evaluate user_variables/expressions
392 391 if reply_content['status'] == 'ok':
393 392 reply_content[u'user_variables'] = \
394 393 shell.user_variables(content.get(u'user_variables', []))
395 394 reply_content[u'user_expressions'] = \
396 395 shell.user_expressions(content.get(u'user_expressions', {}))
397 396 else:
398 397 # If there was an error, don't even try to compute variables or
399 398 # expressions
400 399 reply_content[u'user_variables'] = {}
401 400 reply_content[u'user_expressions'] = {}
402 401
403 402 # Payloads should be retrieved regardless of outcome, so we can both
404 403 # recover partial output (that could have been generated early in a
405 404 # block, before an error) and clear the payload system always.
406 405 reply_content[u'payload'] = shell.payload_manager.read_payload()
407 406 # Be agressive about clearing the payload because we don't want
408 407 # it to sit in memory until the next execute_request comes in.
409 408 shell.payload_manager.clear_payload()
410 409
411 410 # Flush output before sending the reply.
412 411 sys.stdout.flush()
413 412 sys.stderr.flush()
414 413 # FIXME: on rare occasions, the flush doesn't seem to make it to the
415 414 # clients... This seems to mitigate the problem, but we definitely need
416 415 # to better understand what's going on.
417 416 if self._execute_sleep:
418 417 time.sleep(self._execute_sleep)
419 418
420 419 # Send the reply.
421 420 reply_content = json_clean(reply_content)
422 421
423 422 sub['status'] = reply_content['status']
424 423 if reply_content['status'] == 'error' and \
425 424 reply_content['ename'] == 'UnmetDependency':
426 425 sub['dependencies_met'] = False
427 426
428 427 reply_msg = self.session.send(stream, u'execute_reply',
429 428 reply_content, parent, subheader=sub,
430 429 ident=ident)
431 430
432 431 self.log.debug("%s", reply_msg)
433 432
434 433 if not silent and reply_msg['content']['status'] == u'error':
435 434 self._abort_queues()
436 435
437 436 self.session.send(self.iopub_socket,
438 437 u'status',
439 438 {u'execution_state':u'idle'},
440 439 parent=parent,
441 440 ident=self._topic('status'))
442 441
443 442 def complete_request(self, stream, ident, parent):
444 443 txt, matches = self._complete(parent)
445 444 matches = {'matches' : matches,
446 445 'matched_text' : txt,
447 446 'status' : 'ok'}
448 447 matches = json_clean(matches)
449 448 completion_msg = self.session.send(stream, 'complete_reply',
450 449 matches, parent, ident)
451 450 self.log.debug("%s", completion_msg)
452 451
453 452 def object_info_request(self, stream, ident, parent):
454 453 content = parent['content']
455 454 object_info = self.shell.object_inspect(content['oname'],
456 455 detail_level = content.get('detail_level', 0)
457 456 )
458 457 # Before we send this object over, we scrub it for JSON usage
459 458 oinfo = json_clean(object_info)
460 459 msg = self.session.send(stream, 'object_info_reply',
461 460 oinfo, parent, ident)
462 461 self.log.debug("%s", msg)
463 462
464 463 def history_request(self, stream, ident, parent):
465 464 # We need to pull these out, as passing **kwargs doesn't work with
466 465 # unicode keys before Python 2.6.5.
467 466 hist_access_type = parent['content']['hist_access_type']
468 467 raw = parent['content']['raw']
469 468 output = parent['content']['output']
470 469 if hist_access_type == 'tail':
471 470 n = parent['content']['n']
472 471 hist = self.shell.history_manager.get_tail(n, raw=raw, output=output,
473 472 include_latest=True)
474 473
475 474 elif hist_access_type == 'range':
476 475 session = parent['content']['session']
477 476 start = parent['content']['start']
478 477 stop = parent['content']['stop']
479 478 hist = self.shell.history_manager.get_range(session, start, stop,
480 479 raw=raw, output=output)
481 480
482 481 elif hist_access_type == 'search':
483 482 pattern = parent['content']['pattern']
484 483 hist = self.shell.history_manager.search(pattern, raw=raw,
485 484 output=output)
486 485
487 486 else:
488 487 hist = []
489 488 hist = list(hist)
490 489 content = {'history' : hist}
491 490 content = json_clean(content)
492 491 msg = self.session.send(stream, 'history_reply',
493 492 content, parent, ident)
494 493 self.log.debug("Sending history reply with %i entries", len(hist))
495 494
496 495 def connect_request(self, stream, ident, parent):
497 496 if self._recorded_ports is not None:
498 497 content = self._recorded_ports.copy()
499 498 else:
500 499 content = {}
501 500 msg = self.session.send(stream, 'connect_reply',
502 501 content, parent, ident)
503 502 self.log.debug("%s", msg)
504 503
505 504 def shutdown_request(self, stream, ident, parent):
506 505 self.shell.exit_now = True
507 506 content = dict(status='ok')
508 507 content.update(parent['content'])
509 508 self.session.send(stream, u'shutdown_reply', content, parent, ident=ident)
510 509 # same content, but different msg_id for broadcasting on IOPub
511 510 self._shutdown_message = self.session.msg(u'shutdown_reply',
512 511 content, parent
513 512 )
514 513
515 514 self._at_shutdown()
516 515 # call sys.exit after a short delay
517 516 loop = ioloop.IOLoop.instance()
518 517 loop.add_timeout(time.time()+0.1, loop.stop)
519 518
520 519 #---------------------------------------------------------------------------
521 520 # Engine methods
522 521 #---------------------------------------------------------------------------
523 522
524 523 def apply_request(self, stream, ident, parent):
525 524 try:
526 525 content = parent[u'content']
527 526 bufs = parent[u'buffers']
528 527 msg_id = parent['header']['msg_id']
529 528 except:
530 529 self.log.error("Got bad msg: %s", parent, exc_info=True)
531 530 return
532 531
533 532 # Set the parent message of the display hook and out streams.
534 533 self.shell.displayhook.set_parent(parent)
535 534 self.shell.display_pub.set_parent(parent)
536 535 sys.stdout.set_parent(parent)
537 536 sys.stderr.set_parent(parent)
538 537
539 538 # pyin_msg = self.session.msg(u'pyin',{u'code':code}, parent=parent)
540 539 # self.iopub_socket.send(pyin_msg)
541 540 # self.session.send(self.iopub_socket, u'pyin', {u'code':code},parent=parent)
542 541 sub = self._make_subheader()
543 542 try:
544 543 working = self.shell.user_ns
545 544
546 545 prefix = "_"+str(msg_id).replace("-","")+"_"
547 546
548 547 f,args,kwargs = unpack_apply_message(bufs, working, copy=False)
549 548
550 549 fname = getattr(f, '__name__', 'f')
551 550
552 551 fname = prefix+"f"
553 552 argname = prefix+"args"
554 553 kwargname = prefix+"kwargs"
555 554 resultname = prefix+"result"
556 555
557 556 ns = { fname : f, argname : args, kwargname : kwargs , resultname : None }
558 557 # print ns
559 558 working.update(ns)
560 559 code = "%s = %s(*%s,**%s)" % (resultname, fname, argname, kwargname)
561 560 try:
562 561 exec code in self.shell.user_global_ns, self.shell.user_ns
563 562 result = working.get(resultname)
564 563 finally:
565 564 for key in ns.iterkeys():
566 565 working.pop(key)
567 566
568 567 packed_result,buf = serialize_object(result)
569 568 result_buf = [packed_result]+buf
570 569 except:
571 570 exc_content = self._wrap_exception('apply')
572 571 # exc_msg = self.session.msg(u'pyerr', exc_content, parent)
573 572 self.session.send(self.iopub_socket, u'pyerr', exc_content, parent=parent,
574 573 ident=self._topic('pyerr'))
575 574 reply_content = exc_content
576 575 result_buf = []
577 576
578 577 if exc_content['ename'] == 'UnmetDependency':
579 578 sub['dependencies_met'] = False
580 579 else:
581 580 reply_content = {'status' : 'ok'}
582 581
583 582 # put 'ok'/'error' status in header, for scheduler introspection:
584 583 sub['status'] = reply_content['status']
585 584
586 585 # flush i/o
587 586 sys.stdout.flush()
588 587 sys.stderr.flush()
589 588
590 589 reply_msg = self.session.send(stream, u'apply_reply', reply_content,
591 590 parent=parent, ident=ident,buffers=result_buf, subheader=sub)
592 591
593 592 #---------------------------------------------------------------------------
594 593 # Control messages
595 594 #---------------------------------------------------------------------------
596 595
597 596 def abort_request(self, stream, ident, parent):
598 597 """abort a specifig msg by id"""
599 598 msg_ids = parent['content'].get('msg_ids', None)
600 599 if isinstance(msg_ids, basestring):
601 600 msg_ids = [msg_ids]
602 601 if not msg_ids:
603 602 self.abort_queues()
604 603 for mid in msg_ids:
605 604 self.aborted.add(str(mid))
606 605
607 606 content = dict(status='ok')
608 607 reply_msg = self.session.send(stream, 'abort_reply', content=content,
609 608 parent=parent, ident=ident)
610 609 self.log.debug("%s", reply_msg)
611 610
612 611 def clear_request(self, stream, idents, parent):
613 612 """Clear our namespace."""
614 613 self.shell.reset(False)
615 614 msg = self.session.send(stream, 'clear_reply', ident=idents, parent=parent,
616 615 content = dict(status='ok'))
617 616
618 617
619 618 #---------------------------------------------------------------------------
620 619 # Protected interface
621 620 #---------------------------------------------------------------------------
622 621
623 622
624 623 def _wrap_exception(self, method=None):
625 624 # import here, because _wrap_exception is only used in parallel,
626 625 # and parallel has higher min pyzmq version
627 626 from IPython.parallel.error import wrap_exception
628 627 e_info = dict(engine_uuid=self.ident, engine_id=self.int_id, method=method)
629 628 content = wrap_exception(e_info)
630 629 return content
631 630
632 631 def _topic(self, topic):
633 632 """prefixed topic for IOPub messages"""
634 633 if self.int_id >= 0:
635 634 base = "engine.%i" % self.int_id
636 635 else:
637 636 base = "kernel.%s" % self.ident
638 637
639 638 return py3compat.cast_bytes("%s.%s" % (base, topic))
640 639
641 640 def _abort_queues(self):
642 641 for stream in self.shell_streams:
643 642 if stream:
644 643 self._abort_queue(stream)
645 644
646 645 def _abort_queue(self, stream):
647 646 poller = zmq.Poller()
648 647 poller.register(stream.socket, zmq.POLLIN)
649 648 while True:
650 649 idents,msg = self.session.recv(stream, zmq.NOBLOCK, content=True)
651 650 if msg is None:
652 651 return
653 652
654 653 self.log.info("Aborting:")
655 654 self.log.info("%s", msg)
656 655 msg_type = msg['header']['msg_type']
657 656 reply_type = msg_type.split('_')[0] + '_reply'
658 657
659 658 status = {'status' : 'aborted'}
660 659 sub = {'engine' : self.ident}
661 660 sub.update(status)
662 661 reply_msg = self.session.send(stream, reply_type, subheader=sub,
663 662 content=status, parent=msg, ident=idents)
664 663 self.log.debug("%s", reply_msg)
665 664 # We need to wait a bit for requests to come in. This can probably
666 665 # be set shorter for true asynchronous clients.
667 666 poller.poll(50)
668 667
669 668
670 669 def _no_raw_input(self):
671 670 """Raise StdinNotImplentedError if active frontend doesn't support
672 671 stdin."""
673 672 raise StdinNotImplementedError("raw_input was called, but this "
674 673 "frontend does not support stdin.")
675 674
676 675 def _raw_input(self, prompt, ident, parent):
677 676 # Flush output before making the request.
678 677 sys.stderr.flush()
679 678 sys.stdout.flush()
680 679
681 680 # Send the input request.
682 681 content = json_clean(dict(prompt=prompt))
683 682 self.session.send(self.stdin_socket, u'input_request', content, parent,
684 683 ident=ident)
685 684
686 685 # Await a response.
687 686 while True:
688 687 try:
689 688 ident, reply = self.session.recv(self.stdin_socket, 0)
690 689 except Exception:
691 690 self.log.warn("Invalid Message:", exc_info=True)
692 691 else:
693 692 break
694 693 try:
695 694 value = reply['content']['value']
696 695 except:
697 696 self.log.error("Got bad raw_input reply: ")
698 697 self.log.error("%s", parent)
699 698 value = ''
700 699 if value == '\x04':
701 700 # EOF
702 701 raise EOFError
703 702 return value
704 703
705 704 def _complete(self, msg):
706 705 c = msg['content']
707 706 try:
708 707 cpos = int(c['cursor_pos'])
709 708 except:
710 709 # If we don't get something that we can convert to an integer, at
711 710 # least attempt the completion guessing the cursor is at the end of
712 711 # the text, if there's any, and otherwise of the line
713 712 cpos = len(c['text'])
714 713 if cpos==0:
715 714 cpos = len(c['line'])
716 715 return self.shell.complete(c['text'], c['line'], cpos)
717 716
718 717 def _object_info(self, context):
719 718 symbol, leftover = self._symbol_from_context(context)
720 719 if symbol is not None and not leftover:
721 720 doc = getattr(symbol, '__doc__', '')
722 721 else:
723 722 doc = ''
724 723 object_info = dict(docstring = doc)
725 724 return object_info
726 725
727 726 def _symbol_from_context(self, context):
728 727 if not context:
729 728 return None, context
730 729
731 730 base_symbol_string = context[0]
732 731 symbol = self.shell.user_ns.get(base_symbol_string, None)
733 732 if symbol is None:
734 733 symbol = __builtin__.__dict__.get(base_symbol_string, None)
735 734 if symbol is None:
736 735 return None, context
737 736
738 737 context = context[1:]
739 738 for i, name in enumerate(context):
740 739 new_symbol = getattr(symbol, name, None)
741 740 if new_symbol is None:
742 741 return symbol, context[i:]
743 742 else:
744 743 symbol = new_symbol
745 744
746 745 return symbol, []
747 746
748 747 def _at_shutdown(self):
749 748 """Actions taken at shutdown by the kernel, called by python's atexit.
750 749 """
751 750 # io.rprint("Kernel at_shutdown") # dbg
752 751 if self._shutdown_message is not None:
753 752 self.session.send(self.iopub_socket, self._shutdown_message, ident=self._topic('shutdown'))
754 753 self.log.debug("%s", self._shutdown_message)
755 754 [ s.flush(zmq.POLLOUT) for s in self.shell_streams ]
756 755
757 756 #-----------------------------------------------------------------------------
758 757 # Aliases and Flags for the IPKernelApp
759 758 #-----------------------------------------------------------------------------
760 759
761 760 flags = dict(kernel_flags)
762 761 flags.update(shell_flags)
763 762
764 763 addflag = lambda *args: flags.update(boolean_flag(*args))
765 764
766 765 flags['pylab'] = (
767 766 {'IPKernelApp' : {'pylab' : 'auto'}},
768 767 """Pre-load matplotlib and numpy for interactive use with
769 768 the default matplotlib backend."""
770 769 )
771 770
772 771 aliases = dict(kernel_aliases)
773 772 aliases.update(shell_aliases)
774 773
775 # it's possible we don't want short aliases for *all* of these:
776 aliases.update(dict(
777 pylab='IPKernelApp.pylab',
778 ))
779
780 774 #-----------------------------------------------------------------------------
781 775 # The IPKernelApp class
782 776 #-----------------------------------------------------------------------------
783 777
784 778 class IPKernelApp(KernelApp, InteractiveShellApp):
785 779 name = 'ipkernel'
786 780
787 781 aliases = Dict(aliases)
788 782 flags = Dict(flags)
789 783 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
790
791 # configurables
792 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
793 config=True,
794 help="""Pre-load matplotlib and numpy for interactive use,
795 selecting a particular matplotlib backend and loop integration.
796 """
797 )
798
784
799 785 @catch_config_error
800 786 def initialize(self, argv=None):
801 787 super(IPKernelApp, self).initialize(argv)
802 788 self.init_path()
803 789 self.init_shell()
790 self.init_gui_pylab()
804 791 self.init_extensions()
805 792 self.init_code()
806 793
807 794 def init_kernel(self):
808 795
809 796 shell_stream = ZMQStream(self.shell_socket)
810 797
811 798 kernel = Kernel(config=self.config, session=self.session,
812 799 shell_streams=[shell_stream],
813 800 iopub_socket=self.iopub_socket,
814 801 stdin_socket=self.stdin_socket,
815 802 log=self.log,
816 803 profile_dir=self.profile_dir,
817 804 )
818 805 self.kernel = kernel
819 806 kernel.record_ports(self.ports)
820 807 shell = kernel.shell
821 if self.pylab:
822 try:
823 gui, backend = pylabtools.find_gui_and_backend(self.pylab)
824 shell.enable_pylab(gui, import_all=self.pylab_import_all)
825 except Exception:
826 self.log.error("Pylab initialization failed", exc_info=True)
827 # print exception straight to stdout, because normally
828 # _showtraceback associates the reply with an execution,
829 # which means frontends will never draw it, as this exception
830 # is not associated with any execute request.
831
832 # replace pyerr-sending traceback with stdout
833 _showtraceback = shell._showtraceback
834 def print_tb(etype, evalue, stb):
835 print ("Error initializing pylab, pylab mode will not "
836 "be active", file=io.stderr)
837 print (shell.InteractiveTB.stb2text(stb), file=io.stdout)
838 shell._showtraceback = print_tb
839
840 # send the traceback over stdout
841 shell.showtraceback(tb_offset=0)
842
843 # restore proper _showtraceback method
844 shell._showtraceback = _showtraceback
845
808
809 def init_gui_pylab(self):
810 """Enable GUI event loop integration, taking pylab into account."""
811
812 # Provide a wrapper for :meth:`InteractiveShellApp.init_gui_pylab`
813 # to ensure that any exception is printed straight to stderr.
814 # Normally _showtraceback associates the reply with an execution,
815 # which means frontends will never draw it, as this exception
816 # is not associated with any execute request.
817
818 shell = self.shell
819 _showtraceback = shell._showtraceback
820 try:
821 # replace pyerr-sending traceback with stderr
822 def print_tb(etype, evalue, stb):
823 print ("GUI event loop or pylab initialization failed",
824 file=io.stderr)
825 print (shell.InteractiveTB.stb2text(stb), file=io.stderr)
826 shell._showtraceback = print_tb
827 InteractiveShellApp.init_gui_pylab(self)
828 finally:
829 shell._showtraceback = _showtraceback
846 830
847 831 def init_shell(self):
848 832 self.shell = self.kernel.shell
849 833 self.shell.configurables.append(self)
850 834
851 835
852 836 #-----------------------------------------------------------------------------
853 837 # Kernel main and launch functions
854 838 #-----------------------------------------------------------------------------
855 839
856 840 def launch_kernel(*args, **kwargs):
857 841 """Launches a localhost IPython kernel, binding to the specified ports.
858 842
859 843 This function simply calls entry_point.base_launch_kernel with the right
860 844 first command to start an ipkernel. See base_launch_kernel for arguments.
861 845
862 846 Returns
863 847 -------
864 848 A tuple of form:
865 849 (kernel_process, shell_port, iopub_port, stdin_port, hb_port)
866 850 where kernel_process is a Popen object and the ports are integers.
867 851 """
868 852 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
869 853 *args, **kwargs)
870 854
871 855
872 856 def embed_kernel(module=None, local_ns=None, **kwargs):
873 857 """Embed and start an IPython kernel in a given scope.
874 858
875 859 Parameters
876 860 ----------
877 861 module : ModuleType, optional
878 862 The module to load into IPython globals (default: caller)
879 863 local_ns : dict, optional
880 864 The namespace to load into IPython user namespace (default: caller)
881 865
882 866 kwargs : various, optional
883 867 Further keyword args are relayed to the KernelApp constructor,
884 868 allowing configuration of the Kernel. Will only have an effect
885 869 on the first embed_kernel call for a given process.
886 870
887 871 """
888 872 # get the app if it exists, or set it up if it doesn't
889 873 if IPKernelApp.initialized():
890 874 app = IPKernelApp.instance()
891 875 else:
892 876 app = IPKernelApp.instance(**kwargs)
893 877 app.initialize([])
894 878 # Undo unnecessary sys module mangling from init_sys_modules.
895 879 # This would not be necessary if we could prevent it
896 880 # in the first place by using a different InteractiveShell
897 881 # subclass, as in the regular embed case.
898 882 main = app.kernel.shell._orig_sys_modules_main_mod
899 883 if main is not None:
900 884 sys.modules[app.kernel.shell._orig_sys_modules_main_name] = main
901 885
902 886 # load the calling scope if not given
903 887 (caller_module, caller_locals) = extract_module_locals(1)
904 888 if module is None:
905 889 module = caller_module
906 890 if local_ns is None:
907 891 local_ns = caller_locals
908 892
909 893 app.kernel.user_module = module
910 894 app.kernel.user_ns = local_ns
911 895 app.start()
912 896
913 897 def main():
914 898 """Run an IPKernel as an application"""
915 899 app = IPKernelApp.instance()
916 900 app.initialize()
917 901 app.start()
918 902
919 903
920 904 if __name__ == '__main__':
921 905 main()
General Comments 0
You need to be logged in to leave comments. Login now