Skip to content

Commit

Permalink
Merge pull request #1 from ipython/master
Browse files Browse the repository at this point in the history
Update from ipython/ipython:master
  • Loading branch information
grelston committed Mar 4, 2015
2 parents 313bf26 + 34a0e6b commit d587f5e
Show file tree
Hide file tree
Showing 29 changed files with 452 additions and 259 deletions.
3 changes: 2 additions & 1 deletion IPython/core/interactiveshell.py
Expand Up @@ -34,7 +34,7 @@
from IPython.core import prefilter
from IPython.core import shadowns
from IPython.core import ultratb
from IPython.core.alias import AliasManager, AliasError
from IPython.core.alias import Alias, AliasManager
from IPython.core.autocall import ExitAutocall
from IPython.core.builtin_trap import BuiltinTrap
from IPython.core.events import EventManager, available_events
Expand Down Expand Up @@ -1502,6 +1502,7 @@ def _ofind(self, oname, namespaces=None):
found = True
ospace = 'IPython internal'
ismagic = True
isalias = isinstance(obj, Alias)

# Last try: special-case some literals like '', [], {}, etc:
if not found and oname_head in ["''",'""','[]','{}','()']:
Expand Down
109 changes: 57 additions & 52 deletions IPython/core/oinspect.py
Expand Up @@ -36,6 +36,7 @@
from IPython.utils import openpy
from IPython.utils import py3compat
from IPython.utils.dir2 import safe_hasattr
from IPython.utils.path import compress_user
from IPython.utils.text import indent
from IPython.utils.wildcard import list_namespace
from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable
Expand Down Expand Up @@ -554,23 +555,6 @@ def _format_fields(self, fields, title_width=0):
title = header((title+":").ljust(title_width))
out.append(cast_unicode(title) + cast_unicode(content))
return "\n".join(out)

# The fields to be displayed by pinfo: (fancy_name, key_in_info_dict)
pinfo_fields1 = [("Type", "type_name"),
]

pinfo_fields2 = [("String form", "string_form"),
]

pinfo_fields3 = [("Length", "length"),
("File", "file"),
("Definition", "definition"),
]

pinfo_fields_obj = [("Class docstring", "class_docstring"),
("Init docstring", "init_docstring"),
("Call def", "call_def"),
("Call docstring", "call_docstring")]

def _format_info(self, obj, oname='', formatter=None, info=None, detail_level=0):
"""Format an info dict as text"""
Expand All @@ -582,41 +566,62 @@ def add_fields(fields):
field = info[key]
if field is not None:
displayfields.append((title, field.rstrip()))

add_fields(self.pinfo_fields1)

# Base class for old-style instances
if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
displayfields.append(("Base Class", info['base_class'].rstrip()))

add_fields(self.pinfo_fields2)

# Namespace
if info['namespace'] != 'Interactive':
displayfields.append(("Namespace", info['namespace'].rstrip()))

add_fields(self.pinfo_fields3)
if info['isclass'] and info['init_definition']:
displayfields.append(("Init definition",
info['init_definition'].rstrip()))

# Source or docstring, depending on detail level and whether
# source found.
if detail_level > 0 and info['source'] is not None:
displayfields.append(("Source",
self.format(cast_unicode(info['source']))))
elif info['docstring'] is not None:
displayfields.append(("Docstring", info["docstring"]))

# Constructor info for classes
if info['isclass']:
if info['init_docstring'] is not None:
displayfields.append(("Init docstring",
info['init_docstring']))

# Info for objects:

if info['isalias']:
add_fields([('Repr', "string_form")])

elif info['ismagic']:
add_fields([("Docstring", "docstring"),
("File", "file")
])

elif info['isclass'] or is_simple_callable(obj):
# Functions, methods, classes
add_fields([("Signature", "definition"),
("Init signature", "init_definition"),
])
if detail_level > 0 and info['source'] is not None:
add_fields([("Source", "source")])
else:
add_fields([("Docstring", "docstring"),
("Init docstring", "init_docstring"),
])

add_fields([('File', 'file'),
('Type', 'type_name'),
])

else:
add_fields(self.pinfo_fields_obj)
# General Python objects
add_fields([("Type", "type_name")])

# Base class for old-style instances
if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
displayfields.append(("Base Class", info['base_class'].rstrip()))

add_fields([("String form", "string_form")])

# Namespace
if info['namespace'] != 'Interactive':
displayfields.append(("Namespace", info['namespace'].rstrip()))

add_fields([("Length", "length"),
("File", "file"),
("Signature", "definition"),
])

# Source or docstring, depending on detail level and whether
# source found.
if detail_level > 0 and info['source'] is not None:
displayfields.append(("Source",
self.format(cast_unicode(info['source']))))
elif info['docstring'] is not None:
displayfields.append(("Docstring", info["docstring"]))

add_fields([("Class docstring", "class_docstring"),
("Init docstring", "init_docstring"),
("Call signature", "call_def"),
("Call docstring", "call_docstring")])

if displayfields:
return self._format_fields(displayfields)
Expand Down Expand Up @@ -737,7 +742,7 @@ def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
binary_file = True
elif fname.endswith('<string>'):
fname = 'Dynamically generated function. No source code available.'
out['file'] = fname
out['file'] = compress_user(fname)

# Original source code for a callable, class or property.
if detail_level:
Expand Down
23 changes: 4 additions & 19 deletions IPython/core/shellapp.py
Expand Up @@ -2,23 +2,10 @@
"""
A mixin for :class:`~IPython.core.application.Application` classes that
launch InteractiveShell instances, load extensions, etc.
Authors
-------
* Min Ragan-Kelley
"""

#-----------------------------------------------------------------------------
# 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 absolute_import
from __future__ import print_function
Expand Down Expand Up @@ -152,10 +139,6 @@ class InteractiveShellApp(Configurable):
extra_extension = Unicode('', config=True,
help="dotted module name of an IPython extension to load."
)
def _extra_extension_changed(self, name, old, new):
if new:
# add to self.extensions
self.extensions.append(new)

# Extensions that are always loaded (not configurable)
default_extensions = List(Unicode, [u'storemagic'], config=False)
Expand Down Expand Up @@ -269,6 +252,8 @@ def init_extensions(self):
try:
self.log.debug("Loading IPython extensions...")
extensions = self.default_extensions + self.extensions
if self.extra_extension:
extensions.append(self.extra_extension)
for ext in extensions:
try:
self.log.info("Loading IPython extension: %s" % ext)
Expand Down
5 changes: 3 additions & 2 deletions IPython/core/tests/test_oinspect.py
Expand Up @@ -28,6 +28,7 @@
register_line_cell_magic)
from IPython.external.decorator import decorator
from IPython.testing.decorators import skipif
from IPython.utils.path import compress_user
from IPython.utils import py3compat


Expand All @@ -46,7 +47,7 @@
# defined, if any code is inserted above, the following line will need to be
# updated. Do NOT insert any whitespace between the next line and the function
# definition below.
THIS_LINE_NUMBER = 49 # Put here the actual number of this line
THIS_LINE_NUMBER = 50 # Put here the actual number of this line
def test_find_source_lines():
nt.assert_equal(oinspect.find_source_lines(test_find_source_lines),
THIS_LINE_NUMBER+1)
Expand Down Expand Up @@ -241,7 +242,7 @@ def test_info():
fname = fname[:-1]
# case-insensitive comparison needed on some filesystems
# e.g. Windows:
nt.assert_equal(i['file'].lower(), fname.lower())
nt.assert_equal(i['file'].lower(), compress_user(fname.lower()))
nt.assert_equal(i['definition'], None)
nt.assert_equal(i['docstring'], Call.__doc__)
nt.assert_equal(i['source'], None)
Expand Down
2 changes: 2 additions & 0 deletions IPython/html/static/services/kernels/comm.js
Expand Up @@ -117,6 +117,7 @@ define([
// don't return a comm, so that further .then() functions
// get an undefined comm input
});
return this.comms[content.comm_id];
};

CommManager.prototype.comm_msg = function(msg) {
Expand All @@ -134,6 +135,7 @@ define([
}
return comm;
});
return this.comms[content.comm_id];
};

//-----------------------------------------------------------------------
Expand Down
28 changes: 20 additions & 8 deletions IPython/html/static/services/kernels/kernel.js
Expand Up @@ -41,6 +41,7 @@ define([
this.username = "username";
this.session_id = utils.uuid();
this._msg_callbacks = {};
this._msg_queue = Promise.resolve();
this.info_reply = {}; // kernel_info_reply stored here after starting

if (typeof(WebSocket) !== 'undefined') {
Expand Down Expand Up @@ -854,19 +855,23 @@ define([
};

Kernel.prototype._handle_ws_message = function (e) {
serialize.deserialize(e.data, $.proxy(this._finish_ws_message, this));
var that = this;
this._msg_queue = this._msg_queue.then(function() {
return serialize.deserialize(e.data);
}).then(function(msg) {return that._finish_ws_message(msg);})
.catch(utils.reject("Couldn't process kernel message", true));
};

Kernel.prototype._finish_ws_message = function (msg) {
switch (msg.channel) {
case 'shell':
this._handle_shell_reply(msg);
return this._handle_shell_reply(msg);
break;
case 'iopub':
this._handle_iopub_message(msg);
return this._handle_iopub_message(msg);
break;
case 'stdin':
this._handle_input_request(msg);
return this._handle_input_request(msg);
break;
default:
console.error("unrecognized message channel", msg.channel, msg);
Expand All @@ -875,10 +880,12 @@ define([

Kernel.prototype._handle_shell_reply = function (reply) {
this.events.trigger('shell_reply.Kernel', {kernel: this, reply:reply});
var that = this;
var content = reply.content;
var metadata = reply.metadata;
var parent_id = reply.parent_header.msg_id;
var callbacks = this.get_callbacks_for_msg(parent_id);
var promise = Promise.resolve();
if (!callbacks || !callbacks.shell) {
return;
}
Expand All @@ -888,27 +895,32 @@ define([
this._finish_shell(parent_id);

if (shell_callbacks.reply !== undefined) {
shell_callbacks.reply(reply);
promise = promise.then(function() {return shell_callbacks.reply(reply)});
}
if (content.payload && shell_callbacks.payload) {
this._handle_payloads(content.payload, shell_callbacks.payload, reply);
promise = promise.then(function() {
return that._handle_payloads(content.payload, shell_callbacks.payload, reply);
});
}
return promise;
};

/**
* @function _handle_payloads
*/
Kernel.prototype._handle_payloads = function (payloads, payload_callbacks, msg) {
var promise = [];
var l = payloads.length;
// Payloads are handled by triggering events because we don't want the Kernel
// to depend on the Notebook or Pager classes.
for (var i=0; i<l; i++) {
var payload = payloads[i];
var callback = payload_callbacks[payload.source];
if (callback) {
callback(payload, msg);
promise.push(callback(payload, msg));
}
}
return Promise.all(promise);
};

/**
Expand Down Expand Up @@ -1021,7 +1033,7 @@ define([
Kernel.prototype._handle_iopub_message = function (msg) {
var handler = this.get_iopub_handler(msg.header.msg_type);
if (handler !== undefined) {
handler(msg);
return handler(msg);
}
};

Expand Down
25 changes: 14 additions & 11 deletions IPython/html/static/services/kernels/serialize.js
Expand Up @@ -30,7 +30,7 @@ define([
return msg;
};

var _deserialize_binary = function(data, callback) {
var _deserialize_binary = function(data) {
/**
* deserialize the binary message format
* callback will be called with a message whose buffers attribute
Expand All @@ -39,28 +39,31 @@ define([
if (data instanceof Blob) {
// data is Blob, have to deserialize from ArrayBuffer in reader callback
var reader = new FileReader();
reader.onload = function () {
var msg = _deserialize_array_buffer(this.result);
callback(msg);
};
var promise = new Promise(function(resolve, reject) {
reader.onload = function () {
var msg = _deserialize_array_buffer(this.result);
resolve(msg);
};
});
reader.readAsArrayBuffer(data);
return promise;
} else {
// data is ArrayBuffer, can deserialize directly
var msg = _deserialize_array_buffer(data);
callback(msg);
return msg;
}
};

var deserialize = function (data, callback) {
var deserialize = function (data) {
/**
* deserialize a message and pass the unpacked message object to callback
* deserialize a message and return a promise for the unpacked message
*/
if (typeof data === "string") {
// text JSON message
callback(JSON.parse(data));
return Promise.resolve(JSON.parse(data));
} else {
// binary message
_deserialize_binary(data, callback);
return Promise.resolve(_deserialize_binary(data));
}
};

Expand Down Expand Up @@ -117,4 +120,4 @@ define([
serialize: serialize
};
return exports;
});
});

0 comments on commit d587f5e

Please sign in to comment.