diff --git a/IPython/core/display.py b/IPython/core/display.py index 8c043a1..e99a4fa 100644 --- a/IPython/core/display.py +++ b/IPython/core/display.py @@ -126,13 +126,13 @@ def display(*objs, **kwargs): else: continue if raw: - publish_display_data('display', obj, metadata) + publish_display_data(data=obj, metadata=metadata) else: format_dict, md_dict = format(obj, include=include, exclude=exclude) if metadata: # kwarg-specified metadata gets precedence _merge(md_dict, metadata) - publish_display_data('display', format_dict, md_dict) + publish_display_data(data=format_dict, metadata=md_dict) def display_pretty(*objs, **kwargs): diff --git a/IPython/core/displaypub.py b/IPython/core/displaypub.py index dedd9e9..99c4a61 100644 --- a/IPython/core/displaypub.py +++ b/IPython/core/displaypub.py @@ -10,22 +10,10 @@ There are two components of the display system: This module defines the logic display publishing. The display publisher uses the ``display_data`` message type that is defined in the IPython messaging spec. - -Authors: - -* Brian Granger """ -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. from __future__ import print_function @@ -45,29 +33,24 @@ class DisplayPublisher(Configurable): be accessed there. """ - def _validate_data(self, source, data, metadata=None): + def _validate_data(self, data, metadata=None): """Validate the display data. Parameters ---------- - source : str - The fully dotted name of the callable that created the data, like - :func:`foo.bar.my_formatter`. data : dict The formata data dictionary. metadata : dict Any metadata for the data. """ - if not isinstance(source, string_types): - raise TypeError('source must be a str, got: %r' % source) if not isinstance(data, dict): raise TypeError('data must be a dict, got: %r' % data) if metadata is not None: if not isinstance(metadata, dict): raise TypeError('metadata must be a dict, got: %r' % data) - def publish(self, source, data, metadata=None): + def publish(self, data, metadata=None, source=None): """Publish data and metadata to all frontends. See the ``display_data`` message in the messaging documentation for @@ -87,9 +70,6 @@ class DisplayPublisher(Configurable): Parameters ---------- - source : str - A string that give the function or method that created the data, - such as 'IPython.core.page'. data : dict A dictionary having keys that are valid MIME types (like 'text/plain' or 'image/svg+xml') and values that are the data for @@ -104,6 +84,8 @@ class DisplayPublisher(Configurable): the data. Metadata specific to each mime-type can be specified in the metadata dict with the same mime-type keys as the data itself. + source : str, deprecated + Unused. """ # The default is to simply write the plain text data using io.stdout. @@ -122,8 +104,8 @@ class CapturingDisplayPublisher(DisplayPublisher): """A DisplayPublisher that stores""" outputs = List() - def publish(self, source, data, metadata=None): - self.outputs.append((source, data, metadata)) + def publish(self, data, metadata=None, source=None): + self.outputs.append((data, metadata)) def clear_output(self, wait=False): super(CapturingDisplayPublisher, self).clear_output(wait) @@ -132,7 +114,7 @@ class CapturingDisplayPublisher(DisplayPublisher): del self.outputs[:] -def publish_display_data(source, data, metadata=None): +def publish_display_data(data, metadata=None, source=None): """Publish data and metadata to all frontends. See the ``display_data`` message in the messaging documentation for @@ -152,9 +134,6 @@ def publish_display_data(source, data, metadata=None): Parameters ---------- - source : str - A string that give the function or method that created the data, - such as 'IPython.core.page'. data : dict A dictionary having keys that are valid MIME types (like 'text/plain' or 'image/svg+xml') and values that are the data for @@ -168,12 +147,13 @@ def publish_display_data(source, data, metadata=None): arbitrary key, value pairs that frontends can use to interpret the data. mime-type keys matching those in data can be used to specify metadata about particular representations. + source : str, deprecated + Unused. """ from IPython.core.interactiveshell import InteractiveShell InteractiveShell.instance().display_pub.publish( - source, - data, - metadata + data=data, + metadata=metadata, ) diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index 4ab5569..fc710f2 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -10,12 +10,7 @@ # the file COPYING, distributed as part of this software. #----------------------------------------------------------------------------- -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -from __future__ import absolute_import -from __future__ import print_function +from __future__ import absolute_import, print_function import __future__ import abc @@ -57,6 +52,7 @@ from IPython.core.payload import PayloadManager from IPython.core.prefilter import PrefilterManager from IPython.core.profiledir import ProfileDir from IPython.core.prompts import PromptManager +from IPython.core.usage import default_banner from IPython.lib.latextools import LaTeXTool from IPython.testing.skipdoctest import skip_doctest from IPython.utils import PyColorize @@ -233,6 +229,16 @@ class InteractiveShell(SingletonConfigurable): Enable magic commands to be called without the leading %. """ ) + + banner = Unicode('') + + banner1 = Unicode(default_banner, config=True, + help="""The part of the banner to be printed before the profile""" + ) + banner2 = Unicode('', config=True, + help="""The part of the banner to be printed after the profile""" + ) + cache_size = Integer(1000, config=True, help= """ Set the size of the output cache. The default is 1000, you can @@ -773,6 +779,24 @@ class InteractiveShell(SingletonConfigurable): sys.modules[self._orig_sys_modules_main_name] = self._orig_sys_modules_main_mod #------------------------------------------------------------------------- + # Things related to the banner + #------------------------------------------------------------------------- + + @property + def banner(self): + banner = self.banner1 + if self.profile and self.profile != 'default': + banner += '\nIPython profile: %s\n' % self.profile + if self.banner2: + banner += '\n' + self.banner2 + return banner + + def show_banner(self, banner=None): + if banner is None: + banner = self.banner + self.write(banner) + + #------------------------------------------------------------------------- # Things related to hooks #------------------------------------------------------------------------- @@ -1502,6 +1526,7 @@ class InteractiveShell(SingletonConfigurable): return 'not found' # so callers can take other action def object_inspect(self, oname, detail_level=0): + """Get object info about oname""" with self.builtin_trap: info = self._object_find(oname) if info.found: @@ -1511,6 +1536,17 @@ class InteractiveShell(SingletonConfigurable): else: return oinspect.object_info(name=oname, found=False) + def object_inspect_text(self, oname, detail_level=0): + """Get object info as formatted text""" + with self.builtin_trap: + info = self._object_find(oname) + if info.found: + return self.inspector._format_info(info.obj, oname, info=info, + detail_level=detail_level + ) + else: + raise KeyError(oname) + #------------------------------------------------------------------------- # Things related to history management #------------------------------------------------------------------------- @@ -2395,7 +2431,7 @@ class InteractiveShell(SingletonConfigurable): def _user_obj_error(self): """return simple exception dict - for use in user_variables / expressions + for use in user_expressions """ etype, evalue, tb = self._get_exc_info() @@ -2413,7 +2449,7 @@ class InteractiveShell(SingletonConfigurable): def _format_user_obj(self, obj): """format a user object to display dict - for use in user_expressions / variables + for use in user_expressions """ data, md = self.display_formatter.format(obj) @@ -2424,30 +2460,6 @@ class InteractiveShell(SingletonConfigurable): } return value - def user_variables(self, names): - """Get a list of variable names from the user's namespace. - - Parameters - ---------- - names : list of strings - A list of names of variables to be read from the user namespace. - - Returns - ------- - A dict, keyed by the input names and with the rich mime-type repr(s) of each value. - Each element will be a sub-dict of the same form as a display_data message. - """ - out = {} - user_ns = self.user_ns - - for varname in names: - try: - value = self._format_user_obj(user_ns[varname]) - except: - value = self._user_obj_error() - out[varname] = value - return out - def user_expressions(self, expressions): """Evaluate a dict of expressions in the user's namespace. diff --git a/IPython/core/oinspect.py b/IPython/core/oinspect.py index 6353856..253fc26 100644 --- a/IPython/core/oinspect.py +++ b/IPython/core/oinspect.py @@ -7,12 +7,9 @@ Similar in spirit to the inspect module, but all calls take a name argument to reference the name under which an object is being read. """ -#***************************************************************************** -# Copyright (C) 2001-2004 Fernando Perez -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#***************************************************************************** +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. + from __future__ import print_function __all__ = ['Inspector','InspectColors'] @@ -532,21 +529,9 @@ class Inspector: ("Init docstring", "init_docstring"), ("Call def", "call_def"), ("Call docstring", "call_docstring")] - - def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0): - """Show detailed information about an object. - - Optional arguments: - - - oname: name of the variable pointing to the object. - - - formatter: special formatter for docstrings (see pdoc) - - - info: a structure with some information fields which may have been - precomputed already. - - - detail_level: if set to 1, more information is given. - """ + + def _format_info(self, obj, oname='', formatter=None, info=None, detail_level=0): + """Format an info dict as text""" info = self.info(obj, oname=oname, formatter=formatter, info=info, detail_level=detail_level) displayfields = [] @@ -590,11 +575,30 @@ class Inspector: # Info for objects: else: add_fields(self.pinfo_fields_obj) - - # Finally send to printer/pager: + if displayfields: - page.page(self._format_fields(displayfields)) + return self._format_fields(displayfields) + else: + return u'' + + def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0): + """Show detailed information about an object. + + Optional arguments: + + - oname: name of the variable pointing to the object. + - formatter: special formatter for docstrings (see pdoc) + + - info: a structure with some information fields which may have been + precomputed already. + + - detail_level: if set to 1, more information is given. + """ + text = self._format_info(obj, oname, formatter, info, detail_level) + if text: + page.page(text) + def info(self, obj, oname='', formatter=None, info=None, detail_level=0): """Compute a dict with detailed information about an object. diff --git a/IPython/core/page.py b/IPython/core/page.py index 23fedb5..518b6f9 100644 --- a/IPython/core/page.py +++ b/IPython/core/page.py @@ -133,7 +133,10 @@ def _detect_screen_size(screen_lines_def): #screen_cols,'columns.' # dbg def page(strng, start=0, screen_lines=0, pager_cmd=None): - """Print a string, piping through a pager after a certain length. + """Display a string, piping through a pager after a certain length. + + strng can be a mime-bundle dict, supplying multiple representations, + keyed by mime-type. The screen_lines parameter specifies the number of *usable* lines of your terminal screen (total lines minus lines you need to reserve to show other @@ -152,6 +155,10 @@ def page(strng, start=0, screen_lines=0, pager_cmd=None): If no system pager works, the string is sent through a 'dumb pager' written in python, very simplistic. """ + + # for compatibility with mime-bundle form: + if isinstance(strng, dict): + strng = strng['text/plain'] # Some routines may auto-compute start offsets incorrectly and pass a # negative value. Offset to 0 for robustness. diff --git a/IPython/core/payloadpage.py b/IPython/core/payloadpage.py index b1d07a6..682fd9b 100644 --- a/IPython/core/payloadpage.py +++ b/IPython/core/payloadpage.py @@ -1,41 +1,16 @@ # encoding: utf-8 -""" -A payload based version of page. +"""A payload based version of page.""" -Authors: +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. -* Brian Granger -* Fernando Perez -""" - -#----------------------------------------------------------------------------- -# Copyright (C) 2008-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- - -# Third-party -try: - from docutils.core import publish_string -except ImportError: - # html paging won't be available, but we don't raise any errors. It's a - # purely optional feature. - pass - -# Our own -from IPython.core.interactiveshell import InteractiveShell +from IPython.core.getipython import get_ipython #----------------------------------------------------------------------------- # Classes and functions #----------------------------------------------------------------------------- -def page(strng, start=0, screen_lines=0, pager_cmd=None, - html=None, auto_html=False): +def page(strng, start=0, screen_lines=0, pager_cmd=None): """Print a string, piping through a pager. This version ignores the screen_lines and pager_cmd arguments and uses @@ -43,49 +18,28 @@ def page(strng, start=0, screen_lines=0, pager_cmd=None, Parameters ---------- - strng : str - Text to page. + strng : str or mime-dict + Text to page, or a mime-type keyed dict of already formatted data. start : int Starting line at which to place the display. - - html : str, optional - If given, an html string to send as well. - - auto_html : bool, optional - If true, the input string is assumed to be valid reStructuredText and is - converted to HTML with docutils. Note that if docutils is not found, - this option is silently ignored. - - Notes - ----- - - Only one of the ``html`` and ``auto_html`` options can be given, not - both. """ # Some routines may auto-compute start offsets incorrectly and pass a # negative value. Offset to 0 for robustness. start = max(0, start) - shell = InteractiveShell.instance() - - if auto_html: - try: - # These defaults ensure user configuration variables for docutils - # are not loaded, only our config is used here. - defaults = {'file_insertion_enabled': 0, - 'raw_enabled': 0, - '_disable_config': 1} - html = publish_string(strng, writer_name='html', - settings_overrides=defaults) - except: - pass - + shell = get_ipython() + + if isinstance(strng, dict): + data = strng + else: + data = {'text/plain' : strng} payload = dict( source='page', + data=data, text=strng, - html=html, - start_line_number=start + start=start, + screen_lines=screen_lines, ) shell.payload_manager.write_payload(payload) diff --git a/IPython/core/release.py b/IPython/core/release.py index e51a93c..822b940 100644 --- a/IPython/core/release.py +++ b/IPython/core/release.py @@ -40,7 +40,8 @@ version = __version__ # backwards compatibility name version_info = (_version_major, _version_minor, _version_patch, _version_extra) # Change this when incrementing the kernel protocol version -kernel_protocol_version_info = (4, 1) +kernel_protocol_version_info = (5, 0) +kernel_protocol_version = "%i.%i" % kernel_protocol_version_info description = "IPython: Productive Interactive Computing" diff --git a/IPython/core/tests/test_interactiveshell.py b/IPython/core/tests/test_interactiveshell.py index b01dc6d..f5ceb03 100644 --- a/IPython/core/tests/test_interactiveshell.py +++ b/IPython/core/tests/test_interactiveshell.py @@ -4,22 +4,11 @@ Historically the main classes in interactiveshell have been under-tested. This module should grow as many single-method tests as possible to trap many of the recurring bugs we seem to encounter with high-level interaction. - -Authors -------- -* Fernando Perez """ -#----------------------------------------------------------------------------- -# Copyright (C) 2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#----------------------------------------------------------------------------- -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- -# stdlib +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. + import ast import os import signal @@ -33,10 +22,8 @@ except ImportError: import mock from os.path import join -# third-party import nose.tools as nt -# Our own from IPython.core.inputtransformer import InputTransformer from IPython.testing.decorators import skipif, skip_win32, onlyif_unicode_paths from IPython.testing import tools as tt @@ -645,7 +632,7 @@ def test_user_variables(): ip.user_ns['dummy'] = d = DummyRepr() keys = set(['dummy', 'doesnotexist']) - r = ip.user_variables(keys) + r = ip.user_expressions({ key:key for key in keys}) nt.assert_equal(keys, set(r.keys())) dummy = r['dummy'] @@ -660,7 +647,7 @@ def test_user_variables(): dne = r['doesnotexist'] nt.assert_equal(dne['status'], 'error') - nt.assert_equal(dne['ename'], 'KeyError') + nt.assert_equal(dne['ename'], 'NameError') # back to text only ip.display_formatter.active_types = ['text/plain'] diff --git a/IPython/html/static/base/js/utils.js b/IPython/html/static/base/js/utils.js index b8aba88..f12f9d4 100644 --- a/IPython/html/static/base/js/utils.js +++ b/IPython/html/static/base/js/utils.js @@ -1,13 +1,10 @@ -//---------------------------------------------------------------------------- -// Copyright (C) 2008-2012 The IPython Development Team -// -// Distributed under the terms of the BSD License. The full license is in -// the file COPYING, distributed as part of this software. -//---------------------------------------------------------------------------- +// Copyright (c) IPython Development Team. +// Distributed under the terms of the Modified BSD License. //============================================================================ // Utilities //============================================================================ + IPython.namespace('IPython.utils'); IPython.utils = (function (IPython) { @@ -430,7 +427,7 @@ IPython.utils = (function (IPython) { var escape_html = function (text) { // escape text to HTML return $("
").text(text).html(); - } + }; var get_body_data = function(key) { @@ -439,8 +436,40 @@ IPython.utils = (function (IPython) { // until we are building an actual request return decodeURIComponent($('body').data(key)); }; - - + + var to_absolute_cursor_pos = function (cm, cursor) { + // get the absolute cursor position from CodeMirror's col, ch + if (!cursor) { + cursor = cm.getCursor(); + } + var cursor_pos = cursor.ch; + for (var i = 0; i < cursor.line; i++) { + cursor_pos += cm.getLine(i).length + 1; + } + return cursor_pos; + }; + + var from_absolute_cursor_pos = function (cm, cursor_pos) { + // turn absolute cursor postion into CodeMirror col, ch cursor + var i, line; + var offset = 0; + for (i = 0, line=cm.getLine(i); line !== undefined; i++, line=cm.getLine(i)) { + if (offset + line.length < cursor_pos) { + offset += line.length + 1; + } else { + return { + line : i, + ch : cursor_pos - offset, + }; + } + } + // reached end, return endpoint + return { + ch : line.length - 1, + line : i - 1, + }; + }; + // http://stackoverflow.com/questions/2400935/browser-detection-in-javascript var browser = (function() { if (typeof navigator === 'undefined') { @@ -449,7 +478,7 @@ IPython.utils = (function (IPython) { } var N= navigator.appName, ua= navigator.userAgent, tem; var M= ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i); - if (M && (tem= ua.match(/version\/([\.\d]+)/i))!= null) M[2]= tem[1]; + if (M && (tem= ua.match(/version\/([\.\d]+)/i)) !== null) M[2]= tem[1]; M= M? [M[1], M[2]]: [N, navigator.appVersion,'-?']; return M; })(); @@ -465,13 +494,13 @@ IPython.utils = (function (IPython) { if (navigator.appVersion.indexOf("Mac")!=-1) OSName="MacOS"; if (navigator.appVersion.indexOf("X11")!=-1) OSName="UNIX"; if (navigator.appVersion.indexOf("Linux")!=-1) OSName="Linux"; - return OSName + return OSName; })(); var is_or_has = function (a, b) { // Is b a child of a or a itself? return a.has(b).length !==0 || a.is(b); - } + }; var is_focused = function (e) { // Is element e, or one of its children focused? @@ -486,7 +515,7 @@ IPython.utils = (function (IPython) { } else { return false; } - } + }; var log_ajax_error = function (jqXHR, status, error) { // log ajax failures with informative messages @@ -499,7 +528,7 @@ IPython.utils = (function (IPython) { } console.log(msg); }; - + return { regex_split : regex_split, uuid : uuid, @@ -515,6 +544,8 @@ IPython.utils = (function (IPython) { splitext : splitext, escape_html : escape_html, always_new : always_new, + to_absolute_cursor_pos : to_absolute_cursor_pos, + from_absolute_cursor_pos : from_absolute_cursor_pos, browser : browser, platform: platform, is_or_has : is_or_has, diff --git a/IPython/html/static/notebook/js/completer.js b/IPython/html/static/notebook/js/completer.js index df940b3..bddf732 100644 --- a/IPython/html/static/notebook/js/completer.js +++ b/IPython/html/static/notebook/js/completer.js @@ -1,21 +1,26 @@ -// function completer. +// Copyright (c) IPython Development Team. +// Distributed under the terms of the Modified BSD License. + +// Completer // -// completer should be a class that takes an cell instance +// Completer is be a class that takes a cell instance. + var IPython = (function (IPython) { // that will prevent us from misspelling "use strict"; // easier key mapping var keycodes = IPython.keyboard.keycodes; + var utils = IPython.utils; - function prepend_n_prc(str, n) { + var prepend_n_prc = function(str, n) { for( var i =0 ; i< n ; i++){ str = '%'+str ; } return str; }; - function _existing_completion(item, completion_array){ + var _existing_completion = function(item, completion_array){ for( var i=0; i < completion_array.length; i++) { if (completion_array[i].trim().substr(-item.length) == item) { return true; @@ -143,13 +148,17 @@ var IPython = (function (IPython) { // one kernel completion came back, finish_completing will be called with the results // we fork here and directly call finish completing if kernel is busy + var cursor_pos = utils.to_absolute_cursor_pos(this.editor, cur); if (this.skip_kernel_completion) { - this.finish_completing({ - 'matches': [], - matched_text: "" - }); + this.finish_completing({ content: { + matches: [], + cursor_start: cursor_pos, + cursor_end: cursor_pos, + }}); } else { - this.cell.kernel.complete(line, cur.ch, $.proxy(this.finish_completing, this)); + this.cell.kernel.complete(this.editor.getValue(), cursor_pos, + $.proxy(this.finish_completing, this) + ); } }; @@ -157,7 +166,8 @@ var IPython = (function (IPython) { // let's build a function that wrap all that stuff into what is needed // for the new completer: var content = msg.content; - var matched_text = content.matched_text; + var start = content.cursor_start; + var end = content.cursor_end; var matches = content.matches; var cur = this.editor.getCursor(); @@ -165,7 +175,8 @@ var IPython = (function (IPython) { var filtered_results = []; //remove results from context completion //that are already in kernel completion - for (var i=0; i < results.length; i++) { + var i; + for (i=0; i < results.length; i++) { if (!_existing_completion(results[i].str, matches)) { filtered_results.push(results[i]); } @@ -174,18 +185,12 @@ var IPython = (function (IPython) { // append the introspection result, in order, at at the beginning of // the table and compute the replacement range from current cursor // positon and matched_text length. - for (var i = matches.length - 1; i >= 0; --i) { + for (i = matches.length - 1; i >= 0; --i) { filtered_results.unshift({ str: matches[i], type: "introspection", - from: { - line: cur.line, - ch: cur.ch - matched_text.length - }, - to: { - line: cur.line, - ch: cur.ch - } + from: utils.from_absolute_cursor_pos(this.editor, start), + to: utils.from_absolute_cursor_pos(this.editor, end) }); } @@ -249,8 +254,9 @@ var IPython = (function (IPython) { // After everything is on the page, compute the postion. // We put it above the code if it is too close to the bottom of the page. - cur.ch = cur.ch-matched_text.length; - var pos = this.editor.cursorCoords(cur); + var pos = this.editor.cursorCoords( + utils.from_absolute_cursor_pos(this.editor, start) + ); var left = pos.left-3; var top; var cheight = this.complete.height(); diff --git a/IPython/html/static/notebook/js/outputarea.js b/IPython/html/static/notebook/js/outputarea.js index 27a4ca9..337e07f 100644 --- a/IPython/html/static/notebook/js/outputarea.js +++ b/IPython/html/static/notebook/js/outputarea.js @@ -1,9 +1,5 @@ -//---------------------------------------------------------------------------- -// Copyright (C) 2008 The IPython Development Team -// -// Distributed under the terms of the BSD License. The full license is in -// the file COPYING, distributed as part of this software. -//---------------------------------------------------------------------------- +// Copyright (c) IPython Development Team. +// Distributed under the terms of the Modified BSD License. //============================================================================ // OutputArea @@ -221,15 +217,18 @@ var IPython = (function (IPython) { json = content.data; json.output_type = msg_type; json.metadata = content.metadata; - } else if (msg_type === "pyout") { + } else if (msg_type === "execute_result") { json = content.data; json.output_type = msg_type; json.metadata = content.metadata; json.prompt_number = content.execution_count; - } else if (msg_type === "pyerr") { + } else if (msg_type === "error") { json.ename = content.ename; json.evalue = content.evalue; json.traceback = content.traceback; + } else { + console.log("unhandled output message", msg); + return; } this.append_output(json); }; @@ -283,10 +282,10 @@ var IPython = (function (IPython) { needs_height_reset = true; } - if (json.output_type === 'pyout') { - this.append_pyout(json); - } else if (json.output_type === 'pyerr') { - this.append_pyerr(json); + if (json.output_type === 'execute_result') { + this.append_execute_result(json); + } else if (json.output_type === 'error') { + this.append_error(json); } else if (json.output_type === 'stream') { this.append_stream(json); } @@ -406,7 +405,7 @@ var IPython = (function (IPython) { }; - OutputArea.prototype.append_pyout = function (json) { + OutputArea.prototype.append_execute_result = function (json) { var n = json.prompt_number || ' '; var toinsert = this.create_output_area(); if (this.prompt_area) { @@ -414,7 +413,7 @@ var IPython = (function (IPython) { } var inserted = this.append_mime_type(json, toinsert); if (inserted) { - inserted.addClass('output_pyout'); + inserted.addClass('output_result'); } this._safe_append(toinsert); // If we just output latex, typeset it. @@ -426,7 +425,7 @@ var IPython = (function (IPython) { }; - OutputArea.prototype.append_pyerr = function (json) { + OutputArea.prototype.append_error = function (json) { var tb = json.traceback; if (tb !== undefined && tb.length > 0) { var s = ''; @@ -438,7 +437,7 @@ var IPython = (function (IPython) { var toinsert = this.create_output_area(); var append_text = OutputArea.append_map['text/plain']; if (append_text) { - append_text.apply(this, [s, {}, toinsert]).addClass('output_pyerr'); + append_text.apply(this, [s, {}, toinsert]).addClass('output_error'); } this._safe_append(toinsert); } @@ -746,6 +745,8 @@ var IPython = (function (IPython) { // disable any other raw_inputs, if they are left around $("div.output_subarea.raw_input_container").remove(); + var input_type = content.password ? 'password' : 'text'; + area.append( $("
") .addClass("box-flex1 output_subarea raw_input_container") @@ -757,7 +758,7 @@ var IPython = (function (IPython) { .append( $("") .addClass("raw_input") - .attr('type', 'text') + .attr('type', input_type) .attr("size", 47) .keydown(function (event, ui) { // make sure we submit on enter, @@ -786,10 +787,15 @@ var IPython = (function (IPython) { var theprompt = container.find("span.raw_input_prompt"); var theinput = container.find("input.raw_input"); var value = theinput.val(); + var echo = value; + // don't echo if it's a password + if (theinput.attr('type') == 'password') { + echo = '········'; + } var content = { output_type : 'stream', name : 'stdout', - text : theprompt.text() + value + '\n' + text : theprompt.text() + echo + '\n' } // remove form container container.parent().remove(); @@ -850,11 +856,26 @@ var IPython = (function (IPython) { for (var i=0; i