##// END OF EJS Templates
Rework messaging to better conform to our spec....
Fernando Perez -
Show More
1 NO CONTENT: new file 100644
@@ -0,0 +1,40 b''
1 """Test suite for our zeromq-based messaging specification.
2 """
3 #-----------------------------------------------------------------------------
4 # Copyright (C) 2010 The IPython Development Team
5 #
6 # Distributed under the terms of the BSD License. The full license is in
7 # the file COPYING.txt, distributed as part of this software.
8 #-----------------------------------------------------------------------------
9
10 import sys
11 import time
12
13 import nose.tools as nt
14
15 from ..blockingkernelmanager import BlockingKernelManager
16
17 from IPython.utils import io
18
19 def setup():
20 global KM
21 KM = BlockingKernelManager()
22
23 KM.start_kernel()
24 KM.start_channels()
25 # Give the kernel a chance to come up.
26 time.sleep(1)
27
28 def teardown():
29 io.rprint('Entering teardown...') # dbg
30 io.rprint('Stopping channels and kernel...') # dbg
31 KM.stop_channels()
32 KM.kill_kernel()
33
34
35 # Actual tests
36
37 def test_execute():
38 KM.xreq_channel.execute(code='x=1')
39 KM.xreq_channel.execute(code='print 1')
40
@@ -1,2156 +1,2195 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Main IPython class."""
3 3
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 7 # Copyright (C) 2008-2010 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 from __future__ import with_statement
18 18 from __future__ import absolute_import
19 19
20 20 import __builtin__
21 21 import abc
22 22 import codeop
23 23 import exceptions
24 24 import new
25 25 import os
26 26 import re
27 27 import string
28 28 import sys
29 29 import tempfile
30 30 from contextlib import nested
31 31
32 32 from IPython.config.configurable import Configurable
33 33 from IPython.core import debugger, oinspect
34 34 from IPython.core import history as ipcorehist
35 35 from IPython.core import page
36 36 from IPython.core import prefilter
37 37 from IPython.core import shadowns
38 38 from IPython.core import ultratb
39 39 from IPython.core.alias import AliasManager
40 40 from IPython.core.builtin_trap import BuiltinTrap
41 41 from IPython.core.display_trap import DisplayTrap
42 42 from IPython.core.displayhook import DisplayHook
43 43 from IPython.core.error import UsageError
44 44 from IPython.core.extensions import ExtensionManager
45 45 from IPython.core.fakemodule import FakeModule, init_fakemod_dict
46 46 from IPython.core.inputlist import InputList
47 47 from IPython.core.logger import Logger
48 48 from IPython.core.magic import Magic
49 49 from IPython.core.payload import PayloadManager
50 50 from IPython.core.plugin import PluginManager
51 51 from IPython.core.prefilter import PrefilterManager
52 52 from IPython.external.Itpl import ItplNS
53 53 from IPython.utils import PyColorize
54 54 from IPython.utils import io
55 55 from IPython.utils import pickleshare
56 56 from IPython.utils.doctestreload import doctest_reload
57 57 from IPython.utils.io import ask_yes_no, rprint
58 58 from IPython.utils.ipstruct import Struct
59 59 from IPython.utils.path import get_home_dir, get_ipython_dir, HomeDirError
60 60 from IPython.utils.process import system, getoutput
61 61 from IPython.utils.strdispatch import StrDispatch
62 62 from IPython.utils.syspathcontext import prepended_to_syspath
63 63 from IPython.utils.text import num_ini_spaces
64 64 from IPython.utils.traitlets import (Int, Str, CBool, CaselessStrEnum, Enum,
65 65 List, Unicode, Instance, Type)
66 66 from IPython.utils.warn import warn, error, fatal
67 67 import IPython.core.hooks
68 68
69 69 # from IPython.utils import growl
70 70 # growl.start("IPython")
71 71
72 72 #-----------------------------------------------------------------------------
73 73 # Globals
74 74 #-----------------------------------------------------------------------------
75 75
76 76 # compiled regexps for autoindent management
77 77 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
78 78
79 79 #-----------------------------------------------------------------------------
80 80 # Utilities
81 81 #-----------------------------------------------------------------------------
82 82
83 83 # store the builtin raw_input globally, and use this always, in case user code
84 84 # overwrites it (like wx.py.PyShell does)
85 85 raw_input_original = raw_input
86 86
87 87 def softspace(file, newvalue):
88 88 """Copied from code.py, to remove the dependency"""
89 89
90 90 oldvalue = 0
91 91 try:
92 92 oldvalue = file.softspace
93 93 except AttributeError:
94 94 pass
95 95 try:
96 96 file.softspace = newvalue
97 97 except (AttributeError, TypeError):
98 98 # "attribute-less object" or "read-only attributes"
99 99 pass
100 100 return oldvalue
101 101
102 102
103 103 def no_op(*a, **kw): pass
104 104
105 105 class SpaceInInput(exceptions.Exception): pass
106 106
107 107 class Bunch: pass
108 108
109 109
110 110 def get_default_colors():
111 111 if sys.platform=='darwin':
112 112 return "LightBG"
113 113 elif os.name=='nt':
114 114 return 'Linux'
115 115 else:
116 116 return 'Linux'
117 117
118 118
119 119 class SeparateStr(Str):
120 120 """A Str subclass to validate separate_in, separate_out, etc.
121 121
122 122 This is a Str based trait that converts '0'->'' and '\\n'->'\n'.
123 123 """
124 124
125 125 def validate(self, obj, value):
126 126 if value == '0': value = ''
127 127 value = value.replace('\\n','\n')
128 128 return super(SeparateStr, self).validate(obj, value)
129 129
130 130 class MultipleInstanceError(Exception):
131 131 pass
132 132
133 133
134 134 #-----------------------------------------------------------------------------
135 135 # Main IPython class
136 136 #-----------------------------------------------------------------------------
137 137
138 138
139 139 class InteractiveShell(Configurable, Magic):
140 140 """An enhanced, interactive shell for Python."""
141 141
142 142 _instance = None
143 143 autocall = Enum((0,1,2), default_value=1, config=True)
144 144 # TODO: remove all autoindent logic and put into frontends.
145 145 # We can't do this yet because even runlines uses the autoindent.
146 146 autoindent = CBool(True, config=True)
147 147 automagic = CBool(True, config=True)
148 148 cache_size = Int(1000, config=True)
149 149 color_info = CBool(True, config=True)
150 150 colors = CaselessStrEnum(('NoColor','LightBG','Linux'),
151 151 default_value=get_default_colors(), config=True)
152 152 debug = CBool(False, config=True)
153 153 deep_reload = CBool(False, config=True)
154 154 displayhook_class = Type(DisplayHook)
155 155 filename = Str("<ipython console>")
156 156 ipython_dir= Unicode('', config=True) # Set to get_ipython_dir() in __init__
157 157 logstart = CBool(False, config=True)
158 158 logfile = Str('', config=True)
159 159 logappend = Str('', config=True)
160 160 object_info_string_level = Enum((0,1,2), default_value=0,
161 161 config=True)
162 162 pdb = CBool(False, config=True)
163 163 pprint = CBool(True, config=True)
164 164 profile = Str('', config=True)
165 165 prompt_in1 = Str('In [\\#]: ', config=True)
166 166 prompt_in2 = Str(' .\\D.: ', config=True)
167 167 prompt_out = Str('Out[\\#]: ', config=True)
168 168 prompts_pad_left = CBool(True, config=True)
169 169 quiet = CBool(False, config=True)
170 170
171 171 # The readline stuff will eventually be moved to the terminal subclass
172 172 # but for now, we can't do that as readline is welded in everywhere.
173 173 readline_use = CBool(True, config=True)
174 174 readline_merge_completions = CBool(True, config=True)
175 175 readline_omit__names = Enum((0,1,2), default_value=0, config=True)
176 176 readline_remove_delims = Str('-/~', config=True)
177 177 readline_parse_and_bind = List([
178 178 'tab: complete',
179 179 '"\C-l": clear-screen',
180 180 'set show-all-if-ambiguous on',
181 181 '"\C-o": tab-insert',
182 182 '"\M-i": " "',
183 183 '"\M-o": "\d\d\d\d"',
184 184 '"\M-I": "\d\d\d\d"',
185 185 '"\C-r": reverse-search-history',
186 186 '"\C-s": forward-search-history',
187 187 '"\C-p": history-search-backward',
188 188 '"\C-n": history-search-forward',
189 189 '"\e[A": history-search-backward',
190 190 '"\e[B": history-search-forward',
191 191 '"\C-k": kill-line',
192 192 '"\C-u": unix-line-discard',
193 193 ], allow_none=False, config=True)
194 194
195 195 # TODO: this part of prompt management should be moved to the frontends.
196 196 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
197 197 separate_in = SeparateStr('\n', config=True)
198 198 separate_out = SeparateStr('', config=True)
199 199 separate_out2 = SeparateStr('', config=True)
200 200 wildcards_case_sensitive = CBool(True, config=True)
201 201 xmode = CaselessStrEnum(('Context','Plain', 'Verbose'),
202 202 default_value='Context', config=True)
203 203
204 204 # Subcomponents of InteractiveShell
205 205 alias_manager = Instance('IPython.core.alias.AliasManager')
206 206 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
207 207 builtin_trap = Instance('IPython.core.builtin_trap.BuiltinTrap')
208 208 display_trap = Instance('IPython.core.display_trap.DisplayTrap')
209 209 extension_manager = Instance('IPython.core.extensions.ExtensionManager')
210 210 plugin_manager = Instance('IPython.core.plugin.PluginManager')
211 211 payload_manager = Instance('IPython.core.payload.PayloadManager')
212 212
213 213 def __init__(self, config=None, ipython_dir=None,
214 214 user_ns=None, user_global_ns=None,
215 215 custom_exceptions=((),None)):
216 216
217 217 # This is where traits with a config_key argument are updated
218 218 # from the values on config.
219 219 super(InteractiveShell, self).__init__(config=config)
220 220
221 221 # These are relatively independent and stateless
222 222 self.init_ipython_dir(ipython_dir)
223 223 self.init_instance_attrs()
224 224
225 225 # Create namespaces (user_ns, user_global_ns, etc.)
226 226 self.init_create_namespaces(user_ns, user_global_ns)
227 227 # This has to be done after init_create_namespaces because it uses
228 228 # something in self.user_ns, but before init_sys_modules, which
229 229 # is the first thing to modify sys.
230 230 # TODO: When we override sys.stdout and sys.stderr before this class
231 231 # is created, we are saving the overridden ones here. Not sure if this
232 232 # is what we want to do.
233 233 self.save_sys_module_state()
234 234 self.init_sys_modules()
235 235
236 236 self.init_history()
237 237 self.init_encoding()
238 238 self.init_prefilter()
239 239
240 240 Magic.__init__(self, self)
241 241
242 242 self.init_syntax_highlighting()
243 243 self.init_hooks()
244 244 self.init_pushd_popd_magic()
245 245 # self.init_traceback_handlers use to be here, but we moved it below
246 246 # because it and init_io have to come after init_readline.
247 247 self.init_user_ns()
248 248 self.init_logger()
249 249 self.init_alias()
250 250 self.init_builtins()
251 251
252 252 # pre_config_initialization
253 253 self.init_shadow_hist()
254 254
255 255 # The next section should contain averything that was in ipmaker.
256 256 self.init_logstart()
257 257
258 258 # The following was in post_config_initialization
259 259 self.init_inspector()
260 260 # init_readline() must come before init_io(), because init_io uses
261 261 # readline related things.
262 262 self.init_readline()
263 263 # TODO: init_io() needs to happen before init_traceback handlers
264 264 # because the traceback handlers hardcode the stdout/stderr streams.
265 265 # This logic in in debugger.Pdb and should eventually be changed.
266 266 self.init_io()
267 267 self.init_traceback_handlers(custom_exceptions)
268 268 self.init_prompts()
269 269 self.init_displayhook()
270 270 self.init_reload_doctest()
271 271 self.init_magics()
272 272 self.init_pdb()
273 273 self.init_extension_manager()
274 274 self.init_plugin_manager()
275 275 self.init_payload()
276 276 self.hooks.late_startup_hook()
277 277
278 278 @classmethod
279 279 def instance(cls, *args, **kwargs):
280 280 """Returns a global InteractiveShell instance."""
281 281 if cls._instance is None:
282 282 inst = cls(*args, **kwargs)
283 283 # Now make sure that the instance will also be returned by
284 284 # the subclasses instance attribute.
285 285 for subclass in cls.mro():
286 286 if issubclass(cls, subclass) and issubclass(subclass, InteractiveShell):
287 287 subclass._instance = inst
288 288 else:
289 289 break
290 290 if isinstance(cls._instance, cls):
291 291 return cls._instance
292 292 else:
293 293 raise MultipleInstanceError(
294 294 'Multiple incompatible subclass instances of '
295 295 'InteractiveShell are being created.'
296 296 )
297 297
298 298 @classmethod
299 299 def initialized(cls):
300 300 return hasattr(cls, "_instance")
301 301
302 302 def get_ipython(self):
303 303 """Return the currently running IPython instance."""
304 304 return self
305 305
306 306 #-------------------------------------------------------------------------
307 307 # Trait changed handlers
308 308 #-------------------------------------------------------------------------
309 309
310 310 def _ipython_dir_changed(self, name, new):
311 311 if not os.path.isdir(new):
312 312 os.makedirs(new, mode = 0777)
313 313
314 314 def set_autoindent(self,value=None):
315 315 """Set the autoindent flag, checking for readline support.
316 316
317 317 If called with no arguments, it acts as a toggle."""
318 318
319 319 if not self.has_readline:
320 320 if os.name == 'posix':
321 321 warn("The auto-indent feature requires the readline library")
322 322 self.autoindent = 0
323 323 return
324 324 if value is None:
325 325 self.autoindent = not self.autoindent
326 326 else:
327 327 self.autoindent = value
328 328
329 329 #-------------------------------------------------------------------------
330 330 # init_* methods called by __init__
331 331 #-------------------------------------------------------------------------
332 332
333 333 def init_ipython_dir(self, ipython_dir):
334 334 if ipython_dir is not None:
335 335 self.ipython_dir = ipython_dir
336 336 self.config.Global.ipython_dir = self.ipython_dir
337 337 return
338 338
339 339 if hasattr(self.config.Global, 'ipython_dir'):
340 340 self.ipython_dir = self.config.Global.ipython_dir
341 341 else:
342 342 self.ipython_dir = get_ipython_dir()
343 343
344 344 # All children can just read this
345 345 self.config.Global.ipython_dir = self.ipython_dir
346 346
347 347 def init_instance_attrs(self):
348 348 self.more = False
349 349
350 350 # command compiler
351 351 self.compile = codeop.CommandCompiler()
352 352
353 353 # User input buffer
354 354 self.buffer = []
355 355
356 356 # Make an empty namespace, which extension writers can rely on both
357 357 # existing and NEVER being used by ipython itself. This gives them a
358 358 # convenient location for storing additional information and state
359 359 # their extensions may require, without fear of collisions with other
360 360 # ipython names that may develop later.
361 361 self.meta = Struct()
362 362
363 363 # Object variable to store code object waiting execution. This is
364 364 # used mainly by the multithreaded shells, but it can come in handy in
365 365 # other situations. No need to use a Queue here, since it's a single
366 366 # item which gets cleared once run.
367 367 self.code_to_run = None
368 368
369 369 # Temporary files used for various purposes. Deleted at exit.
370 370 self.tempfiles = []
371 371
372 372 # Keep track of readline usage (later set by init_readline)
373 373 self.has_readline = False
374 374
375 375 # keep track of where we started running (mainly for crash post-mortem)
376 376 # This is not being used anywhere currently.
377 377 self.starting_dir = os.getcwd()
378 378
379 379 # Indentation management
380 380 self.indent_current_nsp = 0
381 381
382 382 def init_encoding(self):
383 383 # Get system encoding at startup time. Certain terminals (like Emacs
384 384 # under Win32 have it set to None, and we need to have a known valid
385 385 # encoding to use in the raw_input() method
386 386 try:
387 387 self.stdin_encoding = sys.stdin.encoding or 'ascii'
388 388 except AttributeError:
389 389 self.stdin_encoding = 'ascii'
390 390
391 391 def init_syntax_highlighting(self):
392 392 # Python source parser/formatter for syntax highlighting
393 393 pyformat = PyColorize.Parser().format
394 394 self.pycolorize = lambda src: pyformat(src,'str',self.colors)
395 395
396 396 def init_pushd_popd_magic(self):
397 397 # for pushd/popd management
398 398 try:
399 399 self.home_dir = get_home_dir()
400 400 except HomeDirError, msg:
401 401 fatal(msg)
402 402
403 403 self.dir_stack = []
404 404
405 405 def init_logger(self):
406 406 self.logger = Logger(self, logfname='ipython_log.py', logmode='rotate')
407 407 # local shortcut, this is used a LOT
408 408 self.log = self.logger.log
409 409
410 410 def init_logstart(self):
411 411 if self.logappend:
412 412 self.magic_logstart(self.logappend + ' append')
413 413 elif self.logfile:
414 414 self.magic_logstart(self.logfile)
415 415 elif self.logstart:
416 416 self.magic_logstart()
417 417
418 418 def init_builtins(self):
419 419 self.builtin_trap = BuiltinTrap(shell=self)
420 420
421 421 def init_inspector(self):
422 422 # Object inspector
423 423 self.inspector = oinspect.Inspector(oinspect.InspectColors,
424 424 PyColorize.ANSICodeColors,
425 425 'NoColor',
426 426 self.object_info_string_level)
427 427
428 428 def init_io(self):
429 429 import IPython.utils.io
430 430 if sys.platform == 'win32' and self.has_readline:
431 431 Term = io.IOTerm(
432 432 cout=self.readline._outputfile,cerr=self.readline._outputfile
433 433 )
434 434 else:
435 435 Term = io.IOTerm()
436 436 io.Term = Term
437 437
438 438 def init_prompts(self):
439 439 # TODO: This is a pass for now because the prompts are managed inside
440 440 # the DisplayHook. Once there is a separate prompt manager, this
441 441 # will initialize that object and all prompt related information.
442 442 pass
443 443
444 444 def init_displayhook(self):
445 445 # Initialize displayhook, set in/out prompts and printing system
446 446 self.displayhook = self.displayhook_class(
447 447 shell=self,
448 448 cache_size=self.cache_size,
449 449 input_sep = self.separate_in,
450 450 output_sep = self.separate_out,
451 451 output_sep2 = self.separate_out2,
452 452 ps1 = self.prompt_in1,
453 453 ps2 = self.prompt_in2,
454 454 ps_out = self.prompt_out,
455 455 pad_left = self.prompts_pad_left
456 456 )
457 457 # This is a context manager that installs/revmoes the displayhook at
458 458 # the appropriate time.
459 459 self.display_trap = DisplayTrap(hook=self.displayhook)
460 460
461 461 def init_reload_doctest(self):
462 462 # Do a proper resetting of doctest, including the necessary displayhook
463 463 # monkeypatching
464 464 try:
465 465 doctest_reload()
466 466 except ImportError:
467 467 warn("doctest module does not exist.")
468 468
469 469 #-------------------------------------------------------------------------
470 470 # Things related to injections into the sys module
471 471 #-------------------------------------------------------------------------
472 472
473 473 def save_sys_module_state(self):
474 474 """Save the state of hooks in the sys module.
475 475
476 476 This has to be called after self.user_ns is created.
477 477 """
478 478 self._orig_sys_module_state = {}
479 479 self._orig_sys_module_state['stdin'] = sys.stdin
480 480 self._orig_sys_module_state['stdout'] = sys.stdout
481 481 self._orig_sys_module_state['stderr'] = sys.stderr
482 482 self._orig_sys_module_state['excepthook'] = sys.excepthook
483 483 try:
484 484 self._orig_sys_modules_main_name = self.user_ns['__name__']
485 485 except KeyError:
486 486 pass
487 487
488 488 def restore_sys_module_state(self):
489 489 """Restore the state of the sys module."""
490 490 try:
491 491 for k, v in self._orig_sys_module_state.items():
492 492 setattr(sys, k, v)
493 493 except AttributeError:
494 494 pass
495 495 try:
496 496 delattr(sys, 'ipcompleter')
497 497 except AttributeError:
498 498 pass
499 499 # Reset what what done in self.init_sys_modules
500 500 try:
501 501 sys.modules[self.user_ns['__name__']] = self._orig_sys_modules_main_name
502 502 except (AttributeError, KeyError):
503 503 pass
504 504
505 505 #-------------------------------------------------------------------------
506 506 # Things related to hooks
507 507 #-------------------------------------------------------------------------
508 508
509 509 def init_hooks(self):
510 510 # hooks holds pointers used for user-side customizations
511 511 self.hooks = Struct()
512 512
513 513 self.strdispatchers = {}
514 514
515 515 # Set all default hooks, defined in the IPython.hooks module.
516 516 hooks = IPython.core.hooks
517 517 for hook_name in hooks.__all__:
518 518 # default hooks have priority 100, i.e. low; user hooks should have
519 519 # 0-100 priority
520 520 self.set_hook(hook_name,getattr(hooks,hook_name), 100)
521 521
522 522 def set_hook(self,name,hook, priority = 50, str_key = None, re_key = None):
523 523 """set_hook(name,hook) -> sets an internal IPython hook.
524 524
525 525 IPython exposes some of its internal API as user-modifiable hooks. By
526 526 adding your function to one of these hooks, you can modify IPython's
527 527 behavior to call at runtime your own routines."""
528 528
529 529 # At some point in the future, this should validate the hook before it
530 530 # accepts it. Probably at least check that the hook takes the number
531 531 # of args it's supposed to.
532 532
533 533 f = new.instancemethod(hook,self,self.__class__)
534 534
535 535 # check if the hook is for strdispatcher first
536 536 if str_key is not None:
537 537 sdp = self.strdispatchers.get(name, StrDispatch())
538 538 sdp.add_s(str_key, f, priority )
539 539 self.strdispatchers[name] = sdp
540 540 return
541 541 if re_key is not None:
542 542 sdp = self.strdispatchers.get(name, StrDispatch())
543 543 sdp.add_re(re.compile(re_key), f, priority )
544 544 self.strdispatchers[name] = sdp
545 545 return
546 546
547 547 dp = getattr(self.hooks, name, None)
548 548 if name not in IPython.core.hooks.__all__:
549 549 print "Warning! Hook '%s' is not one of %s" % (name, IPython.core.hooks.__all__ )
550 550 if not dp:
551 551 dp = IPython.core.hooks.CommandChainDispatcher()
552 552
553 553 try:
554 554 dp.add(f,priority)
555 555 except AttributeError:
556 556 # it was not commandchain, plain old func - replace
557 557 dp = f
558 558
559 559 setattr(self.hooks,name, dp)
560 560
561 561 #-------------------------------------------------------------------------
562 562 # Things related to the "main" module
563 563 #-------------------------------------------------------------------------
564 564
565 565 def new_main_mod(self,ns=None):
566 566 """Return a new 'main' module object for user code execution.
567 567 """
568 568 main_mod = self._user_main_module
569 569 init_fakemod_dict(main_mod,ns)
570 570 return main_mod
571 571
572 572 def cache_main_mod(self,ns,fname):
573 573 """Cache a main module's namespace.
574 574
575 575 When scripts are executed via %run, we must keep a reference to the
576 576 namespace of their __main__ module (a FakeModule instance) around so
577 577 that Python doesn't clear it, rendering objects defined therein
578 578 useless.
579 579
580 580 This method keeps said reference in a private dict, keyed by the
581 581 absolute path of the module object (which corresponds to the script
582 582 path). This way, for multiple executions of the same script we only
583 583 keep one copy of the namespace (the last one), thus preventing memory
584 584 leaks from old references while allowing the objects from the last
585 585 execution to be accessible.
586 586
587 587 Note: we can not allow the actual FakeModule instances to be deleted,
588 588 because of how Python tears down modules (it hard-sets all their
589 589 references to None without regard for reference counts). This method
590 590 must therefore make a *copy* of the given namespace, to allow the
591 591 original module's __dict__ to be cleared and reused.
592 592
593 593
594 594 Parameters
595 595 ----------
596 596 ns : a namespace (a dict, typically)
597 597
598 598 fname : str
599 599 Filename associated with the namespace.
600 600
601 601 Examples
602 602 --------
603 603
604 604 In [10]: import IPython
605 605
606 606 In [11]: _ip.cache_main_mod(IPython.__dict__,IPython.__file__)
607 607
608 608 In [12]: IPython.__file__ in _ip._main_ns_cache
609 609 Out[12]: True
610 610 """
611 611 self._main_ns_cache[os.path.abspath(fname)] = ns.copy()
612 612
613 613 def clear_main_mod_cache(self):
614 614 """Clear the cache of main modules.
615 615
616 616 Mainly for use by utilities like %reset.
617 617
618 618 Examples
619 619 --------
620 620
621 621 In [15]: import IPython
622 622
623 623 In [16]: _ip.cache_main_mod(IPython.__dict__,IPython.__file__)
624 624
625 625 In [17]: len(_ip._main_ns_cache) > 0
626 626 Out[17]: True
627 627
628 628 In [18]: _ip.clear_main_mod_cache()
629 629
630 630 In [19]: len(_ip._main_ns_cache) == 0
631 631 Out[19]: True
632 632 """
633 633 self._main_ns_cache.clear()
634 634
635 635 #-------------------------------------------------------------------------
636 636 # Things related to debugging
637 637 #-------------------------------------------------------------------------
638 638
639 639 def init_pdb(self):
640 640 # Set calling of pdb on exceptions
641 641 # self.call_pdb is a property
642 642 self.call_pdb = self.pdb
643 643
644 644 def _get_call_pdb(self):
645 645 return self._call_pdb
646 646
647 647 def _set_call_pdb(self,val):
648 648
649 649 if val not in (0,1,False,True):
650 650 raise ValueError,'new call_pdb value must be boolean'
651 651
652 652 # store value in instance
653 653 self._call_pdb = val
654 654
655 655 # notify the actual exception handlers
656 656 self.InteractiveTB.call_pdb = val
657 657
658 658 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
659 659 'Control auto-activation of pdb at exceptions')
660 660
661 661 def debugger(self,force=False):
662 662 """Call the pydb/pdb debugger.
663 663
664 664 Keywords:
665 665
666 666 - force(False): by default, this routine checks the instance call_pdb
667 667 flag and does not actually invoke the debugger if the flag is false.
668 668 The 'force' option forces the debugger to activate even if the flag
669 669 is false.
670 670 """
671 671
672 672 if not (force or self.call_pdb):
673 673 return
674 674
675 675 if not hasattr(sys,'last_traceback'):
676 676 error('No traceback has been produced, nothing to debug.')
677 677 return
678 678
679 679 # use pydb if available
680 680 if debugger.has_pydb:
681 681 from pydb import pm
682 682 else:
683 683 # fallback to our internal debugger
684 684 pm = lambda : self.InteractiveTB.debugger(force=True)
685 685 self.history_saving_wrapper(pm)()
686 686
687 687 #-------------------------------------------------------------------------
688 688 # Things related to IPython's various namespaces
689 689 #-------------------------------------------------------------------------
690 690
691 691 def init_create_namespaces(self, user_ns=None, user_global_ns=None):
692 692 # Create the namespace where the user will operate. user_ns is
693 693 # normally the only one used, and it is passed to the exec calls as
694 694 # the locals argument. But we do carry a user_global_ns namespace
695 695 # given as the exec 'globals' argument, This is useful in embedding
696 696 # situations where the ipython shell opens in a context where the
697 697 # distinction between locals and globals is meaningful. For
698 698 # non-embedded contexts, it is just the same object as the user_ns dict.
699 699
700 700 # FIXME. For some strange reason, __builtins__ is showing up at user
701 701 # level as a dict instead of a module. This is a manual fix, but I
702 702 # should really track down where the problem is coming from. Alex
703 703 # Schmolck reported this problem first.
704 704
705 705 # A useful post by Alex Martelli on this topic:
706 706 # Re: inconsistent value from __builtins__
707 707 # Von: Alex Martelli <aleaxit@yahoo.com>
708 708 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
709 709 # Gruppen: comp.lang.python
710 710
711 711 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
712 712 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
713 713 # > <type 'dict'>
714 714 # > >>> print type(__builtins__)
715 715 # > <type 'module'>
716 716 # > Is this difference in return value intentional?
717 717
718 718 # Well, it's documented that '__builtins__' can be either a dictionary
719 719 # or a module, and it's been that way for a long time. Whether it's
720 720 # intentional (or sensible), I don't know. In any case, the idea is
721 721 # that if you need to access the built-in namespace directly, you
722 722 # should start with "import __builtin__" (note, no 's') which will
723 723 # definitely give you a module. Yeah, it's somewhat confusing:-(.
724 724
725 725 # These routines return properly built dicts as needed by the rest of
726 726 # the code, and can also be used by extension writers to generate
727 727 # properly initialized namespaces.
728 728 user_ns, user_global_ns = self.make_user_namespaces(user_ns, user_global_ns)
729 729
730 730 # Assign namespaces
731 731 # This is the namespace where all normal user variables live
732 732 self.user_ns = user_ns
733 733 self.user_global_ns = user_global_ns
734 734
735 735 # An auxiliary namespace that checks what parts of the user_ns were
736 736 # loaded at startup, so we can list later only variables defined in
737 737 # actual interactive use. Since it is always a subset of user_ns, it
738 738 # doesn't need to be separately tracked in the ns_table.
739 739 self.user_ns_hidden = {}
740 740
741 741 # A namespace to keep track of internal data structures to prevent
742 742 # them from cluttering user-visible stuff. Will be updated later
743 743 self.internal_ns = {}
744 744
745 745 # Now that FakeModule produces a real module, we've run into a nasty
746 746 # problem: after script execution (via %run), the module where the user
747 747 # code ran is deleted. Now that this object is a true module (needed
748 748 # so docetst and other tools work correctly), the Python module
749 749 # teardown mechanism runs over it, and sets to None every variable
750 750 # present in that module. Top-level references to objects from the
751 751 # script survive, because the user_ns is updated with them. However,
752 752 # calling functions defined in the script that use other things from
753 753 # the script will fail, because the function's closure had references
754 754 # to the original objects, which are now all None. So we must protect
755 755 # these modules from deletion by keeping a cache.
756 756 #
757 757 # To avoid keeping stale modules around (we only need the one from the
758 758 # last run), we use a dict keyed with the full path to the script, so
759 759 # only the last version of the module is held in the cache. Note,
760 760 # however, that we must cache the module *namespace contents* (their
761 761 # __dict__). Because if we try to cache the actual modules, old ones
762 762 # (uncached) could be destroyed while still holding references (such as
763 763 # those held by GUI objects that tend to be long-lived)>
764 764 #
765 765 # The %reset command will flush this cache. See the cache_main_mod()
766 766 # and clear_main_mod_cache() methods for details on use.
767 767
768 768 # This is the cache used for 'main' namespaces
769 769 self._main_ns_cache = {}
770 770 # And this is the single instance of FakeModule whose __dict__ we keep
771 771 # copying and clearing for reuse on each %run
772 772 self._user_main_module = FakeModule()
773 773
774 774 # A table holding all the namespaces IPython deals with, so that
775 775 # introspection facilities can search easily.
776 776 self.ns_table = {'user':user_ns,
777 777 'user_global':user_global_ns,
778 778 'internal':self.internal_ns,
779 779 'builtin':__builtin__.__dict__
780 780 }
781 781
782 782 # Similarly, track all namespaces where references can be held and that
783 783 # we can safely clear (so it can NOT include builtin). This one can be
784 784 # a simple list.
785 785 self.ns_refs_table = [ user_ns, user_global_ns, self.user_ns_hidden,
786 786 self.internal_ns, self._main_ns_cache ]
787 787
788 788 def make_user_namespaces(self, user_ns=None, user_global_ns=None):
789 789 """Return a valid local and global user interactive namespaces.
790 790
791 791 This builds a dict with the minimal information needed to operate as a
792 792 valid IPython user namespace, which you can pass to the various
793 793 embedding classes in ipython. The default implementation returns the
794 794 same dict for both the locals and the globals to allow functions to
795 795 refer to variables in the namespace. Customized implementations can
796 796 return different dicts. The locals dictionary can actually be anything
797 797 following the basic mapping protocol of a dict, but the globals dict
798 798 must be a true dict, not even a subclass. It is recommended that any
799 799 custom object for the locals namespace synchronize with the globals
800 800 dict somehow.
801 801
802 802 Raises TypeError if the provided globals namespace is not a true dict.
803 803
804 804 Parameters
805 805 ----------
806 806 user_ns : dict-like, optional
807 807 The current user namespace. The items in this namespace should
808 808 be included in the output. If None, an appropriate blank
809 809 namespace should be created.
810 810 user_global_ns : dict, optional
811 811 The current user global namespace. The items in this namespace
812 812 should be included in the output. If None, an appropriate
813 813 blank namespace should be created.
814 814
815 815 Returns
816 816 -------
817 817 A pair of dictionary-like object to be used as the local namespace
818 818 of the interpreter and a dict to be used as the global namespace.
819 819 """
820 820
821 821
822 822 # We must ensure that __builtin__ (without the final 's') is always
823 823 # available and pointing to the __builtin__ *module*. For more details:
824 824 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
825 825
826 826 if user_ns is None:
827 827 # Set __name__ to __main__ to better match the behavior of the
828 828 # normal interpreter.
829 829 user_ns = {'__name__' :'__main__',
830 830 '__builtin__' : __builtin__,
831 831 '__builtins__' : __builtin__,
832 832 }
833 833 else:
834 834 user_ns.setdefault('__name__','__main__')
835 835 user_ns.setdefault('__builtin__',__builtin__)
836 836 user_ns.setdefault('__builtins__',__builtin__)
837 837
838 838 if user_global_ns is None:
839 839 user_global_ns = user_ns
840 840 if type(user_global_ns) is not dict:
841 841 raise TypeError("user_global_ns must be a true dict; got %r"
842 842 % type(user_global_ns))
843 843
844 844 return user_ns, user_global_ns
845 845
846 846 def init_sys_modules(self):
847 847 # We need to insert into sys.modules something that looks like a
848 848 # module but which accesses the IPython namespace, for shelve and
849 849 # pickle to work interactively. Normally they rely on getting
850 850 # everything out of __main__, but for embedding purposes each IPython
851 851 # instance has its own private namespace, so we can't go shoving
852 852 # everything into __main__.
853 853
854 854 # note, however, that we should only do this for non-embedded
855 855 # ipythons, which really mimic the __main__.__dict__ with their own
856 856 # namespace. Embedded instances, on the other hand, should not do
857 857 # this because they need to manage the user local/global namespaces
858 858 # only, but they live within a 'normal' __main__ (meaning, they
859 859 # shouldn't overtake the execution environment of the script they're
860 860 # embedded in).
861 861
862 862 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
863 863
864 864 try:
865 865 main_name = self.user_ns['__name__']
866 866 except KeyError:
867 867 raise KeyError('user_ns dictionary MUST have a "__name__" key')
868 868 else:
869 869 sys.modules[main_name] = FakeModule(self.user_ns)
870 870
871 871 def init_user_ns(self):
872 872 """Initialize all user-visible namespaces to their minimum defaults.
873 873
874 874 Certain history lists are also initialized here, as they effectively
875 875 act as user namespaces.
876 876
877 877 Notes
878 878 -----
879 879 All data structures here are only filled in, they are NOT reset by this
880 880 method. If they were not empty before, data will simply be added to
881 881 therm.
882 882 """
883 883 # This function works in two parts: first we put a few things in
884 884 # user_ns, and we sync that contents into user_ns_hidden so that these
885 885 # initial variables aren't shown by %who. After the sync, we add the
886 886 # rest of what we *do* want the user to see with %who even on a new
887 887 # session (probably nothing, so theye really only see their own stuff)
888 888
889 889 # The user dict must *always* have a __builtin__ reference to the
890 890 # Python standard __builtin__ namespace, which must be imported.
891 891 # This is so that certain operations in prompt evaluation can be
892 892 # reliably executed with builtins. Note that we can NOT use
893 893 # __builtins__ (note the 's'), because that can either be a dict or a
894 894 # module, and can even mutate at runtime, depending on the context
895 895 # (Python makes no guarantees on it). In contrast, __builtin__ is
896 896 # always a module object, though it must be explicitly imported.
897 897
898 898 # For more details:
899 899 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
900 900 ns = dict(__builtin__ = __builtin__)
901 901
902 902 # Put 'help' in the user namespace
903 903 try:
904 904 from site import _Helper
905 905 ns['help'] = _Helper()
906 906 except ImportError:
907 907 warn('help() not available - check site.py')
908 908
909 909 # make global variables for user access to the histories
910 910 ns['_ih'] = self.input_hist
911 911 ns['_oh'] = self.output_hist
912 912 ns['_dh'] = self.dir_hist
913 913
914 914 ns['_sh'] = shadowns
915 915
916 916 # user aliases to input and output histories. These shouldn't show up
917 917 # in %who, as they can have very large reprs.
918 918 ns['In'] = self.input_hist
919 919 ns['Out'] = self.output_hist
920 920
921 921 # Store myself as the public api!!!
922 922 ns['get_ipython'] = self.get_ipython
923 923
924 924 # Sync what we've added so far to user_ns_hidden so these aren't seen
925 925 # by %who
926 926 self.user_ns_hidden.update(ns)
927 927
928 928 # Anything put into ns now would show up in %who. Think twice before
929 929 # putting anything here, as we really want %who to show the user their
930 930 # stuff, not our variables.
931 931
932 932 # Finally, update the real user's namespace
933 933 self.user_ns.update(ns)
934 934
935 935
936 936 def reset(self):
937 937 """Clear all internal namespaces.
938 938
939 939 Note that this is much more aggressive than %reset, since it clears
940 940 fully all namespaces, as well as all input/output lists.
941 941 """
942 942 for ns in self.ns_refs_table:
943 943 ns.clear()
944 944
945 945 self.alias_manager.clear_aliases()
946 946
947 947 # Clear input and output histories
948 948 self.input_hist[:] = []
949 949 self.input_hist_raw[:] = []
950 950 self.output_hist.clear()
951 951
952 952 # Restore the user namespaces to minimal usability
953 953 self.init_user_ns()
954 954
955 955 # Restore the default and user aliases
956 956 self.alias_manager.init_aliases()
957 957
958 958 def reset_selective(self, regex=None):
959 959 """Clear selective variables from internal namespaces based on a specified regular expression.
960 960
961 961 Parameters
962 962 ----------
963 963 regex : string or compiled pattern, optional
964 964 A regular expression pattern that will be used in searching variable names in the users
965 965 namespaces.
966 966 """
967 967 if regex is not None:
968 968 try:
969 969 m = re.compile(regex)
970 970 except TypeError:
971 971 raise TypeError('regex must be a string or compiled pattern')
972 972 # Search for keys in each namespace that match the given regex
973 973 # If a match is found, delete the key/value pair.
974 974 for ns in self.ns_refs_table:
975 975 for var in ns:
976 976 if m.search(var):
977 977 del ns[var]
978 978
979 979 def push(self, variables, interactive=True):
980 980 """Inject a group of variables into the IPython user namespace.
981 981
982 982 Parameters
983 983 ----------
984 984 variables : dict, str or list/tuple of str
985 985 The variables to inject into the user's namespace. If a dict,
986 986 a simple update is done. If a str, the string is assumed to
987 987 have variable names separated by spaces. A list/tuple of str
988 988 can also be used to give the variable names. If just the variable
989 989 names are give (list/tuple/str) then the variable values looked
990 990 up in the callers frame.
991 991 interactive : bool
992 992 If True (default), the variables will be listed with the ``who``
993 993 magic.
994 994 """
995 995 vdict = None
996 996
997 997 # We need a dict of name/value pairs to do namespace updates.
998 998 if isinstance(variables, dict):
999 999 vdict = variables
1000 1000 elif isinstance(variables, (basestring, list, tuple)):
1001 1001 if isinstance(variables, basestring):
1002 1002 vlist = variables.split()
1003 1003 else:
1004 1004 vlist = variables
1005 1005 vdict = {}
1006 1006 cf = sys._getframe(1)
1007 1007 for name in vlist:
1008 1008 try:
1009 1009 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1010 1010 except:
1011 1011 print ('Could not get variable %s from %s' %
1012 1012 (name,cf.f_code.co_name))
1013 1013 else:
1014 1014 raise ValueError('variables must be a dict/str/list/tuple')
1015 1015
1016 1016 # Propagate variables to user namespace
1017 1017 self.user_ns.update(vdict)
1018 1018
1019 1019 # And configure interactive visibility
1020 1020 config_ns = self.user_ns_hidden
1021 1021 if interactive:
1022 1022 for name, val in vdict.iteritems():
1023 1023 config_ns.pop(name, None)
1024 1024 else:
1025 1025 for name,val in vdict.iteritems():
1026 1026 config_ns[name] = val
1027 1027
1028 1028 #-------------------------------------------------------------------------
1029 1029 # Things related to history management
1030 1030 #-------------------------------------------------------------------------
1031 1031
1032 1032 def init_history(self):
1033 1033 # List of input with multi-line handling.
1034 1034 self.input_hist = InputList()
1035 1035 # This one will hold the 'raw' input history, without any
1036 1036 # pre-processing. This will allow users to retrieve the input just as
1037 1037 # it was exactly typed in by the user, with %hist -r.
1038 1038 self.input_hist_raw = InputList()
1039 1039
1040 1040 # list of visited directories
1041 1041 try:
1042 1042 self.dir_hist = [os.getcwd()]
1043 1043 except OSError:
1044 1044 self.dir_hist = []
1045 1045
1046 1046 # dict of output history
1047 1047 self.output_hist = {}
1048 1048
1049 1049 # Now the history file
1050 1050 if self.profile:
1051 1051 histfname = 'history-%s' % self.profile
1052 1052 else:
1053 1053 histfname = 'history'
1054 1054 self.histfile = os.path.join(self.ipython_dir, histfname)
1055 1055
1056 1056 # Fill the history zero entry, user counter starts at 1
1057 1057 self.input_hist.append('\n')
1058 1058 self.input_hist_raw.append('\n')
1059 1059
1060 1060 def init_shadow_hist(self):
1061 1061 try:
1062 1062 self.db = pickleshare.PickleShareDB(self.ipython_dir + "/db")
1063 1063 except exceptions.UnicodeDecodeError:
1064 1064 print "Your ipython_dir can't be decoded to unicode!"
1065 1065 print "Please set HOME environment variable to something that"
1066 1066 print r"only has ASCII characters, e.g. c:\home"
1067 1067 print "Now it is", self.ipython_dir
1068 1068 sys.exit()
1069 1069 self.shadowhist = ipcorehist.ShadowHist(self.db)
1070 1070
1071 1071 def savehist(self):
1072 1072 """Save input history to a file (via readline library)."""
1073 1073
1074 1074 try:
1075 1075 self.readline.write_history_file(self.histfile)
1076 1076 except:
1077 1077 print 'Unable to save IPython command history to file: ' + \
1078 1078 `self.histfile`
1079 1079
1080 1080 def reloadhist(self):
1081 1081 """Reload the input history from disk file."""
1082 1082
1083 1083 try:
1084 1084 self.readline.clear_history()
1085 1085 self.readline.read_history_file(self.shell.histfile)
1086 1086 except AttributeError:
1087 1087 pass
1088 1088
1089 1089 def history_saving_wrapper(self, func):
1090 1090 """ Wrap func for readline history saving
1091 1091
1092 1092 Convert func into callable that saves & restores
1093 1093 history around the call """
1094 1094
1095 1095 if self.has_readline:
1096 1096 from IPython.utils import rlineimpl as readline
1097 1097 else:
1098 1098 return func
1099 1099
1100 1100 def wrapper():
1101 1101 self.savehist()
1102 1102 try:
1103 1103 func()
1104 1104 finally:
1105 1105 readline.read_history_file(self.histfile)
1106 1106 return wrapper
1107 1107
1108 1108 def get_history(self, index=None, raw=False, output=True):
1109 1109 """Get the history list.
1110 1110
1111 1111 Get the input and output history.
1112 1112
1113 1113 Parameters
1114 1114 ----------
1115 1115 index : n or (n1, n2) or None
1116 1116 If n, then the last entries. If a tuple, then all in
1117 1117 range(n1, n2). If None, then all entries. Raises IndexError if
1118 1118 the format of index is incorrect.
1119 1119 raw : bool
1120 1120 If True, return the raw input.
1121 1121 output : bool
1122 1122 If True, then return the output as well.
1123 1123
1124 1124 Returns
1125 1125 -------
1126 1126 If output is True, then return a dict of tuples, keyed by the prompt
1127 1127 numbers and with values of (input, output). If output is False, then
1128 1128 a dict, keyed by the prompt number with the values of input. Raises
1129 1129 IndexError if no history is found.
1130 1130 """
1131 1131 if raw:
1132 1132 input_hist = self.input_hist_raw
1133 1133 else:
1134 1134 input_hist = self.input_hist
1135 1135 if output:
1136 1136 output_hist = self.user_ns['Out']
1137 1137 n = len(input_hist)
1138 1138 if index is None:
1139 1139 start=0; stop=n
1140 1140 elif isinstance(index, int):
1141 1141 start=n-index; stop=n
1142 1142 elif isinstance(index, tuple) and len(index) == 2:
1143 1143 start=index[0]; stop=index[1]
1144 1144 else:
1145 1145 raise IndexError('Not a valid index for the input history: %r' % index)
1146 1146 hist = {}
1147 1147 for i in range(start, stop):
1148 1148 if output:
1149 1149 hist[i] = (input_hist[i], output_hist.get(i))
1150 1150 else:
1151 1151 hist[i] = input_hist[i]
1152 1152 if len(hist)==0:
1153 1153 raise IndexError('No history for range of indices: %r' % index)
1154 1154 return hist
1155 1155
1156 1156 #-------------------------------------------------------------------------
1157 1157 # Things related to exception handling and tracebacks (not debugging)
1158 1158 #-------------------------------------------------------------------------
1159 1159
1160 1160 def init_traceback_handlers(self, custom_exceptions):
1161 1161 # Syntax error handler.
1162 1162 self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor')
1163 1163
1164 1164 # The interactive one is initialized with an offset, meaning we always
1165 1165 # want to remove the topmost item in the traceback, which is our own
1166 1166 # internal code. Valid modes: ['Plain','Context','Verbose']
1167 1167 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1168 1168 color_scheme='NoColor',
1169 1169 tb_offset = 1)
1170 1170
1171 1171 # The instance will store a pointer to the system-wide exception hook,
1172 1172 # so that runtime code (such as magics) can access it. This is because
1173 1173 # during the read-eval loop, it may get temporarily overwritten.
1174 1174 self.sys_excepthook = sys.excepthook
1175 1175
1176 1176 # and add any custom exception handlers the user may have specified
1177 1177 self.set_custom_exc(*custom_exceptions)
1178 1178
1179 1179 # Set the exception mode
1180 1180 self.InteractiveTB.set_mode(mode=self.xmode)
1181 1181
1182 1182 def set_custom_exc(self, exc_tuple, handler):
1183 1183 """set_custom_exc(exc_tuple,handler)
1184 1184
1185 1185 Set a custom exception handler, which will be called if any of the
1186 1186 exceptions in exc_tuple occur in the mainloop (specifically, in the
1187 1187 runcode() method.
1188 1188
1189 1189 Inputs:
1190 1190
1191 1191 - exc_tuple: a *tuple* of valid exceptions to call the defined
1192 1192 handler for. It is very important that you use a tuple, and NOT A
1193 1193 LIST here, because of the way Python's except statement works. If
1194 1194 you only want to trap a single exception, use a singleton tuple:
1195 1195
1196 1196 exc_tuple == (MyCustomException,)
1197 1197
1198 1198 - handler: this must be defined as a function with the following
1199 1199 basic interface::
1200 1200
1201 1201 def my_handler(self, etype, value, tb, tb_offset=None)
1202 1202 ...
1203 1203 # The return value must be
1204 1204 return structured_traceback
1205 1205
1206 1206 This will be made into an instance method (via new.instancemethod)
1207 1207 of IPython itself, and it will be called if any of the exceptions
1208 1208 listed in the exc_tuple are caught. If the handler is None, an
1209 1209 internal basic one is used, which just prints basic info.
1210 1210
1211 1211 WARNING: by putting in your own exception handler into IPython's main
1212 1212 execution loop, you run a very good chance of nasty crashes. This
1213 1213 facility should only be used if you really know what you are doing."""
1214 1214
1215 1215 assert type(exc_tuple)==type(()) , \
1216 1216 "The custom exceptions must be given AS A TUPLE."
1217 1217
1218 1218 def dummy_handler(self,etype,value,tb):
1219 1219 print '*** Simple custom exception handler ***'
1220 1220 print 'Exception type :',etype
1221 1221 print 'Exception value:',value
1222 1222 print 'Traceback :',tb
1223 1223 print 'Source code :','\n'.join(self.buffer)
1224 1224
1225 1225 if handler is None: handler = dummy_handler
1226 1226
1227 1227 self.CustomTB = new.instancemethod(handler,self,self.__class__)
1228 1228 self.custom_exceptions = exc_tuple
1229 1229
1230 1230 def excepthook(self, etype, value, tb):
1231 1231 """One more defense for GUI apps that call sys.excepthook.
1232 1232
1233 1233 GUI frameworks like wxPython trap exceptions and call
1234 1234 sys.excepthook themselves. I guess this is a feature that
1235 1235 enables them to keep running after exceptions that would
1236 1236 otherwise kill their mainloop. This is a bother for IPython
1237 1237 which excepts to catch all of the program exceptions with a try:
1238 1238 except: statement.
1239 1239
1240 1240 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
1241 1241 any app directly invokes sys.excepthook, it will look to the user like
1242 1242 IPython crashed. In order to work around this, we can disable the
1243 1243 CrashHandler and replace it with this excepthook instead, which prints a
1244 1244 regular traceback using our InteractiveTB. In this fashion, apps which
1245 1245 call sys.excepthook will generate a regular-looking exception from
1246 1246 IPython, and the CrashHandler will only be triggered by real IPython
1247 1247 crashes.
1248 1248
1249 1249 This hook should be used sparingly, only in places which are not likely
1250 1250 to be true IPython errors.
1251 1251 """
1252 1252 self.showtraceback((etype,value,tb),tb_offset=0)
1253 1253
1254 1254 def showtraceback(self,exc_tuple = None,filename=None,tb_offset=None,
1255 1255 exception_only=False):
1256 1256 """Display the exception that just occurred.
1257 1257
1258 1258 If nothing is known about the exception, this is the method which
1259 1259 should be used throughout the code for presenting user tracebacks,
1260 1260 rather than directly invoking the InteractiveTB object.
1261 1261
1262 1262 A specific showsyntaxerror() also exists, but this method can take
1263 1263 care of calling it if needed, so unless you are explicitly catching a
1264 1264 SyntaxError exception, don't try to analyze the stack manually and
1265 1265 simply call this method."""
1266 1266
1267 1267 try:
1268 1268 if exc_tuple is None:
1269 1269 etype, value, tb = sys.exc_info()
1270 1270 else:
1271 1271 etype, value, tb = exc_tuple
1272 1272
1273 1273 if etype is None:
1274 1274 if hasattr(sys, 'last_type'):
1275 1275 etype, value, tb = sys.last_type, sys.last_value, \
1276 1276 sys.last_traceback
1277 1277 else:
1278 1278 self.write_err('No traceback available to show.\n')
1279 1279 return
1280 1280
1281 1281 if etype is SyntaxError:
1282 1282 # Though this won't be called by syntax errors in the input
1283 1283 # line, there may be SyntaxError cases whith imported code.
1284 1284 self.showsyntaxerror(filename)
1285 1285 elif etype is UsageError:
1286 1286 print "UsageError:", value
1287 1287 else:
1288 1288 # WARNING: these variables are somewhat deprecated and not
1289 1289 # necessarily safe to use in a threaded environment, but tools
1290 1290 # like pdb depend on their existence, so let's set them. If we
1291 1291 # find problems in the field, we'll need to revisit their use.
1292 1292 sys.last_type = etype
1293 1293 sys.last_value = value
1294 1294 sys.last_traceback = tb
1295 1295
1296 1296 if etype in self.custom_exceptions:
1297 1297 # FIXME: Old custom traceback objects may just return a
1298 1298 # string, in that case we just put it into a list
1299 1299 stb = self.CustomTB(etype, value, tb, tb_offset)
1300 1300 if isinstance(ctb, basestring):
1301 1301 stb = [stb]
1302 1302 else:
1303 1303 if exception_only:
1304 1304 stb = ['An exception has occurred, use %tb to see '
1305 1305 'the full traceback.\n']
1306 1306 stb.extend(self.InteractiveTB.get_exception_only(etype,
1307 1307 value))
1308 1308 else:
1309 1309 stb = self.InteractiveTB.structured_traceback(etype,
1310 1310 value, tb, tb_offset=tb_offset)
1311 1311 # FIXME: the pdb calling should be done by us, not by
1312 1312 # the code computing the traceback.
1313 1313 if self.InteractiveTB.call_pdb:
1314 1314 # pdb mucks up readline, fix it back
1315 1315 self.set_completer()
1316 1316
1317 1317 # Actually show the traceback
1318 1318 self._showtraceback(etype, value, stb)
1319 1319
1320 1320 except KeyboardInterrupt:
1321 1321 self.write_err("\nKeyboardInterrupt\n")
1322 1322
1323 1323 def _showtraceback(self, etype, evalue, stb):
1324 1324 """Actually show a traceback.
1325 1325
1326 1326 Subclasses may override this method to put the traceback on a different
1327 1327 place, like a side channel.
1328 1328 """
1329 1329 # FIXME: this should use the proper write channels, but our test suite
1330 1330 # relies on it coming out of stdout...
1331 1331 print >> sys.stdout, self.InteractiveTB.stb2text(stb)
1332 1332
1333 1333 def showsyntaxerror(self, filename=None):
1334 1334 """Display the syntax error that just occurred.
1335 1335
1336 1336 This doesn't display a stack trace because there isn't one.
1337 1337
1338 1338 If a filename is given, it is stuffed in the exception instead
1339 1339 of what was there before (because Python's parser always uses
1340 1340 "<string>" when reading from a string).
1341 1341 """
1342 1342 etype, value, last_traceback = sys.exc_info()
1343 1343
1344 1344 # See note about these variables in showtraceback() above
1345 1345 sys.last_type = etype
1346 1346 sys.last_value = value
1347 1347 sys.last_traceback = last_traceback
1348 1348
1349 1349 if filename and etype is SyntaxError:
1350 1350 # Work hard to stuff the correct filename in the exception
1351 1351 try:
1352 1352 msg, (dummy_filename, lineno, offset, line) = value
1353 1353 except:
1354 1354 # Not the format we expect; leave it alone
1355 1355 pass
1356 1356 else:
1357 1357 # Stuff in the right filename
1358 1358 try:
1359 1359 # Assume SyntaxError is a class exception
1360 1360 value = SyntaxError(msg, (filename, lineno, offset, line))
1361 1361 except:
1362 1362 # If that failed, assume SyntaxError is a string
1363 1363 value = msg, (filename, lineno, offset, line)
1364 1364 stb = self.SyntaxTB.structured_traceback(etype, value, [])
1365 1365 self._showtraceback(etype, value, stb)
1366 1366
1367 1367 #-------------------------------------------------------------------------
1368 1368 # Things related to tab completion
1369 1369 #-------------------------------------------------------------------------
1370 1370
1371 1371 def complete(self, text, line=None, cursor_pos=None):
1372 1372 """Return the completed text and a list of completions.
1373 1373
1374 1374 Parameters
1375 1375 ----------
1376 1376
1377 1377 text : string
1378 1378 A string of text to be completed on. It can be given as empty and
1379 1379 instead a line/position pair are given. In this case, the
1380 1380 completer itself will split the line like readline does.
1381 1381
1382 1382 line : string, optional
1383 1383 The complete line that text is part of.
1384 1384
1385 1385 cursor_pos : int, optional
1386 1386 The position of the cursor on the input line.
1387 1387
1388 1388 Returns
1389 1389 -------
1390 1390 text : string
1391 1391 The actual text that was completed.
1392 1392
1393 1393 matches : list
1394 1394 A sorted list with all possible completions.
1395 1395
1396 1396 The optional arguments allow the completion to take more context into
1397 1397 account, and are part of the low-level completion API.
1398 1398
1399 1399 This is a wrapper around the completion mechanism, similar to what
1400 1400 readline does at the command line when the TAB key is hit. By
1401 1401 exposing it as a method, it can be used by other non-readline
1402 1402 environments (such as GUIs) for text completion.
1403 1403
1404 1404 Simple usage example:
1405 1405
1406 1406 In [1]: x = 'hello'
1407 1407
1408 1408 In [2]: _ip.complete('x.l')
1409 1409 Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
1410 1410 """
1411 1411
1412 1412 # Inject names into __builtin__ so we can complete on the added names.
1413 1413 with self.builtin_trap:
1414 1414 return self.Completer.complete(text, line, cursor_pos)
1415 1415
1416 1416 def set_custom_completer(self, completer, pos=0):
1417 1417 """Adds a new custom completer function.
1418 1418
1419 1419 The position argument (defaults to 0) is the index in the completers
1420 1420 list where you want the completer to be inserted."""
1421 1421
1422 1422 newcomp = new.instancemethod(completer,self.Completer,
1423 1423 self.Completer.__class__)
1424 1424 self.Completer.matchers.insert(pos,newcomp)
1425 1425
1426 1426 def set_completer(self):
1427 1427 """Reset readline's completer to be our own."""
1428 1428 self.readline.set_completer(self.Completer.rlcomplete)
1429 1429
1430 1430 def set_completer_frame(self, frame=None):
1431 1431 """Set the frame of the completer."""
1432 1432 if frame:
1433 1433 self.Completer.namespace = frame.f_locals
1434 1434 self.Completer.global_namespace = frame.f_globals
1435 1435 else:
1436 1436 self.Completer.namespace = self.user_ns
1437 1437 self.Completer.global_namespace = self.user_global_ns
1438 1438
1439 1439 #-------------------------------------------------------------------------
1440 1440 # Things related to readline
1441 1441 #-------------------------------------------------------------------------
1442 1442
1443 1443 def init_readline(self):
1444 1444 """Command history completion/saving/reloading."""
1445 1445
1446 1446 if self.readline_use:
1447 1447 import IPython.utils.rlineimpl as readline
1448 1448
1449 1449 self.rl_next_input = None
1450 1450 self.rl_do_indent = False
1451 1451
1452 1452 if not self.readline_use or not readline.have_readline:
1453 1453 self.has_readline = False
1454 1454 self.readline = None
1455 1455 # Set a number of methods that depend on readline to be no-op
1456 1456 self.savehist = no_op
1457 1457 self.reloadhist = no_op
1458 1458 self.set_completer = no_op
1459 1459 self.set_custom_completer = no_op
1460 1460 self.set_completer_frame = no_op
1461 1461 warn('Readline services not available or not loaded.')
1462 1462 else:
1463 1463 self.has_readline = True
1464 1464 self.readline = readline
1465 1465 sys.modules['readline'] = readline
1466 1466 import atexit
1467 1467 from IPython.core.completer import IPCompleter
1468 1468 self.Completer = IPCompleter(self,
1469 1469 self.user_ns,
1470 1470 self.user_global_ns,
1471 1471 self.readline_omit__names,
1472 1472 self.alias_manager.alias_table)
1473 1473 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
1474 1474 self.strdispatchers['complete_command'] = sdisp
1475 1475 self.Completer.custom_completers = sdisp
1476 1476 # Platform-specific configuration
1477 1477 if os.name == 'nt':
1478 1478 self.readline_startup_hook = readline.set_pre_input_hook
1479 1479 else:
1480 1480 self.readline_startup_hook = readline.set_startup_hook
1481 1481
1482 1482 # Load user's initrc file (readline config)
1483 1483 # Or if libedit is used, load editrc.
1484 1484 inputrc_name = os.environ.get('INPUTRC')
1485 1485 if inputrc_name is None:
1486 1486 home_dir = get_home_dir()
1487 1487 if home_dir is not None:
1488 1488 inputrc_name = '.inputrc'
1489 1489 if readline.uses_libedit:
1490 1490 inputrc_name = '.editrc'
1491 1491 inputrc_name = os.path.join(home_dir, inputrc_name)
1492 1492 if os.path.isfile(inputrc_name):
1493 1493 try:
1494 1494 readline.read_init_file(inputrc_name)
1495 1495 except:
1496 1496 warn('Problems reading readline initialization file <%s>'
1497 1497 % inputrc_name)
1498 1498
1499 1499 # save this in sys so embedded copies can restore it properly
1500 1500 sys.ipcompleter = self.Completer.rlcomplete
1501 1501 self.set_completer()
1502 1502
1503 1503 # Configure readline according to user's prefs
1504 1504 # This is only done if GNU readline is being used. If libedit
1505 1505 # is being used (as on Leopard) the readline config is
1506 1506 # not run as the syntax for libedit is different.
1507 1507 if not readline.uses_libedit:
1508 1508 for rlcommand in self.readline_parse_and_bind:
1509 1509 #print "loading rl:",rlcommand # dbg
1510 1510 readline.parse_and_bind(rlcommand)
1511 1511
1512 1512 # Remove some chars from the delimiters list. If we encounter
1513 1513 # unicode chars, discard them.
1514 1514 delims = readline.get_completer_delims().encode("ascii", "ignore")
1515 1515 delims = delims.translate(string._idmap,
1516 1516 self.readline_remove_delims)
1517 1517 readline.set_completer_delims(delims)
1518 1518 # otherwise we end up with a monster history after a while:
1519 1519 readline.set_history_length(1000)
1520 1520 try:
1521 1521 #print '*** Reading readline history' # dbg
1522 1522 readline.read_history_file(self.histfile)
1523 1523 except IOError:
1524 1524 pass # It doesn't exist yet.
1525 1525
1526 1526 atexit.register(self.atexit_operations)
1527 1527 del atexit
1528 1528
1529 1529 # Configure auto-indent for all platforms
1530 1530 self.set_autoindent(self.autoindent)
1531 1531
1532 1532 def set_next_input(self, s):
1533 1533 """ Sets the 'default' input string for the next command line.
1534 1534
1535 1535 Requires readline.
1536 1536
1537 1537 Example:
1538 1538
1539 1539 [D:\ipython]|1> _ip.set_next_input("Hello Word")
1540 1540 [D:\ipython]|2> Hello Word_ # cursor is here
1541 1541 """
1542 1542
1543 1543 self.rl_next_input = s
1544 1544
1545 1545 # Maybe move this to the terminal subclass?
1546 1546 def pre_readline(self):
1547 1547 """readline hook to be used at the start of each line.
1548 1548
1549 1549 Currently it handles auto-indent only."""
1550 1550
1551 1551 if self.rl_do_indent:
1552 1552 self.readline.insert_text(self._indent_current_str())
1553 1553 if self.rl_next_input is not None:
1554 1554 self.readline.insert_text(self.rl_next_input)
1555 1555 self.rl_next_input = None
1556 1556
1557 1557 def _indent_current_str(self):
1558 1558 """return the current level of indentation as a string"""
1559 1559 return self.indent_current_nsp * ' '
1560 1560
1561 1561 #-------------------------------------------------------------------------
1562 1562 # Things related to magics
1563 1563 #-------------------------------------------------------------------------
1564 1564
1565 1565 def init_magics(self):
1566 1566 # FIXME: Move the color initialization to the DisplayHook, which
1567 1567 # should be split into a prompt manager and displayhook. We probably
1568 1568 # even need a centralize colors management object.
1569 1569 self.magic_colors(self.colors)
1570 1570 # History was moved to a separate module
1571 1571 from . import history
1572 1572 history.init_ipython(self)
1573 1573
1574 1574 def magic(self,arg_s):
1575 1575 """Call a magic function by name.
1576 1576
1577 1577 Input: a string containing the name of the magic function to call and any
1578 1578 additional arguments to be passed to the magic.
1579 1579
1580 1580 magic('name -opt foo bar') is equivalent to typing at the ipython
1581 1581 prompt:
1582 1582
1583 1583 In[1]: %name -opt foo bar
1584 1584
1585 1585 To call a magic without arguments, simply use magic('name').
1586 1586
1587 1587 This provides a proper Python function to call IPython's magics in any
1588 1588 valid Python code you can type at the interpreter, including loops and
1589 1589 compound statements.
1590 1590 """
1591 1591 args = arg_s.split(' ',1)
1592 1592 magic_name = args[0]
1593 1593 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
1594 1594
1595 1595 try:
1596 1596 magic_args = args[1]
1597 1597 except IndexError:
1598 1598 magic_args = ''
1599 1599 fn = getattr(self,'magic_'+magic_name,None)
1600 1600 if fn is None:
1601 1601 error("Magic function `%s` not found." % magic_name)
1602 1602 else:
1603 1603 magic_args = self.var_expand(magic_args,1)
1604 1604 with nested(self.builtin_trap,):
1605 1605 result = fn(magic_args)
1606 1606 return result
1607 1607
1608 1608 def define_magic(self, magicname, func):
1609 1609 """Expose own function as magic function for ipython
1610 1610
1611 1611 def foo_impl(self,parameter_s=''):
1612 1612 'My very own magic!. (Use docstrings, IPython reads them).'
1613 1613 print 'Magic function. Passed parameter is between < >:'
1614 1614 print '<%s>' % parameter_s
1615 1615 print 'The self object is:',self
1616 1616
1617 1617 self.define_magic('foo',foo_impl)
1618 1618 """
1619 1619
1620 1620 import new
1621 1621 im = new.instancemethod(func,self, self.__class__)
1622 1622 old = getattr(self, "magic_" + magicname, None)
1623 1623 setattr(self, "magic_" + magicname, im)
1624 1624 return old
1625 1625
1626 1626 #-------------------------------------------------------------------------
1627 1627 # Things related to macros
1628 1628 #-------------------------------------------------------------------------
1629 1629
1630 1630 def define_macro(self, name, themacro):
1631 1631 """Define a new macro
1632 1632
1633 1633 Parameters
1634 1634 ----------
1635 1635 name : str
1636 1636 The name of the macro.
1637 1637 themacro : str or Macro
1638 1638 The action to do upon invoking the macro. If a string, a new
1639 1639 Macro object is created by passing the string to it.
1640 1640 """
1641 1641
1642 1642 from IPython.core import macro
1643 1643
1644 1644 if isinstance(themacro, basestring):
1645 1645 themacro = macro.Macro(themacro)
1646 1646 if not isinstance(themacro, macro.Macro):
1647 1647 raise ValueError('A macro must be a string or a Macro instance.')
1648 1648 self.user_ns[name] = themacro
1649 1649
1650 1650 #-------------------------------------------------------------------------
1651 1651 # Things related to the running of system commands
1652 1652 #-------------------------------------------------------------------------
1653 1653
1654 1654 def system(self, cmd):
1655 1655 """Call the given cmd in a subprocess."""
1656 1656 # We do not support backgrounding processes because we either use
1657 1657 # pexpect or pipes to read from. Users can always just call
1658 1658 # os.system() if they really want a background process.
1659 1659 if cmd.endswith('&'):
1660 1660 raise OSError("Background processes not supported.")
1661 1661
1662 1662 return system(self.var_expand(cmd, depth=2))
1663 1663
1664 1664 def getoutput(self, cmd):
1665 1665 """Get output (possibly including stderr) from a subprocess."""
1666 1666 if cmd.endswith('&'):
1667 1667 raise OSError("Background processes not supported.")
1668 1668 return getoutput(self.var_expand(cmd, depth=2))
1669 1669
1670 1670 #-------------------------------------------------------------------------
1671 1671 # Things related to aliases
1672 1672 #-------------------------------------------------------------------------
1673 1673
1674 1674 def init_alias(self):
1675 1675 self.alias_manager = AliasManager(shell=self, config=self.config)
1676 1676 self.ns_table['alias'] = self.alias_manager.alias_table,
1677 1677
1678 1678 #-------------------------------------------------------------------------
1679 1679 # Things related to extensions and plugins
1680 1680 #-------------------------------------------------------------------------
1681 1681
1682 1682 def init_extension_manager(self):
1683 1683 self.extension_manager = ExtensionManager(shell=self, config=self.config)
1684 1684
1685 1685 def init_plugin_manager(self):
1686 1686 self.plugin_manager = PluginManager(config=self.config)
1687 1687
1688 1688 #-------------------------------------------------------------------------
1689 1689 # Things related to payloads
1690 1690 #-------------------------------------------------------------------------
1691 1691
1692 1692 def init_payload(self):
1693 1693 self.payload_manager = PayloadManager(config=self.config)
1694 1694
1695 1695 #-------------------------------------------------------------------------
1696 1696 # Things related to the prefilter
1697 1697 #-------------------------------------------------------------------------
1698 1698
1699 1699 def init_prefilter(self):
1700 1700 self.prefilter_manager = PrefilterManager(shell=self, config=self.config)
1701 1701 # Ultimately this will be refactored in the new interpreter code, but
1702 1702 # for now, we should expose the main prefilter method (there's legacy
1703 1703 # code out there that may rely on this).
1704 1704 self.prefilter = self.prefilter_manager.prefilter_lines
1705 1705
1706 1706 #-------------------------------------------------------------------------
1707 # Things related to extracting values/expressions from kernel and user_ns
1708 #-------------------------------------------------------------------------
1709
1710 def _simple_error(self):
1711 etype, value = sys.exc_info()[:2]
1712 return u'[ERROR] {e.__name__}: {v}'.format(e=etype, v=value)
1713
1714 def get_user_variables(self, names):
1715 """Get a list of variable names from the user's namespace.
1716
1717 The return value is a dict with the repr() of each value.
1718 """
1719 out = {}
1720 user_ns = self.user_ns
1721 for varname in names:
1722 try:
1723 value = repr(user_ns[varname])
1724 except:
1725 value = self._simple_error()
1726 out[varname] = value
1727 return out
1728
1729 def eval_expressions(self, expressions):
1730 """Evaluate a dict of expressions in the user's namespace.
1731
1732 The return value is a dict with the repr() of each value.
1733 """
1734 out = {}
1735 user_ns = self.user_ns
1736 global_ns = self.user_global_ns
1737 for key, expr in expressions.iteritems():
1738 try:
1739 value = repr(eval(expr, global_ns, user_ns))
1740 except:
1741 value = self._simple_error()
1742 out[key] = value
1743 return out
1744
1745 #-------------------------------------------------------------------------
1707 1746 # Things related to the running of code
1708 1747 #-------------------------------------------------------------------------
1709 1748
1710 1749 def ex(self, cmd):
1711 1750 """Execute a normal python statement in user namespace."""
1712 1751 with nested(self.builtin_trap,):
1713 1752 exec cmd in self.user_global_ns, self.user_ns
1714 1753
1715 1754 def ev(self, expr):
1716 1755 """Evaluate python expression expr in user namespace.
1717 1756
1718 1757 Returns the result of evaluation
1719 1758 """
1720 1759 with nested(self.builtin_trap,):
1721 1760 return eval(expr, self.user_global_ns, self.user_ns)
1722 1761
1723 1762 def safe_execfile(self, fname, *where, **kw):
1724 1763 """A safe version of the builtin execfile().
1725 1764
1726 1765 This version will never throw an exception, but instead print
1727 1766 helpful error messages to the screen. This only works on pure
1728 1767 Python files with the .py extension.
1729 1768
1730 1769 Parameters
1731 1770 ----------
1732 1771 fname : string
1733 1772 The name of the file to be executed.
1734 1773 where : tuple
1735 1774 One or two namespaces, passed to execfile() as (globals,locals).
1736 1775 If only one is given, it is passed as both.
1737 1776 exit_ignore : bool (False)
1738 1777 If True, then silence SystemExit for non-zero status (it is always
1739 1778 silenced for zero status, as it is so common).
1740 1779 """
1741 1780 kw.setdefault('exit_ignore', False)
1742 1781
1743 1782 fname = os.path.abspath(os.path.expanduser(fname))
1744 1783
1745 1784 # Make sure we have a .py file
1746 1785 if not fname.endswith('.py'):
1747 1786 warn('File must end with .py to be run using execfile: <%s>' % fname)
1748 1787
1749 1788 # Make sure we can open the file
1750 1789 try:
1751 1790 with open(fname) as thefile:
1752 1791 pass
1753 1792 except:
1754 1793 warn('Could not open file <%s> for safe execution.' % fname)
1755 1794 return
1756 1795
1757 1796 # Find things also in current directory. This is needed to mimic the
1758 1797 # behavior of running a script from the system command line, where
1759 1798 # Python inserts the script's directory into sys.path
1760 1799 dname = os.path.dirname(fname)
1761 1800
1762 1801 with prepended_to_syspath(dname):
1763 1802 try:
1764 1803 execfile(fname,*where)
1765 1804 except SystemExit, status:
1766 1805 # If the call was made with 0 or None exit status (sys.exit(0)
1767 1806 # or sys.exit() ), don't bother showing a traceback, as both of
1768 1807 # these are considered normal by the OS:
1769 1808 # > python -c'import sys;sys.exit(0)'; echo $?
1770 1809 # 0
1771 1810 # > python -c'import sys;sys.exit()'; echo $?
1772 1811 # 0
1773 1812 # For other exit status, we show the exception unless
1774 1813 # explicitly silenced, but only in short form.
1775 1814 if status.code not in (0, None) and not kw['exit_ignore']:
1776 1815 self.showtraceback(exception_only=True)
1777 1816 except:
1778 1817 self.showtraceback()
1779 1818
1780 1819 def safe_execfile_ipy(self, fname):
1781 1820 """Like safe_execfile, but for .ipy files with IPython syntax.
1782 1821
1783 1822 Parameters
1784 1823 ----------
1785 1824 fname : str
1786 1825 The name of the file to execute. The filename must have a
1787 1826 .ipy extension.
1788 1827 """
1789 1828 fname = os.path.abspath(os.path.expanduser(fname))
1790 1829
1791 1830 # Make sure we have a .py file
1792 1831 if not fname.endswith('.ipy'):
1793 1832 warn('File must end with .py to be run using execfile: <%s>' % fname)
1794 1833
1795 1834 # Make sure we can open the file
1796 1835 try:
1797 1836 with open(fname) as thefile:
1798 1837 pass
1799 1838 except:
1800 1839 warn('Could not open file <%s> for safe execution.' % fname)
1801 1840 return
1802 1841
1803 1842 # Find things also in current directory. This is needed to mimic the
1804 1843 # behavior of running a script from the system command line, where
1805 1844 # Python inserts the script's directory into sys.path
1806 1845 dname = os.path.dirname(fname)
1807 1846
1808 1847 with prepended_to_syspath(dname):
1809 1848 try:
1810 1849 with open(fname) as thefile:
1811 1850 script = thefile.read()
1812 1851 # self.runlines currently captures all exceptions
1813 1852 # raise in user code. It would be nice if there were
1814 1853 # versions of runlines, execfile that did raise, so
1815 1854 # we could catch the errors.
1816 1855 self.runlines(script, clean=True)
1817 1856 except:
1818 1857 self.showtraceback()
1819 1858 warn('Unknown failure executing file: <%s>' % fname)
1820 1859
1821 1860 def runlines(self, lines, clean=False):
1822 1861 """Run a string of one or more lines of source.
1823 1862
1824 1863 This method is capable of running a string containing multiple source
1825 1864 lines, as if they had been entered at the IPython prompt. Since it
1826 1865 exposes IPython's processing machinery, the given strings can contain
1827 1866 magic calls (%magic), special shell access (!cmd), etc.
1828 1867 """
1829 1868
1830 1869 if isinstance(lines, (list, tuple)):
1831 1870 lines = '\n'.join(lines)
1832 1871
1833 1872 if clean:
1834 1873 lines = self._cleanup_ipy_script(lines)
1835 1874
1836 1875 # We must start with a clean buffer, in case this is run from an
1837 1876 # interactive IPython session (via a magic, for example).
1838 1877 self.resetbuffer()
1839 1878 lines = lines.splitlines()
1840 1879 more = 0
1841 1880 with nested(self.builtin_trap, self.display_trap):
1842 1881 for line in lines:
1843 1882 # skip blank lines so we don't mess up the prompt counter, but do
1844 1883 # NOT skip even a blank line if we are in a code block (more is
1845 1884 # true)
1846 1885
1847 1886 if line or more:
1848 1887 # push to raw history, so hist line numbers stay in sync
1849 1888 self.input_hist_raw.append(line + '\n')
1850 1889 prefiltered = self.prefilter_manager.prefilter_lines(line,
1851 1890 more)
1852 1891 more = self.push_line(prefiltered)
1853 1892 # IPython's runsource returns None if there was an error
1854 1893 # compiling the code. This allows us to stop processing right
1855 1894 # away, so the user gets the error message at the right place.
1856 1895 if more is None:
1857 1896 break
1858 1897 else:
1859 1898 self.input_hist_raw.append("\n")
1860 1899 # final newline in case the input didn't have it, so that the code
1861 1900 # actually does get executed
1862 1901 if more:
1863 1902 self.push_line('\n')
1864 1903
1865 1904 def runsource(self, source, filename='<input>', symbol='single'):
1866 1905 """Compile and run some source in the interpreter.
1867 1906
1868 1907 Arguments are as for compile_command().
1869 1908
1870 1909 One several things can happen:
1871 1910
1872 1911 1) The input is incorrect; compile_command() raised an
1873 1912 exception (SyntaxError or OverflowError). A syntax traceback
1874 1913 will be printed by calling the showsyntaxerror() method.
1875 1914
1876 1915 2) The input is incomplete, and more input is required;
1877 1916 compile_command() returned None. Nothing happens.
1878 1917
1879 1918 3) The input is complete; compile_command() returned a code
1880 1919 object. The code is executed by calling self.runcode() (which
1881 1920 also handles run-time exceptions, except for SystemExit).
1882 1921
1883 1922 The return value is:
1884 1923
1885 1924 - True in case 2
1886 1925
1887 1926 - False in the other cases, unless an exception is raised, where
1888 1927 None is returned instead. This can be used by external callers to
1889 1928 know whether to continue feeding input or not.
1890 1929
1891 1930 The return value can be used to decide whether to use sys.ps1 or
1892 1931 sys.ps2 to prompt the next line."""
1893 1932
1894 1933 # if the source code has leading blanks, add 'if 1:\n' to it
1895 1934 # this allows execution of indented pasted code. It is tempting
1896 1935 # to add '\n' at the end of source to run commands like ' a=1'
1897 1936 # directly, but this fails for more complicated scenarios
1898 1937 source=source.encode(self.stdin_encoding)
1899 1938 if source[:1] in [' ', '\t']:
1900 1939 source = 'if 1:\n%s' % source
1901 1940
1902 1941 try:
1903 1942 code = self.compile(source,filename,symbol)
1904 1943 except (OverflowError, SyntaxError, ValueError, TypeError, MemoryError):
1905 1944 # Case 1
1906 1945 self.showsyntaxerror(filename)
1907 1946 return None
1908 1947
1909 1948 if code is None:
1910 1949 # Case 2
1911 1950 return True
1912 1951
1913 1952 # Case 3
1914 1953 # We store the code object so that threaded shells and
1915 1954 # custom exception handlers can access all this info if needed.
1916 1955 # The source corresponding to this can be obtained from the
1917 1956 # buffer attribute as '\n'.join(self.buffer).
1918 1957 self.code_to_run = code
1919 1958 # now actually execute the code object
1920 1959 if self.runcode(code) == 0:
1921 1960 return False
1922 1961 else:
1923 1962 return None
1924 1963
1925 1964 def runcode(self,code_obj):
1926 1965 """Execute a code object.
1927 1966
1928 1967 When an exception occurs, self.showtraceback() is called to display a
1929 1968 traceback.
1930 1969
1931 1970 Return value: a flag indicating whether the code to be run completed
1932 1971 successfully:
1933 1972
1934 1973 - 0: successful execution.
1935 1974 - 1: an error occurred.
1936 1975 """
1937 1976
1938 1977 # Set our own excepthook in case the user code tries to call it
1939 1978 # directly, so that the IPython crash handler doesn't get triggered
1940 1979 old_excepthook,sys.excepthook = sys.excepthook, self.excepthook
1941 1980
1942 1981 # we save the original sys.excepthook in the instance, in case config
1943 1982 # code (such as magics) needs access to it.
1944 1983 self.sys_excepthook = old_excepthook
1945 1984 outflag = 1 # happens in more places, so it's easier as default
1946 1985 try:
1947 1986 try:
1948 1987 self.hooks.pre_runcode_hook()
1949 1988 #rprint('Running code') # dbg
1950 1989 exec code_obj in self.user_global_ns, self.user_ns
1951 1990 finally:
1952 1991 # Reset our crash handler in place
1953 1992 sys.excepthook = old_excepthook
1954 1993 except SystemExit:
1955 1994 self.resetbuffer()
1956 1995 self.showtraceback(exception_only=True)
1957 1996 warn("To exit: use any of 'exit', 'quit', %Exit or Ctrl-D.", level=1)
1958 1997 except self.custom_exceptions:
1959 1998 etype,value,tb = sys.exc_info()
1960 1999 self.CustomTB(etype,value,tb)
1961 2000 except:
1962 2001 self.showtraceback()
1963 2002 else:
1964 2003 outflag = 0
1965 2004 if softspace(sys.stdout, 0):
1966 2005 print
1967 2006 # Flush out code object which has been run (and source)
1968 2007 self.code_to_run = None
1969 2008 return outflag
1970 2009
1971 2010 def push_line(self, line):
1972 2011 """Push a line to the interpreter.
1973 2012
1974 2013 The line should not have a trailing newline; it may have
1975 2014 internal newlines. The line is appended to a buffer and the
1976 2015 interpreter's runsource() method is called with the
1977 2016 concatenated contents of the buffer as source. If this
1978 2017 indicates that the command was executed or invalid, the buffer
1979 2018 is reset; otherwise, the command is incomplete, and the buffer
1980 2019 is left as it was after the line was appended. The return
1981 2020 value is 1 if more input is required, 0 if the line was dealt
1982 2021 with in some way (this is the same as runsource()).
1983 2022 """
1984 2023
1985 2024 # autoindent management should be done here, and not in the
1986 2025 # interactive loop, since that one is only seen by keyboard input. We
1987 2026 # need this done correctly even for code run via runlines (which uses
1988 2027 # push).
1989 2028
1990 2029 #print 'push line: <%s>' % line # dbg
1991 2030 for subline in line.splitlines():
1992 2031 self._autoindent_update(subline)
1993 2032 self.buffer.append(line)
1994 2033 more = self.runsource('\n'.join(self.buffer), self.filename)
1995 2034 if not more:
1996 2035 self.resetbuffer()
1997 2036 return more
1998 2037
1999 2038 def resetbuffer(self):
2000 2039 """Reset the input buffer."""
2001 2040 self.buffer[:] = []
2002 2041
2003 2042 def _is_secondary_block_start(self, s):
2004 2043 if not s.endswith(':'):
2005 2044 return False
2006 2045 if (s.startswith('elif') or
2007 2046 s.startswith('else') or
2008 2047 s.startswith('except') or
2009 2048 s.startswith('finally')):
2010 2049 return True
2011 2050
2012 2051 def _cleanup_ipy_script(self, script):
2013 2052 """Make a script safe for self.runlines()
2014 2053
2015 2054 Currently, IPython is lines based, with blocks being detected by
2016 2055 empty lines. This is a problem for block based scripts that may
2017 2056 not have empty lines after blocks. This script adds those empty
2018 2057 lines to make scripts safe for running in the current line based
2019 2058 IPython.
2020 2059 """
2021 2060 res = []
2022 2061 lines = script.splitlines()
2023 2062 level = 0
2024 2063
2025 2064 for l in lines:
2026 2065 lstripped = l.lstrip()
2027 2066 stripped = l.strip()
2028 2067 if not stripped:
2029 2068 continue
2030 2069 newlevel = len(l) - len(lstripped)
2031 2070 if level > 0 and newlevel == 0 and \
2032 2071 not self._is_secondary_block_start(stripped):
2033 2072 # add empty line
2034 2073 res.append('')
2035 2074 res.append(l)
2036 2075 level = newlevel
2037 2076
2038 2077 return '\n'.join(res) + '\n'
2039 2078
2040 2079 def _autoindent_update(self,line):
2041 2080 """Keep track of the indent level."""
2042 2081
2043 2082 #debugx('line')
2044 2083 #debugx('self.indent_current_nsp')
2045 2084 if self.autoindent:
2046 2085 if line:
2047 2086 inisp = num_ini_spaces(line)
2048 2087 if inisp < self.indent_current_nsp:
2049 2088 self.indent_current_nsp = inisp
2050 2089
2051 2090 if line[-1] == ':':
2052 2091 self.indent_current_nsp += 4
2053 2092 elif dedent_re.match(line):
2054 2093 self.indent_current_nsp -= 4
2055 2094 else:
2056 2095 self.indent_current_nsp = 0
2057 2096
2058 2097 #-------------------------------------------------------------------------
2059 2098 # Things related to GUI support and pylab
2060 2099 #-------------------------------------------------------------------------
2061 2100
2062 2101 def enable_pylab(self, gui=None):
2063 2102 raise NotImplementedError('Implement enable_pylab in a subclass')
2064 2103
2065 2104 #-------------------------------------------------------------------------
2066 2105 # Utilities
2067 2106 #-------------------------------------------------------------------------
2068 2107
2069 2108 def var_expand(self,cmd,depth=0):
2070 2109 """Expand python variables in a string.
2071 2110
2072 2111 The depth argument indicates how many frames above the caller should
2073 2112 be walked to look for the local namespace where to expand variables.
2074 2113
2075 2114 The global namespace for expansion is always the user's interactive
2076 2115 namespace.
2077 2116 """
2078 2117
2079 2118 return str(ItplNS(cmd,
2080 2119 self.user_ns, # globals
2081 2120 # Skip our own frame in searching for locals:
2082 2121 sys._getframe(depth+1).f_locals # locals
2083 2122 ))
2084 2123
2085 2124 def mktempfile(self,data=None):
2086 2125 """Make a new tempfile and return its filename.
2087 2126
2088 2127 This makes a call to tempfile.mktemp, but it registers the created
2089 2128 filename internally so ipython cleans it up at exit time.
2090 2129
2091 2130 Optional inputs:
2092 2131
2093 2132 - data(None): if data is given, it gets written out to the temp file
2094 2133 immediately, and the file is closed again."""
2095 2134
2096 2135 filename = tempfile.mktemp('.py','ipython_edit_')
2097 2136 self.tempfiles.append(filename)
2098 2137
2099 2138 if data:
2100 2139 tmp_file = open(filename,'w')
2101 2140 tmp_file.write(data)
2102 2141 tmp_file.close()
2103 2142 return filename
2104 2143
2105 2144 # TODO: This should be removed when Term is refactored.
2106 2145 def write(self,data):
2107 2146 """Write a string to the default output"""
2108 2147 io.Term.cout.write(data)
2109 2148
2110 2149 # TODO: This should be removed when Term is refactored.
2111 2150 def write_err(self,data):
2112 2151 """Write a string to the default error output"""
2113 2152 io.Term.cerr.write(data)
2114 2153
2115 2154 def ask_yes_no(self,prompt,default=True):
2116 2155 if self.quiet:
2117 2156 return True
2118 2157 return ask_yes_no(prompt,default)
2119 2158
2120 2159 def show_usage(self):
2121 2160 """Show a usage message"""
2122 2161 page.page(IPython.core.usage.interactive_usage)
2123 2162
2124 2163 #-------------------------------------------------------------------------
2125 2164 # Things related to IPython exiting
2126 2165 #-------------------------------------------------------------------------
2127 2166
2128 2167 def atexit_operations(self):
2129 2168 """This will be executed at the time of exit.
2130 2169
2131 2170 Saving of persistent data should be performed here.
2132 2171 """
2133 2172 self.savehist()
2134 2173
2135 2174 # Cleanup all tempfiles left around
2136 2175 for tfile in self.tempfiles:
2137 2176 try:
2138 2177 os.unlink(tfile)
2139 2178 except OSError:
2140 2179 pass
2141 2180
2142 2181 # Clear all user namespaces to release all references cleanly.
2143 2182 self.reset()
2144 2183
2145 2184 # Run user hooks
2146 2185 self.hooks.shutdown_hook()
2147 2186
2148 2187 def cleanup(self):
2149 2188 self.restore_sys_module_state()
2150 2189
2151 2190
2152 2191 class InteractiveShellABC(object):
2153 2192 """An abstract base class for InteractiveShell."""
2154 2193 __metaclass__ = abc.ABCMeta
2155 2194
2156 2195 InteractiveShellABC.register(InteractiveShell)
@@ -1,449 +1,466 b''
1 1 # Standard library imports
2 2 import signal
3 3 import sys
4 4
5 5 # System library imports
6 6 from pygments.lexers import PythonLexer
7 7 from PyQt4 import QtCore, QtGui
8 8
9 9 # Local imports
10 10 from IPython.core.inputsplitter import InputSplitter
11 11 from IPython.frontend.qt.base_frontend_mixin import BaseFrontendMixin
12 12 from IPython.utils.traitlets import Bool
13 13 from bracket_matcher import BracketMatcher
14 14 from call_tip_widget import CallTipWidget
15 15 from completion_lexer import CompletionLexer
16 16 from console_widget import HistoryConsoleWidget
17 17 from pygments_highlighter import PygmentsHighlighter
18 18
19 19
20 20 class FrontendHighlighter(PygmentsHighlighter):
21 21 """ A PygmentsHighlighter that can be turned on and off and that ignores
22 22 prompts.
23 23 """
24 24
25 25 def __init__(self, frontend):
26 26 super(FrontendHighlighter, self).__init__(frontend._control.document())
27 27 self._current_offset = 0
28 28 self._frontend = frontend
29 29 self.highlighting_on = False
30 30
31 31 def highlightBlock(self, qstring):
32 32 """ Highlight a block of text. Reimplemented to highlight selectively.
33 33 """
34 34 if not self.highlighting_on:
35 35 return
36 36
37 37 # The input to this function is unicode string that may contain
38 38 # paragraph break characters, non-breaking spaces, etc. Here we acquire
39 39 # the string as plain text so we can compare it.
40 40 current_block = self.currentBlock()
41 41 string = self._frontend._get_block_plain_text(current_block)
42 42
43 43 # Decide whether to check for the regular or continuation prompt.
44 44 if current_block.contains(self._frontend._prompt_pos):
45 45 prompt = self._frontend._prompt
46 46 else:
47 47 prompt = self._frontend._continuation_prompt
48 48
49 49 # Don't highlight the part of the string that contains the prompt.
50 50 if string.startswith(prompt):
51 51 self._current_offset = len(prompt)
52 52 qstring.remove(0, len(prompt))
53 53 else:
54 54 self._current_offset = 0
55 55
56 56 PygmentsHighlighter.highlightBlock(self, qstring)
57 57
58 58 def rehighlightBlock(self, block):
59 59 """ Reimplemented to temporarily enable highlighting if disabled.
60 60 """
61 61 old = self.highlighting_on
62 62 self.highlighting_on = True
63 63 super(FrontendHighlighter, self).rehighlightBlock(block)
64 64 self.highlighting_on = old
65 65
66 66 def setFormat(self, start, count, format):
67 67 """ Reimplemented to highlight selectively.
68 68 """
69 69 start += self._current_offset
70 70 PygmentsHighlighter.setFormat(self, start, count, format)
71 71
72 72
73 73 class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):
74 74 """ A Qt frontend for a generic Python kernel.
75 75 """
76 76
77 77 # An option and corresponding signal for overriding the default kernel
78 78 # interrupt behavior.
79 79 custom_interrupt = Bool(False)
80 80 custom_interrupt_requested = QtCore.pyqtSignal()
81 81
82 82 # An option and corresponding signals for overriding the default kernel
83 83 # restart behavior.
84 84 custom_restart = Bool(False)
85 85 custom_restart_kernel_died = QtCore.pyqtSignal(float)
86 86 custom_restart_requested = QtCore.pyqtSignal()
87 87
88 88 # Emitted when an 'execute_reply' has been received from the kernel and
89 89 # processed by the FrontendWidget.
90 90 executed = QtCore.pyqtSignal(object)
91 91
92 92 # Protected class variables.
93 93 _input_splitter_class = InputSplitter
94 94
95 95 #---------------------------------------------------------------------------
96 96 # 'object' interface
97 97 #---------------------------------------------------------------------------
98 98
99 99 def __init__(self, *args, **kw):
100 100 super(FrontendWidget, self).__init__(*args, **kw)
101 101
102 102 # FrontendWidget protected variables.
103 103 self._bracket_matcher = BracketMatcher(self._control)
104 104 self._call_tip_widget = CallTipWidget(self._control)
105 105 self._completion_lexer = CompletionLexer(PythonLexer())
106 106 self._hidden = False
107 107 self._highlighter = FrontendHighlighter(self)
108 108 self._input_splitter = self._input_splitter_class(input_mode='block')
109 109 self._kernel_manager = None
110 110 self._possible_kernel_restart = False
111 111
112 112 # Configure the ConsoleWidget.
113 113 self.tab_width = 4
114 114 self._set_continuation_prompt('... ')
115 115
116 116 # Connect signal handlers.
117 117 document = self._control.document()
118 118 document.contentsChange.connect(self._document_contents_change)
119 119
120 120 #---------------------------------------------------------------------------
121 121 # 'ConsoleWidget' abstract interface
122 122 #---------------------------------------------------------------------------
123 123
124 124 def _is_complete(self, source, interactive):
125 125 """ Returns whether 'source' can be completely processed and a new
126 126 prompt created. When triggered by an Enter/Return key press,
127 127 'interactive' is True; otherwise, it is False.
128 128 """
129 129 complete = self._input_splitter.push(source.expandtabs(4))
130 130 if interactive:
131 131 complete = not self._input_splitter.push_accepts_more()
132 132 return complete
133 133
134 def _execute(self, source, hidden):
134 def _execute(self, source, hidden, user_variables=None,
135 user_expressions=None):
135 136 """ Execute 'source'. If 'hidden', do not show any output.
136 """
137 self.kernel_manager.xreq_channel.execute(source, hidden)
137
138 See parent class :meth:`execute` docstring for full details.
139 """
140 # tmp code for testing, disable in real use with 'if 0'. Only delete
141 # this code once we have automated tests for these fields.
142 if 0:
143 user_variables = ['x', 'y', 'z']
144 user_expressions = {'sum' : '1+1',
145 'bad syntax' : 'klsdafj kasd f',
146 'bad call' : 'range("hi")',
147 'time' : 'time.time()',
148 }
149 # /end tmp code
150
151 # FIXME - user_variables/expressions are not visible in API above us.
152 self.kernel_manager.xreq_channel.execute(source, hidden,
153 user_variables,
154 user_expressions)
138 155 self._hidden = hidden
139 156
140 157 def _prompt_started_hook(self):
141 158 """ Called immediately after a new prompt is displayed.
142 159 """
143 160 if not self._reading:
144 161 self._highlighter.highlighting_on = True
145 162
146 163 def _prompt_finished_hook(self):
147 164 """ Called immediately after a prompt is finished, i.e. when some input
148 165 will be processed and a new prompt displayed.
149 166 """
150 167 if not self._reading:
151 168 self._highlighter.highlighting_on = False
152 169
153 170 def _tab_pressed(self):
154 171 """ Called when the tab key is pressed. Returns whether to continue
155 172 processing the event.
156 173 """
157 174 # Perform tab completion if:
158 175 # 1) The cursor is in the input buffer.
159 176 # 2) There is a non-whitespace character before the cursor.
160 177 text = self._get_input_buffer_cursor_line()
161 178 if text is None:
162 179 return False
163 180 complete = bool(text[:self._get_input_buffer_cursor_column()].strip())
164 181 if complete:
165 182 self._complete()
166 183 return not complete
167 184
168 185 #---------------------------------------------------------------------------
169 186 # 'ConsoleWidget' protected interface
170 187 #---------------------------------------------------------------------------
171 188
172 189 def _event_filter_console_keypress(self, event):
173 190 """ Reimplemented to allow execution interruption.
174 191 """
175 192 key = event.key()
176 193 if self._control_key_down(event.modifiers()):
177 194 if key == QtCore.Qt.Key_C and self._executing:
178 195 self.interrupt_kernel()
179 196 return True
180 197 elif key == QtCore.Qt.Key_Period:
181 198 message = 'Are you sure you want to restart the kernel?'
182 199 self.restart_kernel(message)
183 200 return True
184 201 return super(FrontendWidget, self)._event_filter_console_keypress(event)
185 202
186 203 def _insert_continuation_prompt(self, cursor):
187 204 """ Reimplemented for auto-indentation.
188 205 """
189 206 super(FrontendWidget, self)._insert_continuation_prompt(cursor)
190 207 spaces = self._input_splitter.indent_spaces
191 208 cursor.insertText('\t' * (spaces / self.tab_width))
192 209 cursor.insertText(' ' * (spaces % self.tab_width))
193 210
194 211 #---------------------------------------------------------------------------
195 212 # 'BaseFrontendMixin' abstract interface
196 213 #---------------------------------------------------------------------------
197 214
198 215 def _handle_complete_reply(self, rep):
199 216 """ Handle replies for tab completion.
200 217 """
201 218 cursor = self._get_cursor()
202 219 if rep['parent_header']['msg_id'] == self._complete_id and \
203 220 cursor.position() == self._complete_pos:
204 221 text = '.'.join(self._get_context())
205 222 cursor.movePosition(QtGui.QTextCursor.Left, n=len(text))
206 223 self._complete_with_items(cursor, rep['content']['matches'])
207 224
208 225 def _handle_execute_reply(self, msg):
209 226 """ Handles replies for code execution.
210 227 """
211 228 if not self._hidden:
212 229 # Make sure that all output from the SUB channel has been processed
213 230 # before writing a new prompt.
214 231 self.kernel_manager.sub_channel.flush()
215 232
216 233 content = msg['content']
217 234 status = content['status']
218 235 if status == 'ok':
219 236 self._process_execute_ok(msg)
220 237 elif status == 'error':
221 238 self._process_execute_error(msg)
222 239 elif status == 'abort':
223 240 self._process_execute_abort(msg)
224 241
225 242 self._show_interpreter_prompt_for_reply(msg)
226 243 self.executed.emit(msg)
227 244
228 245 def _handle_input_request(self, msg):
229 246 """ Handle requests for raw_input.
230 247 """
231 248 if self._hidden:
232 249 raise RuntimeError('Request for raw input during hidden execution.')
233 250
234 251 # Make sure that all output from the SUB channel has been processed
235 252 # before entering readline mode.
236 253 self.kernel_manager.sub_channel.flush()
237 254
238 255 def callback(line):
239 256 self.kernel_manager.rep_channel.input(line)
240 257 self._readline(msg['content']['prompt'], callback=callback)
241 258
242 259 def _handle_kernel_died(self, since_last_heartbeat):
243 260 """ Handle the kernel's death by asking if the user wants to restart.
244 261 """
245 262 message = 'The kernel heartbeat has been inactive for %.2f ' \
246 263 'seconds. Do you want to restart the kernel? You may ' \
247 264 'first want to check the network connection.' % \
248 265 since_last_heartbeat
249 266 if self.custom_restart:
250 267 self.custom_restart_kernel_died.emit(since_last_heartbeat)
251 268 else:
252 269 self.restart_kernel(message)
253 270
254 271 def _handle_object_info_reply(self, rep):
255 272 """ Handle replies for call tips.
256 273 """
257 274 cursor = self._get_cursor()
258 275 if rep['parent_header']['msg_id'] == self._call_tip_id and \
259 276 cursor.position() == self._call_tip_pos:
260 277 doc = rep['content']['docstring']
261 278 if doc:
262 279 self._call_tip_widget.show_docstring(doc)
263 280
264 281 def _handle_pyout(self, msg):
265 282 """ Handle display hook output.
266 283 """
267 284 if not self._hidden and self._is_from_this_session(msg):
268 285 self._append_plain_text(msg['content']['data'] + '\n')
269 286
270 287 def _handle_stream(self, msg):
271 288 """ Handle stdout, stderr, and stdin.
272 289 """
273 290 if not self._hidden and self._is_from_this_session(msg):
274 291 self._append_plain_text(msg['content']['data'])
275 292 self._control.moveCursor(QtGui.QTextCursor.End)
276 293
277 294 def _started_channels(self):
278 295 """ Called when the KernelManager channels have started listening or
279 296 when the frontend is assigned an already listening KernelManager.
280 297 """
281 298 self._control.clear()
282 299 self._append_plain_text(self._get_banner())
283 300 self._show_interpreter_prompt()
284 301
285 302 def _stopped_channels(self):
286 303 """ Called when the KernelManager channels have stopped listening or
287 304 when a listening KernelManager is removed from the frontend.
288 305 """
289 306 self._executing = self._reading = False
290 307 self._highlighter.highlighting_on = False
291 308
292 309 #---------------------------------------------------------------------------
293 310 # 'FrontendWidget' interface
294 311 #---------------------------------------------------------------------------
295 312
296 313 def execute_file(self, path, hidden=False):
297 314 """ Attempts to execute file with 'path'. If 'hidden', no output is
298 315 shown.
299 316 """
300 317 self.execute('execfile("%s")' % path, hidden=hidden)
301 318
302 319 def interrupt_kernel(self):
303 320 """ Attempts to interrupt the running kernel.
304 321 """
305 322 if self.custom_interrupt:
306 323 self.custom_interrupt_requested.emit()
307 324 elif self.kernel_manager.has_kernel:
308 325 self.kernel_manager.signal_kernel(signal.SIGINT)
309 326 else:
310 327 self._append_plain_text('Kernel process is either remote or '
311 328 'unspecified. Cannot interrupt.\n')
312 329
313 330 def restart_kernel(self, message):
314 331 """ Attempts to restart the running kernel.
315 332 """
316 333 # We want to make sure that if this dialog is already happening, that
317 334 # other signals don't trigger it again. This can happen when the
318 335 # kernel_died heartbeat signal is emitted and the user is slow to
319 336 # respond to the dialog.
320 337 if not self._possible_kernel_restart:
321 338 if self.custom_restart:
322 339 self.custom_restart_requested.emit()
323 340 elif self.kernel_manager.has_kernel:
324 341 # Setting this to True will prevent this logic from happening
325 342 # again until the current pass is completed.
326 343 self._possible_kernel_restart = True
327 344 buttons = QtGui.QMessageBox.Yes | QtGui.QMessageBox.No
328 345 result = QtGui.QMessageBox.question(self, 'Restart kernel?',
329 346 message, buttons)
330 347 if result == QtGui.QMessageBox.Yes:
331 348 try:
332 349 self.kernel_manager.restart_kernel()
333 350 except RuntimeError:
334 351 message = 'Kernel started externally. Cannot restart.\n'
335 352 self._append_plain_text(message)
336 353 else:
337 354 self._stopped_channels()
338 355 self._append_plain_text('Kernel restarting...\n')
339 356 self._show_interpreter_prompt()
340 357 # This might need to be moved to another location?
341 358 self._possible_kernel_restart = False
342 359 else:
343 360 self._append_plain_text('Kernel process is either remote or '
344 361 'unspecified. Cannot restart.\n')
345 362
346 363 #---------------------------------------------------------------------------
347 364 # 'FrontendWidget' protected interface
348 365 #---------------------------------------------------------------------------
349 366
350 367 def _call_tip(self):
351 368 """ Shows a call tip, if appropriate, at the current cursor location.
352 369 """
353 370 # Decide if it makes sense to show a call tip
354 371 cursor = self._get_cursor()
355 372 cursor.movePosition(QtGui.QTextCursor.Left)
356 373 if cursor.document().characterAt(cursor.position()).toAscii() != '(':
357 374 return False
358 375 context = self._get_context(cursor)
359 376 if not context:
360 377 return False
361 378
362 379 # Send the metadata request to the kernel
363 380 name = '.'.join(context)
364 381 self._call_tip_id = self.kernel_manager.xreq_channel.object_info(name)
365 382 self._call_tip_pos = self._get_cursor().position()
366 383 return True
367 384
368 385 def _complete(self):
369 386 """ Performs completion at the current cursor location.
370 387 """
371 388 context = self._get_context()
372 389 if context:
373 390 # Send the completion request to the kernel
374 391 self._complete_id = self.kernel_manager.xreq_channel.complete(
375 392 '.'.join(context), # text
376 393 self._get_input_buffer_cursor_line(), # line
377 394 self._get_input_buffer_cursor_column(), # cursor_pos
378 395 self.input_buffer) # block
379 396 self._complete_pos = self._get_cursor().position()
380 397
381 398 def _get_banner(self):
382 399 """ Gets a banner to display at the beginning of a session.
383 400 """
384 401 banner = 'Python %s on %s\nType "help", "copyright", "credits" or ' \
385 402 '"license" for more information.'
386 403 return banner % (sys.version, sys.platform)
387 404
388 405 def _get_context(self, cursor=None):
389 406 """ Gets the context for the specified cursor (or the current cursor
390 407 if none is specified).
391 408 """
392 409 if cursor is None:
393 410 cursor = self._get_cursor()
394 411 cursor.movePosition(QtGui.QTextCursor.StartOfBlock,
395 412 QtGui.QTextCursor.KeepAnchor)
396 413 text = str(cursor.selection().toPlainText())
397 414 return self._completion_lexer.get_context(text)
398 415
399 416 def _process_execute_abort(self, msg):
400 417 """ Process a reply for an aborted execution request.
401 418 """
402 419 self._append_plain_text("ERROR: execution aborted\n")
403 420
404 421 def _process_execute_error(self, msg):
405 422 """ Process a reply for an execution request that resulted in an error.
406 423 """
407 424 content = msg['content']
408 425 traceback = ''.join(content['traceback'])
409 426 self._append_plain_text(traceback)
410 427
411 428 def _process_execute_ok(self, msg):
412 429 """ Process a reply for a successful execution equest.
413 430 """
414 431 payload = msg['content']['payload']
415 432 for item in payload:
416 433 if not self._process_execute_payload(item):
417 434 warning = 'Received unknown payload of type %s\n'
418 435 self._append_plain_text(warning % repr(item['source']))
419 436
420 437 def _process_execute_payload(self, item):
421 438 """ Process a single payload item from the list of payload items in an
422 439 execution reply. Returns whether the payload was handled.
423 440 """
424 441 # The basic FrontendWidget doesn't handle payloads, as they are a
425 442 # mechanism for going beyond the standard Python interpreter model.
426 443 return False
427 444
428 445 def _show_interpreter_prompt(self):
429 446 """ Shows a prompt for the interpreter.
430 447 """
431 448 self._show_prompt('>>> ')
432 449
433 450 def _show_interpreter_prompt_for_reply(self, msg):
434 451 """ Shows a prompt for the interpreter given an 'execute_reply' message.
435 452 """
436 453 self._show_interpreter_prompt()
437 454
438 455 #------ Signal handlers ----------------------------------------------------
439 456
440 457 def _document_contents_change(self, position, removed, added):
441 458 """ Called whenever the document's content changes. Display a call tip
442 459 if appropriate.
443 460 """
444 461 # Calculate where the cursor should be *after* the change:
445 462 position += added
446 463
447 464 document = self._control.document()
448 465 if position == self._get_cursor().position():
449 466 self._call_tip()
@@ -1,402 +1,408 b''
1 1 """ A FrontendWidget that emulates the interface of the console IPython and
2 2 supports the additional functionality provided by the IPython kernel.
3 3
4 4 TODO: Add support for retrieving the system default editor. Requires code
5 5 paths for Windows (use the registry), Mac OS (use LaunchServices), and
6 6 Linux (use the xdg system).
7 7 """
8 8
9 9 #-----------------------------------------------------------------------------
10 10 # Imports
11 11 #-----------------------------------------------------------------------------
12 12
13 13 # Standard library imports
14 14 from collections import namedtuple
15 15 import re
16 16 from subprocess import Popen
17 17
18 18 # System library imports
19 19 from PyQt4 import QtCore, QtGui
20 20
21 21 # Local imports
22 22 from IPython.core.inputsplitter import IPythonInputSplitter
23 23 from IPython.core.usage import default_banner
24 from IPython.utils import io
24 25 from IPython.utils.traitlets import Bool, Str
25 26 from frontend_widget import FrontendWidget
26 27
27 28 #-----------------------------------------------------------------------------
28 29 # Constants
29 30 #-----------------------------------------------------------------------------
30 31
31 32 # The default light style sheet: black text on a white background.
32 33 default_light_style_sheet = '''
33 34 .error { color: red; }
34 35 .in-prompt { color: navy; }
35 36 .in-prompt-number { font-weight: bold; }
36 37 .out-prompt { color: darkred; }
37 38 .out-prompt-number { font-weight: bold; }
38 39 '''
39 40 default_light_syntax_style = 'default'
40 41
41 42 # The default dark style sheet: white text on a black background.
42 43 default_dark_style_sheet = '''
43 44 QPlainTextEdit, QTextEdit { background-color: black; color: white }
44 45 QFrame { border: 1px solid grey; }
45 46 .error { color: red; }
46 47 .in-prompt { color: lime; }
47 48 .in-prompt-number { color: lime; font-weight: bold; }
48 49 .out-prompt { color: red; }
49 50 .out-prompt-number { color: red; font-weight: bold; }
50 51 '''
51 52 default_dark_syntax_style = 'monokai'
52 53
53 # Default prompts.
54 # Default strings to build and display input and output prompts (and separators
55 # in between)
54 56 default_in_prompt = 'In [<span class="in-prompt-number">%i</span>]: '
55 57 default_out_prompt = 'Out[<span class="out-prompt-number">%i</span>]: '
58 default_input_sep = '\n'
59 default_output_sep = ''
60 default_output_sep2 = ''
56 61
57 62 #-----------------------------------------------------------------------------
58 63 # IPythonWidget class
59 64 #-----------------------------------------------------------------------------
60 65
61 66 class IPythonWidget(FrontendWidget):
62 67 """ A FrontendWidget for an IPython kernel.
63 68 """
64 69
65 70 # If set, the 'custom_edit_requested(str, int)' signal will be emitted when
66 71 # an editor is needed for a file. This overrides 'editor' and 'editor_line'
67 72 # settings.
68 73 custom_edit = Bool(False)
69 74 custom_edit_requested = QtCore.pyqtSignal(object, object)
70 75
71 76 # A command for invoking a system text editor. If the string contains a
72 77 # {filename} format specifier, it will be used. Otherwise, the filename will
73 78 # be appended to the end the command.
74 79 editor = Str('default', config=True)
75 80
76 81 # The editor command to use when a specific line number is requested. The
77 82 # string should contain two format specifiers: {line} and {filename}. If
78 83 # this parameter is not specified, the line number option to the %edit magic
79 84 # will be ignored.
80 85 editor_line = Str(config=True)
81 86
82 87 # A CSS stylesheet. The stylesheet can contain classes for:
83 88 # 1. Qt: QPlainTextEdit, QFrame, QWidget, etc
84 89 # 2. Pygments: .c, .k, .o, etc (see PygmentsHighlighter)
85 90 # 3. IPython: .error, .in-prompt, .out-prompt, etc
86 91 style_sheet = Str(config=True)
87 92
88 93 # If not empty, use this Pygments style for syntax highlighting. Otherwise,
89 94 # the style sheet is queried for Pygments style information.
90 95 syntax_style = Str(config=True)
91 96
92 97 # Prompts.
93 98 in_prompt = Str(default_in_prompt, config=True)
94 99 out_prompt = Str(default_out_prompt, config=True)
100 input_sep = Str(default_input_sep, config=True)
101 output_sep = Str(default_output_sep, config=True)
102 output_sep2 = Str(default_output_sep2, config=True)
95 103
96 104 # FrontendWidget protected class variables.
97 105 _input_splitter_class = IPythonInputSplitter
98 106
99 107 # IPythonWidget protected class variables.
100 108 _PromptBlock = namedtuple('_PromptBlock', ['block', 'length', 'number'])
101 109 _payload_source_edit = 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic'
102 110 _payload_source_page = 'IPython.zmq.page.page'
103 111
104 112 #---------------------------------------------------------------------------
105 113 # 'object' interface
106 114 #---------------------------------------------------------------------------
107 115
108 116 def __init__(self, *args, **kw):
109 117 super(IPythonWidget, self).__init__(*args, **kw)
110 118
111 119 # IPythonWidget protected variables.
112 120 self._previous_prompt_obj = None
113 121
114 122 # Initialize widget styling.
115 123 if self.style_sheet:
116 124 self._style_sheet_changed()
117 125 self._syntax_style_changed()
118 126 else:
119 127 self.set_default_style()
120 128
121 129 #---------------------------------------------------------------------------
122 130 # 'BaseFrontendMixin' abstract interface
123 131 #---------------------------------------------------------------------------
124 132
125 133 def _handle_complete_reply(self, rep):
126 134 """ Reimplemented to support IPython's improved completion machinery.
127 135 """
128 136 cursor = self._get_cursor()
129 137 if rep['parent_header']['msg_id'] == self._complete_id and \
130 138 cursor.position() == self._complete_pos:
131 139 matches = rep['content']['matches']
132 140 text = rep['content']['matched_text']
133 141
134 142 # Clean up matches with '.'s and path separators.
135 143 parts = re.split(r'[./\\]', text)
136 144 sep_count = len(parts) - 1
137 145 if sep_count:
138 146 chop_length = sum(map(len, parts[:sep_count])) + sep_count
139 147 matches = [ match[chop_length:] for match in matches ]
140 148 text = text[chop_length:]
141 149
142 150 # Move the cursor to the start of the match and complete.
143 151 cursor.movePosition(QtGui.QTextCursor.Left, n=len(text))
144 152 self._complete_with_items(cursor, matches)
145 153
146 154 def _handle_history_reply(self, msg):
147 155 """ Implemented to handle history replies, which are only supported by
148 156 the IPython kernel.
149 157 """
150 158 history_dict = msg['content']['history']
151 159 items = [ history_dict[key] for key in sorted(history_dict.keys()) ]
152 160 self._set_history(items)
153 161
154 162 def _handle_prompt_reply(self, msg):
155 163 """ Implemented to handle prompt number replies, which are only
156 164 supported by the IPython kernel.
157 165 """
158 content = msg['content']
159 self._show_interpreter_prompt(content['prompt_number'],
160 content['input_sep'])
166 self._show_interpreter_prompt(msg['content']['execution_count'])
161 167
162 168 def _handle_pyout(self, msg):
163 169 """ Reimplemented for IPython-style "display hook".
164 170 """
165 171 if not self._hidden and self._is_from_this_session(msg):
166 172 content = msg['content']
167 prompt_number = content['prompt_number']
168 self._append_plain_text(content['output_sep'])
173 prompt_number = content['execution_count']
174 self._append_plain_text(self.output_sep)
169 175 self._append_html(self._make_out_prompt(prompt_number))
170 self._append_plain_text(content['data'] + '\n' +
171 content['output_sep2'])
176 self._append_plain_text(content['data']+self.output_sep2)
172 177
173 178 def _started_channels(self):
174 179 """ Reimplemented to make a history request.
175 180 """
176 181 super(IPythonWidget, self)._started_channels()
177 182 # FIXME: Disabled until history requests are properly implemented.
178 183 #self.kernel_manager.xreq_channel.history(raw=True, output=False)
179 184
180 185 #---------------------------------------------------------------------------
181 186 # 'FrontendWidget' interface
182 187 #---------------------------------------------------------------------------
183 188
184 189 def execute_file(self, path, hidden=False):
185 190 """ Reimplemented to use the 'run' magic.
186 191 """
187 192 self.execute('%%run %s' % path, hidden=hidden)
188 193
189 194 #---------------------------------------------------------------------------
190 195 # 'FrontendWidget' protected interface
191 196 #---------------------------------------------------------------------------
192 197
193 198 def _complete(self):
194 199 """ Reimplemented to support IPython's improved completion machinery.
195 200 """
196 201 # We let the kernel split the input line, so we *always* send an empty
197 202 # text field. Readline-based frontends do get a real text field which
198 203 # they can use.
199 204 text = ''
200 205
201 206 # Send the completion request to the kernel
202 207 self._complete_id = self.kernel_manager.xreq_channel.complete(
203 208 text, # text
204 209 self._get_input_buffer_cursor_line(), # line
205 210 self._get_input_buffer_cursor_column(), # cursor_pos
206 211 self.input_buffer) # block
207 212 self._complete_pos = self._get_cursor().position()
208 213
209 214 def _get_banner(self):
210 215 """ Reimplemented to return IPython's default banner.
211 216 """
212 217 return default_banner + '\n'
213 218
214 219 def _process_execute_error(self, msg):
215 220 """ Reimplemented for IPython-style traceback formatting.
216 221 """
217 222 content = msg['content']
218 223 traceback = '\n'.join(content['traceback']) + '\n'
219 224 if False:
220 225 # FIXME: For now, tracebacks come as plain text, so we can't use
221 226 # the html renderer yet. Once we refactor ultratb to produce
222 227 # properly styled tracebacks, this branch should be the default
223 228 traceback = traceback.replace(' ', '&nbsp;')
224 229 traceback = traceback.replace('\n', '<br/>')
225 230
226 231 ename = content['ename']
227 232 ename_styled = '<span class="error">%s</span>' % ename
228 233 traceback = traceback.replace(ename, ename_styled)
229 234
230 235 self._append_html(traceback)
231 236 else:
232 237 # This is the fallback for now, using plain text with ansi escapes
233 238 self._append_plain_text(traceback)
234 239
235 240 def _process_execute_payload(self, item):
236 241 """ Reimplemented to handle %edit and paging payloads.
237 242 """
238 243 if item['source'] == self._payload_source_edit:
239 244 self._edit(item['filename'], item['line_number'])
240 245 return True
241 246 elif item['source'] == self._payload_source_page:
242 247 self._page(item['data'])
243 248 return True
244 249 else:
245 250 return False
246 251
247 def _show_interpreter_prompt(self, number=None, input_sep='\n'):
252 def _show_interpreter_prompt(self, number=None):
248 253 """ Reimplemented for IPython-style prompts.
249 254 """
250 255 # If a number was not specified, make a prompt number request.
251 256 if number is None:
252 self.kernel_manager.xreq_channel.prompt()
253 return
257 # FIXME - fperez: this should be a silent code request
258 number = 1
259 ##self.kernel_manager.xreq_channel.prompt()
260 ##return
254 261
255 262 # Show a new prompt and save information about it so that it can be
256 263 # updated later if the prompt number turns out to be wrong.
257 self._prompt_sep = input_sep
264 self._prompt_sep = self.input_sep
258 265 self._show_prompt(self._make_in_prompt(number), html=True)
259 266 block = self._control.document().lastBlock()
260 267 length = len(self._prompt)
261 268 self._previous_prompt_obj = self._PromptBlock(block, length, number)
262 269
263 270 # Update continuation prompt to reflect (possibly) new prompt length.
264 271 self._set_continuation_prompt(
265 272 self._make_continuation_prompt(self._prompt), html=True)
266 273
267 274 def _show_interpreter_prompt_for_reply(self, msg):
268 275 """ Reimplemented for IPython-style prompts.
269 276 """
270 277 # Update the old prompt number if necessary.
271 278 content = msg['content']
272 previous_prompt_number = content['prompt_number']
279 ##io.rprint('_show_interpreter_prompt_for_reply\n', content) # dbg
280 previous_prompt_number = content['execution_count']
273 281 if self._previous_prompt_obj and \
274 282 self._previous_prompt_obj.number != previous_prompt_number:
275 283 block = self._previous_prompt_obj.block
276 284
277 285 # Make sure the prompt block has not been erased.
278 286 if block.isValid() and not block.text().isEmpty():
279 287
280 288 # Remove the old prompt and insert a new prompt.
281 289 cursor = QtGui.QTextCursor(block)
282 290 cursor.movePosition(QtGui.QTextCursor.Right,
283 291 QtGui.QTextCursor.KeepAnchor,
284 292 self._previous_prompt_obj.length)
285 293 prompt = self._make_in_prompt(previous_prompt_number)
286 294 self._prompt = self._insert_html_fetching_plain_text(
287 295 cursor, prompt)
288 296
289 297 # When the HTML is inserted, Qt blows away the syntax
290 298 # highlighting for the line, so we need to rehighlight it.
291 299 self._highlighter.rehighlightBlock(cursor.block())
292 300
293 301 self._previous_prompt_obj = None
294 302
295 303 # Show a new prompt with the kernel's estimated prompt number.
296 next_prompt = content['next_prompt']
297 self._show_interpreter_prompt(next_prompt['prompt_number'],
298 next_prompt['input_sep'])
304 self._show_interpreter_prompt(previous_prompt_number+1)
299 305
300 306 #---------------------------------------------------------------------------
301 307 # 'IPythonWidget' interface
302 308 #---------------------------------------------------------------------------
303 309
304 310 def set_default_style(self, lightbg=True):
305 311 """ Sets the widget style to the class defaults.
306 312
307 313 Parameters:
308 314 -----------
309 315 lightbg : bool, optional (default True)
310 316 Whether to use the default IPython light background or dark
311 317 background style.
312 318 """
313 319 if lightbg:
314 320 self.style_sheet = default_light_style_sheet
315 321 self.syntax_style = default_light_syntax_style
316 322 else:
317 323 self.style_sheet = default_dark_style_sheet
318 324 self.syntax_style = default_dark_syntax_style
319 325
320 326 #---------------------------------------------------------------------------
321 327 # 'IPythonWidget' protected interface
322 328 #---------------------------------------------------------------------------
323 329
324 330 def _edit(self, filename, line=None):
325 331 """ Opens a Python script for editing.
326 332
327 333 Parameters:
328 334 -----------
329 335 filename : str
330 336 A path to a local system file.
331 337
332 338 line : int, optional
333 339 A line of interest in the file.
334 340 """
335 341 if self.custom_edit:
336 342 self.custom_edit_requested.emit(filename, line)
337 343 elif self.editor == 'default':
338 344 self._append_plain_text('No default editor available.\n')
339 345 else:
340 346 try:
341 347 filename = '"%s"' % filename
342 348 if line and self.editor_line:
343 349 command = self.editor_line.format(filename=filename,
344 350 line=line)
345 351 else:
346 352 try:
347 353 command = self.editor.format()
348 354 except KeyError:
349 355 command = self.editor.format(filename=filename)
350 356 else:
351 357 command += ' ' + filename
352 358 except KeyError:
353 359 self._append_plain_text('Invalid editor command.\n')
354 360 else:
355 361 try:
356 362 Popen(command, shell=True)
357 363 except OSError:
358 364 msg = 'Opening editor with command "%s" failed.\n'
359 365 self._append_plain_text(msg % command)
360 366
361 367 def _make_in_prompt(self, number):
362 368 """ Given a prompt number, returns an HTML In prompt.
363 369 """
364 370 body = self.in_prompt % number
365 371 return '<span class="in-prompt">%s</span>' % body
366 372
367 373 def _make_continuation_prompt(self, prompt):
368 374 """ Given a plain text version of an In prompt, returns an HTML
369 375 continuation prompt.
370 376 """
371 377 end_chars = '...: '
372 378 space_count = len(prompt.lstrip('\n')) - len(end_chars)
373 379 body = '&nbsp;' * space_count + end_chars
374 380 return '<span class="in-prompt">%s</span>' % body
375 381
376 382 def _make_out_prompt(self, number):
377 383 """ Given a prompt number, returns an HTML Out prompt.
378 384 """
379 385 body = self.out_prompt % number
380 386 return '<span class="out-prompt">%s</span>' % body
381 387
382 388 #------ Trait change handlers ---------------------------------------------
383 389
384 390 def _style_sheet_changed(self):
385 391 """ Set the style sheets of the underlying widgets.
386 392 """
387 393 self.setStyleSheet(self.style_sheet)
388 394 self._control.document().setDefaultStyleSheet(self.style_sheet)
389 395 if self._page_control:
390 396 self._page_control.document().setDefaultStyleSheet(self.style_sheet)
391 397
392 398 bg_color = self._control.palette().background().color()
393 399 self._ansi_processor.set_background_color(bg_color)
394 400
395 401 def _syntax_style_changed(self):
396 402 """ Set the style for the syntax highlighter.
397 403 """
398 404 if self.syntax_style:
399 405 self._highlighter.set_style(self.syntax_style)
400 406 else:
401 407 self._highlighter.set_style_sheet(self.style_sheet)
402 408
@@ -1,120 +1,121 b''
1 1 """Common utilities for the various process_* implementations.
2 2
3 3 This file is only meant to be imported by the platform-specific implementations
4 4 of subprocess utilities, and it contains tools that are common to all of them.
5 5 """
6 6
7 7 #-----------------------------------------------------------------------------
8 8 # Copyright (C) 2010 The IPython Development Team
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17 import subprocess
18 18 import sys
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Function definitions
22 22 #-----------------------------------------------------------------------------
23 23
24 24 def read_no_interrupt(p):
25 25 """Read from a pipe ignoring EINTR errors.
26 26
27 27 This is necessary because when reading from pipes with GUI event loops
28 28 running in the background, often interrupts are raised that stop the
29 29 command from completing."""
30 30 import errno
31 31
32 32 try:
33 33 return p.read()
34 34 except IOError, err:
35 35 if err.errno != errno.EINTR:
36 36 raise
37 37
38 38
39 39 def process_handler(cmd, callback, stderr=subprocess.PIPE):
40 40 """Open a command in a shell subprocess and execute a callback.
41 41
42 42 This function provides common scaffolding for creating subprocess.Popen()
43 43 calls. It creates a Popen object and then calls the callback with it.
44 44
45 45 Parameters
46 46 ----------
47 47 cmd : str
48 48 A string to be executed with the underlying system shell (by calling
49 49 :func:`Popen` with ``shell=True``.
50 50
51 51 callback : callable
52 52 A one-argument function that will be called with the Popen object.
53 53
54 54 stderr : file descriptor number, optional
55 55 By default this is set to ``subprocess.PIPE``, but you can also pass the
56 56 value ``subprocess.STDOUT`` to force the subprocess' stderr to go into
57 57 the same file descriptor as its stdout. This is useful to read stdout
58 58 and stderr combined in the order they are generated.
59 59
60 60 Returns
61 61 -------
62 62 The return value of the provided callback is returned.
63 63 """
64 64 sys.stdout.flush()
65 65 sys.stderr.flush()
66 close_fds = False if sys.platform=='win32' else True
66 # On win32, close_fds can't be true when using pipes for stdin/out/err
67 close_fds = sys.platform != 'win32'
67 68 p = subprocess.Popen(cmd, shell=True,
68 69 stdin=subprocess.PIPE,
69 70 stdout=subprocess.PIPE,
70 71 stderr=stderr,
71 72 close_fds=close_fds)
72 73
73 74 try:
74 75 out = callback(p)
75 76 except KeyboardInterrupt:
76 77 print('^C')
77 78 sys.stdout.flush()
78 79 sys.stderr.flush()
79 80 out = None
80 81 finally:
81 82 # Make really sure that we don't leave processes behind, in case the
82 83 # call above raises an exception
83 84 # We start by assuming the subprocess finished (to avoid NameErrors
84 85 # later depending on the path taken)
85 86 if p.returncode is None:
86 87 try:
87 88 p.terminate()
88 89 p.poll()
89 90 except OSError:
90 91 pass
91 92 # One last try on our way out
92 93 if p.returncode is None:
93 94 try:
94 95 p.kill()
95 96 except OSError:
96 97 pass
97 98
98 99 return out
99 100
100 101
101 102 def getoutputerror(cmd):
102 103 """Return (standard output, standard error) of executing cmd in a shell.
103 104
104 105 Accepts the same arguments as os.system().
105 106
106 107 Parameters
107 108 ----------
108 109 cmd : str
109 110 A command to be executed in the system shell.
110 111
111 112 Returns
112 113 -------
113 114 stdout : str
114 115 stderr : str
115 116 """
116 117
117 118 out_err = process_handler(cmd, lambda p: p.communicate())
118 119 if out_err is None:
119 120 out_err = '', ''
120 121 return out_err
@@ -1,44 +1,114 b''
1 from kernelmanager import SubSocketChannel
1 """Implement a fully blocking kernel manager.
2
3 Useful for test suites and blocking terminal interfaces.
4 """
5 #-----------------------------------------------------------------------------
6 # Copyright (C) 2010 The IPython Development Team
7 #
8 # Distributed under the terms of the BSD License. The full license is in
9 # the file COPYING.txt, distributed as part of this software.
10 #-----------------------------------------------------------------------------
11
12 #-----------------------------------------------------------------------------
13 # Imports
14 #-----------------------------------------------------------------------------
15 from __future__ import print_function
16
17 # Stdlib
2 18 from Queue import Queue, Empty
3 19
20 # Our own
21 from IPython.utils import io
22 from IPython.utils.traitlets import Type
4 23
5 class MsgNotReady(Exception):
6 pass
24 from .kernelmanager import (KernelManager, SubSocketChannel,
25 XReqSocketChannel, RepSocketChannel, HBSocketChannel)
7 26
27 #-----------------------------------------------------------------------------
28 # Functions and classes
29 #-----------------------------------------------------------------------------
8 30
9 31 class BlockingSubSocketChannel(SubSocketChannel):
10 32
11 33 def __init__(self, context, session, address=None):
12 34 super(BlockingSubSocketChannel, self).__init__(context, session, address)
13 35 self._in_queue = Queue()
14 36
15 37 def call_handlers(self, msg):
38 io.rprint('[[Sub]]', msg) # dbg
16 39 self._in_queue.put(msg)
17 40
18 41 def msg_ready(self):
19 42 """Is there a message that has been received?"""
20 43 if self._in_queue.qsize() == 0:
21 44 return False
22 45 else:
23 46 return True
24 47
25 48 def get_msg(self, block=True, timeout=None):
26 49 """Get a message if there is one that is ready."""
27 try:
28 msg = self.in_queue.get(block, timeout)
29 except Empty:
30 raise MsgNotReady('No message has been received.')
50 return self.in_queue.get(block, timeout)
51
52 def get_msgs(self):
53 """Get all messages that are currently ready."""
54 msgs = []
55 while True:
56 try:
57 msgs.append(self.get_msg(block=False))
58 except Empty:
59 break
60 return msgs
61
62
63
64 class BlockingXReqSocketChannel(XReqSocketChannel):
65
66 def __init__(self, context, session, address=None):
67 super(BlockingXReqSocketChannel, self).__init__(context, session, address)
68 self._in_queue = Queue()
69
70 def call_handlers(self, msg):
71 io.rprint('[[XReq]]', msg) # dbg
72
73 def msg_ready(self):
74 """Is there a message that has been received?"""
75 if self._in_queue.qsize() == 0:
76 return False
31 77 else:
32 return msg
78 return True
79
80 def get_msg(self, block=True, timeout=None):
81 """Get a message if there is one that is ready."""
82 return self.in_queue.get(block, timeout)
33 83
34 84 def get_msgs(self):
35 85 """Get all messages that are currently ready."""
36 86 msgs = []
37 87 while True:
38 88 try:
39 msg = self.get_msg(block=False)
40 except MsgNotReady:
89 msgs.append(self.get_msg(block=False))
90 except Empty:
41 91 break
42 else:
43 msgs.append(msg)
44 return msgs No newline at end of file
92 return msgs
93
94 class BlockingRepSocketChannel(RepSocketChannel):
95 def call_handlers(self, msg):
96 io.rprint('[[Rep]]', msg) # dbg
97
98
99 class BlockingHBSocketChannel(HBSocketChannel):
100 # This kernel needs rapid monitoring capabilities
101 time_to_dead = 0.2
102
103 def call_handlers(self, since_last_heartbeat):
104 io.rprint('[[Heart]]', since_last_heartbeat) # dbg
105
106
107 class BlockingKernelManager(KernelManager):
108
109 # The classes to use for the various channels.
110 xreq_channel_class = Type(BlockingXReqSocketChannel)
111 sub_channel_class = Type(BlockingSubSocketChannel)
112 rep_channel_class = Type(BlockingRepSocketChannel)
113 hb_channel_class = Type(BlockingHBSocketChannel)
114
@@ -1,462 +1,486 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 sys
21 21 import time
22 22 import traceback
23 23
24 24 # System library imports.
25 25 import zmq
26 26
27 27 # Local imports.
28 28 from IPython.config.configurable import Configurable
29 29 from IPython.utils import io
30 30 from IPython.lib import pylabtools
31 31 from IPython.utils.traitlets import Instance
32 32 from entry_point import base_launch_kernel, make_argument_parser, make_kernel, \
33 33 start_kernel
34 34 from iostream import OutStream
35 35 from session import Session, Message
36 36 from zmqshell import ZMQInteractiveShell
37 37
38
38 39 #-----------------------------------------------------------------------------
39 40 # Main kernel class
40 41 #-----------------------------------------------------------------------------
41 42
42 43 class Kernel(Configurable):
43 44
44 45 #---------------------------------------------------------------------------
45 46 # Kernel interface
46 47 #---------------------------------------------------------------------------
47 48
48 49 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
49 50 session = Instance(Session)
50 51 reply_socket = Instance('zmq.Socket')
51 52 pub_socket = Instance('zmq.Socket')
52 53 req_socket = Instance('zmq.Socket')
53 54
54 55 def __init__(self, **kwargs):
55 56 super(Kernel, self).__init__(**kwargs)
56 57
57 58 # Initialize the InteractiveShell subclass
58 59 self.shell = ZMQInteractiveShell.instance()
59 60 self.shell.displayhook.session = self.session
60 61 self.shell.displayhook.pub_socket = self.pub_socket
61 62
62 63 # TMP - hack while developing
63 64 self.shell._reply_content = None
64 65
65 66 # Build dict of handlers for message types
66 67 msg_types = [ 'execute_request', 'complete_request',
67 'object_info_request', 'prompt_request',
68 'history_request' ]
68 'object_info_request', 'history_request' ]
69 69 self.handlers = {}
70 70 for msg_type in msg_types:
71 71 self.handlers[msg_type] = getattr(self, msg_type)
72 72
73 73 def do_one_iteration(self):
74 74 try:
75 75 ident = self.reply_socket.recv(zmq.NOBLOCK)
76 76 except zmq.ZMQError, e:
77 77 if e.errno == zmq.EAGAIN:
78 78 return
79 79 else:
80 80 raise
81 81 # FIXME: Bug in pyzmq/zmq?
82 82 # assert self.reply_socket.rcvmore(), "Missing message part."
83 83 msg = self.reply_socket.recv_json()
84 omsg = Message(msg)
85 io.raw_print('\n')
86 io.raw_print(omsg)
87 handler = self.handlers.get(omsg.msg_type, None)
84
85 # Print some info about this message and leave a '--->' marker, so it's
86 # easier to trace visually the message chain when debugging. Each
87 # handler prints its message at the end.
88 # Eventually we'll move these from stdout to a logger.
89 io.raw_print('\n*** MESSAGE TYPE:', msg['msg_type'], '***')
90 io.raw_print(' Content: ', msg['content'],
91 '\n --->\n ', sep='', end='')
92
93 # Find and call actual handler for message
94 handler = self.handlers.get(msg['msg_type'], None)
88 95 if handler is None:
89 io.raw_print_err("UNKNOWN MESSAGE TYPE:", omsg)
96 io.raw_print_err("UNKNOWN MESSAGE TYPE:", msg)
90 97 else:
91 handler(ident, omsg)
98 handler(ident, msg)
92 99
93 100 def start(self):
94 101 """ Start the kernel main loop.
95 102 """
96 103 while True:
97 104 time.sleep(0.05)
98 105 self.do_one_iteration()
99 106
100
101 107 #---------------------------------------------------------------------------
102 108 # Kernel request handlers
103 109 #---------------------------------------------------------------------------
104 110
111 def _publish_pyin(self, code, parent):
112 """Publish the code request on the pyin stream."""
113
114 pyin_msg = self.session.msg(u'pyin',{u'code':code}, parent=parent)
115 self.pub_socket.send_json(pyin_msg)
116
105 117 def execute_request(self, ident, parent):
106 118 try:
107 code = parent[u'content'][u'code']
119 content = parent[u'content']
120 code = content[u'code']
121 silent = content[u'silent']
108 122 except:
109 123 io.raw_print_err("Got bad msg: ")
110 124 io.raw_print_err(Message(parent))
111 125 return
112 pyin_msg = self.session.msg(u'pyin',{u'code':code}, parent=parent)
113 self.pub_socket.send_json(pyin_msg)
114 126
127 shell = self.shell # we'll need this a lot here
128
129 # Replace raw_input. Note that is not sufficient to replace
130 # raw_input in the user namespace.
131 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
132 __builtin__.raw_input = raw_input
133
134 # Set the parent message of the display hook and out streams.
135 shell.displayhook.set_parent(parent)
136 sys.stdout.set_parent(parent)
137 sys.stderr.set_parent(parent)
138
139 # Re-broadcast our input for the benefit of listening clients, and
140 # start computing output
141 if not silent:
142 self._publish_pyin(code, parent)
143
144 reply_content = {}
115 145 try:
116 # Replace raw_input. Note that is not sufficient to replace
117 # raw_input in the user namespace.
118 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
119 __builtin__.raw_input = raw_input
120
121 # Set the parent message of the display hook and out streams.
122 self.shell.displayhook.set_parent(parent)
123 sys.stdout.set_parent(parent)
124 sys.stderr.set_parent(parent)
125
126 # FIXME: runlines calls the exception handler itself. We should
127 # clean this up.
128 self.shell._reply_content = None
129 self.shell.runlines(code)
146 if silent:
147 # runcode uses 'exec' mode, so no displayhook will fire, and it
148 # doesn't call logging or history manipulations. Print
149 # statements in that code will obviously still execute.
150 shell.runcode(code)
151 else:
152 # FIXME: runlines calls the exception handler itself.
153 shell._reply_content = None
154 shell.runlines(code)
130 155 except:
156 status = u'error'
131 157 # FIXME: this code right now isn't being used yet by default,
132 158 # because the runlines() call above directly fires off exception
133 159 # reporting. This code, therefore, is only active in the scenario
134 160 # where runlines itself has an unhandled exception. We need to
135 161 # uniformize this, for all exception construction to come from a
136 162 # single location in the codbase.
137 163 etype, evalue, tb = sys.exc_info()
138 164 tb_list = traceback.format_exception(etype, evalue, tb)
139 reply_content = self.shell._showtraceback(etype, evalue, tb_list)
165 reply_content.update(shell._showtraceback(etype, evalue, tb_list))
140 166 else:
141 payload = self.shell.payload_manager.read_payload()
167 status = u'ok'
168 reply_content[u'payload'] = shell.payload_manager.read_payload()
142 169 # Be agressive about clearing the payload because we don't want
143 170 # it to sit in memory until the next execute_request comes in.
144 self.shell.payload_manager.clear_payload()
145 reply_content = { 'status' : 'ok', 'payload' : payload }
146
147 # Compute the prompt information
148 prompt_number = self.shell.displayhook.prompt_count
149 reply_content['prompt_number'] = prompt_number
150 prompt_string = self.shell.displayhook.prompt1.peek_next_prompt()
151 next_prompt = {'prompt_string' : prompt_string,
152 'prompt_number' : prompt_number+1,
153 'input_sep' : self.shell.displayhook.input_sep}
154 reply_content['next_prompt'] = next_prompt
155
156 # TMP - fish exception info out of shell, possibly left there by
157 # runlines
158 if self.shell._reply_content is not None:
159 reply_content.update(self.shell._reply_content)
160
161 # Flush output before sending the reply.
162 sys.stderr.flush()
163 sys.stdout.flush()
164
171 shell.payload_manager.clear_payload()
172
173 reply_content[u'status'] = status
174 # Compute the execution counter so clients can display prompts
175 reply_content['execution_count'] = shell.displayhook.prompt_count
176
177 # FIXME - fish exception info out of shell, possibly left there by
178 # runlines. We'll need to clean up this logic later.
179 if shell._reply_content is not None:
180 reply_content.update(shell._reply_content)
181
182 # At this point, we can tell whether the main code execution succeeded
183 # or not. If it did, we proceed to evaluate user_variables/expressions
184 if reply_content['status'] == 'ok':
185 reply_content[u'user_variables'] = \
186 shell.get_user_variables(content[u'user_variables'])
187 reply_content[u'user_expressions'] = \
188 shell.eval_expressions(content[u'user_expressions'])
189 else:
190 # If there was an error, don't even try to compute variables or
191 # expressions
192 reply_content[u'user_variables'] = {}
193 reply_content[u'user_expressions'] = {}
194
165 195 # Send the reply.
166 196 reply_msg = self.session.msg(u'execute_reply', reply_content, parent)
167 io.raw_print(Message(reply_msg))
197 io.raw_print(reply_msg)
168 198 self.reply_socket.send(ident, zmq.SNDMORE)
169 199 self.reply_socket.send_json(reply_msg)
170 200 if reply_msg['content']['status'] == u'error':
171 201 self._abort_queue()
172 202
173 203 def complete_request(self, ident, parent):
174 204 txt, matches = self._complete(parent)
175 205 matches = {'matches' : matches,
176 206 'matched_text' : txt,
177 207 'status' : 'ok'}
178 208 completion_msg = self.session.send(self.reply_socket, 'complete_reply',
179 209 matches, parent, ident)
180 210 io.raw_print(completion_msg)
181 211
182 212 def object_info_request(self, ident, parent):
183 213 context = parent['content']['oname'].split('.')
184 214 object_info = self._object_info(context)
185 215 msg = self.session.send(self.reply_socket, 'object_info_reply',
186 216 object_info, parent, ident)
187 217 io.raw_print(msg)
188 218
189 def prompt_request(self, ident, parent):
190 prompt_number = self.shell.displayhook.prompt_count
191 prompt_string = self.shell.displayhook.prompt1.peek_next_prompt()
192 content = {'prompt_string' : prompt_string,
193 'prompt_number' : prompt_number+1,
194 'input_sep' : self.shell.displayhook.input_sep}
195 msg = self.session.send(self.reply_socket, 'prompt_reply',
196 content, parent, ident)
197 io.raw_print(msg)
198
199 219 def history_request(self, ident, parent):
200 220 output = parent['content']['output']
201 221 index = parent['content']['index']
202 222 raw = parent['content']['raw']
203 223 hist = self.shell.get_history(index=index, raw=raw, output=output)
204 224 content = {'history' : hist}
205 225 msg = self.session.send(self.reply_socket, 'history_reply',
206 226 content, parent, ident)
207 227 io.raw_print(msg)
208 228
209 229 #---------------------------------------------------------------------------
210 230 # Protected interface
211 231 #---------------------------------------------------------------------------
212 232
213 233 def _abort_queue(self):
214 234 while True:
215 235 try:
216 236 ident = self.reply_socket.recv(zmq.NOBLOCK)
217 237 except zmq.ZMQError, e:
218 238 if e.errno == zmq.EAGAIN:
219 239 break
220 240 else:
221 assert self.reply_socket.rcvmore(), "Unexpected missing message part."
241 assert self.reply_socket.rcvmore(), \
242 "Unexpected missing message part."
222 243 msg = self.reply_socket.recv_json()
223 244 io.raw_print("Aborting:\n", Message(msg))
224 245 msg_type = msg['msg_type']
225 246 reply_type = msg_type.split('_')[0] + '_reply'
226 247 reply_msg = self.session.msg(reply_type, {'status' : 'aborted'}, msg)
227 io.raw_print(Message(reply_msg))
248 io.raw_print(reply_msg)
228 249 self.reply_socket.send(ident,zmq.SNDMORE)
229 250 self.reply_socket.send_json(reply_msg)
230 251 # We need to wait a bit for requests to come in. This can probably
231 252 # be set shorter for true asynchronous clients.
232 253 time.sleep(0.1)
233 254
234 255 def _raw_input(self, prompt, ident, parent):
235 256 # Flush output before making the request.
236 257 sys.stderr.flush()
237 258 sys.stdout.flush()
238 259
239 260 # Send the input request.
240 261 content = dict(prompt=prompt)
241 262 msg = self.session.msg(u'input_request', content, parent)
242 263 self.req_socket.send_json(msg)
243 264
244 265 # Await a response.
245 266 reply = self.req_socket.recv_json()
246 267 try:
247 268 value = reply['content']['value']
248 269 except:
249 270 io.raw_print_err("Got bad raw_input reply: ")
250 271 io.raw_print_err(Message(parent))
251 272 value = ''
252 273 return value
253 274
254 275 def _complete(self, msg):
255 276 c = msg['content']
256 277 try:
257 278 cpos = int(c['cursor_pos'])
258 279 except:
259 280 # If we don't get something that we can convert to an integer, at
260 281 # least attempt the completion guessing the cursor is at the end of
261 282 # the text, if there's any, and otherwise of the line
262 283 cpos = len(c['text'])
263 284 if cpos==0:
264 285 cpos = len(c['line'])
265 286 return self.shell.complete(c['text'], c['line'], cpos)
266 287
267 288 def _object_info(self, context):
268 289 symbol, leftover = self._symbol_from_context(context)
269 290 if symbol is not None and not leftover:
270 291 doc = getattr(symbol, '__doc__', '')
271 292 else:
272 293 doc = ''
273 294 object_info = dict(docstring = doc)
274 295 return object_info
275 296
276 297 def _symbol_from_context(self, context):
277 298 if not context:
278 299 return None, context
279 300
280 301 base_symbol_string = context[0]
281 302 symbol = self.shell.user_ns.get(base_symbol_string, None)
282 303 if symbol is None:
283 304 symbol = __builtin__.__dict__.get(base_symbol_string, None)
284 305 if symbol is None:
285 306 return None, context
286 307
287 308 context = context[1:]
288 309 for i, name in enumerate(context):
289 310 new_symbol = getattr(symbol, name, None)
290 311 if new_symbol is None:
291 312 return symbol, context[i:]
292 313 else:
293 314 symbol = new_symbol
294 315
295 316 return symbol, []
296 317
297 318
298 319 class QtKernel(Kernel):
299 320 """A Kernel subclass with Qt support."""
300 321
301 322 def start(self):
302 323 """Start a kernel with QtPy4 event loop integration."""
303 324
304 325 from PyQt4 import QtGui, QtCore
305 326 from IPython.lib.guisupport import (
306 327 get_app_qt4, start_event_loop_qt4
307 328 )
308 329 self.app = get_app_qt4([" "])
309 330 self.app.setQuitOnLastWindowClosed(False)
310 331 self.timer = QtCore.QTimer()
311 332 self.timer.timeout.connect(self.do_one_iteration)
312 333 self.timer.start(50)
313 334 start_event_loop_qt4(self.app)
314 335
336
315 337 class WxKernel(Kernel):
316 338 """A Kernel subclass with Wx support."""
317 339
318 340 def start(self):
319 341 """Start a kernel with wx event loop support."""
320 342
321 343 import wx
322 344 from IPython.lib.guisupport import start_event_loop_wx
323 345 doi = self.do_one_iteration
324 346
325 347 # We have to put the wx.Timer in a wx.Frame for it to fire properly.
326 348 # We make the Frame hidden when we create it in the main app below.
327 349 class TimerFrame(wx.Frame):
328 350 def __init__(self, func):
329 351 wx.Frame.__init__(self, None, -1)
330 352 self.timer = wx.Timer(self)
331 353 self.timer.Start(50)
332 354 self.Bind(wx.EVT_TIMER, self.on_timer)
333 355 self.func = func
334 356 def on_timer(self, event):
335 357 self.func()
336 358
337 359 # We need a custom wx.App to create our Frame subclass that has the
338 360 # wx.Timer to drive the ZMQ event loop.
339 361 class IPWxApp(wx.App):
340 362 def OnInit(self):
341 363 self.frame = TimerFrame(doi)
342 364 self.frame.Show(False)
343 365 return True
344 366
345 367 # The redirect=False here makes sure that wx doesn't replace
346 368 # sys.stdout/stderr with its own classes.
347 369 self.app = IPWxApp(redirect=False)
348 370 start_event_loop_wx(self.app)
349 371
350 372
351 373 class TkKernel(Kernel):
352 374 """A Kernel subclass with Tk support."""
353 375
354 376 def start(self):
355 377 """Start a Tk enabled event loop."""
356 378
357 379 import Tkinter
358 380 doi = self.do_one_iteration
359 381
360 382 # For Tkinter, we create a Tk object and call its withdraw method.
361 383 class Timer(object):
362 384 def __init__(self, func):
363 385 self.app = Tkinter.Tk()
364 386 self.app.withdraw()
365 387 self.func = func
366 388 def on_timer(self):
367 389 self.func()
368 390 self.app.after(50, self.on_timer)
369 391 def start(self):
370 392 self.on_timer() # Call it once to get things going.
371 393 self.app.mainloop()
372 394
373 395 self.timer = Timer(doi)
374 396 self.timer.start()
375 397
376 398 #-----------------------------------------------------------------------------
377 399 # Kernel main and launch functions
378 400 #-----------------------------------------------------------------------------
379 401
380 402 def launch_kernel(xrep_port=0, pub_port=0, req_port=0, hb_port=0,
381 403 independent=False, pylab=False):
382 404 """ Launches a localhost kernel, binding to the specified ports.
383 405
384 406 Parameters
385 407 ----------
386 408 xrep_port : int, optional
387 409 The port to use for XREP channel.
388 410
389 411 pub_port : int, optional
390 412 The port to use for the SUB channel.
391 413
392 414 req_port : int, optional
393 415 The port to use for the REQ (raw input) channel.
394 416
395 417 hb_port : int, optional
396 418 The port to use for the hearbeat REP channel.
397 419
398 420 independent : bool, optional (default False)
399 421 If set, the kernel process is guaranteed to survive if this process
400 422 dies. If not set, an effort is made to ensure that the kernel is killed
401 423 when this process dies. Note that in this case it is still good practice
402 424 to kill kernels manually before exiting.
403 425
404 426 pylab : bool or string, optional (default False)
405 427 If not False, the kernel will be launched with pylab enabled. If a
406 428 string is passed, matplotlib will use the specified backend. Otherwise,
407 429 matplotlib's default backend will be used.
408 430
409 431 Returns
410 432 -------
411 433 A tuple of form:
412 434 (kernel_process, xrep_port, pub_port, req_port)
413 435 where kernel_process is a Popen object and the ports are integers.
414 436 """
415 437 extra_arguments = []
416 438 if pylab:
417 439 extra_arguments.append('--pylab')
418 440 if isinstance(pylab, basestring):
419 441 extra_arguments.append(pylab)
420 442 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
421 443 xrep_port, pub_port, req_port, hb_port,
422 444 independent, extra_arguments)
423 445
446
424 447 def main():
425 448 """ The IPython kernel main entry point.
426 449 """
427 450 parser = make_argument_parser()
428 451 parser.add_argument('--pylab', type=str, metavar='GUI', nargs='?',
429 452 const='auto', help = \
430 453 "Pre-load matplotlib and numpy for interactive use. If GUI is not \
431 454 given, the GUI backend is matplotlib's, otherwise use one of: \
432 455 ['tk', 'gtk', 'qt', 'wx', 'payload-svg'].")
433 456 namespace = parser.parse_args()
434 457
435 458 kernel_class = Kernel
436 459
437 460 _kernel_classes = {
438 461 'qt' : QtKernel,
439 462 'qt4' : QtKernel,
440 463 'payload-svg': Kernel,
441 464 'wx' : WxKernel,
442 465 'tk' : TkKernel
443 466 }
444 467 if namespace.pylab:
445 468 if namespace.pylab == 'auto':
446 469 gui, backend = pylabtools.find_gui_and_backend()
447 470 else:
448 471 gui, backend = pylabtools.find_gui_and_backend(namespace.pylab)
449 472 kernel_class = _kernel_classes.get(gui)
450 473 if kernel_class is None:
451 474 raise ValueError('GUI is not supported: %r' % gui)
452 475 pylabtools.activate_matplotlib(backend)
453 476
454 477 kernel = make_kernel(namespace, kernel_class, OutStream)
455 478
456 479 if namespace.pylab:
457 480 pylabtools.import_pylab(kernel.shell.user_ns)
458 481
459 482 start_kernel(namespace, kernel)
460 483
484
461 485 if __name__ == '__main__':
462 486 main()
@@ -1,729 +1,786 b''
1 1 """Base classes to manage the interaction with a running kernel.
2 2
3 3 Todo
4 4 ====
5 5
6 6 * Create logger to handle debugging and console messages.
7 7 """
8 8
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (C) 2008-2010 The IPython Development Team
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #-----------------------------------------------------------------------------
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Imports
18 18 #-----------------------------------------------------------------------------
19 19
20 20 # Standard library imports.
21 21 from Queue import Queue, Empty
22 22 from subprocess import Popen
23 23 from threading import Thread
24 24 import time
25 25
26 26 # System library imports.
27 27 import zmq
28 28 from zmq import POLLIN, POLLOUT, POLLERR
29 29 from zmq.eventloop import ioloop
30 30
31 31 # Local imports.
32 from IPython.utils import io
32 33 from IPython.utils.traitlets import HasTraits, Any, Instance, Type, TCPAddress
33 34 from session import Session
34 35
35 36 #-----------------------------------------------------------------------------
36 37 # Constants and exceptions
37 38 #-----------------------------------------------------------------------------
38 39
39 40 LOCALHOST = '127.0.0.1'
40 41
41 42 class InvalidPortNumber(Exception):
42 43 pass
43 44
44 45 #-----------------------------------------------------------------------------
46 # Utility functions
47 #-----------------------------------------------------------------------------
48
49 # some utilities to validate message structure, these might get moved elsewhere
50 # if they prove to have more generic utility
51
52 def validate_string_list(lst):
53 """Validate that the input is a list of strings.
54
55 Raises ValueError if not."""
56 if not isinstance(lst, list):
57 raise ValueError('input %r must be a list' % lst)
58 for x in lst:
59 if not isinstance(x, basestring):
60 raise ValueError('element %r in list must be a string' % x)
61
62
63 def validate_string_dict(dct):
64 """Validate that the input is a dict with string keys and values.
65
66 Raises ValueError if not."""
67 for k,v in dct.iteritems():
68 if not isinstance(k, basestring):
69 raise ValueError('key %r in dict must be a string' % k)
70 if not isinstance(v, basestring):
71 raise ValueError('value %r in dict must be a string' % v)
72
73
74 #-----------------------------------------------------------------------------
45 75 # ZMQ Socket Channel classes
46 76 #-----------------------------------------------------------------------------
47 77
48 78 class ZmqSocketChannel(Thread):
49 79 """The base class for the channels that use ZMQ sockets.
50 80 """
51 81 context = None
52 82 session = None
53 83 socket = None
54 84 ioloop = None
55 85 iostate = None
56 86 _address = None
57 87
58 88 def __init__(self, context, session, address):
59 89 """Create a channel
60 90
61 91 Parameters
62 92 ----------
63 93 context : :class:`zmq.Context`
64 94 The ZMQ context to use.
65 95 session : :class:`session.Session`
66 96 The session to use.
67 97 address : tuple
68 98 Standard (ip, port) tuple that the kernel is listening on.
69 99 """
70 100 super(ZmqSocketChannel, self).__init__()
71 101 self.daemon = True
72 102
73 103 self.context = context
74 104 self.session = session
75 105 if address[1] == 0:
76 106 message = 'The port number for a channel cannot be 0.'
77 107 raise InvalidPortNumber(message)
78 108 self._address = address
79 109
80 110 def stop(self):
81 111 """Stop the channel's activity.
82 112
83 113 This calls :method:`Thread.join` and returns when the thread
84 114 terminates. :class:`RuntimeError` will be raised if
85 115 :method:`self.start` is called again.
86 116 """
87 117 self.join()
88 118
89 119 @property
90 120 def address(self):
91 121 """Get the channel's address as an (ip, port) tuple.
92 122
93 123 By the default, the address is (localhost, 0), where 0 means a random
94 124 port.
95 125 """
96 126 return self._address
97 127
98 128 def add_io_state(self, state):
99 129 """Add IO state to the eventloop.
100 130
101 131 Parameters
102 132 ----------
103 133 state : zmq.POLLIN|zmq.POLLOUT|zmq.POLLERR
104 134 The IO state flag to set.
105 135
106 136 This is thread safe as it uses the thread safe IOLoop.add_callback.
107 137 """
108 138 def add_io_state_callback():
109 139 if not self.iostate & state:
110 140 self.iostate = self.iostate | state
111 141 self.ioloop.update_handler(self.socket, self.iostate)
112 142 self.ioloop.add_callback(add_io_state_callback)
113 143
114 144 def drop_io_state(self, state):
115 145 """Drop IO state from the eventloop.
116 146
117 147 Parameters
118 148 ----------
119 149 state : zmq.POLLIN|zmq.POLLOUT|zmq.POLLERR
120 150 The IO state flag to set.
121 151
122 152 This is thread safe as it uses the thread safe IOLoop.add_callback.
123 153 """
124 154 def drop_io_state_callback():
125 155 if self.iostate & state:
126 156 self.iostate = self.iostate & (~state)
127 157 self.ioloop.update_handler(self.socket, self.iostate)
128 158 self.ioloop.add_callback(drop_io_state_callback)
129 159
130 160
131 161 class XReqSocketChannel(ZmqSocketChannel):
132 162 """The XREQ channel for issues request/replies to the kernel.
133 163 """
134 164
135 165 command_queue = None
136 166
137 167 def __init__(self, context, session, address):
138 168 self.command_queue = Queue()
139 169 super(XReqSocketChannel, self).__init__(context, session, address)
140 170
141 171 def run(self):
142 172 """The thread's main activity. Call start() instead."""
143 173 self.socket = self.context.socket(zmq.XREQ)
144 174 self.socket.setsockopt(zmq.IDENTITY, self.session.session)
145 175 self.socket.connect('tcp://%s:%i' % self.address)
146 176 self.ioloop = ioloop.IOLoop()
147 177 self.iostate = POLLERR|POLLIN
148 178 self.ioloop.add_handler(self.socket, self._handle_events,
149 179 self.iostate)
150 180 self.ioloop.start()
151 181
152 182 def stop(self):
153 183 self.ioloop.stop()
154 184 super(XReqSocketChannel, self).stop()
155 185
156 186 def call_handlers(self, msg):
157 187 """This method is called in the ioloop thread when a message arrives.
158 188
159 189 Subclasses should override this method to handle incoming messages.
160 190 It is important to remember that this method is called in the thread
161 191 so that some logic must be done to ensure that the application leve
162 192 handlers are called in the application thread.
163 193 """
164 194 raise NotImplementedError('call_handlers must be defined in a subclass.')
165 195
166 def execute(self, code, silent=False):
196 def execute(self, code, silent=False,
197 user_variables=None, user_expressions=None):
167 198 """Execute code in the kernel.
168 199
169 200 Parameters
170 201 ----------
171 202 code : str
172 203 A string of Python code.
204
173 205 silent : bool, optional (default False)
174 206 If set, the kernel will execute the code as quietly possible.
175 207
208 user_variables : list, optional
209
210 A list of variable names to pull from the user's namespace. They
211 will come back as a dict with these names as keys and their
212 :func:`repr` as values.
213
214 user_expressions : dict, optional
215 A dict with string keys and to pull from the user's
216 namespace. They will come back as a dict with these names as keys
217 and their :func:`repr` as values.
218
176 219 Returns
177 220 -------
178 221 The msg_id of the message sent.
179 222 """
223 if user_variables is None:
224 user_variables = []
225 if user_expressions is None:
226 user_expressions = {}
227
228 # Don't waste network traffic if inputs are invalid
229 if not isinstance(code, basestring):
230 raise ValueError('code %r must be a string' % code)
231 validate_string_list(user_variables)
232 validate_string_dict(user_expressions)
233
180 234 # Create class for content/msg creation. Related to, but possibly
181 235 # not in Session.
182 content = dict(code=code, silent=silent)
236 content = dict(code=code, silent=silent,
237 user_variables=user_variables,
238 user_expressions=user_expressions)
183 239 msg = self.session.msg('execute_request', content)
184 240 self._queue_request(msg)
185 241 return msg['header']['msg_id']
186 242
187 243 def complete(self, text, line, cursor_pos, block=None):
188 244 """Tab complete text in the kernel's namespace.
189 245
190 246 Parameters
191 247 ----------
192 248 text : str
193 249 The text to complete.
194 250 line : str
195 251 The full line of text that is the surrounding context for the
196 252 text to complete.
197 253 cursor_pos : int
198 254 The position of the cursor in the line where the completion was
199 255 requested.
200 256 block : str, optional
201 257 The full block of code in which the completion is being requested.
202 258
203 259 Returns
204 260 -------
205 261 The msg_id of the message sent.
206 262 """
207 263 content = dict(text=text, line=line, block=block, cursor_pos=cursor_pos)
208 264 msg = self.session.msg('complete_request', content)
209 265 self._queue_request(msg)
210 266 return msg['header']['msg_id']
211 267
212 268 def object_info(self, oname):
213 269 """Get metadata information about an object.
214 270
215 271 Parameters
216 272 ----------
217 273 oname : str
218 274 A string specifying the object name.
219 275
220 276 Returns
221 277 -------
222 278 The msg_id of the message sent.
223 279 """
224 280 content = dict(oname=oname)
225 281 msg = self.session.msg('object_info_request', content)
226 282 self._queue_request(msg)
227 283 return msg['header']['msg_id']
228 284
229 285 def history(self, index=None, raw=False, output=True):
230 286 """Get the history list.
231 287
232 288 Parameters
233 289 ----------
234 290 index : n or (n1, n2) or None
235 291 If n, then the last entries. If a tuple, then all in
236 292 range(n1, n2). If None, then all entries. Raises IndexError if
237 293 the format of index is incorrect.
238 294 raw : bool
239 295 If True, return the raw input.
240 296 output : bool
241 297 If True, then return the output as well.
242 298
243 299 Returns
244 300 -------
245 301 The msg_id of the message sent.
246 302 """
247 303 content = dict(index=index, raw=raw, output=output)
248 304 msg = self.session.msg('history_request', content)
249 305 self._queue_request(msg)
250 306 return msg['header']['msg_id']
251 307
252 def prompt(self):
253 """Requests a prompt number from the kernel.
254
255 Returns
256 -------
257 The msg_id of the message sent.
258 """
259 msg = self.session.msg('prompt_request')
260 self._queue_request(msg)
261 return msg['header']['msg_id']
262
263 308 def _handle_events(self, socket, events):
264 309 if events & POLLERR:
265 310 self._handle_err()
266 311 if events & POLLOUT:
267 312 self._handle_send()
268 313 if events & POLLIN:
269 314 self._handle_recv()
270 315
271 316 def _handle_recv(self):
272 317 msg = self.socket.recv_json()
273 318 self.call_handlers(msg)
274 319
275 320 def _handle_send(self):
276 321 try:
277 322 msg = self.command_queue.get(False)
278 323 except Empty:
279 324 pass
280 325 else:
281 326 self.socket.send_json(msg)
282 327 if self.command_queue.empty():
283 328 self.drop_io_state(POLLOUT)
284 329
285 330 def _handle_err(self):
286 331 # We don't want to let this go silently, so eventually we should log.
287 332 raise zmq.ZMQError()
288 333
289 334 def _queue_request(self, msg):
290 335 self.command_queue.put(msg)
291 336 self.add_io_state(POLLOUT)
292 337
293 338
294 339 class SubSocketChannel(ZmqSocketChannel):
295 340 """The SUB channel which listens for messages that the kernel publishes.
296 341 """
297 342
298 343 def __init__(self, context, session, address):
299 344 super(SubSocketChannel, self).__init__(context, session, address)
300 345
301 346 def run(self):
302 347 """The thread's main activity. Call start() instead."""
303 348 self.socket = self.context.socket(zmq.SUB)
304 349 self.socket.setsockopt(zmq.SUBSCRIBE,'')
305 350 self.socket.setsockopt(zmq.IDENTITY, self.session.session)
306 351 self.socket.connect('tcp://%s:%i' % self.address)
307 352 self.ioloop = ioloop.IOLoop()
308 353 self.iostate = POLLIN|POLLERR
309 354 self.ioloop.add_handler(self.socket, self._handle_events,
310 355 self.iostate)
311 356 self.ioloop.start()
312 357
313 358 def stop(self):
314 359 self.ioloop.stop()
315 360 super(SubSocketChannel, self).stop()
316 361
317 362 def call_handlers(self, msg):
318 363 """This method is called in the ioloop thread when a message arrives.
319 364
320 365 Subclasses should override this method to handle incoming messages.
321 366 It is important to remember that this method is called in the thread
322 367 so that some logic must be done to ensure that the application leve
323 368 handlers are called in the application thread.
324 369 """
325 370 raise NotImplementedError('call_handlers must be defined in a subclass.')
326 371
327 372 def flush(self, timeout=1.0):
328 373 """Immediately processes all pending messages on the SUB channel.
329 374
330 375 Callers should use this method to ensure that :method:`call_handlers`
331 376 has been called for all messages that have been received on the
332 377 0MQ SUB socket of this channel.
333 378
334 379 This method is thread safe.
335 380
336 381 Parameters
337 382 ----------
338 383 timeout : float, optional
339 384 The maximum amount of time to spend flushing, in seconds. The
340 385 default is one second.
341 386 """
342 387 # We do the IOLoop callback process twice to ensure that the IOLoop
343 388 # gets to perform at least one full poll.
344 389 stop_time = time.time() + timeout
345 390 for i in xrange(2):
346 391 self._flushed = False
347 392 self.ioloop.add_callback(self._flush)
348 393 while not self._flushed and time.time() < stop_time:
349 394 time.sleep(0.01)
350 395
351 396 def _handle_events(self, socket, events):
352 397 # Turn on and off POLLOUT depending on if we have made a request
353 398 if events & POLLERR:
354 399 self._handle_err()
355 400 if events & POLLIN:
356 401 self._handle_recv()
357 402
358 403 def _handle_err(self):
359 404 # We don't want to let this go silently, so eventually we should log.
360 405 raise zmq.ZMQError()
361 406
362 407 def _handle_recv(self):
363 408 # Get all of the messages we can
364 409 while True:
365 410 try:
366 411 msg = self.socket.recv_json(zmq.NOBLOCK)
367 412 except zmq.ZMQError:
368 413 # Check the errno?
369 414 # Will this trigger POLLERR?
370 415 break
371 416 else:
372 417 self.call_handlers(msg)
373 418
374 419 def _flush(self):
375 420 """Callback for :method:`self.flush`."""
376 421 self._flushed = True
377 422
378 423
379 424 class RepSocketChannel(ZmqSocketChannel):
380 425 """A reply channel to handle raw_input requests that the kernel makes."""
381 426
382 427 msg_queue = None
383 428
384 429 def __init__(self, context, session, address):
385 430 self.msg_queue = Queue()
386 431 super(RepSocketChannel, self).__init__(context, session, address)
387 432
388 433 def run(self):
389 434 """The thread's main activity. Call start() instead."""
390 435 self.socket = self.context.socket(zmq.XREQ)
391 436 self.socket.setsockopt(zmq.IDENTITY, self.session.session)
392 437 self.socket.connect('tcp://%s:%i' % self.address)
393 438 self.ioloop = ioloop.IOLoop()
394 439 self.iostate = POLLERR|POLLIN
395 440 self.ioloop.add_handler(self.socket, self._handle_events,
396 441 self.iostate)
397 442 self.ioloop.start()
398 443
399 444 def stop(self):
400 445 self.ioloop.stop()
401 446 super(RepSocketChannel, self).stop()
402 447
403 448 def call_handlers(self, msg):
404 449 """This method is called in the ioloop thread when a message arrives.
405 450
406 451 Subclasses should override this method to handle incoming messages.
407 452 It is important to remember that this method is called in the thread
408 453 so that some logic must be done to ensure that the application leve
409 454 handlers are called in the application thread.
410 455 """
411 456 raise NotImplementedError('call_handlers must be defined in a subclass.')
412 457
413 458 def input(self, string):
414 459 """Send a string of raw input to the kernel."""
415 460 content = dict(value=string)
416 461 msg = self.session.msg('input_reply', content)
417 462 self._queue_reply(msg)
418 463
419 464 def _handle_events(self, socket, events):
420 465 if events & POLLERR:
421 466 self._handle_err()
422 467 if events & POLLOUT:
423 468 self._handle_send()
424 469 if events & POLLIN:
425 470 self._handle_recv()
426 471
427 472 def _handle_recv(self):
428 473 msg = self.socket.recv_json()
429 474 self.call_handlers(msg)
430 475
431 476 def _handle_send(self):
432 477 try:
433 478 msg = self.msg_queue.get(False)
434 479 except Empty:
435 480 pass
436 481 else:
437 482 self.socket.send_json(msg)
438 483 if self.msg_queue.empty():
439 484 self.drop_io_state(POLLOUT)
440 485
441 486 def _handle_err(self):
442 487 # We don't want to let this go silently, so eventually we should log.
443 488 raise zmq.ZMQError()
444 489
445 490 def _queue_reply(self, msg):
446 491 self.msg_queue.put(msg)
447 492 self.add_io_state(POLLOUT)
448 493
449 494
450 495 class HBSocketChannel(ZmqSocketChannel):
451 496 """The heartbeat channel which monitors the kernel heartbeat."""
452 497
453 498 time_to_dead = 3.0
454 499 socket = None
455 500 poller = None
456 501
457 502 def __init__(self, context, session, address):
458 503 super(HBSocketChannel, self).__init__(context, session, address)
459 504 self._running = False
460 505
461 506 def _create_socket(self):
462 507 self.socket = self.context.socket(zmq.REQ)
463 508 self.socket.setsockopt(zmq.IDENTITY, self.session.session)
464 509 self.socket.connect('tcp://%s:%i' % self.address)
465 510 self.poller = zmq.Poller()
466 511 self.poller.register(self.socket, zmq.POLLIN)
467 512
468 513 def run(self):
469 514 """The thread's main activity. Call start() instead."""
470 515 self._create_socket()
471 516 self._running = True
472 517 # Wait 2 seconds for the kernel to come up and the sockets to auto
473 518 # connect. If we don't we will see the kernel as dead. Also, before
474 519 # the sockets are connected, the poller.poll line below is returning
475 520 # too fast. This avoids that because the polling doesn't start until
476 521 # after the sockets are connected.
477 522 time.sleep(2.0)
478 523 while self._running:
479 524 since_last_heartbeat = 0.0
480 525 request_time = time.time()
481 526 try:
527 #io.rprint('Ping from HB channel') # dbg
482 528 self.socket.send_json('ping')
483 529 except zmq.ZMQError, e:
530 #io.rprint('*** HB Error:', e) # dbg
484 531 if e.errno == zmq.EFSM:
532 #io.rprint('sleep...', self.time_to_dead) # dbg
485 533 time.sleep(self.time_to_dead)
486 534 self._create_socket()
487 535 else:
488 536 raise
489 537 else:
490 538 while True:
491 539 try:
492 reply = self.socket.recv_json(zmq.NOBLOCK)
540 self.socket.recv_json(zmq.NOBLOCK)
493 541 except zmq.ZMQError, e:
542 #io.rprint('*** HB Error 2:', e) # dbg
494 543 if e.errno == zmq.EAGAIN:
495 until_dead = self.time_to_dead - (time.time() -
544 before_poll = time.time()
545 until_dead = self.time_to_dead - (before_poll -
496 546 request_time)
497 # poll timeout is in milliseconds.
498 poll_result = self.poller.poll(1000*until_dead)
547
548 # When the return value of poll() is an empty list,
549 # that is when things have gone wrong (zeromq bug).
550 # As long as it is not an empty list, poll is
551 # working correctly even if it returns quickly.
552 # Note: poll timeout is in milliseconds.
553 self.poller.poll(1000*until_dead)
554
499 555 since_last_heartbeat = time.time() - request_time
500 556 if since_last_heartbeat > self.time_to_dead:
501 557 self.call_handlers(since_last_heartbeat)
502 558 break
503 559 else:
504 560 # FIXME: We should probably log this instead.
505 561 raise
506 562 else:
507 563 until_dead = self.time_to_dead - (time.time() -
508 564 request_time)
509 565 if until_dead > 0.0:
566 #io.rprint('sleep...', self.time_to_dead) # dbg
510 567 time.sleep(until_dead)
511 568 break
512 569
513 570 def stop(self):
514 571 self._running = False
515 572 super(HBSocketChannel, self).stop()
516 573
517 574 def call_handlers(self, since_last_heartbeat):
518 575 """This method is called in the ioloop thread when a message arrives.
519 576
520 577 Subclasses should override this method to handle incoming messages.
521 578 It is important to remember that this method is called in the thread
522 579 so that some logic must be done to ensure that the application leve
523 580 handlers are called in the application thread.
524 581 """
525 582 raise NotImplementedError('call_handlers must be defined in a subclass.')
526 583
527 584
528 585 #-----------------------------------------------------------------------------
529 586 # Main kernel manager class
530 587 #-----------------------------------------------------------------------------
531 588
532 589 class KernelManager(HasTraits):
533 590 """ Manages a kernel for a frontend.
534 591
535 592 The SUB channel is for the frontend to receive messages published by the
536 593 kernel.
537 594
538 595 The REQ channel is for the frontend to make requests of the kernel.
539 596
540 597 The REP channel is for the kernel to request stdin (raw_input) from the
541 598 frontend.
542 599 """
543 600 # The PyZMQ Context to use for communication with the kernel.
544 601 context = Instance(zmq.Context,(),{})
545 602
546 603 # The Session to use for communication with the kernel.
547 604 session = Instance(Session,(),{})
548 605
549 606 # The kernel process with which the KernelManager is communicating.
550 607 kernel = Instance(Popen)
551 608
552 609 # The addresses for the communication channels.
553 610 xreq_address = TCPAddress((LOCALHOST, 0))
554 611 sub_address = TCPAddress((LOCALHOST, 0))
555 612 rep_address = TCPAddress((LOCALHOST, 0))
556 613 hb_address = TCPAddress((LOCALHOST, 0))
557 614
558 615 # The classes to use for the various channels.
559 616 xreq_channel_class = Type(XReqSocketChannel)
560 617 sub_channel_class = Type(SubSocketChannel)
561 618 rep_channel_class = Type(RepSocketChannel)
562 619 hb_channel_class = Type(HBSocketChannel)
563 620
564 621 # Protected traits.
565 622 _launch_args = Any
566 623 _xreq_channel = Any
567 624 _sub_channel = Any
568 625 _rep_channel = Any
569 626 _hb_channel = Any
570 627
571 628 #--------------------------------------------------------------------------
572 629 # Channel management methods:
573 630 #--------------------------------------------------------------------------
574 631
575 632 def start_channels(self):
576 633 """Starts the channels for this kernel.
577 634
578 635 This will create the channels if they do not exist and then start
579 636 them. If port numbers of 0 are being used (random ports) then you
580 637 must first call :method:`start_kernel`. If the channels have been
581 638 stopped and you call this, :class:`RuntimeError` will be raised.
582 639 """
583 640 self.xreq_channel.start()
584 641 self.sub_channel.start()
585 642 self.rep_channel.start()
586 643 self.hb_channel.start()
587 644
588 645 def stop_channels(self):
589 646 """Stops the channels for this kernel.
590 647
591 648 This stops the channels by joining their threads. If the channels
592 649 were not started, :class:`RuntimeError` will be raised.
593 650 """
594 651 self.xreq_channel.stop()
595 652 self.sub_channel.stop()
596 653 self.rep_channel.stop()
597 654 self.hb_channel.stop()
598 655
599 656 @property
600 657 def channels_running(self):
601 658 """Are all of the channels created and running?"""
602 659 return self.xreq_channel.is_alive() \
603 660 and self.sub_channel.is_alive() \
604 661 and self.rep_channel.is_alive() \
605 662 and self.hb_channel.is_alive()
606 663
607 664 #--------------------------------------------------------------------------
608 665 # Kernel process management methods:
609 666 #--------------------------------------------------------------------------
610 667
611 668 def start_kernel(self, **kw):
612 669 """Starts a kernel process and configures the manager to use it.
613 670
614 671 If random ports (port=0) are being used, this method must be called
615 672 before the channels are created.
616 673
617 674 Parameters:
618 675 -----------
619 676 ipython : bool, optional (default True)
620 677 Whether to use an IPython kernel instead of a plain Python kernel.
621 678 """
622 679 xreq, sub, rep, hb = self.xreq_address, self.sub_address, \
623 680 self.rep_address, self.hb_address
624 681 if xreq[0] != LOCALHOST or sub[0] != LOCALHOST or \
625 682 rep[0] != LOCALHOST or hb[0] != LOCALHOST:
626 683 raise RuntimeError("Can only launch a kernel on localhost."
627 684 "Make sure that the '*_address' attributes are "
628 685 "configured properly.")
629 686
630 687 self._launch_args = kw.copy()
631 688 if kw.pop('ipython', True):
632 689 from ipkernel import launch_kernel as launch
633 690 else:
634 691 from pykernel import launch_kernel as launch
635 692 self.kernel, xrep, pub, req, hb = launch(
636 693 xrep_port=xreq[1], pub_port=sub[1],
637 694 req_port=rep[1], hb_port=hb[1], **kw)
638 695 self.xreq_address = (LOCALHOST, xrep)
639 696 self.sub_address = (LOCALHOST, pub)
640 697 self.rep_address = (LOCALHOST, req)
641 698 self.hb_address = (LOCALHOST, hb)
642 699
643 700 def restart_kernel(self):
644 701 """Restarts a kernel with the same arguments that were used to launch
645 702 it. If the old kernel was launched with random ports, the same ports
646 703 will be used for the new kernel.
647 704 """
648 705 if self._launch_args is None:
649 706 raise RuntimeError("Cannot restart the kernel. "
650 707 "No previous call to 'start_kernel'.")
651 708 else:
652 709 if self.has_kernel:
653 710 self.kill_kernel()
654 711 self.start_kernel(**self._launch_args)
655 712
656 713 @property
657 714 def has_kernel(self):
658 715 """Returns whether a kernel process has been specified for the kernel
659 716 manager.
660 717 """
661 718 return self.kernel is not None
662 719
663 720 def kill_kernel(self):
664 721 """ Kill the running kernel. """
665 722 if self.kernel is not None:
666 723 self.kernel.kill()
667 724 self.kernel = None
668 725 else:
669 726 raise RuntimeError("Cannot kill kernel. No kernel is running!")
670 727
671 728 def signal_kernel(self, signum):
672 729 """ Sends a signal to the kernel. """
673 730 if self.kernel is not None:
674 731 self.kernel.send_signal(signum)
675 732 else:
676 733 raise RuntimeError("Cannot signal kernel. No kernel is running!")
677 734
678 735 @property
679 736 def is_alive(self):
680 737 """Is the kernel process still running?"""
681 738 if self.kernel is not None:
682 739 if self.kernel.poll() is None:
683 740 return True
684 741 else:
685 742 return False
686 743 else:
687 744 # We didn't start the kernel with this KernelManager so we don't
688 745 # know if it is running. We should use a heartbeat for this case.
689 746 return True
690 747
691 748 #--------------------------------------------------------------------------
692 749 # Channels used for communication with the kernel:
693 750 #--------------------------------------------------------------------------
694 751
695 752 @property
696 753 def xreq_channel(self):
697 754 """Get the REQ socket channel object to make requests of the kernel."""
698 755 if self._xreq_channel is None:
699 756 self._xreq_channel = self.xreq_channel_class(self.context,
700 757 self.session,
701 758 self.xreq_address)
702 759 return self._xreq_channel
703 760
704 761 @property
705 762 def sub_channel(self):
706 763 """Get the SUB socket channel object."""
707 764 if self._sub_channel is None:
708 765 self._sub_channel = self.sub_channel_class(self.context,
709 766 self.session,
710 767 self.sub_address)
711 768 return self._sub_channel
712 769
713 770 @property
714 771 def rep_channel(self):
715 772 """Get the REP socket channel object to handle stdin (raw_input)."""
716 773 if self._rep_channel is None:
717 774 self._rep_channel = self.rep_channel_class(self.context,
718 775 self.session,
719 776 self.rep_address)
720 777 return self._rep_channel
721 778
722 779 @property
723 780 def hb_channel(self):
724 781 """Get the REP socket channel object to handle stdin (raw_input)."""
725 782 if self._hb_channel is None:
726 783 self._hb_channel = self.hb_channel_class(self.context,
727 784 self.session,
728 785 self.hb_address)
729 786 return self._hb_channel
@@ -1,409 +1,408 b''
1 1 """A ZMQ-based subclass of InteractiveShell.
2 2
3 3 This code is meant to ease the refactoring of the base InteractiveShell into
4 4 something with a cleaner architecture for 2-process use, without actually
5 5 breaking InteractiveShell itself. So we're doing something a bit ugly, where
6 6 we subclass and override what we want to fix. Once this is working well, we
7 7 can go back to the base class and refactor the code for a cleaner inheritance
8 8 implementation that doesn't rely on so much monkeypatching.
9 9
10 10 But this lets us maintain a fully working IPython as we develop the new
11 11 machinery. This should thus be thought of as scaffolding.
12 12 """
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 from __future__ import print_function
17 17
18 18 # Stdlib
19 19 import inspect
20 20 import os
21 21 import re
22 22
23 23 # Our own
24 24 from IPython.core.interactiveshell import (
25 25 InteractiveShell, InteractiveShellABC
26 26 )
27 27 from IPython.core.displayhook import DisplayHook
28 28 from IPython.core.macro import Macro
29 29 from IPython.utils.path import get_py_filename
30 30 from IPython.utils.text import StringTypes
31 31 from IPython.utils.traitlets import Instance, Type, Dict
32 32 from IPython.utils.warn import warn
33 33 from IPython.zmq.session import extract_header
34 34 from IPython.core.payloadpage import install_payload_page
35 35 from session import Session
36 36
37 37 #-----------------------------------------------------------------------------
38 38 # Globals and side-effects
39 39 #-----------------------------------------------------------------------------
40 40
41 41 # Install the payload version of page.
42 42 install_payload_page()
43 43
44 44 #-----------------------------------------------------------------------------
45 45 # Functions and classes
46 46 #-----------------------------------------------------------------------------
47 47
48 48 class ZMQDisplayHook(DisplayHook):
49 49
50 50 session = Instance(Session)
51 51 pub_socket = Instance('zmq.Socket')
52 52 parent_header = Dict({})
53 53
54 54 def set_parent(self, parent):
55 55 """Set the parent for outbound messages."""
56 56 self.parent_header = extract_header(parent)
57 57
58 58 def start_displayhook(self):
59 59 self.msg = self.session.msg(u'pyout', {}, parent=self.parent_header)
60 60
61 61 def write_output_prompt(self):
62 62 """Write the output prompt."""
63 63 if self.do_full_cache:
64 self.msg['content']['output_sep'] = self.output_sep
65 self.msg['content']['prompt_string'] = str(self.prompt_out)
66 self.msg['content']['prompt_number'] = self.prompt_count
67 self.msg['content']['output_sep2'] = self.output_sep2
64 self.msg['content']['execution_count'] = self.prompt_count
68 65
69 66 def write_result_repr(self, result_repr):
70 67 self.msg['content']['data'] = result_repr
71 68
72 69 def finish_displayhook(self):
73 70 """Finish up all displayhook activities."""
74 71 self.pub_socket.send_json(self.msg)
75 72 self.msg = None
76 73
77 74
78 75 class ZMQInteractiveShell(InteractiveShell):
79 76 """A subclass of InteractiveShell for ZMQ."""
80 77
81 78 displayhook_class = Type(ZMQDisplayHook)
82 79
83 80 def init_io(self):
84 81 # This will just use sys.stdout and sys.stderr. If you want to
85 82 # override sys.stdout and sys.stderr themselves, you need to do that
86 83 # *before* instantiating this class, because Term holds onto
87 84 # references to the underlying streams.
88 85 import IPython.utils.io
89 86 Term = IPython.utils.io.IOTerm()
90 87 IPython.utils.io.Term = Term
91 88
92 89 def magic_edit(self,parameter_s='',last_call=['','']):
93 90 """Bring up an editor and execute the resulting code.
94 91
95 92 Usage:
96 93 %edit [options] [args]
97 94
98 95 %edit runs IPython's editor hook. The default version of this hook is
99 96 set to call the __IPYTHON__.rc.editor command. This is read from your
100 97 environment variable $EDITOR. If this isn't found, it will default to
101 98 vi under Linux/Unix and to notepad under Windows. See the end of this
102 99 docstring for how to change the editor hook.
103 100
104 101 You can also set the value of this editor via the command line option
105 102 '-editor' or in your ipythonrc file. This is useful if you wish to use
106 103 specifically for IPython an editor different from your typical default
107 104 (and for Windows users who typically don't set environment variables).
108 105
109 106 This command allows you to conveniently edit multi-line code right in
110 107 your IPython session.
111 108
112 109 If called without arguments, %edit opens up an empty editor with a
113 110 temporary file and will execute the contents of this file when you
114 111 close it (don't forget to save it!).
115 112
116 113
117 114 Options:
118 115
119 116 -n <number>: open the editor at a specified line number. By default,
120 117 the IPython editor hook uses the unix syntax 'editor +N filename', but
121 118 you can configure this by providing your own modified hook if your
122 119 favorite editor supports line-number specifications with a different
123 120 syntax.
124 121
125 122 -p: this will call the editor with the same data as the previous time
126 123 it was used, regardless of how long ago (in your current session) it
127 124 was.
128 125
129 126 -r: use 'raw' input. This option only applies to input taken from the
130 127 user's history. By default, the 'processed' history is used, so that
131 128 magics are loaded in their transformed version to valid Python. If
132 129 this option is given, the raw input as typed as the command line is
133 130 used instead. When you exit the editor, it will be executed by
134 131 IPython's own processor.
135 132
136 133 -x: do not execute the edited code immediately upon exit. This is
137 134 mainly useful if you are editing programs which need to be called with
138 135 command line arguments, which you can then do using %run.
139 136
140 137
141 138 Arguments:
142 139
143 140 If arguments are given, the following possibilites exist:
144 141
145 142 - The arguments are numbers or pairs of colon-separated numbers (like
146 143 1 4:8 9). These are interpreted as lines of previous input to be
147 144 loaded into the editor. The syntax is the same of the %macro command.
148 145
149 146 - If the argument doesn't start with a number, it is evaluated as a
150 147 variable and its contents loaded into the editor. You can thus edit
151 148 any string which contains python code (including the result of
152 149 previous edits).
153 150
154 151 - If the argument is the name of an object (other than a string),
155 152 IPython will try to locate the file where it was defined and open the
156 153 editor at the point where it is defined. You can use `%edit function`
157 154 to load an editor exactly at the point where 'function' is defined,
158 155 edit it and have the file be executed automatically.
159 156
160 157 If the object is a macro (see %macro for details), this opens up your
161 158 specified editor with a temporary file containing the macro's data.
162 159 Upon exit, the macro is reloaded with the contents of the file.
163 160
164 161 Note: opening at an exact line is only supported under Unix, and some
165 162 editors (like kedit and gedit up to Gnome 2.8) do not understand the
166 163 '+NUMBER' parameter necessary for this feature. Good editors like
167 164 (X)Emacs, vi, jed, pico and joe all do.
168 165
169 166 - If the argument is not found as a variable, IPython will look for a
170 167 file with that name (adding .py if necessary) and load it into the
171 168 editor. It will execute its contents with execfile() when you exit,
172 169 loading any code in the file into your interactive namespace.
173 170
174 171 After executing your code, %edit will return as output the code you
175 172 typed in the editor (except when it was an existing file). This way
176 173 you can reload the code in further invocations of %edit as a variable,
177 174 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
178 175 the output.
179 176
180 177 Note that %edit is also available through the alias %ed.
181 178
182 179 This is an example of creating a simple function inside the editor and
183 180 then modifying it. First, start up the editor:
184 181
185 182 In [1]: ed
186 183 Editing... done. Executing edited code...
187 184 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
188 185
189 186 We can then call the function foo():
190 187
191 188 In [2]: foo()
192 189 foo() was defined in an editing session
193 190
194 191 Now we edit foo. IPython automatically loads the editor with the
195 192 (temporary) file where foo() was previously defined:
196 193
197 194 In [3]: ed foo
198 195 Editing... done. Executing edited code...
199 196
200 197 And if we call foo() again we get the modified version:
201 198
202 199 In [4]: foo()
203 200 foo() has now been changed!
204 201
205 202 Here is an example of how to edit a code snippet successive
206 203 times. First we call the editor:
207 204
208 205 In [5]: ed
209 206 Editing... done. Executing edited code...
210 207 hello
211 208 Out[5]: "print 'hello'n"
212 209
213 210 Now we call it again with the previous output (stored in _):
214 211
215 212 In [6]: ed _
216 213 Editing... done. Executing edited code...
217 214 hello world
218 215 Out[6]: "print 'hello world'n"
219 216
220 217 Now we call it with the output #8 (stored in _8, also as Out[8]):
221 218
222 219 In [7]: ed _8
223 220 Editing... done. Executing edited code...
224 221 hello again
225 222 Out[7]: "print 'hello again'n"
226 223
227 224
228 225 Changing the default editor hook:
229 226
230 227 If you wish to write your own editor hook, you can put it in a
231 228 configuration file which you load at startup time. The default hook
232 229 is defined in the IPython.core.hooks module, and you can use that as a
233 230 starting example for further modifications. That file also has
234 231 general instructions on how to set a new hook for use once you've
235 232 defined it."""
236 233
237 234 # FIXME: This function has become a convoluted mess. It needs a
238 235 # ground-up rewrite with clean, simple logic.
239 236
240 237 def make_filename(arg):
241 238 "Make a filename from the given args"
242 239 try:
243 240 filename = get_py_filename(arg)
244 241 except IOError:
245 242 if args.endswith('.py'):
246 243 filename = arg
247 244 else:
248 245 filename = None
249 246 return filename
250 247
251 248 # custom exceptions
252 249 class DataIsObject(Exception): pass
253 250
254 251 opts,args = self.parse_options(parameter_s,'prn:')
255 252 # Set a few locals from the options for convenience:
256 253 opts_p = opts.has_key('p')
257 254 opts_r = opts.has_key('r')
258 255
259 256 # Default line number value
260 257 lineno = opts.get('n',None)
261 258 if lineno is not None:
262 259 try:
263 260 lineno = int(lineno)
264 261 except:
265 262 warn("The -n argument must be an integer.")
266 263 return
267 264
268 265 if opts_p:
269 266 args = '_%s' % last_call[0]
270 267 if not self.shell.user_ns.has_key(args):
271 268 args = last_call[1]
272 269
273 270 # use last_call to remember the state of the previous call, but don't
274 271 # let it be clobbered by successive '-p' calls.
275 272 try:
276 273 last_call[0] = self.shell.displayhook.prompt_count
277 274 if not opts_p:
278 275 last_call[1] = parameter_s
279 276 except:
280 277 pass
281 278
282 279 # by default this is done with temp files, except when the given
283 280 # arg is a filename
284 281 use_temp = 1
285 282
286 283 if re.match(r'\d',args):
287 284 # Mode where user specifies ranges of lines, like in %macro.
288 285 # This means that you can't edit files whose names begin with
289 286 # numbers this way. Tough.
290 287 ranges = args.split()
291 288 data = ''.join(self.extract_input_slices(ranges,opts_r))
292 289 elif args.endswith('.py'):
293 290 filename = make_filename(args)
294 291 data = ''
295 292 use_temp = 0
296 293 elif args:
297 294 try:
298 295 # Load the parameter given as a variable. If not a string,
299 296 # process it as an object instead (below)
300 297
301 298 #print '*** args',args,'type',type(args) # dbg
302 299 data = eval(args,self.shell.user_ns)
303 300 if not type(data) in StringTypes:
304 301 raise DataIsObject
305 302
306 303 except (NameError,SyntaxError):
307 304 # given argument is not a variable, try as a filename
308 305 filename = make_filename(args)
309 306 if filename is None:
310 307 warn("Argument given (%s) can't be found as a variable "
311 308 "or as a filename." % args)
312 309 return
313 310
314 311 data = ''
315 312 use_temp = 0
316 313 except DataIsObject:
317 314
318 315 # macros have a special edit function
319 316 if isinstance(data,Macro):
320 317 self._edit_macro(args,data)
321 318 return
322 319
323 320 # For objects, try to edit the file where they are defined
324 321 try:
325 322 filename = inspect.getabsfile(data)
326 323 if 'fakemodule' in filename.lower() and inspect.isclass(data):
327 324 # class created by %edit? Try to find source
328 325 # by looking for method definitions instead, the
329 326 # __module__ in those classes is FakeModule.
330 327 attrs = [getattr(data, aname) for aname in dir(data)]
331 328 for attr in attrs:
332 329 if not inspect.ismethod(attr):
333 330 continue
334 331 filename = inspect.getabsfile(attr)
335 332 if filename and 'fakemodule' not in filename.lower():
336 333 # change the attribute to be the edit target instead
337 334 data = attr
338 335 break
339 336
340 337 datafile = 1
341 338 except TypeError:
342 339 filename = make_filename(args)
343 340 datafile = 1
344 341 warn('Could not find file where `%s` is defined.\n'
345 342 'Opening a file named `%s`' % (args,filename))
346 343 # Now, make sure we can actually read the source (if it was in
347 344 # a temp file it's gone by now).
348 345 if datafile:
349 346 try:
350 347 if lineno is None:
351 348 lineno = inspect.getsourcelines(data)[1]
352 349 except IOError:
353 350 filename = make_filename(args)
354 351 if filename is None:
355 352 warn('The file `%s` where `%s` was defined cannot '
356 353 'be read.' % (filename,data))
357 354 return
358 355 use_temp = 0
359 356 else:
360 357 data = ''
361 358
362 359 if use_temp:
363 360 filename = self.shell.mktempfile(data)
364 361 print('IPython will make a temporary file named:', filename)
365 362
366 363 # Make sure we send to the client an absolute path, in case the working
367 364 # directory of client and kernel don't match
368 365 filename = os.path.abspath(filename)
369 366
370 367 payload = {
371 368 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
372 369 'filename' : filename,
373 370 'line_number' : lineno
374 371 }
375 372 self.payload_manager.write_payload(payload)
376 373
377 374 def magic_gui(self, *args, **kwargs):
378 375 raise NotImplementedError('GUI support must be enabled in command line options.')
379 376
380 377 def magic_pylab(self, *args, **kwargs):
381 378 raise NotImplementedError('pylab support must be enabled in commandl in options.')
382 379
383 380 def _showtraceback(self, etype, evalue, stb):
384 381
385 382 exc_content = {
386 u'status' : u'error',
387 383 u'traceback' : stb,
388 384 u'ename' : unicode(etype.__name__),
389 385 u'evalue' : unicode(evalue)
390 386 }
391 387
392 388 dh = self.displayhook
393 389 exc_msg = dh.session.msg(u'pyerr', exc_content, dh.parent_header)
394 390 # Send exception info over pub socket for other clients than the caller
395 391 # to pick up
396 392 dh.pub_socket.send_json(exc_msg)
397 393
398 394 # FIXME - Hack: store exception info in shell object. Right now, the
399 395 # caller is reading this info after the fact, we need to fix this logic
400 # to remove this hack.
396 # to remove this hack. Even uglier, we need to store the error status
397 # here, because in the main loop, the logic that sets it is being
398 # skipped because runlines swallows the exceptions.
399 exc_content[u'status'] = u'error'
401 400 self._reply_content = exc_content
402 401 # /FIXME
403 402
404 403 return exc_content
405 404
406 405 def runlines(self, lines, clean=False):
407 406 return InteractiveShell.runlines(self, lines, clean)
408 407
409 408 InteractiveShellABC.register(ZMQInteractiveShell)
@@ -1,708 +1,707 b''
1 1 .. _messaging:
2 2
3 3 ======================
4 4 Messaging in IPython
5 5 ======================
6 6
7 7
8 8 Introduction
9 9 ============
10 10
11 11 This document explains the basic communications design and messaging
12 12 specification for how the various IPython objects interact over a network
13 13 transport. The current implementation uses the ZeroMQ_ library for messaging
14 14 within and between hosts.
15 15
16 16 .. Note::
17 17
18 18 This document should be considered the authoritative description of the
19 19 IPython messaging protocol, and all developers are strongly encouraged to
20 20 keep it updated as the implementation evolves, so that we have a single
21 21 common reference for all protocol details.
22 22
23 23 The basic design is explained in the following diagram:
24 24
25 25 .. image:: frontend-kernel.png
26 26 :width: 450px
27 27 :alt: IPython kernel/frontend messaging architecture.
28 28 :align: center
29 29 :target: ../_images/frontend-kernel.png
30 30
31 31 A single kernel can be simultaneously connected to one or more frontends. The
32 32 kernel has three sockets that serve the following functions:
33 33
34 34 1. REQ: this socket is connected to a *single* frontend at a time, and it allows
35 35 the kernel to request input from a frontend when :func:`raw_input` is called.
36 36 The frontend holding the matching REP socket acts as a 'virtual keyboard'
37 37 for the kernel while this communication is happening (illustrated in the
38 38 figure by the black outline around the central keyboard). In practice,
39 39 frontends may display such kernel requests using a special input widget or
40 40 otherwise indicating that the user is to type input for the kernel instead
41 41 of normal commands in the frontend.
42 42
43 43 2. XREP: this single sockets allows multiple incoming connections from
44 44 frontends, and this is the socket where requests for code execution, object
45 45 information, prompts, etc. are made to the kernel by any frontend. The
46 46 communication on this socket is a sequence of request/reply actions from
47 47 each frontend and the kernel.
48 48
49 49 3. PUB: this socket is the 'broadcast channel' where the kernel publishes all
50 50 side effects (stdout, stderr, etc.) as well as the requests coming from any
51 51 client over the XREP socket and its own requests on the REP socket. There
52 52 are a number of actions in Python which generate side effects: :func:`print`
53 53 writes to ``sys.stdout``, errors generate tracebacks, etc. Additionally, in
54 54 a multi-client scenario, we want all frontends to be able to know what each
55 55 other has sent to the kernel (this can be useful in collaborative scenarios,
56 56 for example). This socket allows both side effects and the information
57 57 about communications taking place with one client over the XREQ/XREP channel
58 58 to be made available to all clients in a uniform manner.
59 59
60 60 All messages are tagged with enough information (details below) for clients
61 61 to know which messages come from their own interaction with the kernel and
62 62 which ones are from other clients, so they can display each type
63 63 appropriately.
64 64
65 65 The actual format of the messages allowed on each of these channels is
66 66 specified below. Messages are dicts of dicts with string keys and values that
67 67 are reasonably representable in JSON. Our current implementation uses JSON
68 68 explicitly as its message format, but this shouldn't be considered a permanent
69 69 feature. As we've discovered that JSON has non-trivial performance issues due
70 70 to excessive copying, we may in the future move to a pure pickle-based raw
71 71 message format. However, it should be possible to easily convert from the raw
72 72 objects to JSON, since we may have non-python clients (e.g. a web frontend).
73 73 As long as it's easy to make a JSON version of the objects that is a faithful
74 74 representation of all the data, we can communicate with such clients.
75 75
76 76 .. Note::
77 77
78 78 Not all of these have yet been fully fleshed out, but the key ones are, see
79 79 kernel and frontend files for actual implementation details.
80 80
81 81
82 82 Python functional API
83 83 =====================
84 84
85 85 As messages are dicts, they map naturally to a ``func(**kw)`` call form. We
86 86 should develop, at a few key points, functional forms of all the requests that
87 87 take arguments in this manner and automatically construct the necessary dict
88 88 for sending.
89 89
90 90
91 91 General Message Format
92 92 ======================
93 93
94 94 All messages send or received by any IPython process should have the following
95 95 generic structure::
96 96
97 97 {
98 98 # The message header contains a pair of unique identifiers for the
99 99 # originating session and the actual message id, in addition to the
100 100 # username for the process that generated the message. This is useful in
101 101 # collaborative settings where multiple users may be interacting with the
102 102 # same kernel simultaneously, so that frontends can label the various
103 103 # messages in a meaningful way.
104 104 'header' : { 'msg_id' : uuid,
105 105 'username' : str,
106 106 'session' : uuid
107 107 },
108 108
109 109 # In a chain of messages, the header from the parent is copied so that
110 110 # clients can track where messages come from.
111 111 'parent_header' : dict,
112 112
113 113 # All recognized message type strings are listed below.
114 114 'msg_type' : str,
115 115
116 116 # The actual content of the message must be a dict, whose structure
117 117 # depends on the message type.x
118 118 'content' : dict,
119 119 }
120 120
121 121 For each message type, the actual content will differ and all existing message
122 122 types are specified in what follows of this document.
123 123
124 124
125 125 Messages on the XREP/XREQ socket
126 126 ================================
127 127
128 128 .. _execute:
129 129
130 130 Execute
131 131 -------
132 132
133 133 This message type is used by frontends to ask the kernel to execute code on
134 134 behalf of the user, in a namespace reserved to the user's variables (and thus
135 135 separate from the kernel's own internal code and variables).
136 136
137 137 Message type: ``execute_request``::
138 138
139 139 content = {
140 140 # Source code to be executed by the kernel, one or more lines.
141 141 'code' : str,
142 142
143 143 # A boolean flag which, if True, signals the kernel to execute this
144 144 # code as quietly as possible. This means that the kernel will compile
145 145 # the code witIPython/core/tests/h 'exec' instead of 'single' (so
146 146 # sys.displayhook will not fire), and will *not*:
147 147 # - broadcast exceptions on the PUB socket
148 148 # - do any logging
149 149 # - populate any history
150 150 #
151 151 # The default is False.
152 152 'silent' : bool,
153 153
154 154 # A list of variable names from the user's namespace to be retrieved. What
155 155 # returns is a JSON string of the variable's repr(), not a python object.
156 156 'user_variables' : list,
157 157
158 158 # Similarly, a dict mapping names to expressions to be evaluated in the
159 159 # user's dict.
160 160 'user_expressions' : dict,
161 161 }
162 162
163 163 The ``code`` field contains a single string, but this may be a multiline
164 164 string. The kernel is responsible for splitting this into possibly more than
165 165 one block and deciding whether to compile these in 'single' or 'exec' mode.
166 166 We're still sorting out this policy. The current inputsplitter is capable of
167 167 splitting the input for blocks that can all be run as 'single', but in the long
168 168 run it may prove cleaner to only use 'single' mode for truly single-line
169 169 inputs, and run all multiline input in 'exec' mode. This would preserve the
170 170 natural behavior of single-line inputs while allowing long cells to behave more
171 171 likea a script. This design will be refined as we complete the implementation.
172 172
173 173 The ``user_`` fields deserve a detailed explanation. In the past, IPython had
174 174 the notion of a prompt string that allowed arbitrary code to be evaluated, and
175 175 this was put to good use by many in creating prompts that displayed system
176 176 status, path information, and even more esoteric uses like remote instrument
177 177 status aqcuired over the network. But now that IPython has a clean separation
178 178 between the kernel and the clients, the notion of embedding 'prompt'
179 179 maninpulations into the kernel itself feels awkward. Prompts should be a
180 180 frontend-side feature, and it should be even possible for different frontends
181 181 to display different prompts while interacting with the same kernel.
182 182
183 183 We have therefore abandoned the idea of a 'prompt string' to be evaluated by
184 184 the kernel, and instead provide the ability to retrieve from the user's
185 185 namespace information after the execution of the main ``code``, with two fields
186 186 of the execution request:
187 187
188 188 - ``user_variables``: If only variables from the user's namespace are needed, a
189 189 list of variable names can be passed and a dict with these names as keys and
190 190 their :func:`repr()` as values will be returned.
191 191
192 192 - ``user_expressions``: For more complex expressions that require function
193 193 evaluations, a dict can be provided with string keys and arbitrary python
194 194 expressions as values. The return message will contain also a dict with the
195 195 same keys and the :func:`repr()` of the evaluated expressions as value.
196 196
197 197 With this information, frontends can display any status information they wish
198 198 in the form that best suits each frontend (a status line, a popup, inline for a
199 199 terminal, etc).
200 200
201 201 .. Note::
202 202
203 203 In order to obtain the current execution counter for the purposes of
204 204 displaying input prompts, frontends simply make an execution request with an
205 205 empty code string and ``silent=True``.
206 206
207 207 Execution semantics
208 208 Upon completion of the execution request, the kernel *always* sends a
209 209 reply, with a status code indicating what happened and additional data
210 210 depending on the outcome.
211 211
212 212 The ``code`` field is executed first, and then the ``user_variables`` and
213 213 ``user_expressions`` are computed. This ensures that any error in the
214 214 latter don't harm the main code execution.
215 215
216 216 Any error in retrieving the ``user_variables`` or evaluating the
217 217 ``user_expressions`` will result in a simple error message in the return
218 218 fields of the form::
219 219
220 220 [ERROR] ExceptionType: Exception message
221 221
222 222 The user can simply send the same variable name or expression for
223 223 evaluation to see a regular traceback.
224 224
225 225 Execution counter (old prompt number)
226 226 The kernel has a single, monotonically increasing counter of all execution
227 227 requests that are made with ``silent=False``. This counter is used to
228 228 populate the ``In[n]``, ``Out[n]`` and ``_n`` variables, so clients will
229 229 likely want to display it in some form to the user, which will typically
230 230 (but not necessarily) be done in the prompts. The value of this counter
231 231 will be returned as the ``execution_count`` field of all ``execute_reply```
232 232 messages.
233 233
234 234 Message type: ``execute_reply``::
235 235
236 236 content = {
237 237 # One of: 'ok' OR 'error' OR 'abort'
238 238 'status' : str,
239 239
240 240 # The global kernel counter that increases by one with each non-silent
241 241 # executed request. This will typically be used by clients to display
242 242 # prompt numbers to the user. If the request was a silent one, this will
243 243 # be the current value of the counter in the kernel.
244 244 'execution_count' : int,
245
246 # If the state_template was provided, this will contain the evaluated
247 # form of the template.
248 'state' : str,
249 245 }
250 246
251 247 When status is 'ok', the following extra fields are present::
252 248
253 249 {
254 # The kernel will often transform the input provided to it. If the
255 # '---->' transform had been applied, this is filled, otherwise it's the
256 # empty string. So transformations like magics don't appear here, only
257 # autocall ones.
258
259 'transformed_code' : str,
260
261 250 # The execution payload is a dict with string keys that may have been
262 251 # produced by the code being executed. It is retrieved by the kernel at
263 252 # the end of the execution and sent back to the front end, which can take
264 253 # action on it as needed. See main text for further details.
265 254 'payload' : dict,
266 }
255
256 # Results for the user_variables and user_expressions.
257 'user_variables' : dict,
258 'user_expressions' : dict,
259
260 # The kernel will often transform the input provided to it. If the
261 # '---->' transform had been applied, this is filled, otherwise it's the
262 # empty string. So transformations like magics don't appear here, only
263 # autocall ones.
264 'transformed_code' : str,
265 }
267 266
268 267 .. admonition:: Execution payloads
269 268
270 269 The notion of an 'execution payload' is different from a return value of a
271 270 given set of code, which normally is just displayed on the pyout stream
272 271 through the PUB socket. The idea of a payload is to allow special types of
273 272 code, typically magics, to populate a data container in the IPython kernel
274 273 that will be shipped back to the caller via this channel. The kernel will
275 274 have an API for this, probably something along the lines of::
276 275
277 276 ip.exec_payload_add(key, value)
278 277
279 278 though this API is still in the design stages. The data returned in this
280 279 payload will allow frontends to present special views of what just happened.
281 280
282 281
283 282 When status is 'error', the following extra fields are present::
284 283
285 284 {
286 285 'exc_name' : str, # Exception name, as a string
287 286 'exc_value' : str, # Exception value, as a string
288 287
289 288 # The traceback will contain a list of frames, represented each as a
290 289 # string. For now we'll stick to the existing design of ultraTB, which
291 290 # controls exception level of detail statefully. But eventually we'll
292 291 # want to grow into a model where more information is collected and
293 292 # packed into the traceback object, with clients deciding how little or
294 293 # how much of it to unpack. But for now, let's start with a simple list
295 294 # of strings, since that requires only minimal changes to ultratb as
296 295 # written.
297 296 'traceback' : list,
298 297 }
299 298
300 299
301 300 When status is 'abort', there are for now no additional data fields. This
302 301 happens when the kernel was interrupted by a signal.
303 302
304 303 Kernel attribute access
305 304 -----------------------
306 305
307 306 While this protocol does not specify full RPC access to arbitrary methods of
308 307 the kernel object, the kernel does allow read (and in some cases write) access
309 308 to certain attributes.
310 309
311 310 The policy for which attributes can be read is: any attribute of the kernel, or
312 311 its sub-objects, that belongs to a :class:`Configurable` object and has been
313 312 declared at the class-level with Traits validation, is in principle accessible
314 313 as long as its name does not begin with a leading underscore. The attribute
315 314 itself will have metadata indicating whether it allows remote read and/or write
316 315 access. The message spec follows for attribute read and write requests.
317 316
318 317 Message type: ``getattr_request``::
319 318
320 319 content = {
321 320 # The (possibly dotted) name of the attribute
322 321 'name' : str,
323 322 }
324 323
325 324 When a ``getattr_request`` fails, there are two possible error types:
326 325
327 326 - AttributeError: this type of error was raised when trying to access the
328 327 given name by the kernel itself. This means that the attribute likely
329 328 doesn't exist.
330 329
331 330 - AccessError: the attribute exists but its value is not readable remotely.
332 331
333 332
334 333 Message type: ``getattr_reply``::
335 334
336 335 content = {
337 336 # One of ['ok', 'AttributeError', 'AccessError'].
338 337 'status' : str,
339 338 # If status is 'ok', a JSON object.
340 339 'value' : object,
341 340 }
342 341
343 342 Message type: ``setattr_request``::
344 343
345 344 content = {
346 345 # The (possibly dotted) name of the attribute
347 346 'name' : str,
348 347
349 348 # A JSON-encoded object, that will be validated by the Traits
350 349 # information in the kernel
351 350 'value' : object,
352 351 }
353 352
354 353 When a ``setattr_request`` fails, there are also two possible error types with
355 354 similar meanings as those of the ``getattr_request`` case, but for writing.
356 355
357 356 Message type: ``setattr_reply``::
358 357
359 358 content = {
360 359 # One of ['ok', 'AttributeError', 'AccessError'].
361 360 'status' : str,
362 361 }
363 362
364 363
365 364 Object information
366 365 ------------------
367 366
368 367 One of IPython's most used capabilities is the introspection of Python objects
369 368 in the user's namespace, typically invoked via the ``?`` and ``??`` characters
370 369 (which in reality are shorthands for the ``%pinfo`` magic). This is used often
371 370 enough that it warrants an explicit message type, especially because frontends
372 371 may want to get object information in response to user keystrokes (like Tab or
373 372 F1) besides from the user explicitly typing code like ``x??``.
374 373
375 374 Message type: ``object_info_request``::
376 375
377 376 content = {
378 377 # The (possibly dotted) name of the object to be searched in all
379 378 # relevant namespaces
380 379 'name' : str,
381 380
382 381 # The level of detail desired. The default (0) is equivalent to typing
383 382 # 'x?' at the prompt, 1 is equivalent to 'x??'.
384 383 'detail_level' : int,
385 384 }
386 385
387 386 The returned information will be a dictionary with keys very similar to the
388 387 field names that IPython prints at the terminal.
389 388
390 389 Message type: ``object_info_reply``::
391 390
392 391 content = {
393 392 # Flags for magics and system aliases
394 393 'ismagic' : bool,
395 394 'isalias' : bool,
396 395
397 396 # The name of the namespace where the object was found ('builtin',
398 397 # 'magics', 'alias', 'interactive', etc.)
399 398 'namespace' : str,
400 399
401 400 # The type name will be type.__name__ for normal Python objects, but it
402 401 # can also be a string like 'Magic function' or 'System alias'
403 402 'type_name' : str,
404 403
405 404 'string_form' : str,
406 405
407 406 # For objects with a __class__ attribute this will be set
408 407 'base_class' : str,
409 408
410 409 # For objects with a __len__ attribute this will be set
411 410 'length' : int,
412 411
413 412 # If the object is a function, class or method whose file we can find,
414 413 # we give its full path
415 414 'file' : str,
416 415
417 416 # For pure Python callable objects, we can reconstruct the object
418 417 # definition line which provides its call signature. For convenience this
419 418 # is returned as a single 'definition' field, but below the raw parts that
420 419 # compose it are also returned as the argspec field.
421 420 'definition' : str,
422 421
423 422 # The individual parts that together form the definition string. Clients
424 423 # with rich display capabilities may use this to provide a richer and more
425 424 # precise representation of the definition line (e.g. by highlighting
426 425 # arguments based on the user's cursor position). For non-callable
427 426 # objects, this field is empty.
428 427 'argspec' : { # The names of all the arguments
429 428 args : list,
430 429 # The name of the varargs (*args), if any
431 430 varargs : str,
432 431 # The name of the varkw (**kw), if any
433 432 varkw : str,
434 433 # The values (as strings) of all default arguments. Note
435 434 # that these must be matched *in reverse* with the 'args'
436 435 # list above, since the first positional args have no default
437 436 # value at all.
438 437 func_defaults : list,
439 438 },
440 439
441 440 # For instances, provide the constructor signature (the definition of
442 441 # the __init__ method):
443 442 'init_definition' : str,
444 443
445 444 # Docstrings: for any object (function, method, module, package) with a
446 445 # docstring, we show it. But in addition, we may provide additional
447 446 # docstrings. For example, for instances we will show the constructor
448 447 # and class docstrings as well, if available.
449 448 'docstring' : str,
450 449
451 450 # For instances, provide the constructor and class docstrings
452 451 'init_docstring' : str,
453 452 'class_docstring' : str,
454 453
455 454 # If detail_level was 1, we also try to find the source code that
456 455 # defines the object, if possible. The string 'None' will indicate
457 456 # that no source was found.
458 457 'source' : str,
459 458 }
460 459
461 460
462 461 Complete
463 462 --------
464 463
465 464 Message type: ``complete_request``::
466 465
467 466 content = {
468 467 # The text to be completed, such as 'a.is'
469 468 'text' : str,
470 469
471 470 # The full line, such as 'print a.is'. This allows completers to
472 471 # make decisions that may require information about more than just the
473 472 # current word.
474 473 'line' : str,
475 474
476 475 # The entire block of text where the line is. This may be useful in the
477 476 # case of multiline completions where more context may be needed. Note: if
478 477 # in practice this field proves unnecessary, remove it to lighten the
479 478 # messages.
480 479
481 480 'block' : str,
482 481
483 482 # The position of the cursor where the user hit 'TAB' on the line.
484 483 'cursor_pos' : int,
485 484 }
486 485
487 486 Message type: ``complete_reply``::
488 487
489 488 content = {
490 489 # The list of all matches to the completion request, such as
491 490 # ['a.isalnum', 'a.isalpha'] for the above example.
492 491 'matches' : list
493 492 }
494 493
495 494
496 495 History
497 496 -------
498 497
499 498 For clients to explicitly request history from a kernel. The kernel has all
500 499 the actual execution history stored in a single location, so clients can
501 500 request it from the kernel when needed.
502 501
503 502 Message type: ``history_request``::
504 503
505 504 content = {
506 505
507 506 # If True, also return output history in the resulting dict.
508 507 'output' : bool,
509 508
510 509 # If True, return the raw input history, else the transformed input.
511 510 'raw' : bool,
512 511
513 512 # This parameter can be one of: A number, a pair of numbers, None
514 513 # If not given, last 40 are returned.
515 514 # - number n: return the last n entries.
516 515 # - pair n1, n2: return entries in the range(n1, n2).
517 516 # - None: return all history
518 517 'index' : n or (n1, n2) or None,
519 518 }
520 519
521 520 Message type: ``history_reply``::
522 521
523 522 content = {
524 523 # A dict with prompt numbers as keys and either (input, output) or input
525 524 # as the value depending on whether output was True or False,
526 525 # respectively.
527 526 'history' : dict,
528 527 }
529 528
530 529 Messages on the PUB/SUB socket
531 530 ==============================
532 531
533 532 Streams (stdout, stderr, etc)
534 533 ------------------------------
535 534
536 535 Message type: ``stream``::
537 536
538 537 content = {
539 538 # The name of the stream is one of 'stdin', 'stdout', 'stderr'
540 539 'name' : str,
541 540
542 541 # The data is an arbitrary string to be written to that stream
543 542 'data' : str,
544 543 }
545 544
546 545 When a kernel receives a raw_input call, it should also broadcast it on the pub
547 546 socket with the names 'stdin' and 'stdin_reply'. This will allow other clients
548 547 to monitor/display kernel interactions and possibly replay them to their user
549 548 or otherwise expose them.
550 549
551 550 Python inputs
552 551 -------------
553 552
554 553 These messages are the re-broadcast of the ``execute_request``.
555 554
556 555 Message type: ``pyin``::
557 556
558 557 content = {
559 558 # Source code to be executed, one or more lines
560 559 'code' : str
561 560 }
562 561
563 562 Python outputs
564 563 --------------
565 564
566 565 When Python produces output from code that has been compiled in with the
567 566 'single' flag to :func:`compile`, any expression that produces a value (such as
568 567 ``1+1``) is passed to ``sys.displayhook``, which is a callable that can do with
569 568 this value whatever it wants. The default behavior of ``sys.displayhook`` in
570 569 the Python interactive prompt is to print to ``sys.stdout`` the :func:`repr` of
571 570 the value as long as it is not ``None`` (which isn't printed at all). In our
572 571 case, the kernel instantiates as ``sys.displayhook`` an object which has
573 572 similar behavior, but which instead of printing to stdout, broadcasts these
574 573 values as ``pyout`` messages for clients to display appropriately.
575 574
576 575 Message type: ``pyout``::
577 576
578 577 content = {
579 578 # The data is typically the repr() of the object.
580 579 'data' : str,
581 580
582 581 # The counter for this execution is also provided so that clients can
583 582 # display it, since IPython automatically creates variables called _N (for
584 583 # prompt N).
585 584 'execution_count' : int,
586 585 }
587 586
588 587 Python errors
589 588 -------------
590 589
591 590 When an error occurs during code execution
592 591
593 592 Message type: ``pyerr``::
594 593
595 594 content = {
596 595 # Similar content to the execute_reply messages for the 'error' case,
597 596 # except the 'status' field is omitted.
598 597 }
599 598
600 599 Kernel crashes
601 600 --------------
602 601
603 602 When the kernel has an unexpected exception, caught by the last-resort
604 603 sys.excepthook, we should broadcast the crash handler's output before exiting.
605 604 This will allow clients to notice that a kernel died, inform the user and
606 605 propose further actions.
607 606
608 607 Message type: ``crash``::
609 608
610 609 content = {
611 610 # Similarly to the 'error' case for execute_reply messages, this will
612 611 # contain exc_name, exc_type and traceback fields.
613 612
614 613 # An additional field with supplementary information such as where to
615 614 # send the crash message
616 615 'info' : str,
617 616 }
618 617
619 618
620 619 Future ideas
621 620 ------------
622 621
623 622 Other potential message types, currently unimplemented, listed below as ideas.
624 623
625 624 Message type: ``file``::
626 625
627 626 content = {
628 627 'path' : 'cool.jpg',
629 628 'mimetype' : str,
630 629 'data' : str,
631 630 }
632 631
633 632
634 633 Messages on the REQ/REP socket
635 634 ==============================
636 635
637 636 This is a socket that goes in the opposite direction: from the kernel to a
638 637 *single* frontend, and its purpose is to allow ``raw_input`` and similar
639 638 operations that read from ``sys.stdin`` on the kernel to be fulfilled by the
640 639 client. For now we will keep these messages as simple as possible, since they
641 640 basically only mean to convey the ``raw_input(prompt)`` call.
642 641
643 642 Message type: ``input_request``::
644 643
645 644 content = { 'prompt' : str }
646 645
647 646 Message type: ``input_reply``::
648 647
649 648 content = { 'value' : str }
650 649
651 650 .. Note::
652 651
653 652 We do not explicitly try to forward the raw ``sys.stdin`` object, because in
654 653 practice the kernel should behave like an interactive program. When a
655 654 program is opened on the console, the keyboard effectively takes over the
656 655 ``stdin`` file descriptor, and it can't be used for raw reading anymore.
657 656 Since the IPython kernel effectively behaves like a console program (albeit
658 657 one whose "keyboard" is actually living in a separate process and
659 658 transported over the zmq connection), raw ``stdin`` isn't expected to be
660 659 available.
661 660
662 661
663 662 Heartbeat for kernels
664 663 =====================
665 664
666 665 Initially we had considered using messages like those above over ZMQ for a
667 666 kernel 'heartbeat' (a way to detect quickly and reliably whether a kernel is
668 667 alive at all, even if it may be busy executing user code). But this has the
669 668 problem that if the kernel is locked inside extension code, it wouldn't execute
670 669 the python heartbeat code. But it turns out that we can implement a basic
671 670 heartbeat with pure ZMQ, without using any Python messaging at all.
672 671
673 672 The monitor sends out a single zmq message (right now, it is a str of the
674 673 monitor's lifetime in seconds), and gets the same message right back, prefixed
675 674 with the zmq identity of the XREQ socket in the heartbeat process. This can be
676 675 a uuid, or even a full message, but there doesn't seem to be a need for packing
677 676 up a message when the sender and receiver are the exact same Python object.
678 677
679 678 The model is this::
680 679
681 680 monitor.send(str(self.lifetime)) # '1.2345678910'
682 681
683 682 and the monitor receives some number of messages of the form::
684 683
685 684 ['uuid-abcd-dead-beef', '1.2345678910']
686 685
687 686 where the first part is the zmq.IDENTITY of the heart's XREQ on the engine, and
688 687 the rest is the message sent by the monitor. No Python code ever has any
689 688 access to the message between the monitor's send, and the monitor's recv.
690 689
691 690
692 691 ToDo
693 692 ====
694 693
695 694 Missing things include:
696 695
697 696 * Important: finish thinking through the payload concept and API.
698 697
699 698 * Important: ensure that we have a good solution for magics like %edit. It's
700 699 likely that with the payload concept we can build a full solution, but not
701 700 100% clear yet.
702 701
703 702 * Finishing the details of the heartbeat protocol.
704 703
705 704 * Signal handling: specify what kind of information kernel should broadcast (or
706 705 not) when it receives signals.
707 706
708 707 .. include:: ../links.rst
General Comments 0
You need to be logged in to leave comments. Login now