##// END OF EJS Templates
Make errors clearer!
Make errors clearer!

File last commit:

r18545:dbb3d415 merge
r18901:850a84df
Show More
ipkernel.py
327 lines | 12.4 KiB | text/x-python | PythonLexer
Thomas Kluyver
Separate IPython kernel implementation from kernel machinery
r16857 """The IPython kernel implementation"""
import getpass
import sys
import traceback
from IPython.core import release
Jonathan Frederic
Register the Widget target with the comm manager after construction.
r18510 from IPython.html.widgets import Widget
Thomas Kluyver
Separate IPython kernel implementation from kernel machinery
r16857 from IPython.utils.py3compat import builtin_mod, PY3
MinRK
only complete on current line...
r18478 from IPython.utils.tokenutil import token_at_cursor, line_at_cursor
Thomas Kluyver
Separate IPython kernel implementation from kernel machinery
r16857 from IPython.utils.traitlets import Instance, Type, Any
Thomas Kluyver
Rename KernelBase & Kernel to Kernel & IPythonKernel
r17095 from IPython.utils.decorators import undoc
Thomas Kluyver
Separate IPython kernel implementation from kernel machinery
r16857
Thomas Kluyver
Make comm_manager a property of kernel, not shell
r17987 from ..comm import CommManager
Thomas Kluyver
Rename KernelBase & Kernel to Kernel & IPythonKernel
r17095 from .kernelbase import Kernel as KernelBase
Thomas Kluyver
Separate IPython kernel implementation from kernel machinery
r16857 from .serialize import serialize_object, unpack_apply_message
from .zmqshell import ZMQInteractiveShell
Thomas Kluyver
Restore ipkernel module
r16856
Thomas Kluyver
Rename KernelBase & Kernel to Kernel & IPythonKernel
r17095 class IPythonKernel(KernelBase):
Thomas Kluyver
Separate IPython kernel implementation from kernel machinery
r16857 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
shell_class = Type(ZMQInteractiveShell)
user_module = Any()
def _user_module_changed(self, name, old, new):
if self.shell is not None:
self.shell.user_module = new
user_ns = Instance(dict, args=None, allow_none=True)
def _user_ns_changed(self, name, old, new):
if self.shell is not None:
self.shell.user_ns = new
self.shell.init_user_ns()
# A reference to the Python builtin 'raw_input' function.
# (i.e., __builtin__.raw_input for Python 2.7, builtins.input for Python 3)
_sys_raw_input = Any()
_sys_eval_input = Any()
def __init__(self, **kwargs):
Thomas Kluyver
Rename KernelBase & Kernel to Kernel & IPythonKernel
r17095 super(IPythonKernel, self).__init__(**kwargs)
Thomas Kluyver
Separate IPython kernel implementation from kernel machinery
r16857
# Initialize the InteractiveShell subclass
self.shell = self.shell_class.instance(parent=self,
profile_dir = self.profile_dir,
user_module = self.user_module,
user_ns = self.user_ns,
kernel = self,
)
self.shell.displayhook.session = self.session
self.shell.displayhook.pub_socket = self.iopub_socket
self.shell.displayhook.topic = self._topic('execute_result')
self.shell.display_pub.session = self.session
self.shell.display_pub.pub_socket = self.iopub_socket
self.shell.data_pub.session = self.session
self.shell.data_pub.pub_socket = self.iopub_socket
# TMP - hack while developing
self.shell._reply_content = None
Thomas Kluyver
Make comm_manager a property of kernel, not shell
r17987 self.comm_manager = CommManager(shell=self.shell, parent=self,
kernel=self)
Jonathan Frederic
Register the Widget target with the comm manager after construction.
r18510 self.comm_manager.register_target('ipython.widget', Widget.handle_comm_opened)
Thomas Kluyver
Make comm_manager a property of kernel, not shell
r17987 self.shell.configurables.append(self.comm_manager)
Thomas Kluyver
Separate IPython kernel implementation from kernel machinery
r16857 comm_msg_types = [ 'comm_open', 'comm_msg', 'comm_close' ]
for msg_type in comm_msg_types:
Thomas Kluyver
Make comm_manager a property of kernel, not shell
r17987 self.shell_handlers[msg_type] = getattr(self.comm_manager, msg_type)
Thomas Kluyver
Separate IPython kernel implementation from kernel machinery
r16857
# Kernel info fields
implementation = 'ipython'
implementation_version = release.version
language = 'python'
language_version = sys.version.split()[0]
Thomas Kluyver
Move language info from kernelspec to kernel_info_reply
r18468 language_info = {'mimetype': 'text/x-python',
'codemirror_mode': {'name': 'ipython',
'version': sys.version_info[0]},
'pygments_lexer': 'ipython%d' % (3 if PY3 else 2),
}
Thomas Kluyver
Separate IPython kernel implementation from kernel machinery
r16857 @property
def banner(self):
return self.shell.banner
Thomas Kluyver
Stub out kernel methods to allow overriding a subset of them.
r16858 def start(self):
self.shell.exit_now = False
Thomas Kluyver
Rename KernelBase & Kernel to Kernel & IPythonKernel
r17095 super(IPythonKernel, self).start()
Thomas Kluyver
Stub out kernel methods to allow overriding a subset of them.
r16858
Thomas Kluyver
Separate IPython kernel implementation from kernel machinery
r16857 def set_parent(self, ident, parent):
"""Overridden from parent to tell the display hook and output streams
about the parent message.
"""
Thomas Kluyver
Rename KernelBase & Kernel to Kernel & IPythonKernel
r17095 super(IPythonKernel, self).set_parent(ident, parent)
Thomas Kluyver
Separate IPython kernel implementation from kernel machinery
r16857 self.shell.set_parent(parent)
def _forward_input(self, allow_stdin=False):
"""Forward raw_input and getpass to the current frontend.
via input_request
"""
self._allow_stdin = allow_stdin
if PY3:
self._sys_raw_input = builtin_mod.input
builtin_mod.input = self.raw_input
else:
self._sys_raw_input = builtin_mod.raw_input
self._sys_eval_input = builtin_mod.input
builtin_mod.raw_input = self.raw_input
builtin_mod.input = lambda prompt='': eval(self.raw_input(prompt))
self._save_getpass = getpass.getpass
getpass.getpass = self.getpass
def _restore_input(self):
"""Restore raw_input, getpass"""
if PY3:
builtin_mod.input = self._sys_raw_input
else:
builtin_mod.raw_input = self._sys_raw_input
builtin_mod.input = self._sys_eval_input
getpass.getpass = self._save_getpass
@property
def execution_count(self):
return self.shell.execution_count
@execution_count.setter
def execution_count(self, value):
# Ignore the incrememnting done by KernelBase, in favour of our shell's
# execution counter.
pass
def do_execute(self, code, silent, store_history=True,
user_expressions=None, allow_stdin=False):
shell = self.shell # we'll need this a lot here
self._forward_input(allow_stdin)
reply_content = {}
# FIXME: the shell calls the exception handler itself.
shell._reply_content = None
try:
shell.run_cell(code, store_history=store_history, silent=silent)
except:
status = u'error'
# FIXME: this code right now isn't being used yet by default,
# because the run_cell() call above directly fires off exception
# reporting. This code, therefore, is only active in the scenario
# where runlines itself has an unhandled exception. We need to
# uniformize this, for all exception construction to come from a
# single location in the codbase.
etype, evalue, tb = sys.exc_info()
tb_list = traceback.format_exception(etype, evalue, tb)
reply_content.update(shell._showtraceback(etype, evalue, tb_list))
else:
status = u'ok'
finally:
self._restore_input()
reply_content[u'status'] = status
# Return the execution counter so clients can display prompts
reply_content['execution_count'] = shell.execution_count - 1
# FIXME - fish exception info out of shell, possibly left there by
# runlines. We'll need to clean up this logic later.
if shell._reply_content is not None:
reply_content.update(shell._reply_content)
e_info = dict(engine_uuid=self.ident, engine_id=self.int_id, method='execute')
reply_content['engine_info'] = e_info
# reset after use
shell._reply_content = None
if 'traceback' in reply_content:
self.log.info("Exception in execute request:\n%s", '\n'.join(reply_content['traceback']))
# At this point, we can tell whether the main code execution succeeded
# or not. If it did, we proceed to evaluate user_expressions
if reply_content['status'] == 'ok':
reply_content[u'user_expressions'] = \
shell.user_expressions(user_expressions or {})
else:
# If there was an error, don't even try to compute expressions
reply_content[u'user_expressions'] = {}
# Payloads should be retrieved regardless of outcome, so we can both
# recover partial output (that could have been generated early in a
# block, before an error) and clear the payload system always.
reply_content[u'payload'] = shell.payload_manager.read_payload()
# Be agressive about clearing the payload because we don't want
# it to sit in memory until the next execute_request comes in.
shell.payload_manager.clear_payload()
return reply_content
def do_complete(self, code, cursor_pos):
MinRK
only complete on current line...
r18478 # FIXME: IPython completers currently assume single line,
# but completion messages give multi-line context
# For now, extract line from cell, based on cursor_pos:
if cursor_pos is None:
cursor_pos = len(code)
line, offset = line_at_cursor(code, cursor_pos)
line_cursor = cursor_pos - offset
txt, matches = self.shell.complete('', line, line_cursor)
Thomas Kluyver
Separate IPython kernel implementation from kernel machinery
r16857 return {'matches' : matches,
'cursor_end' : cursor_pos,
'cursor_start' : cursor_pos - len(txt),
'metadata' : {},
'status' : 'ok'}
def do_inspect(self, code, cursor_pos, detail_level=0):
name = token_at_cursor(code, cursor_pos)
info = self.shell.object_inspect(name)
reply_content = {'status' : 'ok'}
reply_content['data'] = data = {}
reply_content['metadata'] = {}
reply_content['found'] = info['found']
if info['found']:
info_text = self.shell.object_inspect_text(
name,
detail_level=detail_level,
)
data['text/plain'] = info_text
return reply_content
def do_history(self, hist_access_type, output, raw, session=None, start=None,
stop=None, n=None, pattern=None, unique=False):
if hist_access_type == 'tail':
hist = self.shell.history_manager.get_tail(n, raw=raw, output=output,
include_latest=True)
elif hist_access_type == 'range':
hist = self.shell.history_manager.get_range(session, start, stop,
raw=raw, output=output)
elif hist_access_type == 'search':
hist = self.shell.history_manager.search(
pattern, raw=raw, output=output, n=n, unique=unique)
else:
hist = []
return {'history' : list(hist)}
def do_shutdown(self, restart):
self.shell.exit_now = True
return dict(status='ok', restart=restart)
Thomas Kluyver
Expose IPython machinery for testing code completeness
r17624 def do_is_complete(self, code):
Thomas Kluyver
Four possible states for completion reply, & indent hint
r17804 status, indent_spaces = self.shell.input_transformer_manager.check_complete(code)
r = {'status': status}
if status == 'incomplete':
r['indent'] = ' ' * indent_spaces
return r
Thomas Kluyver
Expose IPython machinery for testing code completeness
r17624
Thomas Kluyver
Separate IPython kernel implementation from kernel machinery
r16857 def do_apply(self, content, bufs, msg_id, reply_metadata):
shell = self.shell
try:
working = shell.user_ns
prefix = "_"+str(msg_id).replace("-","")+"_"
f,args,kwargs = unpack_apply_message(bufs, working, copy=False)
fname = getattr(f, '__name__', 'f')
fname = prefix+"f"
argname = prefix+"args"
kwargname = prefix+"kwargs"
resultname = prefix+"result"
ns = { fname : f, argname : args, kwargname : kwargs , resultname : None }
# print ns
working.update(ns)
code = "%s = %s(*%s,**%s)" % (resultname, fname, argname, kwargname)
try:
exec(code, shell.user_global_ns, shell.user_ns)
result = working.get(resultname)
finally:
for key in ns:
working.pop(key)
result_buf = serialize_object(result,
buffer_threshold=self.session.buffer_threshold,
item_threshold=self.session.item_threshold,
)
except:
# invoke IPython traceback formatting
shell.showtraceback()
# FIXME - fish exception info out of shell, possibly left there by
# run_code. We'll need to clean up this logic later.
reply_content = {}
if shell._reply_content is not None:
reply_content.update(shell._reply_content)
e_info = dict(engine_uuid=self.ident, engine_id=self.int_id, method='apply')
reply_content['engine_info'] = e_info
# reset after use
shell._reply_content = None
self.send_response(self.iopub_socket, u'error', reply_content,
ident=self._topic('error'))
self.log.info("Exception in apply request:\n%s", '\n'.join(reply_content['traceback']))
result_buf = []
if reply_content['ename'] == 'UnmetDependency':
reply_metadata['dependencies_met'] = False
else:
reply_content = {'status' : 'ok'}
return reply_content, result_buf
def do_clear(self):
self.shell.reset(False)
return dict(status='ok')
Thomas Kluyver
Rename KernelBase & Kernel to Kernel & IPythonKernel
r17095
# This exists only for backwards compatibility - use IPythonKernel instead
@undoc
class Kernel(IPythonKernel):
def __init__(self, *args, **kwargs):
import warnings
warnings.warn('Kernel is a deprecated alias of IPython.kernel.zmq.ipkernel.IPythonKernel',
DeprecationWarning)
super(Kernel, self).__init__(*args, **kwargs)