##// END OF EJS Templates
Merge pull request #4979 from minrk/clear-output-msgspec...
Thomas Kluyver -
r15001:cf7b62ae merge
parent child Browse files
Show More
@@ -1,148 +1,148 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Release data for the IPython project."""
2 """Release data for the IPython project."""
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (c) 2008, IPython Development Team.
5 # Copyright (c) 2008, IPython Development Team.
6 # Copyright (c) 2001, Fernando Perez <fernando.perez@colorado.edu>
6 # Copyright (c) 2001, Fernando Perez <fernando.perez@colorado.edu>
7 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
7 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
8 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
8 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
9 #
9 #
10 # Distributed under the terms of the Modified BSD License.
10 # Distributed under the terms of the Modified BSD License.
11 #
11 #
12 # The full license is in the file COPYING.txt, distributed with this software.
12 # The full license is in the file COPYING.txt, distributed with this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Name of the package for release purposes. This is the name which labels
15 # Name of the package for release purposes. This is the name which labels
16 # the tarballs and RPMs made by distutils, so it's best to lowercase it.
16 # the tarballs and RPMs made by distutils, so it's best to lowercase it.
17 name = 'ipython'
17 name = 'ipython'
18
18
19 # IPython version information. An empty _version_extra corresponds to a full
19 # IPython version information. An empty _version_extra corresponds to a full
20 # release. 'dev' as a _version_extra string means this is a development
20 # release. 'dev' as a _version_extra string means this is a development
21 # version
21 # version
22 _version_major = 2
22 _version_major = 2
23 _version_minor = 0
23 _version_minor = 0
24 _version_patch = 0
24 _version_patch = 0
25 _version_extra = 'dev'
25 _version_extra = 'dev'
26 # _version_extra = 'rc1'
26 # _version_extra = 'rc1'
27 # _version_extra = '' # Uncomment this for full releases
27 # _version_extra = '' # Uncomment this for full releases
28
28
29 codename = 'Work in Progress'
29 codename = 'Work in Progress'
30
30
31 # Construct full version string from these.
31 # Construct full version string from these.
32 _ver = [_version_major, _version_minor, _version_patch]
32 _ver = [_version_major, _version_minor, _version_patch]
33
33
34 __version__ = '.'.join(map(str, _ver))
34 __version__ = '.'.join(map(str, _ver))
35 if _version_extra:
35 if _version_extra:
36 __version__ = __version__ + '-' + _version_extra
36 __version__ = __version__ + '-' + _version_extra
37
37
38 version = __version__ # backwards compatibility name
38 version = __version__ # backwards compatibility name
39 version_info = (_version_major, _version_minor, _version_patch, _version_extra)
39 version_info = (_version_major, _version_minor, _version_patch, _version_extra)
40
40
41 # Change this when incrementing the kernel protocol version
41 # Change this when incrementing the kernel protocol version
42 kernel_protocol_version_info = (4, 0)
42 kernel_protocol_version_info = (4, 1)
43
43
44 description = "IPython: Productive Interactive Computing"
44 description = "IPython: Productive Interactive Computing"
45
45
46 long_description = \
46 long_description = \
47 """
47 """
48 IPython provides a rich toolkit to help you make the most out of using Python
48 IPython provides a rich toolkit to help you make the most out of using Python
49 interactively. Its main components are:
49 interactively. Its main components are:
50
50
51 * Powerful interactive Python shells (terminal- and Qt-based).
51 * Powerful interactive Python shells (terminal- and Qt-based).
52 * A web-based interactive notebook environment with all shell features plus
52 * A web-based interactive notebook environment with all shell features plus
53 support for embedded figures, animations and rich media.
53 support for embedded figures, animations and rich media.
54 * Support for interactive data visualization and use of GUI toolkits.
54 * Support for interactive data visualization and use of GUI toolkits.
55 * Flexible, embeddable interpreters to load into your own projects.
55 * Flexible, embeddable interpreters to load into your own projects.
56 * A high-performance library for high level and interactive parallel computing
56 * A high-performance library for high level and interactive parallel computing
57 that works in multicore systems, clusters, supercomputing and cloud scenarios.
57 that works in multicore systems, clusters, supercomputing and cloud scenarios.
58
58
59 The enhanced interactive Python shells have the following main features:
59 The enhanced interactive Python shells have the following main features:
60
60
61 * Comprehensive object introspection.
61 * Comprehensive object introspection.
62
62
63 * Input history, persistent across sessions.
63 * Input history, persistent across sessions.
64
64
65 * Caching of output results during a session with automatically generated
65 * Caching of output results during a session with automatically generated
66 references.
66 references.
67
67
68 * Extensible tab completion, with support by default for completion of python
68 * Extensible tab completion, with support by default for completion of python
69 variables and keywords, filenames and function keywords.
69 variables and keywords, filenames and function keywords.
70
70
71 * Extensible system of 'magic' commands for controlling the environment and
71 * Extensible system of 'magic' commands for controlling the environment and
72 performing many tasks related either to IPython or the operating system.
72 performing many tasks related either to IPython or the operating system.
73
73
74 * A rich configuration system with easy switching between different setups
74 * A rich configuration system with easy switching between different setups
75 (simpler than changing $PYTHONSTARTUP environment variables every time).
75 (simpler than changing $PYTHONSTARTUP environment variables every time).
76
76
77 * Session logging and reloading.
77 * Session logging and reloading.
78
78
79 * Extensible syntax processing for special purpose situations.
79 * Extensible syntax processing for special purpose situations.
80
80
81 * Access to the system shell with user-extensible alias system.
81 * Access to the system shell with user-extensible alias system.
82
82
83 * Easily embeddable in other Python programs and GUIs.
83 * Easily embeddable in other Python programs and GUIs.
84
84
85 * Integrated access to the pdb debugger and the Python profiler.
85 * Integrated access to the pdb debugger and the Python profiler.
86
86
87 The parallel computing architecture has the following main features:
87 The parallel computing architecture has the following main features:
88
88
89 * Quickly parallelize Python code from an interactive Python/IPython session.
89 * Quickly parallelize Python code from an interactive Python/IPython session.
90
90
91 * A flexible and dynamic process model that be deployed on anything from
91 * A flexible and dynamic process model that be deployed on anything from
92 multicore workstations to supercomputers.
92 multicore workstations to supercomputers.
93
93
94 * An architecture that supports many different styles of parallelism, from
94 * An architecture that supports many different styles of parallelism, from
95 message passing to task farming.
95 message passing to task farming.
96
96
97 * Both blocking and fully asynchronous interfaces.
97 * Both blocking and fully asynchronous interfaces.
98
98
99 * High level APIs that enable many things to be parallelized in a few lines
99 * High level APIs that enable many things to be parallelized in a few lines
100 of code.
100 of code.
101
101
102 * Share live parallel jobs with other users securely.
102 * Share live parallel jobs with other users securely.
103
103
104 * Dynamically load balanced task farming system.
104 * Dynamically load balanced task farming system.
105
105
106 * Robust error handling in parallel code.
106 * Robust error handling in parallel code.
107
107
108 The latest development version is always available from IPython's `GitHub
108 The latest development version is always available from IPython's `GitHub
109 site <http://github.com/ipython>`_.
109 site <http://github.com/ipython>`_.
110 """
110 """
111
111
112 license = 'BSD'
112 license = 'BSD'
113
113
114 authors = {'Fernando' : ('Fernando Perez','fperez.net@gmail.com'),
114 authors = {'Fernando' : ('Fernando Perez','fperez.net@gmail.com'),
115 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
115 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
116 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
116 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
117 'Ville' : ('Ville Vainio','vivainio@gmail.com'),
117 'Ville' : ('Ville Vainio','vivainio@gmail.com'),
118 'Brian' : ('Brian E Granger', 'ellisonbg@gmail.com'),
118 'Brian' : ('Brian E Granger', 'ellisonbg@gmail.com'),
119 'Min' : ('Min Ragan-Kelley', 'benjaminrk@gmail.com'),
119 'Min' : ('Min Ragan-Kelley', 'benjaminrk@gmail.com'),
120 'Thomas' : ('Thomas A. Kluyver', 'takowl@gmail.com'),
120 'Thomas' : ('Thomas A. Kluyver', 'takowl@gmail.com'),
121 'Jorgen' : ('Jorgen Stenarson', 'jorgen.stenarson@bostream.nu'),
121 'Jorgen' : ('Jorgen Stenarson', 'jorgen.stenarson@bostream.nu'),
122 'Matthias' : ('Matthias Bussonnier', 'bussonniermatthias@gmail.com'),
122 'Matthias' : ('Matthias Bussonnier', 'bussonniermatthias@gmail.com'),
123 }
123 }
124
124
125 author = 'The IPython Development Team'
125 author = 'The IPython Development Team'
126
126
127 author_email = 'ipython-dev@scipy.org'
127 author_email = 'ipython-dev@scipy.org'
128
128
129 url = 'http://ipython.org'
129 url = 'http://ipython.org'
130
130
131 download_url = 'https://github.com/ipython/ipython/downloads'
131 download_url = 'https://github.com/ipython/ipython/downloads'
132
132
133 platforms = ['Linux','Mac OSX','Windows XP/Vista/7/8']
133 platforms = ['Linux','Mac OSX','Windows XP/Vista/7/8']
134
134
135 keywords = ['Interactive','Interpreter','Shell','Parallel','Distributed',
135 keywords = ['Interactive','Interpreter','Shell','Parallel','Distributed',
136 'Web-based computing', 'Qt console', 'Embedding']
136 'Web-based computing', 'Qt console', 'Embedding']
137
137
138 classifiers = [
138 classifiers = [
139 'Intended Audience :: Developers',
139 'Intended Audience :: Developers',
140 'Intended Audience :: Science/Research',
140 'Intended Audience :: Science/Research',
141 'License :: OSI Approved :: BSD License',
141 'License :: OSI Approved :: BSD License',
142 'Programming Language :: Python',
142 'Programming Language :: Python',
143 'Programming Language :: Python :: 2',
143 'Programming Language :: Python :: 2',
144 'Programming Language :: Python :: 2.7',
144 'Programming Language :: Python :: 2.7',
145 'Programming Language :: Python :: 3',
145 'Programming Language :: Python :: 3',
146 'Topic :: System :: Distributed Computing',
146 'Topic :: System :: Distributed Computing',
147 'Topic :: System :: Shells'
147 'Topic :: System :: Shells'
148 ]
148 ]
@@ -1,822 +1,827 b''
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2008 The IPython Development Team
2 // Copyright (C) 2008 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // OutputArea
9 // OutputArea
10 //============================================================================
10 //============================================================================
11
11
12 /**
12 /**
13 * @module IPython
13 * @module IPython
14 * @namespace IPython
14 * @namespace IPython
15 * @submodule OutputArea
15 * @submodule OutputArea
16 */
16 */
17 var IPython = (function (IPython) {
17 var IPython = (function (IPython) {
18 "use strict";
18 "use strict";
19
19
20 var utils = IPython.utils;
20 var utils = IPython.utils;
21
21
22 /**
22 /**
23 * @class OutputArea
23 * @class OutputArea
24 *
24 *
25 * @constructor
25 * @constructor
26 */
26 */
27
27
28 var OutputArea = function (selector, prompt_area) {
28 var OutputArea = function (selector, prompt_area) {
29 this.selector = selector;
29 this.selector = selector;
30 this.wrapper = $(selector);
30 this.wrapper = $(selector);
31 this.outputs = [];
31 this.outputs = [];
32 this.collapsed = false;
32 this.collapsed = false;
33 this.scrolled = false;
33 this.scrolled = false;
34 this.trusted = true;
34 this.trusted = true;
35 this.clear_queued = null;
35 this.clear_queued = null;
36 if (prompt_area === undefined) {
36 if (prompt_area === undefined) {
37 this.prompt_area = true;
37 this.prompt_area = true;
38 } else {
38 } else {
39 this.prompt_area = prompt_area;
39 this.prompt_area = prompt_area;
40 }
40 }
41 this.create_elements();
41 this.create_elements();
42 this.style();
42 this.style();
43 this.bind_events();
43 this.bind_events();
44 };
44 };
45
45
46 OutputArea.prototype.create_elements = function () {
46 OutputArea.prototype.create_elements = function () {
47 this.element = $("<div/>");
47 this.element = $("<div/>");
48 this.collapse_button = $("<div/>");
48 this.collapse_button = $("<div/>");
49 this.prompt_overlay = $("<div/>");
49 this.prompt_overlay = $("<div/>");
50 this.wrapper.append(this.prompt_overlay);
50 this.wrapper.append(this.prompt_overlay);
51 this.wrapper.append(this.element);
51 this.wrapper.append(this.element);
52 this.wrapper.append(this.collapse_button);
52 this.wrapper.append(this.collapse_button);
53 };
53 };
54
54
55
55
56 OutputArea.prototype.style = function () {
56 OutputArea.prototype.style = function () {
57 this.collapse_button.hide();
57 this.collapse_button.hide();
58 this.prompt_overlay.hide();
58 this.prompt_overlay.hide();
59
59
60 this.wrapper.addClass('output_wrapper');
60 this.wrapper.addClass('output_wrapper');
61 this.element.addClass('output');
61 this.element.addClass('output');
62
62
63 this.collapse_button.addClass("btn output_collapsed");
63 this.collapse_button.addClass("btn output_collapsed");
64 this.collapse_button.attr('title', 'click to expand output');
64 this.collapse_button.attr('title', 'click to expand output');
65 this.collapse_button.text('. . .');
65 this.collapse_button.text('. . .');
66
66
67 this.prompt_overlay.addClass('out_prompt_overlay prompt');
67 this.prompt_overlay.addClass('out_prompt_overlay prompt');
68 this.prompt_overlay.attr('title', 'click to expand output; double click to hide output');
68 this.prompt_overlay.attr('title', 'click to expand output; double click to hide output');
69
69
70 this.collapse();
70 this.collapse();
71 };
71 };
72
72
73 /**
73 /**
74 * Should the OutputArea scroll?
74 * Should the OutputArea scroll?
75 * Returns whether the height (in lines) exceeds a threshold.
75 * Returns whether the height (in lines) exceeds a threshold.
76 *
76 *
77 * @private
77 * @private
78 * @method _should_scroll
78 * @method _should_scroll
79 * @param [lines=100]{Integer}
79 * @param [lines=100]{Integer}
80 * @return {Bool}
80 * @return {Bool}
81 *
81 *
82 */
82 */
83 OutputArea.prototype._should_scroll = function (lines) {
83 OutputArea.prototype._should_scroll = function (lines) {
84 if (lines <=0 ){ return }
84 if (lines <=0 ){ return }
85 if (!lines) {
85 if (!lines) {
86 lines = 100;
86 lines = 100;
87 }
87 }
88 // line-height from http://stackoverflow.com/questions/1185151
88 // line-height from http://stackoverflow.com/questions/1185151
89 var fontSize = this.element.css('font-size');
89 var fontSize = this.element.css('font-size');
90 var lineHeight = Math.floor(parseInt(fontSize.replace('px','')) * 1.5);
90 var lineHeight = Math.floor(parseInt(fontSize.replace('px','')) * 1.5);
91
91
92 return (this.element.height() > lines * lineHeight);
92 return (this.element.height() > lines * lineHeight);
93 };
93 };
94
94
95
95
96 OutputArea.prototype.bind_events = function () {
96 OutputArea.prototype.bind_events = function () {
97 var that = this;
97 var that = this;
98 this.prompt_overlay.dblclick(function () { that.toggle_output(); });
98 this.prompt_overlay.dblclick(function () { that.toggle_output(); });
99 this.prompt_overlay.click(function () { that.toggle_scroll(); });
99 this.prompt_overlay.click(function () { that.toggle_scroll(); });
100
100
101 this.element.resize(function () {
101 this.element.resize(function () {
102 // FIXME: Firefox on Linux misbehaves, so automatic scrolling is disabled
102 // FIXME: Firefox on Linux misbehaves, so automatic scrolling is disabled
103 if ( IPython.utils.browser[0] === "Firefox" ) {
103 if ( IPython.utils.browser[0] === "Firefox" ) {
104 return;
104 return;
105 }
105 }
106 // maybe scroll output,
106 // maybe scroll output,
107 // if it's grown large enough and hasn't already been scrolled.
107 // if it's grown large enough and hasn't already been scrolled.
108 if ( !that.scrolled && that._should_scroll(OutputArea.auto_scroll_threshold)) {
108 if ( !that.scrolled && that._should_scroll(OutputArea.auto_scroll_threshold)) {
109 that.scroll_area();
109 that.scroll_area();
110 }
110 }
111 });
111 });
112 this.collapse_button.click(function () {
112 this.collapse_button.click(function () {
113 that.expand();
113 that.expand();
114 });
114 });
115 };
115 };
116
116
117
117
118 OutputArea.prototype.collapse = function () {
118 OutputArea.prototype.collapse = function () {
119 if (!this.collapsed) {
119 if (!this.collapsed) {
120 this.element.hide();
120 this.element.hide();
121 this.prompt_overlay.hide();
121 this.prompt_overlay.hide();
122 if (this.element.html()){
122 if (this.element.html()){
123 this.collapse_button.show();
123 this.collapse_button.show();
124 }
124 }
125 this.collapsed = true;
125 this.collapsed = true;
126 }
126 }
127 };
127 };
128
128
129
129
130 OutputArea.prototype.expand = function () {
130 OutputArea.prototype.expand = function () {
131 if (this.collapsed) {
131 if (this.collapsed) {
132 this.collapse_button.hide();
132 this.collapse_button.hide();
133 this.element.show();
133 this.element.show();
134 this.prompt_overlay.show();
134 this.prompt_overlay.show();
135 this.collapsed = false;
135 this.collapsed = false;
136 }
136 }
137 };
137 };
138
138
139
139
140 OutputArea.prototype.toggle_output = function () {
140 OutputArea.prototype.toggle_output = function () {
141 if (this.collapsed) {
141 if (this.collapsed) {
142 this.expand();
142 this.expand();
143 } else {
143 } else {
144 this.collapse();
144 this.collapse();
145 }
145 }
146 };
146 };
147
147
148
148
149 OutputArea.prototype.scroll_area = function () {
149 OutputArea.prototype.scroll_area = function () {
150 this.element.addClass('output_scroll');
150 this.element.addClass('output_scroll');
151 this.prompt_overlay.attr('title', 'click to unscroll output; double click to hide');
151 this.prompt_overlay.attr('title', 'click to unscroll output; double click to hide');
152 this.scrolled = true;
152 this.scrolled = true;
153 };
153 };
154
154
155
155
156 OutputArea.prototype.unscroll_area = function () {
156 OutputArea.prototype.unscroll_area = function () {
157 this.element.removeClass('output_scroll');
157 this.element.removeClass('output_scroll');
158 this.prompt_overlay.attr('title', 'click to scroll output; double click to hide');
158 this.prompt_overlay.attr('title', 'click to scroll output; double click to hide');
159 this.scrolled = false;
159 this.scrolled = false;
160 };
160 };
161
161
162 /**
162 /**
163 * Threshold to trigger autoscroll when the OutputArea is resized,
163 * Threshold to trigger autoscroll when the OutputArea is resized,
164 * typically when new outputs are added.
164 * typically when new outputs are added.
165 *
165 *
166 * Behavior is undefined if autoscroll is lower than minimum_scroll_threshold,
166 * Behavior is undefined if autoscroll is lower than minimum_scroll_threshold,
167 * unless it is < 0, in which case autoscroll will never be triggered
167 * unless it is < 0, in which case autoscroll will never be triggered
168 *
168 *
169 * @property auto_scroll_threshold
169 * @property auto_scroll_threshold
170 * @type Number
170 * @type Number
171 * @default 100
171 * @default 100
172 *
172 *
173 **/
173 **/
174 OutputArea.auto_scroll_threshold = 100;
174 OutputArea.auto_scroll_threshold = 100;
175
175
176
176
177 /**
177 /**
178 * Lower limit (in lines) for OutputArea to be made scrollable. OutputAreas
178 * Lower limit (in lines) for OutputArea to be made scrollable. OutputAreas
179 * shorter than this are never scrolled.
179 * shorter than this are never scrolled.
180 *
180 *
181 * @property minimum_scroll_threshold
181 * @property minimum_scroll_threshold
182 * @type Number
182 * @type Number
183 * @default 20
183 * @default 20
184 *
184 *
185 **/
185 **/
186 OutputArea.minimum_scroll_threshold = 20;
186 OutputArea.minimum_scroll_threshold = 20;
187
187
188
188
189 /**
189 /**
190 *
190 *
191 * Scroll OutputArea if height supperior than a threshold (in lines).
191 * Scroll OutputArea if height supperior than a threshold (in lines).
192 *
192 *
193 * Threshold is a maximum number of lines. If unspecified, defaults to
193 * Threshold is a maximum number of lines. If unspecified, defaults to
194 * OutputArea.minimum_scroll_threshold.
194 * OutputArea.minimum_scroll_threshold.
195 *
195 *
196 * Negative threshold will prevent the OutputArea from ever scrolling.
196 * Negative threshold will prevent the OutputArea from ever scrolling.
197 *
197 *
198 * @method scroll_if_long
198 * @method scroll_if_long
199 *
199 *
200 * @param [lines=20]{Number} Default to 20 if not set,
200 * @param [lines=20]{Number} Default to 20 if not set,
201 * behavior undefined for value of `0`.
201 * behavior undefined for value of `0`.
202 *
202 *
203 **/
203 **/
204 OutputArea.prototype.scroll_if_long = function (lines) {
204 OutputArea.prototype.scroll_if_long = function (lines) {
205 var n = lines | OutputArea.minimum_scroll_threshold;
205 var n = lines | OutputArea.minimum_scroll_threshold;
206 if(n <= 0){
206 if(n <= 0){
207 return
207 return
208 }
208 }
209
209
210 if (this._should_scroll(n)) {
210 if (this._should_scroll(n)) {
211 // only allow scrolling long-enough output
211 // only allow scrolling long-enough output
212 this.scroll_area();
212 this.scroll_area();
213 }
213 }
214 };
214 };
215
215
216
216
217 OutputArea.prototype.toggle_scroll = function () {
217 OutputArea.prototype.toggle_scroll = function () {
218 if (this.scrolled) {
218 if (this.scrolled) {
219 this.unscroll_area();
219 this.unscroll_area();
220 } else {
220 } else {
221 // only allow scrolling long-enough output
221 // only allow scrolling long-enough output
222 this.scroll_if_long();
222 this.scroll_if_long();
223 }
223 }
224 };
224 };
225
225
226
226
227 // typeset with MathJax if MathJax is available
227 // typeset with MathJax if MathJax is available
228 OutputArea.prototype.typeset = function () {
228 OutputArea.prototype.typeset = function () {
229 if (window.MathJax){
229 if (window.MathJax){
230 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
230 MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
231 }
231 }
232 };
232 };
233
233
234
234
235 OutputArea.prototype.handle_output = function (msg) {
235 OutputArea.prototype.handle_output = function (msg) {
236 var json = {};
236 var json = {};
237 var msg_type = json.output_type = msg.header.msg_type;
237 var msg_type = json.output_type = msg.header.msg_type;
238 var content = msg.content;
238 var content = msg.content;
239 if (msg_type === "stream") {
239 if (msg_type === "stream") {
240 json.text = content.data;
240 json.text = content.data;
241 json.stream = content.name;
241 json.stream = content.name;
242 } else if (msg_type === "display_data") {
242 } else if (msg_type === "display_data") {
243 json = content.data;
243 json = content.data;
244 json.output_type = msg_type;
244 json.output_type = msg_type;
245 json.metadata = content.metadata;
245 json.metadata = content.metadata;
246 } else if (msg_type === "pyout") {
246 } else if (msg_type === "pyout") {
247 json = content.data;
247 json = content.data;
248 json.output_type = msg_type;
248 json.output_type = msg_type;
249 json.metadata = content.metadata;
249 json.metadata = content.metadata;
250 json.prompt_number = content.execution_count;
250 json.prompt_number = content.execution_count;
251 } else if (msg_type === "pyerr") {
251 } else if (msg_type === "pyerr") {
252 json.ename = content.ename;
252 json.ename = content.ename;
253 json.evalue = content.evalue;
253 json.evalue = content.evalue;
254 json.traceback = content.traceback;
254 json.traceback = content.traceback;
255 }
255 }
256 this.append_output(json);
256 this.append_output(json);
257 };
257 };
258
258
259 OutputArea.mime_map = {
259 OutputArea.mime_map = {
260 "text/plain" : "text",
260 "text/plain" : "text",
261 "text/html" : "html",
261 "text/html" : "html",
262 "image/svg+xml" : "svg",
262 "image/svg+xml" : "svg",
263 "image/png" : "png",
263 "image/png" : "png",
264 "image/jpeg" : "jpeg",
264 "image/jpeg" : "jpeg",
265 "text/latex" : "latex",
265 "text/latex" : "latex",
266 "application/json" : "json",
266 "application/json" : "json",
267 "application/javascript" : "javascript",
267 "application/javascript" : "javascript",
268 };
268 };
269
269
270 OutputArea.mime_map_r = {
270 OutputArea.mime_map_r = {
271 "text" : "text/plain",
271 "text" : "text/plain",
272 "html" : "text/html",
272 "html" : "text/html",
273 "svg" : "image/svg+xml",
273 "svg" : "image/svg+xml",
274 "png" : "image/png",
274 "png" : "image/png",
275 "jpeg" : "image/jpeg",
275 "jpeg" : "image/jpeg",
276 "latex" : "text/latex",
276 "latex" : "text/latex",
277 "json" : "application/json",
277 "json" : "application/json",
278 "javascript" : "application/javascript",
278 "javascript" : "application/javascript",
279 };
279 };
280
280
281 OutputArea.prototype.rename_keys = function (data, key_map) {
281 OutputArea.prototype.rename_keys = function (data, key_map) {
282 var remapped = {};
282 var remapped = {};
283 for (var key in data) {
283 for (var key in data) {
284 var new_key = key_map[key] || key;
284 var new_key = key_map[key] || key;
285 remapped[new_key] = data[key];
285 remapped[new_key] = data[key];
286 }
286 }
287 return remapped;
287 return remapped;
288 };
288 };
289
289
290
290
291 OutputArea.output_types = [
291 OutputArea.output_types = [
292 'application/javascript',
292 'application/javascript',
293 'text/html',
293 'text/html',
294 'text/latex',
294 'text/latex',
295 'image/svg+xml',
295 'image/svg+xml',
296 'image/png',
296 'image/png',
297 'image/jpeg',
297 'image/jpeg',
298 'text/plain'
298 'text/plain'
299 ];
299 ];
300
300
301 OutputArea.prototype.validate_output = function (json) {
301 OutputArea.prototype.validate_output = function (json) {
302 // scrub invalid outputs
302 // scrub invalid outputs
303 // TODO: right now everything is a string, but JSON really shouldn't be.
303 // TODO: right now everything is a string, but JSON really shouldn't be.
304 // nbformat 4 will fix that.
304 // nbformat 4 will fix that.
305 $.map(OutputArea.output_types, function(key){
305 $.map(OutputArea.output_types, function(key){
306 if (json[key] !== undefined && typeof json[key] !== 'string') {
306 if (json[key] !== undefined && typeof json[key] !== 'string') {
307 console.log("Invalid type for " + key, json[key]);
307 console.log("Invalid type for " + key, json[key]);
308 delete json[key];
308 delete json[key];
309 }
309 }
310 });
310 });
311 return json;
311 return json;
312 };
312 };
313
313
314 OutputArea.prototype.append_output = function (json) {
314 OutputArea.prototype.append_output = function (json) {
315 this.expand();
315 this.expand();
316 // Clear the output if clear is queued.
316 // Clear the output if clear is queued.
317 var needs_height_reset = false;
317 var needs_height_reset = false;
318 if (this.clear_queued) {
318 if (this.clear_queued) {
319 this.clear_output(false);
319 this.clear_output(false);
320 needs_height_reset = true;
320 needs_height_reset = true;
321 }
321 }
322
322
323 // validate output data types
323 // validate output data types
324 json = this.validate_output(json);
324 json = this.validate_output(json);
325
325
326 if (json.output_type === 'pyout') {
326 if (json.output_type === 'pyout') {
327 this.append_pyout(json);
327 this.append_pyout(json);
328 } else if (json.output_type === 'pyerr') {
328 } else if (json.output_type === 'pyerr') {
329 this.append_pyerr(json);
329 this.append_pyerr(json);
330 } else if (json.output_type === 'display_data') {
330 } else if (json.output_type === 'display_data') {
331 this.append_display_data(json);
331 this.append_display_data(json);
332 } else if (json.output_type === 'stream') {
332 } else if (json.output_type === 'stream') {
333 this.append_stream(json);
333 this.append_stream(json);
334 }
334 }
335
335
336 this.outputs.push(json);
336 this.outputs.push(json);
337
337
338 // Only reset the height to automatic if the height is currently
338 // Only reset the height to automatic if the height is currently
339 // fixed (done by wait=True flag on clear_output).
339 // fixed (done by wait=True flag on clear_output).
340 if (needs_height_reset) {
340 if (needs_height_reset) {
341 this.element.height('');
341 this.element.height('');
342 }
342 }
343
343
344 var that = this;
344 var that = this;
345 setTimeout(function(){that.element.trigger('resize');}, 100);
345 setTimeout(function(){that.element.trigger('resize');}, 100);
346 };
346 };
347
347
348
348
349 OutputArea.prototype.create_output_area = function () {
349 OutputArea.prototype.create_output_area = function () {
350 var oa = $("<div/>").addClass("output_area");
350 var oa = $("<div/>").addClass("output_area");
351 if (this.prompt_area) {
351 if (this.prompt_area) {
352 oa.append($('<div/>').addClass('prompt'));
352 oa.append($('<div/>').addClass('prompt'));
353 }
353 }
354 return oa;
354 return oa;
355 };
355 };
356
356
357
357
358 function _get_metadata_key(metadata, key, mime) {
358 function _get_metadata_key(metadata, key, mime) {
359 var mime_md = metadata[mime];
359 var mime_md = metadata[mime];
360 // mime-specific higher priority
360 // mime-specific higher priority
361 if (mime_md && mime_md[key] !== undefined) {
361 if (mime_md && mime_md[key] !== undefined) {
362 return mime_md[key];
362 return mime_md[key];
363 }
363 }
364 // fallback on global
364 // fallback on global
365 return metadata[key];
365 return metadata[key];
366 }
366 }
367
367
368 OutputArea.prototype.create_output_subarea = function(md, classes, mime) {
368 OutputArea.prototype.create_output_subarea = function(md, classes, mime) {
369 var subarea = $('<div/>').addClass('output_subarea').addClass(classes);
369 var subarea = $('<div/>').addClass('output_subarea').addClass(classes);
370 if (_get_metadata_key(md, 'isolated', mime)) {
370 if (_get_metadata_key(md, 'isolated', mime)) {
371 // Create an iframe to isolate the subarea from the rest of the
371 // Create an iframe to isolate the subarea from the rest of the
372 // document
372 // document
373 var iframe = $('<iframe/>').addClass('box-flex1');
373 var iframe = $('<iframe/>').addClass('box-flex1');
374 iframe.css({'height':1, 'width':'100%', 'display':'block'});
374 iframe.css({'height':1, 'width':'100%', 'display':'block'});
375 iframe.attr('frameborder', 0);
375 iframe.attr('frameborder', 0);
376 iframe.attr('scrolling', 'auto');
376 iframe.attr('scrolling', 'auto');
377
377
378 // Once the iframe is loaded, the subarea is dynamically inserted
378 // Once the iframe is loaded, the subarea is dynamically inserted
379 iframe.on('load', function() {
379 iframe.on('load', function() {
380 // Workaround needed by Firefox, to properly render svg inside
380 // Workaround needed by Firefox, to properly render svg inside
381 // iframes, see http://stackoverflow.com/questions/10177190/
381 // iframes, see http://stackoverflow.com/questions/10177190/
382 // svg-dynamically-added-to-iframe-does-not-render-correctly
382 // svg-dynamically-added-to-iframe-does-not-render-correctly
383 this.contentDocument.open();
383 this.contentDocument.open();
384
384
385 // Insert the subarea into the iframe
385 // Insert the subarea into the iframe
386 // We must directly write the html. When using Jquery's append
386 // We must directly write the html. When using Jquery's append
387 // method, javascript is evaluated in the parent document and
387 // method, javascript is evaluated in the parent document and
388 // not in the iframe document.
388 // not in the iframe document.
389 this.contentDocument.write(subarea.html());
389 this.contentDocument.write(subarea.html());
390
390
391 this.contentDocument.close();
391 this.contentDocument.close();
392
392
393 var body = this.contentDocument.body;
393 var body = this.contentDocument.body;
394 // Adjust the iframe height automatically
394 // Adjust the iframe height automatically
395 iframe.height(body.scrollHeight + 'px');
395 iframe.height(body.scrollHeight + 'px');
396 });
396 });
397
397
398 // Elements should be appended to the inner subarea and not to the
398 // Elements should be appended to the inner subarea and not to the
399 // iframe
399 // iframe
400 iframe.append = function(that) {
400 iframe.append = function(that) {
401 subarea.append(that);
401 subarea.append(that);
402 };
402 };
403
403
404 return iframe;
404 return iframe;
405 } else {
405 } else {
406 return subarea;
406 return subarea;
407 }
407 }
408 }
408 }
409
409
410
410
411 OutputArea.prototype._append_javascript_error = function (err, element) {
411 OutputArea.prototype._append_javascript_error = function (err, element) {
412 // display a message when a javascript error occurs in display output
412 // display a message when a javascript error occurs in display output
413 var msg = "Javascript error adding output!"
413 var msg = "Javascript error adding output!"
414 if ( element === undefined ) return;
414 if ( element === undefined ) return;
415 element.append(
415 element.append(
416 $('<div/>').html(msg + "<br/>" +
416 $('<div/>').html(msg + "<br/>" +
417 err.toString() +
417 err.toString() +
418 '<br/>See your browser Javascript console for more details.'
418 '<br/>See your browser Javascript console for more details.'
419 ).addClass('js-error')
419 ).addClass('js-error')
420 );
420 );
421 };
421 };
422
422
423 OutputArea.prototype._safe_append = function (toinsert) {
423 OutputArea.prototype._safe_append = function (toinsert) {
424 // safely append an item to the document
424 // safely append an item to the document
425 // this is an object created by user code,
425 // this is an object created by user code,
426 // and may have errors, which should not be raised
426 // and may have errors, which should not be raised
427 // under any circumstances.
427 // under any circumstances.
428 try {
428 try {
429 this.element.append(toinsert);
429 this.element.append(toinsert);
430 } catch(err) {
430 } catch(err) {
431 console.log(err);
431 console.log(err);
432 // Create an actual output_area and output_subarea, which creates
432 // Create an actual output_area and output_subarea, which creates
433 // the prompt area and the proper indentation.
433 // the prompt area and the proper indentation.
434 var toinsert = this.create_output_area();
434 var toinsert = this.create_output_area();
435 var subarea = $('<div/>').addClass('output_subarea');
435 var subarea = $('<div/>').addClass('output_subarea');
436 toinsert.append(subarea);
436 toinsert.append(subarea);
437 this._append_javascript_error(err, subarea);
437 this._append_javascript_error(err, subarea);
438 this.element.append(toinsert);
438 this.element.append(toinsert);
439 }
439 }
440 };
440 };
441
441
442
442
443 OutputArea.prototype.append_pyout = function (json) {
443 OutputArea.prototype.append_pyout = function (json) {
444 var n = json.prompt_number || ' ';
444 var n = json.prompt_number || ' ';
445 var toinsert = this.create_output_area();
445 var toinsert = this.create_output_area();
446 if (this.prompt_area) {
446 if (this.prompt_area) {
447 toinsert.find('div.prompt').addClass('output_prompt').text('Out[' + n + ']:');
447 toinsert.find('div.prompt').addClass('output_prompt').text('Out[' + n + ']:');
448 }
448 }
449 this.append_mime_type(json, toinsert);
449 this.append_mime_type(json, toinsert);
450 this._safe_append(toinsert);
450 this._safe_append(toinsert);
451 // If we just output latex, typeset it.
451 // If we just output latex, typeset it.
452 if ((json['text/latex'] !== undefined) || (json['text/html'] !== undefined)) {
452 if ((json['text/latex'] !== undefined) || (json['text/html'] !== undefined)) {
453 this.typeset();
453 this.typeset();
454 }
454 }
455 };
455 };
456
456
457
457
458 OutputArea.prototype.append_pyerr = function (json) {
458 OutputArea.prototype.append_pyerr = function (json) {
459 var tb = json.traceback;
459 var tb = json.traceback;
460 if (tb !== undefined && tb.length > 0) {
460 if (tb !== undefined && tb.length > 0) {
461 var s = '';
461 var s = '';
462 var len = tb.length;
462 var len = tb.length;
463 for (var i=0; i<len; i++) {
463 for (var i=0; i<len; i++) {
464 s = s + tb[i] + '\n';
464 s = s + tb[i] + '\n';
465 }
465 }
466 s = s + '\n';
466 s = s + '\n';
467 var toinsert = this.create_output_area();
467 var toinsert = this.create_output_area();
468 this.append_text(s, {}, toinsert);
468 this.append_text(s, {}, toinsert);
469 this._safe_append(toinsert);
469 this._safe_append(toinsert);
470 }
470 }
471 };
471 };
472
472
473
473
474 OutputArea.prototype.append_stream = function (json) {
474 OutputArea.prototype.append_stream = function (json) {
475 // temporary fix: if stream undefined (json file written prior to this patch),
475 // temporary fix: if stream undefined (json file written prior to this patch),
476 // default to most likely stdout:
476 // default to most likely stdout:
477 if (json.stream == undefined){
477 if (json.stream == undefined){
478 json.stream = 'stdout';
478 json.stream = 'stdout';
479 }
479 }
480 var text = json.text;
480 var text = json.text;
481 var subclass = "output_"+json.stream;
481 var subclass = "output_"+json.stream;
482 if (this.outputs.length > 0){
482 if (this.outputs.length > 0){
483 // have at least one output to consider
483 // have at least one output to consider
484 var last = this.outputs[this.outputs.length-1];
484 var last = this.outputs[this.outputs.length-1];
485 if (last.output_type == 'stream' && json.stream == last.stream){
485 if (last.output_type == 'stream' && json.stream == last.stream){
486 // latest output was in the same stream,
486 // latest output was in the same stream,
487 // so append directly into its pre tag
487 // so append directly into its pre tag
488 // escape ANSI & HTML specials:
488 // escape ANSI & HTML specials:
489 var pre = this.element.find('div.'+subclass).last().find('pre');
489 var pre = this.element.find('div.'+subclass).last().find('pre');
490 var html = utils.fixCarriageReturn(
490 var html = utils.fixCarriageReturn(
491 pre.html() + utils.fixConsole(text));
491 pre.html() + utils.fixConsole(text));
492 pre.html(html);
492 pre.html(html);
493 return;
493 return;
494 }
494 }
495 }
495 }
496
496
497 if (!text.replace("\r", "")) {
497 if (!text.replace("\r", "")) {
498 // text is nothing (empty string, \r, etc.)
498 // text is nothing (empty string, \r, etc.)
499 // so don't append any elements, which might add undesirable space
499 // so don't append any elements, which might add undesirable space
500 return;
500 return;
501 }
501 }
502
502
503 // If we got here, attach a new div
503 // If we got here, attach a new div
504 var toinsert = this.create_output_area();
504 var toinsert = this.create_output_area();
505 this.append_text(text, {}, toinsert, "output_stream "+subclass);
505 this.append_text(text, {}, toinsert, "output_stream "+subclass);
506 this._safe_append(toinsert);
506 this._safe_append(toinsert);
507 };
507 };
508
508
509
509
510 OutputArea.prototype.append_display_data = function (json) {
510 OutputArea.prototype.append_display_data = function (json) {
511 var toinsert = this.create_output_area();
511 var toinsert = this.create_output_area();
512 if (this.append_mime_type(json, toinsert)) {
512 if (this.append_mime_type(json, toinsert)) {
513 this._safe_append(toinsert);
513 this._safe_append(toinsert);
514 // If we just output latex, typeset it.
514 // If we just output latex, typeset it.
515 if ((json['text/latex'] !== undefined) || (json['text/html'] !== undefined)) {
515 if ((json['text/latex'] !== undefined) || (json['text/html'] !== undefined)) {
516 this.typeset();
516 this.typeset();
517 }
517 }
518 }
518 }
519 };
519 };
520
520
521 OutputArea.display_order = [
521 OutputArea.display_order = [
522 'application/javascript',
522 'application/javascript',
523 'text/html',
523 'text/html',
524 'text/latex',
524 'text/latex',
525 'image/svg+xml',
525 'image/svg+xml',
526 'image/png',
526 'image/png',
527 'image/jpeg',
527 'image/jpeg',
528 'text/plain'
528 'text/plain'
529 ];
529 ];
530
530
531 OutputArea.safe_outputs = {
531 OutputArea.safe_outputs = {
532 'text/plain' : true,
532 'text/plain' : true,
533 'image/png' : true,
533 'image/png' : true,
534 'image/jpeg' : true
534 'image/jpeg' : true
535 };
535 };
536
536
537 OutputArea.prototype.append_mime_type = function (json, element) {
537 OutputArea.prototype.append_mime_type = function (json, element) {
538 for (var type_i in OutputArea.display_order) {
538 for (var type_i in OutputArea.display_order) {
539 var type = OutputArea.display_order[type_i];
539 var type = OutputArea.display_order[type_i];
540 var append = OutputArea.append_map[type];
540 var append = OutputArea.append_map[type];
541 if ((json[type] !== undefined) && append) {
541 if ((json[type] !== undefined) && append) {
542 if (!this.trusted && !OutputArea.safe_outputs[type]) {
542 if (!this.trusted && !OutputArea.safe_outputs[type]) {
543 // not trusted show warning and do not display
543 // not trusted show warning and do not display
544 var content = {
544 var content = {
545 text : "Untrusted " + type + " output ignored.",
545 text : "Untrusted " + type + " output ignored.",
546 stream : "stderr"
546 stream : "stderr"
547 }
547 }
548 this.append_stream(content);
548 this.append_stream(content);
549 continue;
549 continue;
550 }
550 }
551 var md = json.metadata || {};
551 var md = json.metadata || {};
552 append.apply(this, [json[type], md, element]);
552 append.apply(this, [json[type], md, element]);
553 return true;
553 return true;
554 }
554 }
555 }
555 }
556 return false;
556 return false;
557 };
557 };
558
558
559
559
560 OutputArea.prototype.append_html = function (html, md, element) {
560 OutputArea.prototype.append_html = function (html, md, element) {
561 var type = 'text/html';
561 var type = 'text/html';
562 var toinsert = this.create_output_subarea(md, "output_html rendered_html", type);
562 var toinsert = this.create_output_subarea(md, "output_html rendered_html", type);
563 IPython.keyboard_manager.register_events(toinsert);
563 IPython.keyboard_manager.register_events(toinsert);
564 toinsert.append(html);
564 toinsert.append(html);
565 element.append(toinsert);
565 element.append(toinsert);
566 };
566 };
567
567
568
568
569 OutputArea.prototype.append_javascript = function (js, md, container) {
569 OutputArea.prototype.append_javascript = function (js, md, container) {
570 // We just eval the JS code, element appears in the local scope.
570 // We just eval the JS code, element appears in the local scope.
571 var type = 'application/javascript';
571 var type = 'application/javascript';
572 var element = this.create_output_subarea(md, "output_javascript", type);
572 var element = this.create_output_subarea(md, "output_javascript", type);
573 IPython.keyboard_manager.register_events(element);
573 IPython.keyboard_manager.register_events(element);
574 container.append(element);
574 container.append(element);
575 try {
575 try {
576 eval(js);
576 eval(js);
577 } catch(err) {
577 } catch(err) {
578 console.log(err);
578 console.log(err);
579 this._append_javascript_error(err, element);
579 this._append_javascript_error(err, element);
580 }
580 }
581 };
581 };
582
582
583
583
584 OutputArea.prototype.append_text = function (data, md, element, extra_class) {
584 OutputArea.prototype.append_text = function (data, md, element, extra_class) {
585 var type = 'text/plain';
585 var type = 'text/plain';
586 var toinsert = this.create_output_subarea(md, "output_text", type);
586 var toinsert = this.create_output_subarea(md, "output_text", type);
587 // escape ANSI & HTML specials in plaintext:
587 // escape ANSI & HTML specials in plaintext:
588 data = utils.fixConsole(data);
588 data = utils.fixConsole(data);
589 data = utils.fixCarriageReturn(data);
589 data = utils.fixCarriageReturn(data);
590 data = utils.autoLinkUrls(data);
590 data = utils.autoLinkUrls(data);
591 if (extra_class){
591 if (extra_class){
592 toinsert.addClass(extra_class);
592 toinsert.addClass(extra_class);
593 }
593 }
594 toinsert.append($("<pre/>").html(data));
594 toinsert.append($("<pre/>").html(data));
595 element.append(toinsert);
595 element.append(toinsert);
596 };
596 };
597
597
598
598
599 OutputArea.prototype.append_svg = function (svg, md, element) {
599 OutputArea.prototype.append_svg = function (svg, md, element) {
600 var type = 'image/svg+xml';
600 var type = 'image/svg+xml';
601 var toinsert = this.create_output_subarea(md, "output_svg", type);
601 var toinsert = this.create_output_subarea(md, "output_svg", type);
602 toinsert.append(svg);
602 toinsert.append(svg);
603 element.append(toinsert);
603 element.append(toinsert);
604 };
604 };
605
605
606
606
607 OutputArea.prototype._dblclick_to_reset_size = function (img) {
607 OutputArea.prototype._dblclick_to_reset_size = function (img) {
608 // schedule wrapping image in resizable after a delay,
608 // schedule wrapping image in resizable after a delay,
609 // so we don't end up calling resize on a zero-size object
609 // so we don't end up calling resize on a zero-size object
610 var that = this;
610 var that = this;
611 setTimeout(function () {
611 setTimeout(function () {
612 var h0 = img.height();
612 var h0 = img.height();
613 var w0 = img.width();
613 var w0 = img.width();
614 if (!(h0 && w0)) {
614 if (!(h0 && w0)) {
615 // zero size, schedule another timeout
615 // zero size, schedule another timeout
616 that._dblclick_to_reset_size(img);
616 that._dblclick_to_reset_size(img);
617 return;
617 return;
618 }
618 }
619 img.resizable({
619 img.resizable({
620 aspectRatio: true,
620 aspectRatio: true,
621 autoHide: true
621 autoHide: true
622 });
622 });
623 img.dblclick(function () {
623 img.dblclick(function () {
624 // resize wrapper & image together for some reason:
624 // resize wrapper & image together for some reason:
625 img.parent().height(h0);
625 img.parent().height(h0);
626 img.height(h0);
626 img.height(h0);
627 img.parent().width(w0);
627 img.parent().width(w0);
628 img.width(w0);
628 img.width(w0);
629 });
629 });
630 }, 250);
630 }, 250);
631 };
631 };
632
632
633 var set_width_height = function (img, md, mime) {
633 var set_width_height = function (img, md, mime) {
634 // set width and height of an img element from metadata
634 // set width and height of an img element from metadata
635 var height = _get_metadata_key(md, 'height', mime);
635 var height = _get_metadata_key(md, 'height', mime);
636 if (height !== undefined) img.attr('height', height);
636 if (height !== undefined) img.attr('height', height);
637 var width = _get_metadata_key(md, 'width', mime);
637 var width = _get_metadata_key(md, 'width', mime);
638 if (width !== undefined) img.attr('width', width);
638 if (width !== undefined) img.attr('width', width);
639 };
639 };
640
640
641 OutputArea.prototype.append_png = function (png, md, element) {
641 OutputArea.prototype.append_png = function (png, md, element) {
642 var type = 'image/png';
642 var type = 'image/png';
643 var toinsert = this.create_output_subarea(md, "output_png", type);
643 var toinsert = this.create_output_subarea(md, "output_png", type);
644 var img = $("<img/>").attr('src','data:image/png;base64,'+png);
644 var img = $("<img/>").attr('src','data:image/png;base64,'+png);
645 set_width_height(img, md, 'image/png');
645 set_width_height(img, md, 'image/png');
646 this._dblclick_to_reset_size(img);
646 this._dblclick_to_reset_size(img);
647 toinsert.append(img);
647 toinsert.append(img);
648 element.append(toinsert);
648 element.append(toinsert);
649 };
649 };
650
650
651
651
652 OutputArea.prototype.append_jpeg = function (jpeg, md, element) {
652 OutputArea.prototype.append_jpeg = function (jpeg, md, element) {
653 var type = 'image/jpeg';
653 var type = 'image/jpeg';
654 var toinsert = this.create_output_subarea(md, "output_jpeg", type);
654 var toinsert = this.create_output_subarea(md, "output_jpeg", type);
655 var img = $("<img/>").attr('src','data:image/jpeg;base64,'+jpeg);
655 var img = $("<img/>").attr('src','data:image/jpeg;base64,'+jpeg);
656 set_width_height(img, md, 'image/jpeg');
656 set_width_height(img, md, 'image/jpeg');
657 this._dblclick_to_reset_size(img);
657 this._dblclick_to_reset_size(img);
658 toinsert.append(img);
658 toinsert.append(img);
659 element.append(toinsert);
659 element.append(toinsert);
660 };
660 };
661
661
662
662
663 OutputArea.prototype.append_latex = function (latex, md, element) {
663 OutputArea.prototype.append_latex = function (latex, md, element) {
664 // This method cannot do the typesetting because the latex first has to
664 // This method cannot do the typesetting because the latex first has to
665 // be on the page.
665 // be on the page.
666 var type = 'text/latex';
666 var type = 'text/latex';
667 var toinsert = this.create_output_subarea(md, "output_latex", type);
667 var toinsert = this.create_output_subarea(md, "output_latex", type);
668 toinsert.append(latex);
668 toinsert.append(latex);
669 element.append(toinsert);
669 element.append(toinsert);
670 };
670 };
671
671
672 OutputArea.append_map = {
672 OutputArea.append_map = {
673 "text/plain" : OutputArea.prototype.append_text,
673 "text/plain" : OutputArea.prototype.append_text,
674 "text/html" : OutputArea.prototype.append_html,
674 "text/html" : OutputArea.prototype.append_html,
675 "image/svg+xml" : OutputArea.prototype.append_svg,
675 "image/svg+xml" : OutputArea.prototype.append_svg,
676 "image/png" : OutputArea.prototype.append_png,
676 "image/png" : OutputArea.prototype.append_png,
677 "image/jpeg" : OutputArea.prototype.append_jpeg,
677 "image/jpeg" : OutputArea.prototype.append_jpeg,
678 "text/latex" : OutputArea.prototype.append_latex,
678 "text/latex" : OutputArea.prototype.append_latex,
679 "application/json" : OutputArea.prototype.append_json,
679 "application/json" : OutputArea.prototype.append_json,
680 "application/javascript" : OutputArea.prototype.append_javascript,
680 "application/javascript" : OutputArea.prototype.append_javascript,
681 };
681 };
682
682
683 OutputArea.prototype.append_raw_input = function (msg) {
683 OutputArea.prototype.append_raw_input = function (msg) {
684 var that = this;
684 var that = this;
685 this.expand();
685 this.expand();
686 var content = msg.content;
686 var content = msg.content;
687 var area = this.create_output_area();
687 var area = this.create_output_area();
688
688
689 // disable any other raw_inputs, if they are left around
689 // disable any other raw_inputs, if they are left around
690 $("div.output_subarea.raw_input").remove();
690 $("div.output_subarea.raw_input").remove();
691
691
692 area.append(
692 area.append(
693 $("<div/>")
693 $("<div/>")
694 .addClass("box-flex1 output_subarea raw_input")
694 .addClass("box-flex1 output_subarea raw_input")
695 .append(
695 .append(
696 $("<span/>")
696 $("<span/>")
697 .addClass("input_prompt")
697 .addClass("input_prompt")
698 .text(content.prompt)
698 .text(content.prompt)
699 )
699 )
700 .append(
700 .append(
701 $("<input/>")
701 $("<input/>")
702 .addClass("raw_input")
702 .addClass("raw_input")
703 .attr('type', 'text')
703 .attr('type', 'text')
704 .attr("size", 47)
704 .attr("size", 47)
705 .keydown(function (event, ui) {
705 .keydown(function (event, ui) {
706 // make sure we submit on enter,
706 // make sure we submit on enter,
707 // and don't re-execute the *cell* on shift-enter
707 // and don't re-execute the *cell* on shift-enter
708 if (event.which === utils.keycodes.ENTER) {
708 if (event.which === utils.keycodes.ENTER) {
709 that._submit_raw_input();
709 that._submit_raw_input();
710 return false;
710 return false;
711 }
711 }
712 })
712 })
713 )
713 )
714 );
714 );
715
715
716 this.element.append(area);
716 this.element.append(area);
717 var raw_input = area.find('input.raw_input');
717 var raw_input = area.find('input.raw_input');
718 // Register events that enable/disable the keyboard manager while raw
718 // Register events that enable/disable the keyboard manager while raw
719 // input is focused.
719 // input is focused.
720 IPython.keyboard_manager.register_events(raw_input);
720 IPython.keyboard_manager.register_events(raw_input);
721 // Note, the following line used to read raw_input.focus().focus().
721 // Note, the following line used to read raw_input.focus().focus().
722 // This seemed to be needed otherwise only the cell would be focused.
722 // This seemed to be needed otherwise only the cell would be focused.
723 // But with the modal UI, this seems to work fine with one call to focus().
723 // But with the modal UI, this seems to work fine with one call to focus().
724 raw_input.focus();
724 raw_input.focus();
725 }
725 }
726
726
727 OutputArea.prototype._submit_raw_input = function (evt) {
727 OutputArea.prototype._submit_raw_input = function (evt) {
728 var container = this.element.find("div.raw_input");
728 var container = this.element.find("div.raw_input");
729 var theprompt = container.find("span.input_prompt");
729 var theprompt = container.find("span.input_prompt");
730 var theinput = container.find("input.raw_input");
730 var theinput = container.find("input.raw_input");
731 var value = theinput.val();
731 var value = theinput.val();
732 var content = {
732 var content = {
733 output_type : 'stream',
733 output_type : 'stream',
734 name : 'stdout',
734 name : 'stdout',
735 text : theprompt.text() + value + '\n'
735 text : theprompt.text() + value + '\n'
736 }
736 }
737 // remove form container
737 // remove form container
738 container.parent().remove();
738 container.parent().remove();
739 // replace with plaintext version in stdout
739 // replace with plaintext version in stdout
740 this.append_output(content, false);
740 this.append_output(content, false);
741 $([IPython.events]).trigger('send_input_reply.Kernel', value);
741 $([IPython.events]).trigger('send_input_reply.Kernel', value);
742 }
742 }
743
743
744
744
745 OutputArea.prototype.handle_clear_output = function (msg) {
745 OutputArea.prototype.handle_clear_output = function (msg) {
746 this.clear_output(msg.content.wait);
746 // msg spec v4 had stdout, stderr, display keys
747 // v4.1 replaced these with just wait
748 // The default behavior is the same (stdout=stderr=display=True, wait=False),
749 // so v4 messages will still be properly handled,
750 // except for the rarely used clearing less than all output.
751 this.clear_output(msg.content.wait || false);
747 };
752 };
748
753
749
754
750 OutputArea.prototype.clear_output = function(wait) {
755 OutputArea.prototype.clear_output = function(wait) {
751 if (wait) {
756 if (wait) {
752
757
753 // If a clear is queued, clear before adding another to the queue.
758 // If a clear is queued, clear before adding another to the queue.
754 if (this.clear_queued) {
759 if (this.clear_queued) {
755 this.clear_output(false);
760 this.clear_output(false);
756 };
761 };
757
762
758 this.clear_queued = true;
763 this.clear_queued = true;
759 } else {
764 } else {
760
765
761 // Fix the output div's height if the clear_output is waiting for
766 // Fix the output div's height if the clear_output is waiting for
762 // new output (it is being used in an animation).
767 // new output (it is being used in an animation).
763 if (this.clear_queued) {
768 if (this.clear_queued) {
764 var height = this.element.height();
769 var height = this.element.height();
765 this.element.height(height);
770 this.element.height(height);
766 this.clear_queued = false;
771 this.clear_queued = false;
767 }
772 }
768
773
769 // clear all, no need for logic
774 // clear all, no need for logic
770 this.element.html("");
775 this.element.html("");
771 this.outputs = [];
776 this.outputs = [];
772 this.trusted = true;
777 this.trusted = true;
773 this.unscroll_area();
778 this.unscroll_area();
774 return;
779 return;
775 };
780 };
776 };
781 };
777
782
778
783
779 // JSON serialization
784 // JSON serialization
780
785
781 OutputArea.prototype.fromJSON = function (outputs) {
786 OutputArea.prototype.fromJSON = function (outputs) {
782 var len = outputs.length;
787 var len = outputs.length;
783 var data;
788 var data;
784
789
785 for (var i=0; i<len; i++) {
790 for (var i=0; i<len; i++) {
786 data = outputs[i];
791 data = outputs[i];
787 var msg_type = data.output_type;
792 var msg_type = data.output_type;
788 if (msg_type === "display_data" || msg_type === "pyout") {
793 if (msg_type === "display_data" || msg_type === "pyout") {
789 // convert short keys to mime keys
794 // convert short keys to mime keys
790 // TODO: remove mapping of short keys when we update to nbformat 4
795 // TODO: remove mapping of short keys when we update to nbformat 4
791 data = this.rename_keys(data, OutputArea.mime_map_r);
796 data = this.rename_keys(data, OutputArea.mime_map_r);
792 data.metadata = this.rename_keys(data.metadata, OutputArea.mime_map_r);
797 data.metadata = this.rename_keys(data.metadata, OutputArea.mime_map_r);
793 }
798 }
794
799
795 this.append_output(data);
800 this.append_output(data);
796 }
801 }
797 };
802 };
798
803
799
804
800 OutputArea.prototype.toJSON = function () {
805 OutputArea.prototype.toJSON = function () {
801 var outputs = [];
806 var outputs = [];
802 var len = this.outputs.length;
807 var len = this.outputs.length;
803 var data;
808 var data;
804 for (var i=0; i<len; i++) {
809 for (var i=0; i<len; i++) {
805 data = this.outputs[i];
810 data = this.outputs[i];
806 var msg_type = data.output_type;
811 var msg_type = data.output_type;
807 if (msg_type === "display_data" || msg_type === "pyout") {
812 if (msg_type === "display_data" || msg_type === "pyout") {
808 // convert mime keys to short keys
813 // convert mime keys to short keys
809 data = this.rename_keys(data, OutputArea.mime_map);
814 data = this.rename_keys(data, OutputArea.mime_map);
810 data.metadata = this.rename_keys(data.metadata, OutputArea.mime_map);
815 data.metadata = this.rename_keys(data.metadata, OutputArea.mime_map);
811 }
816 }
812 outputs[i] = data;
817 outputs[i] = data;
813 }
818 }
814 return outputs;
819 return outputs;
815 };
820 };
816
821
817
822
818 IPython.OutputArea = OutputArea;
823 IPython.OutputArea = OutputArea;
819
824
820 return IPython;
825 return IPython;
821
826
822 }(IPython));
827 }(IPython));
@@ -1,1156 +1,1171 b''
1 .. _messaging:
1 .. _messaging:
2
2
3 ======================
3 ======================
4 Messaging in IPython
4 Messaging in IPython
5 ======================
5 ======================
6
6
7
7
8 Versioning
9 ==========
10
11 The IPython message specification is versioned independently of IPython.
12 The current version of the specification is 4.1.
13
14
8 Introduction
15 Introduction
9 ============
16 ============
10
17
11 This document explains the basic communications design and messaging
18 This document explains the basic communications design and messaging
12 specification for how the various IPython objects interact over a network
19 specification for how the various IPython objects interact over a network
13 transport. The current implementation uses the ZeroMQ_ library for messaging
20 transport. The current implementation uses the ZeroMQ_ library for messaging
14 within and between hosts.
21 within and between hosts.
15
22
16 .. Note::
23 .. Note::
17
24
18 This document should be considered the authoritative description of the
25 This document should be considered the authoritative description of the
19 IPython messaging protocol, and all developers are strongly encouraged to
26 IPython messaging protocol, and all developers are strongly encouraged to
20 keep it updated as the implementation evolves, so that we have a single
27 keep it updated as the implementation evolves, so that we have a single
21 common reference for all protocol details.
28 common reference for all protocol details.
22
29
23 The basic design is explained in the following diagram:
30 The basic design is explained in the following diagram:
24
31
25 .. image:: figs/frontend-kernel.png
32 .. image:: figs/frontend-kernel.png
26 :width: 450px
33 :width: 450px
27 :alt: IPython kernel/frontend messaging architecture.
34 :alt: IPython kernel/frontend messaging architecture.
28 :align: center
35 :align: center
29 :target: ../_images/frontend-kernel.png
36 :target: ../_images/frontend-kernel.png
30
37
31 A single kernel can be simultaneously connected to one or more frontends. The
38 A single kernel can be simultaneously connected to one or more frontends. The
32 kernel has three sockets that serve the following functions:
39 kernel has three sockets that serve the following functions:
33
40
34 1. stdin: this ROUTER socket is connected to all frontends, and it allows
41 1. stdin: this ROUTER socket is connected to all frontends, and it allows
35 the kernel to request input from the active frontend when :func:`raw_input` is called.
42 the kernel to request input from the active frontend when :func:`raw_input` is called.
36 The frontend that executed the code has a DEALER socket that acts as a 'virtual keyboard'
43 The frontend that executed the code has a DEALER socket that acts as a 'virtual keyboard'
37 for the kernel while this communication is happening (illustrated in the
44 for the kernel while this communication is happening (illustrated in the
38 figure by the black outline around the central keyboard). In practice,
45 figure by the black outline around the central keyboard). In practice,
39 frontends may display such kernel requests using a special input widget or
46 frontends may display such kernel requests using a special input widget or
40 otherwise indicating that the user is to type input for the kernel instead
47 otherwise indicating that the user is to type input for the kernel instead
41 of normal commands in the frontend.
48 of normal commands in the frontend.
42
49
43 2. Shell: this single ROUTER socket allows multiple incoming connections from
50 2. Shell: this single ROUTER socket allows multiple incoming connections from
44 frontends, and this is the socket where requests for code execution, object
51 frontends, and this is the socket where requests for code execution, object
45 information, prompts, etc. are made to the kernel by any frontend. The
52 information, prompts, etc. are made to the kernel by any frontend. The
46 communication on this socket is a sequence of request/reply actions from
53 communication on this socket is a sequence of request/reply actions from
47 each frontend and the kernel.
54 each frontend and the kernel.
48
55
49 3. IOPub: this socket is the 'broadcast channel' where the kernel publishes all
56 3. IOPub: this socket is the 'broadcast channel' where the kernel publishes all
50 side effects (stdout, stderr, etc.) as well as the requests coming from any
57 side effects (stdout, stderr, etc.) as well as the requests coming from any
51 client over the shell socket and its own requests on the stdin socket. There
58 client over the shell socket and its own requests on the stdin socket. There
52 are a number of actions in Python which generate side effects: :func:`print`
59 are a number of actions in Python which generate side effects: :func:`print`
53 writes to ``sys.stdout``, errors generate tracebacks, etc. Additionally, in
60 writes to ``sys.stdout``, errors generate tracebacks, etc. Additionally, in
54 a multi-client scenario, we want all frontends to be able to know what each
61 a multi-client scenario, we want all frontends to be able to know what each
55 other has sent to the kernel (this can be useful in collaborative scenarios,
62 other has sent to the kernel (this can be useful in collaborative scenarios,
56 for example). This socket allows both side effects and the information
63 for example). This socket allows both side effects and the information
57 about communications taking place with one client over the shell channel
64 about communications taking place with one client over the shell channel
58 to be made available to all clients in a uniform manner.
65 to be made available to all clients in a uniform manner.
59
66
60 All messages are tagged with enough information (details below) for clients
67 All messages are tagged with enough information (details below) for clients
61 to know which messages come from their own interaction with the kernel and
68 to know which messages come from their own interaction with the kernel and
62 which ones are from other clients, so they can display each type
69 which ones are from other clients, so they can display each type
63 appropriately.
70 appropriately.
64
71
65 The actual format of the messages allowed on each of these channels is
72 The actual format of the messages allowed on each of these channels is
66 specified below. Messages are dicts of dicts with string keys and values that
73 specified below. Messages are dicts of dicts with string keys and values that
67 are reasonably representable in JSON. Our current implementation uses JSON
74 are reasonably representable in JSON. Our current implementation uses JSON
68 explicitly as its message format, but this shouldn't be considered a permanent
75 explicitly as its message format, but this shouldn't be considered a permanent
69 feature. As we've discovered that JSON has non-trivial performance issues due
76 feature. As we've discovered that JSON has non-trivial performance issues due
70 to excessive copying, we may in the future move to a pure pickle-based raw
77 to excessive copying, we may in the future move to a pure pickle-based raw
71 message format. However, it should be possible to easily convert from the raw
78 message format. However, it should be possible to easily convert from the raw
72 objects to JSON, since we may have non-python clients (e.g. a web frontend).
79 objects to JSON, since we may have non-python clients (e.g. a web frontend).
73 As long as it's easy to make a JSON version of the objects that is a faithful
80 As long as it's easy to make a JSON version of the objects that is a faithful
74 representation of all the data, we can communicate with such clients.
81 representation of all the data, we can communicate with such clients.
75
82
76 .. Note::
83 .. Note::
77
84
78 Not all of these have yet been fully fleshed out, but the key ones are, see
85 Not all of these have yet been fully fleshed out, but the key ones are, see
79 kernel and frontend files for actual implementation details.
86 kernel and frontend files for actual implementation details.
80
87
81 General Message Format
88 General Message Format
82 ======================
89 ======================
83
90
84 A message is defined by the following four-dictionary structure::
91 A message is defined by the following four-dictionary structure::
85
92
86 {
93 {
87 # The message header contains a pair of unique identifiers for the
94 # The message header contains a pair of unique identifiers for the
88 # originating session and the actual message id, in addition to the
95 # originating session and the actual message id, in addition to the
89 # username for the process that generated the message. This is useful in
96 # username for the process that generated the message. This is useful in
90 # collaborative settings where multiple users may be interacting with the
97 # collaborative settings where multiple users may be interacting with the
91 # same kernel simultaneously, so that frontends can label the various
98 # same kernel simultaneously, so that frontends can label the various
92 # messages in a meaningful way.
99 # messages in a meaningful way.
93 'header' : {
100 'header' : {
94 'msg_id' : uuid,
101 'msg_id' : uuid,
95 'username' : str,
102 'username' : str,
96 'session' : uuid,
103 'session' : uuid,
97 # All recognized message type strings are listed below.
104 # All recognized message type strings are listed below.
98 'msg_type' : str,
105 'msg_type' : str,
99 },
106 },
100
107
101 # In a chain of messages, the header from the parent is copied so that
108 # In a chain of messages, the header from the parent is copied so that
102 # clients can track where messages come from.
109 # clients can track where messages come from.
103 'parent_header' : dict,
110 'parent_header' : dict,
104
111
105 # Any metadata associated with the message.
112 # Any metadata associated with the message.
106 'metadata' : dict,
113 'metadata' : dict,
107
114
108 # The actual content of the message must be a dict, whose structure
115 # The actual content of the message must be a dict, whose structure
109 # depends on the message type.
116 # depends on the message type.
110 'content' : dict,
117 'content' : dict,
111 }
118 }
112
119
113 The Wire Protocol
120 The Wire Protocol
114 =================
121 =================
115
122
116
123
117 This message format exists at a high level,
124 This message format exists at a high level,
118 but does not describe the actual *implementation* at the wire level in zeromq.
125 but does not describe the actual *implementation* at the wire level in zeromq.
119 The canonical implementation of the message spec is our :class:`~IPython.kernel.zmq.session.Session` class.
126 The canonical implementation of the message spec is our :class:`~IPython.kernel.zmq.session.Session` class.
120
127
121 .. note::
128 .. note::
122
129
123 This section should only be relevant to non-Python consumers of the protocol.
130 This section should only be relevant to non-Python consumers of the protocol.
124 Python consumers should simply import and use IPython's own implementation of the wire protocol
131 Python consumers should simply import and use IPython's own implementation of the wire protocol
125 in the :class:`IPython.kernel.zmq.session.Session` object.
132 in the :class:`IPython.kernel.zmq.session.Session` object.
126
133
127 Every message is serialized to a sequence of at least six blobs of bytes:
134 Every message is serialized to a sequence of at least six blobs of bytes:
128
135
129 .. sourcecode:: python
136 .. sourcecode:: python
130
137
131 [
138 [
132 b'u-u-i-d', # zmq identity(ies)
139 b'u-u-i-d', # zmq identity(ies)
133 b'<IDS|MSG>', # delimiter
140 b'<IDS|MSG>', # delimiter
134 b'baddad42', # HMAC signature
141 b'baddad42', # HMAC signature
135 b'{header}', # serialized header dict
142 b'{header}', # serialized header dict
136 b'{parent_header}', # serialized parent header dict
143 b'{parent_header}', # serialized parent header dict
137 b'{metadata}', # serialized metadata dict
144 b'{metadata}', # serialized metadata dict
138 b'{content}, # serialized content dict
145 b'{content}, # serialized content dict
139 b'blob', # extra raw data buffer(s)
146 b'blob', # extra raw data buffer(s)
140 ...
147 ...
141 ]
148 ]
142
149
143 The front of the message is the ZeroMQ routing prefix,
150 The front of the message is the ZeroMQ routing prefix,
144 which can be zero or more socket identities.
151 which can be zero or more socket identities.
145 This is every piece of the message prior to the delimiter key ``<IDS|MSG>``.
152 This is every piece of the message prior to the delimiter key ``<IDS|MSG>``.
146 In the case of IOPub, there should be just one prefix component,
153 In the case of IOPub, there should be just one prefix component,
147 which is the topic for IOPub subscribers, e.g. ``pyout``, ``display_data``.
154 which is the topic for IOPub subscribers, e.g. ``pyout``, ``display_data``.
148
155
149 .. note::
156 .. note::
150
157
151 In most cases, the IOPub topics are irrelevant and completely ignored,
158 In most cases, the IOPub topics are irrelevant and completely ignored,
152 because frontends just subscribe to all topics.
159 because frontends just subscribe to all topics.
153 The convention used in the IPython kernel is to use the msg_type as the topic,
160 The convention used in the IPython kernel is to use the msg_type as the topic,
154 and possibly extra information about the message, e.g. ``pyout`` or ``stream.stdout``
161 and possibly extra information about the message, e.g. ``pyout`` or ``stream.stdout``
155
162
156 After the delimiter is the `HMAC`_ signature of the message, used for authentication.
163 After the delimiter is the `HMAC`_ signature of the message, used for authentication.
157 If authentication is disabled, this should be an empty string.
164 If authentication is disabled, this should be an empty string.
158 By default, the hashing function used for computing these signatures is sha256.
165 By default, the hashing function used for computing these signatures is sha256.
159
166
160 .. _HMAC: http://en.wikipedia.org/wiki/HMAC
167 .. _HMAC: http://en.wikipedia.org/wiki/HMAC
161
168
162 .. note::
169 .. note::
163
170
164 To disable authentication and signature checking,
171 To disable authentication and signature checking,
165 set the `key` field of a connection file to an empty string.
172 set the `key` field of a connection file to an empty string.
166
173
167 The signature is the HMAC hex digest of the concatenation of:
174 The signature is the HMAC hex digest of the concatenation of:
168
175
169 - A shared key (typically the ``key`` field of a connection file)
176 - A shared key (typically the ``key`` field of a connection file)
170 - The serialized header dict
177 - The serialized header dict
171 - The serialized parent header dict
178 - The serialized parent header dict
172 - The serialized metadata dict
179 - The serialized metadata dict
173 - The serialized content dict
180 - The serialized content dict
174
181
175 In Python, this is implemented via:
182 In Python, this is implemented via:
176
183
177 .. sourcecode:: python
184 .. sourcecode:: python
178
185
179 # once:
186 # once:
180 digester = HMAC(key, digestmod=hashlib.sha256)
187 digester = HMAC(key, digestmod=hashlib.sha256)
181
188
182 # for each message
189 # for each message
183 d = digester.copy()
190 d = digester.copy()
184 for serialized_dict in (header, parent, metadata, content):
191 for serialized_dict in (header, parent, metadata, content):
185 d.update(serialized_dict)
192 d.update(serialized_dict)
186 signature = d.hexdigest()
193 signature = d.hexdigest()
187
194
188 After the signature is the actual message, always in four frames of bytes.
195 After the signature is the actual message, always in four frames of bytes.
189 The four dictionaries that compose a message are serialized separately,
196 The four dictionaries that compose a message are serialized separately,
190 in the order of header, parent header, metadata, and content.
197 in the order of header, parent header, metadata, and content.
191 These can be serialized by any function that turns a dict into bytes.
198 These can be serialized by any function that turns a dict into bytes.
192 The default and most common serialization is JSON, but msgpack and pickle
199 The default and most common serialization is JSON, but msgpack and pickle
193 are common alternatives.
200 are common alternatives.
194
201
195 After the serialized dicts are zero to many raw data buffers,
202 After the serialized dicts are zero to many raw data buffers,
196 which can be used by message types that support binary data (mainly apply and data_pub).
203 which can be used by message types that support binary data (mainly apply and data_pub).
197
204
198
205
199 Python functional API
206 Python functional API
200 =====================
207 =====================
201
208
202 As messages are dicts, they map naturally to a ``func(**kw)`` call form. We
209 As messages are dicts, they map naturally to a ``func(**kw)`` call form. We
203 should develop, at a few key points, functional forms of all the requests that
210 should develop, at a few key points, functional forms of all the requests that
204 take arguments in this manner and automatically construct the necessary dict
211 take arguments in this manner and automatically construct the necessary dict
205 for sending.
212 for sending.
206
213
207 In addition, the Python implementation of the message specification extends
214 In addition, the Python implementation of the message specification extends
208 messages upon deserialization to the following form for convenience::
215 messages upon deserialization to the following form for convenience::
209
216
210 {
217 {
211 'header' : dict,
218 'header' : dict,
212 # The msg's unique identifier and type are always stored in the header,
219 # The msg's unique identifier and type are always stored in the header,
213 # but the Python implementation copies them to the top level.
220 # but the Python implementation copies them to the top level.
214 'msg_id' : uuid,
221 'msg_id' : uuid,
215 'msg_type' : str,
222 'msg_type' : str,
216 'parent_header' : dict,
223 'parent_header' : dict,
217 'content' : dict,
224 'content' : dict,
218 'metadata' : dict,
225 'metadata' : dict,
219 }
226 }
220
227
221 All messages sent to or received by any IPython process should have this
228 All messages sent to or received by any IPython process should have this
222 extended structure.
229 extended structure.
223
230
224
231
225 Messages on the shell ROUTER/DEALER sockets
232 Messages on the shell ROUTER/DEALER sockets
226 ===========================================
233 ===========================================
227
234
228 .. _execute:
235 .. _execute:
229
236
230 Execute
237 Execute
231 -------
238 -------
232
239
233 This message type is used by frontends to ask the kernel to execute code on
240 This message type is used by frontends to ask the kernel to execute code on
234 behalf of the user, in a namespace reserved to the user's variables (and thus
241 behalf of the user, in a namespace reserved to the user's variables (and thus
235 separate from the kernel's own internal code and variables).
242 separate from the kernel's own internal code and variables).
236
243
237 Message type: ``execute_request``::
244 Message type: ``execute_request``::
238
245
239 content = {
246 content = {
240 # Source code to be executed by the kernel, one or more lines.
247 # Source code to be executed by the kernel, one or more lines.
241 'code' : str,
248 'code' : str,
242
249
243 # A boolean flag which, if True, signals the kernel to execute
250 # A boolean flag which, if True, signals the kernel to execute
244 # this code as quietly as possible. This means that the kernel
251 # this code as quietly as possible. This means that the kernel
245 # will compile the code with 'exec' instead of 'single' (so
252 # will compile the code with 'exec' instead of 'single' (so
246 # sys.displayhook will not fire), forces store_history to be False,
253 # sys.displayhook will not fire), forces store_history to be False,
247 # and will *not*:
254 # and will *not*:
248 # - broadcast exceptions on the PUB socket
255 # - broadcast exceptions on the PUB socket
249 # - do any logging
256 # - do any logging
250 #
257 #
251 # The default is False.
258 # The default is False.
252 'silent' : bool,
259 'silent' : bool,
253
260
254 # A boolean flag which, if True, signals the kernel to populate history
261 # A boolean flag which, if True, signals the kernel to populate history
255 # The default is True if silent is False. If silent is True, store_history
262 # The default is True if silent is False. If silent is True, store_history
256 # is forced to be False.
263 # is forced to be False.
257 'store_history' : bool,
264 'store_history' : bool,
258
265
259 # A list of variable names from the user's namespace to be retrieved.
266 # A list of variable names from the user's namespace to be retrieved.
260 # What returns is a rich representation of each variable (dict keyed by name).
267 # What returns is a rich representation of each variable (dict keyed by name).
261 # See the display_data content for the structure of the representation data.
268 # See the display_data content for the structure of the representation data.
262 'user_variables' : list,
269 'user_variables' : list,
263
270
264 # Similarly, a dict mapping names to expressions to be evaluated in the
271 # Similarly, a dict mapping names to expressions to be evaluated in the
265 # user's dict.
272 # user's dict.
266 'user_expressions' : dict,
273 'user_expressions' : dict,
267
274
268 # Some frontends (e.g. the Notebook) do not support stdin requests. If
275 # Some frontends (e.g. the Notebook) do not support stdin requests. If
269 # raw_input is called from code executed from such a frontend, a
276 # raw_input is called from code executed from such a frontend, a
270 # StdinNotImplementedError will be raised.
277 # StdinNotImplementedError will be raised.
271 'allow_stdin' : True,
278 'allow_stdin' : True,
272
279
273 }
280 }
274
281
275 The ``code`` field contains a single string (possibly multiline). The kernel
282 The ``code`` field contains a single string (possibly multiline). The kernel
276 is responsible for splitting this into one or more independent execution blocks
283 is responsible for splitting this into one or more independent execution blocks
277 and deciding whether to compile these in 'single' or 'exec' mode (see below for
284 and deciding whether to compile these in 'single' or 'exec' mode (see below for
278 detailed execution semantics).
285 detailed execution semantics).
279
286
280 The ``user_`` fields deserve a detailed explanation. In the past, IPython had
287 The ``user_`` fields deserve a detailed explanation. In the past, IPython had
281 the notion of a prompt string that allowed arbitrary code to be evaluated, and
288 the notion of a prompt string that allowed arbitrary code to be evaluated, and
282 this was put to good use by many in creating prompts that displayed system
289 this was put to good use by many in creating prompts that displayed system
283 status, path information, and even more esoteric uses like remote instrument
290 status, path information, and even more esoteric uses like remote instrument
284 status acquired over the network. But now that IPython has a clean separation
291 status acquired over the network. But now that IPython has a clean separation
285 between the kernel and the clients, the kernel has no prompt knowledge; prompts
292 between the kernel and the clients, the kernel has no prompt knowledge; prompts
286 are a frontend-side feature, and it should be even possible for different
293 are a frontend-side feature, and it should be even possible for different
287 frontends to display different prompts while interacting with the same kernel.
294 frontends to display different prompts while interacting with the same kernel.
288
295
289 The kernel now provides the ability to retrieve data from the user's namespace
296 The kernel now provides the ability to retrieve data from the user's namespace
290 after the execution of the main ``code``, thanks to two fields in the
297 after the execution of the main ``code``, thanks to two fields in the
291 ``execute_request`` message:
298 ``execute_request`` message:
292
299
293 - ``user_variables``: If only variables from the user's namespace are needed, a
300 - ``user_variables``: If only variables from the user's namespace are needed, a
294 list of variable names can be passed and a dict with these names as keys and
301 list of variable names can be passed and a dict with these names as keys and
295 their :func:`repr()` as values will be returned.
302 their :func:`repr()` as values will be returned.
296
303
297 - ``user_expressions``: For more complex expressions that require function
304 - ``user_expressions``: For more complex expressions that require function
298 evaluations, a dict can be provided with string keys and arbitrary python
305 evaluations, a dict can be provided with string keys and arbitrary python
299 expressions as values. The return message will contain also a dict with the
306 expressions as values. The return message will contain also a dict with the
300 same keys and the :func:`repr()` of the evaluated expressions as value.
307 same keys and the :func:`repr()` of the evaluated expressions as value.
301
308
302 With this information, frontends can display any status information they wish
309 With this information, frontends can display any status information they wish
303 in the form that best suits each frontend (a status line, a popup, inline for a
310 in the form that best suits each frontend (a status line, a popup, inline for a
304 terminal, etc).
311 terminal, etc).
305
312
306 .. Note::
313 .. Note::
307
314
308 In order to obtain the current execution counter for the purposes of
315 In order to obtain the current execution counter for the purposes of
309 displaying input prompts, frontends simply make an execution request with an
316 displaying input prompts, frontends simply make an execution request with an
310 empty code string and ``silent=True``.
317 empty code string and ``silent=True``.
311
318
312 Execution semantics
319 Execution semantics
313 ~~~~~~~~~~~~~~~~~~~
320 ~~~~~~~~~~~~~~~~~~~
314
321
315 When the silent flag is false, the execution of use code consists of the
322 When the silent flag is false, the execution of use code consists of the
316 following phases (in silent mode, only the ``code`` field is executed):
323 following phases (in silent mode, only the ``code`` field is executed):
317
324
318 1. Run the ``pre_runcode_hook``.
325 1. Run the ``pre_runcode_hook``.
319
326
320 2. Execute the ``code`` field, see below for details.
327 2. Execute the ``code`` field, see below for details.
321
328
322 3. If #2 succeeds, compute ``user_variables`` and ``user_expressions`` are
329 3. If #2 succeeds, compute ``user_variables`` and ``user_expressions`` are
323 computed. This ensures that any error in the latter don't harm the main
330 computed. This ensures that any error in the latter don't harm the main
324 code execution.
331 code execution.
325
332
326 4. Call any method registered with :meth:`register_post_execute`.
333 4. Call any method registered with :meth:`register_post_execute`.
327
334
328 .. warning::
335 .. warning::
329
336
330 The API for running code before/after the main code block is likely to
337 The API for running code before/after the main code block is likely to
331 change soon. Both the ``pre_runcode_hook`` and the
338 change soon. Both the ``pre_runcode_hook`` and the
332 :meth:`register_post_execute` are susceptible to modification, as we find a
339 :meth:`register_post_execute` are susceptible to modification, as we find a
333 consistent model for both.
340 consistent model for both.
334
341
335 To understand how the ``code`` field is executed, one must know that Python
342 To understand how the ``code`` field is executed, one must know that Python
336 code can be compiled in one of three modes (controlled by the ``mode`` argument
343 code can be compiled in one of three modes (controlled by the ``mode`` argument
337 to the :func:`compile` builtin):
344 to the :func:`compile` builtin):
338
345
339 *single*
346 *single*
340 Valid for a single interactive statement (though the source can contain
347 Valid for a single interactive statement (though the source can contain
341 multiple lines, such as a for loop). When compiled in this mode, the
348 multiple lines, such as a for loop). When compiled in this mode, the
342 generated bytecode contains special instructions that trigger the calling of
349 generated bytecode contains special instructions that trigger the calling of
343 :func:`sys.displayhook` for any expression in the block that returns a value.
350 :func:`sys.displayhook` for any expression in the block that returns a value.
344 This means that a single statement can actually produce multiple calls to
351 This means that a single statement can actually produce multiple calls to
345 :func:`sys.displayhook`, if for example it contains a loop where each
352 :func:`sys.displayhook`, if for example it contains a loop where each
346 iteration computes an unassigned expression would generate 10 calls::
353 iteration computes an unassigned expression would generate 10 calls::
347
354
348 for i in range(10):
355 for i in range(10):
349 i**2
356 i**2
350
357
351 *exec*
358 *exec*
352 An arbitrary amount of source code, this is how modules are compiled.
359 An arbitrary amount of source code, this is how modules are compiled.
353 :func:`sys.displayhook` is *never* implicitly called.
360 :func:`sys.displayhook` is *never* implicitly called.
354
361
355 *eval*
362 *eval*
356 A single expression that returns a value. :func:`sys.displayhook` is *never*
363 A single expression that returns a value. :func:`sys.displayhook` is *never*
357 implicitly called.
364 implicitly called.
358
365
359
366
360 The ``code`` field is split into individual blocks each of which is valid for
367 The ``code`` field is split into individual blocks each of which is valid for
361 execution in 'single' mode, and then:
368 execution in 'single' mode, and then:
362
369
363 - If there is only a single block: it is executed in 'single' mode.
370 - If there is only a single block: it is executed in 'single' mode.
364
371
365 - If there is more than one block:
372 - If there is more than one block:
366
373
367 * if the last one is a single line long, run all but the last in 'exec' mode
374 * if the last one is a single line long, run all but the last in 'exec' mode
368 and the very last one in 'single' mode. This makes it easy to type simple
375 and the very last one in 'single' mode. This makes it easy to type simple
369 expressions at the end to see computed values.
376 expressions at the end to see computed values.
370
377
371 * if the last one is no more than two lines long, run all but the last in
378 * if the last one is no more than two lines long, run all but the last in
372 'exec' mode and the very last one in 'single' mode. This makes it easy to
379 'exec' mode and the very last one in 'single' mode. This makes it easy to
373 type simple expressions at the end to see computed values. - otherwise
380 type simple expressions at the end to see computed values. - otherwise
374 (last one is also multiline), run all in 'exec' mode
381 (last one is also multiline), run all in 'exec' mode
375
382
376 * otherwise (last one is also multiline), run all in 'exec' mode as a single
383 * otherwise (last one is also multiline), run all in 'exec' mode as a single
377 unit.
384 unit.
378
385
379 Any error in retrieving the ``user_variables`` or evaluating the
386 Any error in retrieving the ``user_variables`` or evaluating the
380 ``user_expressions`` will result in a simple error message in the return fields
387 ``user_expressions`` will result in a simple error message in the return fields
381 of the form::
388 of the form::
382
389
383 [ERROR] ExceptionType: Exception message
390 [ERROR] ExceptionType: Exception message
384
391
385 The user can simply send the same variable name or expression for evaluation to
392 The user can simply send the same variable name or expression for evaluation to
386 see a regular traceback.
393 see a regular traceback.
387
394
388 Errors in any registered post_execute functions are also reported similarly,
395 Errors in any registered post_execute functions are also reported similarly,
389 and the failing function is removed from the post_execution set so that it does
396 and the failing function is removed from the post_execution set so that it does
390 not continue triggering failures.
397 not continue triggering failures.
391
398
392 Upon completion of the execution request, the kernel *always* sends a reply,
399 Upon completion of the execution request, the kernel *always* sends a reply,
393 with a status code indicating what happened and additional data depending on
400 with a status code indicating what happened and additional data depending on
394 the outcome. See :ref:`below <execution_results>` for the possible return
401 the outcome. See :ref:`below <execution_results>` for the possible return
395 codes and associated data.
402 codes and associated data.
396
403
397
404
398 Execution counter (old prompt number)
405 Execution counter (old prompt number)
399 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
406 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
400
407
401 The kernel has a single, monotonically increasing counter of all execution
408 The kernel has a single, monotonically increasing counter of all execution
402 requests that are made with ``store_history=True``. This counter is used to populate
409 requests that are made with ``store_history=True``. This counter is used to populate
403 the ``In[n]``, ``Out[n]`` and ``_n`` variables, so clients will likely want to
410 the ``In[n]``, ``Out[n]`` and ``_n`` variables, so clients will likely want to
404 display it in some form to the user, which will typically (but not necessarily)
411 display it in some form to the user, which will typically (but not necessarily)
405 be done in the prompts. The value of this counter will be returned as the
412 be done in the prompts. The value of this counter will be returned as the
406 ``execution_count`` field of all ``execute_reply`` messages.
413 ``execution_count`` field of all ``execute_reply`` messages.
407
414
408 .. _execution_results:
415 .. _execution_results:
409
416
410 Execution results
417 Execution results
411 ~~~~~~~~~~~~~~~~~
418 ~~~~~~~~~~~~~~~~~
412
419
413 Message type: ``execute_reply``::
420 Message type: ``execute_reply``::
414
421
415 content = {
422 content = {
416 # One of: 'ok' OR 'error' OR 'abort'
423 # One of: 'ok' OR 'error' OR 'abort'
417 'status' : str,
424 'status' : str,
418
425
419 # The global kernel counter that increases by one with each request that
426 # The global kernel counter that increases by one with each request that
420 # stores history. This will typically be used by clients to display
427 # stores history. This will typically be used by clients to display
421 # prompt numbers to the user. If the request did not store history, this will
428 # prompt numbers to the user. If the request did not store history, this will
422 # be the current value of the counter in the kernel.
429 # be the current value of the counter in the kernel.
423 'execution_count' : int,
430 'execution_count' : int,
424 }
431 }
425
432
426 When status is 'ok', the following extra fields are present::
433 When status is 'ok', the following extra fields are present::
427
434
428 {
435 {
429 # 'payload' will be a list of payload dicts.
436 # 'payload' will be a list of payload dicts.
430 # Each execution payload is a dict with string keys that may have been
437 # Each execution payload is a dict with string keys that may have been
431 # produced by the code being executed. It is retrieved by the kernel at
438 # produced by the code being executed. It is retrieved by the kernel at
432 # the end of the execution and sent back to the front end, which can take
439 # the end of the execution and sent back to the front end, which can take
433 # action on it as needed.
440 # action on it as needed.
434 # The only requirement of each payload dict is that it have a 'source' key,
441 # The only requirement of each payload dict is that it have a 'source' key,
435 # which is a string classifying the payload (e.g. 'pager').
442 # which is a string classifying the payload (e.g. 'pager').
436 'payload' : list(dict),
443 'payload' : list(dict),
437
444
438 # Results for the user_variables and user_expressions.
445 # Results for the user_variables and user_expressions.
439 'user_variables' : dict,
446 'user_variables' : dict,
440 'user_expressions' : dict,
447 'user_expressions' : dict,
441 }
448 }
442
449
443 .. admonition:: Execution payloads
450 .. admonition:: Execution payloads
444
451
445 The notion of an 'execution payload' is different from a return value of a
452 The notion of an 'execution payload' is different from a return value of a
446 given set of code, which normally is just displayed on the pyout stream
453 given set of code, which normally is just displayed on the pyout stream
447 through the PUB socket. The idea of a payload is to allow special types of
454 through the PUB socket. The idea of a payload is to allow special types of
448 code, typically magics, to populate a data container in the IPython kernel
455 code, typically magics, to populate a data container in the IPython kernel
449 that will be shipped back to the caller via this channel. The kernel
456 that will be shipped back to the caller via this channel. The kernel
450 has an API for this in the PayloadManager::
457 has an API for this in the PayloadManager::
451
458
452 ip.payload_manager.write_payload(payload_dict)
459 ip.payload_manager.write_payload(payload_dict)
453
460
454 which appends a dictionary to the list of payloads.
461 which appends a dictionary to the list of payloads.
455
462
456 The payload API is not yet stabilized,
463 The payload API is not yet stabilized,
457 and should probably not be supported by non-Python kernels at this time.
464 and should probably not be supported by non-Python kernels at this time.
458 In such cases, the payload list should always be empty.
465 In such cases, the payload list should always be empty.
459
466
460
467
461 When status is 'error', the following extra fields are present::
468 When status is 'error', the following extra fields are present::
462
469
463 {
470 {
464 'ename' : str, # Exception name, as a string
471 'ename' : str, # Exception name, as a string
465 'evalue' : str, # Exception value, as a string
472 'evalue' : str, # Exception value, as a string
466
473
467 # The traceback will contain a list of frames, represented each as a
474 # The traceback will contain a list of frames, represented each as a
468 # string. For now we'll stick to the existing design of ultraTB, which
475 # string. For now we'll stick to the existing design of ultraTB, which
469 # controls exception level of detail statefully. But eventually we'll
476 # controls exception level of detail statefully. But eventually we'll
470 # want to grow into a model where more information is collected and
477 # want to grow into a model where more information is collected and
471 # packed into the traceback object, with clients deciding how little or
478 # packed into the traceback object, with clients deciding how little or
472 # how much of it to unpack. But for now, let's start with a simple list
479 # how much of it to unpack. But for now, let's start with a simple list
473 # of strings, since that requires only minimal changes to ultratb as
480 # of strings, since that requires only minimal changes to ultratb as
474 # written.
481 # written.
475 'traceback' : list,
482 'traceback' : list,
476 }
483 }
477
484
478
485
479 When status is 'abort', there are for now no additional data fields. This
486 When status is 'abort', there are for now no additional data fields. This
480 happens when the kernel was interrupted by a signal.
487 happens when the kernel was interrupted by a signal.
481
488
482
489
483 Object information
490 Object information
484 ------------------
491 ------------------
485
492
486 One of IPython's most used capabilities is the introspection of Python objects
493 One of IPython's most used capabilities is the introspection of Python objects
487 in the user's namespace, typically invoked via the ``?`` and ``??`` characters
494 in the user's namespace, typically invoked via the ``?`` and ``??`` characters
488 (which in reality are shorthands for the ``%pinfo`` magic). This is used often
495 (which in reality are shorthands for the ``%pinfo`` magic). This is used often
489 enough that it warrants an explicit message type, especially because frontends
496 enough that it warrants an explicit message type, especially because frontends
490 may want to get object information in response to user keystrokes (like Tab or
497 may want to get object information in response to user keystrokes (like Tab or
491 F1) besides from the user explicitly typing code like ``x??``.
498 F1) besides from the user explicitly typing code like ``x??``.
492
499
493 Message type: ``object_info_request``::
500 Message type: ``object_info_request``::
494
501
495 content = {
502 content = {
496 # The (possibly dotted) name of the object to be searched in all
503 # The (possibly dotted) name of the object to be searched in all
497 # relevant namespaces
504 # relevant namespaces
498 'oname' : str,
505 'oname' : str,
499
506
500 # The level of detail desired. The default (0) is equivalent to typing
507 # The level of detail desired. The default (0) is equivalent to typing
501 # 'x?' at the prompt, 1 is equivalent to 'x??'.
508 # 'x?' at the prompt, 1 is equivalent to 'x??'.
502 'detail_level' : int,
509 'detail_level' : int,
503 }
510 }
504
511
505 The returned information will be a dictionary with keys very similar to the
512 The returned information will be a dictionary with keys very similar to the
506 field names that IPython prints at the terminal.
513 field names that IPython prints at the terminal.
507
514
508 Message type: ``object_info_reply``::
515 Message type: ``object_info_reply``::
509
516
510 content = {
517 content = {
511 # The name the object was requested under
518 # The name the object was requested under
512 'name' : str,
519 'name' : str,
513
520
514 # Boolean flag indicating whether the named object was found or not. If
521 # Boolean flag indicating whether the named object was found or not. If
515 # it's false, all other fields will be empty.
522 # it's false, all other fields will be empty.
516 'found' : bool,
523 'found' : bool,
517
524
518 # Flags for magics and system aliases
525 # Flags for magics and system aliases
519 'ismagic' : bool,
526 'ismagic' : bool,
520 'isalias' : bool,
527 'isalias' : bool,
521
528
522 # The name of the namespace where the object was found ('builtin',
529 # The name of the namespace where the object was found ('builtin',
523 # 'magics', 'alias', 'interactive', etc.)
530 # 'magics', 'alias', 'interactive', etc.)
524 'namespace' : str,
531 'namespace' : str,
525
532
526 # The type name will be type.__name__ for normal Python objects, but it
533 # The type name will be type.__name__ for normal Python objects, but it
527 # can also be a string like 'Magic function' or 'System alias'
534 # can also be a string like 'Magic function' or 'System alias'
528 'type_name' : str,
535 'type_name' : str,
529
536
530 # The string form of the object, possibly truncated for length if
537 # The string form of the object, possibly truncated for length if
531 # detail_level is 0
538 # detail_level is 0
532 'string_form' : str,
539 'string_form' : str,
533
540
534 # For objects with a __class__ attribute this will be set
541 # For objects with a __class__ attribute this will be set
535 'base_class' : str,
542 'base_class' : str,
536
543
537 # For objects with a __len__ attribute this will be set
544 # For objects with a __len__ attribute this will be set
538 'length' : int,
545 'length' : int,
539
546
540 # If the object is a function, class or method whose file we can find,
547 # If the object is a function, class or method whose file we can find,
541 # we give its full path
548 # we give its full path
542 'file' : str,
549 'file' : str,
543
550
544 # For pure Python callable objects, we can reconstruct the object
551 # For pure Python callable objects, we can reconstruct the object
545 # definition line which provides its call signature. For convenience this
552 # definition line which provides its call signature. For convenience this
546 # is returned as a single 'definition' field, but below the raw parts that
553 # is returned as a single 'definition' field, but below the raw parts that
547 # compose it are also returned as the argspec field.
554 # compose it are also returned as the argspec field.
548 'definition' : str,
555 'definition' : str,
549
556
550 # The individual parts that together form the definition string. Clients
557 # The individual parts that together form the definition string. Clients
551 # with rich display capabilities may use this to provide a richer and more
558 # with rich display capabilities may use this to provide a richer and more
552 # precise representation of the definition line (e.g. by highlighting
559 # precise representation of the definition line (e.g. by highlighting
553 # arguments based on the user's cursor position). For non-callable
560 # arguments based on the user's cursor position). For non-callable
554 # objects, this field is empty.
561 # objects, this field is empty.
555 'argspec' : { # The names of all the arguments
562 'argspec' : { # The names of all the arguments
556 args : list,
563 args : list,
557 # The name of the varargs (*args), if any
564 # The name of the varargs (*args), if any
558 varargs : str,
565 varargs : str,
559 # The name of the varkw (**kw), if any
566 # The name of the varkw (**kw), if any
560 varkw : str,
567 varkw : str,
561 # The values (as strings) of all default arguments. Note
568 # The values (as strings) of all default arguments. Note
562 # that these must be matched *in reverse* with the 'args'
569 # that these must be matched *in reverse* with the 'args'
563 # list above, since the first positional args have no default
570 # list above, since the first positional args have no default
564 # value at all.
571 # value at all.
565 defaults : list,
572 defaults : list,
566 },
573 },
567
574
568 # For instances, provide the constructor signature (the definition of
575 # For instances, provide the constructor signature (the definition of
569 # the __init__ method):
576 # the __init__ method):
570 'init_definition' : str,
577 'init_definition' : str,
571
578
572 # Docstrings: for any object (function, method, module, package) with a
579 # Docstrings: for any object (function, method, module, package) with a
573 # docstring, we show it. But in addition, we may provide additional
580 # docstring, we show it. But in addition, we may provide additional
574 # docstrings. For example, for instances we will show the constructor
581 # docstrings. For example, for instances we will show the constructor
575 # and class docstrings as well, if available.
582 # and class docstrings as well, if available.
576 'docstring' : str,
583 'docstring' : str,
577
584
578 # For instances, provide the constructor and class docstrings
585 # For instances, provide the constructor and class docstrings
579 'init_docstring' : str,
586 'init_docstring' : str,
580 'class_docstring' : str,
587 'class_docstring' : str,
581
588
582 # If it's a callable object whose call method has a separate docstring and
589 # If it's a callable object whose call method has a separate docstring and
583 # definition line:
590 # definition line:
584 'call_def' : str,
591 'call_def' : str,
585 'call_docstring' : str,
592 'call_docstring' : str,
586
593
587 # If detail_level was 1, we also try to find the source code that
594 # If detail_level was 1, we also try to find the source code that
588 # defines the object, if possible. The string 'None' will indicate
595 # defines the object, if possible. The string 'None' will indicate
589 # that no source was found.
596 # that no source was found.
590 'source' : str,
597 'source' : str,
591 }
598 }
592
599
593
600
594 Complete
601 Complete
595 --------
602 --------
596
603
597 Message type: ``complete_request``::
604 Message type: ``complete_request``::
598
605
599 content = {
606 content = {
600 # The text to be completed, such as 'a.is'
607 # The text to be completed, such as 'a.is'
601 # this may be an empty string if the frontend does not do any lexing,
608 # this may be an empty string if the frontend does not do any lexing,
602 # in which case the kernel must figure out the completion
609 # in which case the kernel must figure out the completion
603 # based on 'line' and 'cursor_pos'.
610 # based on 'line' and 'cursor_pos'.
604 'text' : str,
611 'text' : str,
605
612
606 # The full line, such as 'print a.is'. This allows completers to
613 # The full line, such as 'print a.is'. This allows completers to
607 # make decisions that may require information about more than just the
614 # make decisions that may require information about more than just the
608 # current word.
615 # current word.
609 'line' : str,
616 'line' : str,
610
617
611 # The entire block of text where the line is. This may be useful in the
618 # The entire block of text where the line is. This may be useful in the
612 # case of multiline completions where more context may be needed. Note: if
619 # case of multiline completions where more context may be needed. Note: if
613 # in practice this field proves unnecessary, remove it to lighten the
620 # in practice this field proves unnecessary, remove it to lighten the
614 # messages.
621 # messages.
615
622
616 'block' : str or null/None,
623 'block' : str or null/None,
617
624
618 # The position of the cursor where the user hit 'TAB' on the line.
625 # The position of the cursor where the user hit 'TAB' on the line.
619 'cursor_pos' : int,
626 'cursor_pos' : int,
620 }
627 }
621
628
622 Message type: ``complete_reply``::
629 Message type: ``complete_reply``::
623
630
624 content = {
631 content = {
625 # The list of all matches to the completion request, such as
632 # The list of all matches to the completion request, such as
626 # ['a.isalnum', 'a.isalpha'] for the above example.
633 # ['a.isalnum', 'a.isalpha'] for the above example.
627 'matches' : list,
634 'matches' : list,
628
635
629 # the substring of the matched text
636 # the substring of the matched text
630 # this is typically the common prefix of the matches,
637 # this is typically the common prefix of the matches,
631 # and the text that is already in the block that would be replaced by the full completion.
638 # and the text that is already in the block that would be replaced by the full completion.
632 # This would be 'a.is' in the above example.
639 # This would be 'a.is' in the above example.
633 'matched_text' : str,
640 'matched_text' : str,
634
641
635 # status should be 'ok' unless an exception was raised during the request,
642 # status should be 'ok' unless an exception was raised during the request,
636 # in which case it should be 'error', along with the usual error message content
643 # in which case it should be 'error', along with the usual error message content
637 # in other messages.
644 # in other messages.
638 'status' : 'ok'
645 'status' : 'ok'
639 }
646 }
640
647
641
648
642 History
649 History
643 -------
650 -------
644
651
645 For clients to explicitly request history from a kernel. The kernel has all
652 For clients to explicitly request history from a kernel. The kernel has all
646 the actual execution history stored in a single location, so clients can
653 the actual execution history stored in a single location, so clients can
647 request it from the kernel when needed.
654 request it from the kernel when needed.
648
655
649 Message type: ``history_request``::
656 Message type: ``history_request``::
650
657
651 content = {
658 content = {
652
659
653 # If True, also return output history in the resulting dict.
660 # If True, also return output history in the resulting dict.
654 'output' : bool,
661 'output' : bool,
655
662
656 # If True, return the raw input history, else the transformed input.
663 # If True, return the raw input history, else the transformed input.
657 'raw' : bool,
664 'raw' : bool,
658
665
659 # So far, this can be 'range', 'tail' or 'search'.
666 # So far, this can be 'range', 'tail' or 'search'.
660 'hist_access_type' : str,
667 'hist_access_type' : str,
661
668
662 # If hist_access_type is 'range', get a range of input cells. session can
669 # If hist_access_type is 'range', get a range of input cells. session can
663 # be a positive session number, or a negative number to count back from
670 # be a positive session number, or a negative number to count back from
664 # the current session.
671 # the current session.
665 'session' : int,
672 'session' : int,
666 # start and stop are line numbers within that session.
673 # start and stop are line numbers within that session.
667 'start' : int,
674 'start' : int,
668 'stop' : int,
675 'stop' : int,
669
676
670 # If hist_access_type is 'tail' or 'search', get the last n cells.
677 # If hist_access_type is 'tail' or 'search', get the last n cells.
671 'n' : int,
678 'n' : int,
672
679
673 # If hist_access_type is 'search', get cells matching the specified glob
680 # If hist_access_type is 'search', get cells matching the specified glob
674 # pattern (with * and ? as wildcards).
681 # pattern (with * and ? as wildcards).
675 'pattern' : str,
682 'pattern' : str,
676
683
677 # If hist_access_type is 'search' and unique is true, do not
684 # If hist_access_type is 'search' and unique is true, do not
678 # include duplicated history. Default is false.
685 # include duplicated history. Default is false.
679 'unique' : bool,
686 'unique' : bool,
680
687
681 }
688 }
682
689
683 .. versionadded:: 4.0
690 .. versionadded:: 4.0
684 The key ``unique`` for ``history_request``.
691 The key ``unique`` for ``history_request``.
685
692
686 Message type: ``history_reply``::
693 Message type: ``history_reply``::
687
694
688 content = {
695 content = {
689 # A list of 3 tuples, either:
696 # A list of 3 tuples, either:
690 # (session, line_number, input) or
697 # (session, line_number, input) or
691 # (session, line_number, (input, output)),
698 # (session, line_number, (input, output)),
692 # depending on whether output was False or True, respectively.
699 # depending on whether output was False or True, respectively.
693 'history' : list,
700 'history' : list,
694 }
701 }
695
702
696
703
697 Connect
704 Connect
698 -------
705 -------
699
706
700 When a client connects to the request/reply socket of the kernel, it can issue
707 When a client connects to the request/reply socket of the kernel, it can issue
701 a connect request to get basic information about the kernel, such as the ports
708 a connect request to get basic information about the kernel, such as the ports
702 the other ZeroMQ sockets are listening on. This allows clients to only have
709 the other ZeroMQ sockets are listening on. This allows clients to only have
703 to know about a single port (the shell channel) to connect to a kernel.
710 to know about a single port (the shell channel) to connect to a kernel.
704
711
705 Message type: ``connect_request``::
712 Message type: ``connect_request``::
706
713
707 content = {
714 content = {
708 }
715 }
709
716
710 Message type: ``connect_reply``::
717 Message type: ``connect_reply``::
711
718
712 content = {
719 content = {
713 'shell_port' : int, # The port the shell ROUTER socket is listening on.
720 'shell_port' : int, # The port the shell ROUTER socket is listening on.
714 'iopub_port' : int, # The port the PUB socket is listening on.
721 'iopub_port' : int, # The port the PUB socket is listening on.
715 'stdin_port' : int, # The port the stdin ROUTER socket is listening on.
722 'stdin_port' : int, # The port the stdin ROUTER socket is listening on.
716 'hb_port' : int, # The port the heartbeat socket is listening on.
723 'hb_port' : int, # The port the heartbeat socket is listening on.
717 }
724 }
718
725
719
726
720 Kernel info
727 Kernel info
721 -----------
728 -----------
722
729
723 If a client needs to know information about the kernel, it can
730 If a client needs to know information about the kernel, it can
724 make a request of the kernel's information.
731 make a request of the kernel's information.
725 This message can be used to fetch core information of the
732 This message can be used to fetch core information of the
726 kernel, including language (e.g., Python), language version number and
733 kernel, including language (e.g., Python), language version number and
727 IPython version number, and the IPython message spec version number.
734 IPython version number, and the IPython message spec version number.
728
735
729 Message type: ``kernel_info_request``::
736 Message type: ``kernel_info_request``::
730
737
731 content = {
738 content = {
732 }
739 }
733
740
734 Message type: ``kernel_info_reply``::
741 Message type: ``kernel_info_reply``::
735
742
736 content = {
743 content = {
737 # Version of messaging protocol (mandatory).
744 # Version of messaging protocol (mandatory).
738 # The first integer indicates major version. It is incremented when
745 # The first integer indicates major version. It is incremented when
739 # there is any backward incompatible change.
746 # there is any backward incompatible change.
740 # The second integer indicates minor version. It is incremented when
747 # The second integer indicates minor version. It is incremented when
741 # there is any backward compatible change.
748 # there is any backward compatible change.
742 'protocol_version': [int, int],
749 'protocol_version': [int, int],
743
750
744 # IPython version number (optional).
751 # IPython version number (optional).
745 # Non-python kernel backend may not have this version number.
752 # Non-python kernel backend may not have this version number.
746 # The last component is an extra field, which may be 'dev' or
753 # The last component is an extra field, which may be 'dev' or
747 # 'rc1' in development version. It is an empty string for
754 # 'rc1' in development version. It is an empty string for
748 # released version.
755 # released version.
749 'ipython_version': [int, int, int, str],
756 'ipython_version': [int, int, int, str],
750
757
751 # Language version number (mandatory).
758 # Language version number (mandatory).
752 # It is Python version number (e.g., [2, 7, 3]) for the kernel
759 # It is Python version number (e.g., [2, 7, 3]) for the kernel
753 # included in IPython.
760 # included in IPython.
754 'language_version': [int, ...],
761 'language_version': [int, ...],
755
762
756 # Programming language in which kernel is implemented (mandatory).
763 # Programming language in which kernel is implemented (mandatory).
757 # Kernel included in IPython returns 'python'.
764 # Kernel included in IPython returns 'python'.
758 'language': str,
765 'language': str,
759 }
766 }
760
767
761
768
762 Kernel shutdown
769 Kernel shutdown
763 ---------------
770 ---------------
764
771
765 The clients can request the kernel to shut itself down; this is used in
772 The clients can request the kernel to shut itself down; this is used in
766 multiple cases:
773 multiple cases:
767
774
768 - when the user chooses to close the client application via a menu or window
775 - when the user chooses to close the client application via a menu or window
769 control.
776 control.
770 - when the user types 'exit' or 'quit' (or their uppercase magic equivalents).
777 - when the user types 'exit' or 'quit' (or their uppercase magic equivalents).
771 - when the user chooses a GUI method (like the 'Ctrl-C' shortcut in the
778 - when the user chooses a GUI method (like the 'Ctrl-C' shortcut in the
772 IPythonQt client) to force a kernel restart to get a clean kernel without
779 IPythonQt client) to force a kernel restart to get a clean kernel without
773 losing client-side state like history or inlined figures.
780 losing client-side state like history or inlined figures.
774
781
775 The client sends a shutdown request to the kernel, and once it receives the
782 The client sends a shutdown request to the kernel, and once it receives the
776 reply message (which is otherwise empty), it can assume that the kernel has
783 reply message (which is otherwise empty), it can assume that the kernel has
777 completed shutdown safely.
784 completed shutdown safely.
778
785
779 Upon their own shutdown, client applications will typically execute a last
786 Upon their own shutdown, client applications will typically execute a last
780 minute sanity check and forcefully terminate any kernel that is still alive, to
787 minute sanity check and forcefully terminate any kernel that is still alive, to
781 avoid leaving stray processes in the user's machine.
788 avoid leaving stray processes in the user's machine.
782
789
783 Message type: ``shutdown_request``::
790 Message type: ``shutdown_request``::
784
791
785 content = {
792 content = {
786 'restart' : bool # whether the shutdown is final, or precedes a restart
793 'restart' : bool # whether the shutdown is final, or precedes a restart
787 }
794 }
788
795
789 Message type: ``shutdown_reply``::
796 Message type: ``shutdown_reply``::
790
797
791 content = {
798 content = {
792 'restart' : bool # whether the shutdown is final, or precedes a restart
799 'restart' : bool # whether the shutdown is final, or precedes a restart
793 }
800 }
794
801
795 .. Note::
802 .. Note::
796
803
797 When the clients detect a dead kernel thanks to inactivity on the heartbeat
804 When the clients detect a dead kernel thanks to inactivity on the heartbeat
798 socket, they simply send a forceful process termination signal, since a dead
805 socket, they simply send a forceful process termination signal, since a dead
799 process is unlikely to respond in any useful way to messages.
806 process is unlikely to respond in any useful way to messages.
800
807
801
808
802 Messages on the PUB/SUB socket
809 Messages on the PUB/SUB socket
803 ==============================
810 ==============================
804
811
805 Streams (stdout, stderr, etc)
812 Streams (stdout, stderr, etc)
806 ------------------------------
813 ------------------------------
807
814
808 Message type: ``stream``::
815 Message type: ``stream``::
809
816
810 content = {
817 content = {
811 # The name of the stream is one of 'stdout', 'stderr'
818 # The name of the stream is one of 'stdout', 'stderr'
812 'name' : str,
819 'name' : str,
813
820
814 # The data is an arbitrary string to be written to that stream
821 # The data is an arbitrary string to be written to that stream
815 'data' : str,
822 'data' : str,
816 }
823 }
817
824
818 Display Data
825 Display Data
819 ------------
826 ------------
820
827
821 This type of message is used to bring back data that should be displayed (text,
828 This type of message is used to bring back data that should be displayed (text,
822 html, svg, etc.) in the frontends. This data is published to all frontends.
829 html, svg, etc.) in the frontends. This data is published to all frontends.
823 Each message can have multiple representations of the data; it is up to the
830 Each message can have multiple representations of the data; it is up to the
824 frontend to decide which to use and how. A single message should contain all
831 frontend to decide which to use and how. A single message should contain all
825 possible representations of the same information. Each representation should
832 possible representations of the same information. Each representation should
826 be a JSON'able data structure, and should be a valid MIME type.
833 be a JSON'able data structure, and should be a valid MIME type.
827
834
828 Some questions remain about this design:
835 Some questions remain about this design:
829
836
830 * Do we use this message type for pyout/displayhook? Probably not, because
837 * Do we use this message type for pyout/displayhook? Probably not, because
831 the displayhook also has to handle the Out prompt display. On the other hand
838 the displayhook also has to handle the Out prompt display. On the other hand
832 we could put that information into the metadata section.
839 we could put that information into the metadata section.
833
840
834 Message type: ``display_data``::
841 Message type: ``display_data``::
835
842
836 content = {
843 content = {
837
844
838 # Who create the data
845 # Who create the data
839 'source' : str,
846 'source' : str,
840
847
841 # The data dict contains key/value pairs, where the keys are MIME
848 # The data dict contains key/value pairs, where the keys are MIME
842 # types and the values are the raw data of the representation in that
849 # types and the values are the raw data of the representation in that
843 # format.
850 # format.
844 'data' : dict,
851 'data' : dict,
845
852
846 # Any metadata that describes the data
853 # Any metadata that describes the data
847 'metadata' : dict
854 'metadata' : dict
848 }
855 }
849
856
850
857
851 The ``metadata`` contains any metadata that describes the output.
858 The ``metadata`` contains any metadata that describes the output.
852 Global keys are assumed to apply to the output as a whole.
859 Global keys are assumed to apply to the output as a whole.
853 The ``metadata`` dict can also contain mime-type keys, which will be sub-dictionaries,
860 The ``metadata`` dict can also contain mime-type keys, which will be sub-dictionaries,
854 which are interpreted as applying only to output of that type.
861 which are interpreted as applying only to output of that type.
855 Third parties should put any data they write into a single dict
862 Third parties should put any data they write into a single dict
856 with a reasonably unique name to avoid conflicts.
863 with a reasonably unique name to avoid conflicts.
857
864
858 The only metadata keys currently defined in IPython are the width and height
865 The only metadata keys currently defined in IPython are the width and height
859 of images::
866 of images::
860
867
861 'metadata' : {
868 'metadata' : {
862 'image/png' : {
869 'image/png' : {
863 'width': 640,
870 'width': 640,
864 'height': 480
871 'height': 480
865 }
872 }
866 }
873 }
867
874
868
875
869 Raw Data Publication
876 Raw Data Publication
870 --------------------
877 --------------------
871
878
872 ``display_data`` lets you publish *representations* of data, such as images and html.
879 ``display_data`` lets you publish *representations* of data, such as images and html.
873 This ``data_pub`` message lets you publish *actual raw data*, sent via message buffers.
880 This ``data_pub`` message lets you publish *actual raw data*, sent via message buffers.
874
881
875 data_pub messages are constructed via the :func:`IPython.lib.datapub.publish_data` function:
882 data_pub messages are constructed via the :func:`IPython.lib.datapub.publish_data` function:
876
883
877 .. sourcecode:: python
884 .. sourcecode:: python
878
885
879 from IPython.kernel.zmq.datapub import publish_data
886 from IPython.kernel.zmq.datapub import publish_data
880 ns = dict(x=my_array)
887 ns = dict(x=my_array)
881 publish_data(ns)
888 publish_data(ns)
882
889
883
890
884 Message type: ``data_pub``::
891 Message type: ``data_pub``::
885
892
886 content = {
893 content = {
887 # the keys of the data dict, after it has been unserialized
894 # the keys of the data dict, after it has been unserialized
888 keys = ['a', 'b']
895 keys = ['a', 'b']
889 }
896 }
890 # the namespace dict will be serialized in the message buffers,
897 # the namespace dict will be serialized in the message buffers,
891 # which will have a length of at least one
898 # which will have a length of at least one
892 buffers = ['pdict', ...]
899 buffers = ['pdict', ...]
893
900
894
901
895 The interpretation of a sequence of data_pub messages for a given parent request should be
902 The interpretation of a sequence of data_pub messages for a given parent request should be
896 to update a single namespace with subsequent results.
903 to update a single namespace with subsequent results.
897
904
898 .. note::
905 .. note::
899
906
900 No frontends directly handle data_pub messages at this time.
907 No frontends directly handle data_pub messages at this time.
901 It is currently only used by the client/engines in :mod:`IPython.parallel`,
908 It is currently only used by the client/engines in :mod:`IPython.parallel`,
902 where engines may publish *data* to the Client,
909 where engines may publish *data* to the Client,
903 of which the Client can then publish *representations* via ``display_data``
910 of which the Client can then publish *representations* via ``display_data``
904 to various frontends.
911 to various frontends.
905
912
906 Python inputs
913 Python inputs
907 -------------
914 -------------
908
915
909 These messages are the re-broadcast of the ``execute_request``.
916 These messages are the re-broadcast of the ``execute_request``.
910
917
911 Message type: ``pyin``::
918 Message type: ``pyin``::
912
919
913 content = {
920 content = {
914 'code' : str, # Source code to be executed, one or more lines
921 'code' : str, # Source code to be executed, one or more lines
915
922
916 # The counter for this execution is also provided so that clients can
923 # The counter for this execution is also provided so that clients can
917 # display it, since IPython automatically creates variables called _iN
924 # display it, since IPython automatically creates variables called _iN
918 # (for input prompt In[N]).
925 # (for input prompt In[N]).
919 'execution_count' : int
926 'execution_count' : int
920 }
927 }
921
928
922 Python outputs
929 Python outputs
923 --------------
930 --------------
924
931
925 When Python produces output from code that has been compiled in with the
932 When Python produces output from code that has been compiled in with the
926 'single' flag to :func:`compile`, any expression that produces a value (such as
933 'single' flag to :func:`compile`, any expression that produces a value (such as
927 ``1+1``) is passed to ``sys.displayhook``, which is a callable that can do with
934 ``1+1``) is passed to ``sys.displayhook``, which is a callable that can do with
928 this value whatever it wants. The default behavior of ``sys.displayhook`` in
935 this value whatever it wants. The default behavior of ``sys.displayhook`` in
929 the Python interactive prompt is to print to ``sys.stdout`` the :func:`repr` of
936 the Python interactive prompt is to print to ``sys.stdout`` the :func:`repr` of
930 the value as long as it is not ``None`` (which isn't printed at all). In our
937 the value as long as it is not ``None`` (which isn't printed at all). In our
931 case, the kernel instantiates as ``sys.displayhook`` an object which has
938 case, the kernel instantiates as ``sys.displayhook`` an object which has
932 similar behavior, but which instead of printing to stdout, broadcasts these
939 similar behavior, but which instead of printing to stdout, broadcasts these
933 values as ``pyout`` messages for clients to display appropriately.
940 values as ``pyout`` messages for clients to display appropriately.
934
941
935 IPython's displayhook can handle multiple simultaneous formats depending on its
942 IPython's displayhook can handle multiple simultaneous formats depending on its
936 configuration. The default pretty-printed repr text is always given with the
943 configuration. The default pretty-printed repr text is always given with the
937 ``data`` entry in this message. Any other formats are provided in the
944 ``data`` entry in this message. Any other formats are provided in the
938 ``extra_formats`` list. Frontends are free to display any or all of these
945 ``extra_formats`` list. Frontends are free to display any or all of these
939 according to its capabilities. ``extra_formats`` list contains 3-tuples of an ID
946 according to its capabilities. ``extra_formats`` list contains 3-tuples of an ID
940 string, a type string, and the data. The ID is unique to the formatter
947 string, a type string, and the data. The ID is unique to the formatter
941 implementation that created the data. Frontends will typically ignore the ID
948 implementation that created the data. Frontends will typically ignore the ID
942 unless if it has requested a particular formatter. The type string tells the
949 unless if it has requested a particular formatter. The type string tells the
943 frontend how to interpret the data. It is often, but not always a MIME type.
950 frontend how to interpret the data. It is often, but not always a MIME type.
944 Frontends should ignore types that it does not understand. The data itself is
951 Frontends should ignore types that it does not understand. The data itself is
945 any JSON object and depends on the format. It is often, but not always a string.
952 any JSON object and depends on the format. It is often, but not always a string.
946
953
947 Message type: ``pyout``::
954 Message type: ``pyout``::
948
955
949 content = {
956 content = {
950
957
951 # The counter for this execution is also provided so that clients can
958 # The counter for this execution is also provided so that clients can
952 # display it, since IPython automatically creates variables called _N
959 # display it, since IPython automatically creates variables called _N
953 # (for prompt N).
960 # (for prompt N).
954 'execution_count' : int,
961 'execution_count' : int,
955
962
956 # data and metadata are identical to a display_data message.
963 # data and metadata are identical to a display_data message.
957 # the object being displayed is that passed to the display hook,
964 # the object being displayed is that passed to the display hook,
958 # i.e. the *result* of the execution.
965 # i.e. the *result* of the execution.
959 'data' : dict,
966 'data' : dict,
960 'metadata' : dict,
967 'metadata' : dict,
961 }
968 }
962
969
963 Python errors
970 Python errors
964 -------------
971 -------------
965
972
966 When an error occurs during code execution
973 When an error occurs during code execution
967
974
968 Message type: ``pyerr``::
975 Message type: ``pyerr``::
969
976
970 content = {
977 content = {
971 # Similar content to the execute_reply messages for the 'error' case,
978 # Similar content to the execute_reply messages for the 'error' case,
972 # except the 'status' field is omitted.
979 # except the 'status' field is omitted.
973 }
980 }
974
981
975 Kernel status
982 Kernel status
976 -------------
983 -------------
977
984
978 This message type is used by frontends to monitor the status of the kernel.
985 This message type is used by frontends to monitor the status of the kernel.
979
986
980 Message type: ``status``::
987 Message type: ``status``::
981
988
982 content = {
989 content = {
983 # When the kernel starts to execute code, it will enter the 'busy'
990 # When the kernel starts to execute code, it will enter the 'busy'
984 # state and when it finishes, it will enter the 'idle' state.
991 # state and when it finishes, it will enter the 'idle' state.
985 # The kernel will publish state 'starting' exactly once at process startup.
992 # The kernel will publish state 'starting' exactly once at process startup.
986 execution_state : ('busy', 'idle', 'starting')
993 execution_state : ('busy', 'idle', 'starting')
987 }
994 }
988
995
989 Clear output
996 Clear output
990 ------------
997 ------------
991
998
992 This message type is used to clear the output that is visible on the frontend.
999 This message type is used to clear the output that is visible on the frontend.
993
1000
994 Message type: ``clear_output``::
1001 Message type: ``clear_output``::
995
1002
996 content = {
1003 content = {
997
1004
998 # Wait to clear the output until new output is available. Clears the
1005 # Wait to clear the output until new output is available. Clears the
999 # existing output immediately before the new output is displayed.
1006 # existing output immediately before the new output is displayed.
1000 # Useful for creating simple animations with minimal flickering.
1007 # Useful for creating simple animations with minimal flickering.
1001 'wait' : bool,
1008 'wait' : bool,
1002 }
1009 }
1003
1010
1011 .. versionchanged:: 4.1
1012
1013 'stdout', 'stderr', and 'display' boolean keys for selective clearing are removed,
1014 and 'wait' is added.
1015 The selective clearing keys are ignored in v4 and the default behavior remains the same,
1016 so v4 clear_output messages will be safely handled by a v4.1 frontend.
1017
1018
1004 Messages on the stdin ROUTER/DEALER sockets
1019 Messages on the stdin ROUTER/DEALER sockets
1005 ===========================================
1020 ===========================================
1006
1021
1007 This is a socket where the request/reply pattern goes in the opposite direction:
1022 This is a socket where the request/reply pattern goes in the opposite direction:
1008 from the kernel to a *single* frontend, and its purpose is to allow
1023 from the kernel to a *single* frontend, and its purpose is to allow
1009 ``raw_input`` and similar operations that read from ``sys.stdin`` on the kernel
1024 ``raw_input`` and similar operations that read from ``sys.stdin`` on the kernel
1010 to be fulfilled by the client. The request should be made to the frontend that
1025 to be fulfilled by the client. The request should be made to the frontend that
1011 made the execution request that prompted ``raw_input`` to be called. For now we
1026 made the execution request that prompted ``raw_input`` to be called. For now we
1012 will keep these messages as simple as possible, since they only mean to convey
1027 will keep these messages as simple as possible, since they only mean to convey
1013 the ``raw_input(prompt)`` call.
1028 the ``raw_input(prompt)`` call.
1014
1029
1015 Message type: ``input_request``::
1030 Message type: ``input_request``::
1016
1031
1017 content = { 'prompt' : str }
1032 content = { 'prompt' : str }
1018
1033
1019 Message type: ``input_reply``::
1034 Message type: ``input_reply``::
1020
1035
1021 content = { 'value' : str }
1036 content = { 'value' : str }
1022
1037
1023 .. note::
1038 .. note::
1024
1039
1025 The stdin socket of the client is required to have the same zmq IDENTITY
1040 The stdin socket of the client is required to have the same zmq IDENTITY
1026 as the client's shell socket.
1041 as the client's shell socket.
1027 Because of this, the ``input_request`` must be sent with the same IDENTITY
1042 Because of this, the ``input_request`` must be sent with the same IDENTITY
1028 routing prefix as the ``execute_reply`` in order for the frontend to receive
1043 routing prefix as the ``execute_reply`` in order for the frontend to receive
1029 the message.
1044 the message.
1030
1045
1031 .. note::
1046 .. note::
1032
1047
1033 We do not explicitly try to forward the raw ``sys.stdin`` object, because in
1048 We do not explicitly try to forward the raw ``sys.stdin`` object, because in
1034 practice the kernel should behave like an interactive program. When a
1049 practice the kernel should behave like an interactive program. When a
1035 program is opened on the console, the keyboard effectively takes over the
1050 program is opened on the console, the keyboard effectively takes over the
1036 ``stdin`` file descriptor, and it can't be used for raw reading anymore.
1051 ``stdin`` file descriptor, and it can't be used for raw reading anymore.
1037 Since the IPython kernel effectively behaves like a console program (albeit
1052 Since the IPython kernel effectively behaves like a console program (albeit
1038 one whose "keyboard" is actually living in a separate process and
1053 one whose "keyboard" is actually living in a separate process and
1039 transported over the zmq connection), raw ``stdin`` isn't expected to be
1054 transported over the zmq connection), raw ``stdin`` isn't expected to be
1040 available.
1055 available.
1041
1056
1042
1057
1043 Heartbeat for kernels
1058 Heartbeat for kernels
1044 =====================
1059 =====================
1045
1060
1046 Initially we had considered using messages like those above over ZMQ for a
1061 Initially we had considered using messages like those above over ZMQ for a
1047 kernel 'heartbeat' (a way to detect quickly and reliably whether a kernel is
1062 kernel 'heartbeat' (a way to detect quickly and reliably whether a kernel is
1048 alive at all, even if it may be busy executing user code). But this has the
1063 alive at all, even if it may be busy executing user code). But this has the
1049 problem that if the kernel is locked inside extension code, it wouldn't execute
1064 problem that if the kernel is locked inside extension code, it wouldn't execute
1050 the python heartbeat code. But it turns out that we can implement a basic
1065 the python heartbeat code. But it turns out that we can implement a basic
1051 heartbeat with pure ZMQ, without using any Python messaging at all.
1066 heartbeat with pure ZMQ, without using any Python messaging at all.
1052
1067
1053 The monitor sends out a single zmq message (right now, it is a str of the
1068 The monitor sends out a single zmq message (right now, it is a str of the
1054 monitor's lifetime in seconds), and gets the same message right back, prefixed
1069 monitor's lifetime in seconds), and gets the same message right back, prefixed
1055 with the zmq identity of the DEALER socket in the heartbeat process. This can be
1070 with the zmq identity of the DEALER socket in the heartbeat process. This can be
1056 a uuid, or even a full message, but there doesn't seem to be a need for packing
1071 a uuid, or even a full message, but there doesn't seem to be a need for packing
1057 up a message when the sender and receiver are the exact same Python object.
1072 up a message when the sender and receiver are the exact same Python object.
1058
1073
1059 The model is this::
1074 The model is this::
1060
1075
1061 monitor.send(str(self.lifetime)) # '1.2345678910'
1076 monitor.send(str(self.lifetime)) # '1.2345678910'
1062
1077
1063 and the monitor receives some number of messages of the form::
1078 and the monitor receives some number of messages of the form::
1064
1079
1065 ['uuid-abcd-dead-beef', '1.2345678910']
1080 ['uuid-abcd-dead-beef', '1.2345678910']
1066
1081
1067 where the first part is the zmq.IDENTITY of the heart's DEALER on the engine, and
1082 where the first part is the zmq.IDENTITY of the heart's DEALER on the engine, and
1068 the rest is the message sent by the monitor. No Python code ever has any
1083 the rest is the message sent by the monitor. No Python code ever has any
1069 access to the message between the monitor's send, and the monitor's recv.
1084 access to the message between the monitor's send, and the monitor's recv.
1070
1085
1071 Custom Messages
1086 Custom Messages
1072 ===============
1087 ===============
1073
1088
1074 IPython 2.0 adds a messaging system for developers to add their own objects with Frontend
1089 .. versionadded:: 4.1
1090
1091 IPython 2.0 (msgspec v4.1) adds a messaging system for developers to add their own objects with Frontend
1075 and Kernel-side components, and allow them to communicate with each other.
1092 and Kernel-side components, and allow them to communicate with each other.
1076 To do this, IPython adds a notion of a ``Comm``, which exists on both sides,
1093 To do this, IPython adds a notion of a ``Comm``, which exists on both sides,
1077 and can communicate in either direction.
1094 and can communicate in either direction.
1078
1095
1079 These messages are fully symmetrical - both the Kernel and the Frontend can send each message,
1096 These messages are fully symmetrical - both the Kernel and the Frontend can send each message,
1080 and no messages expect a reply.
1097 and no messages expect a reply.
1081 The Kernel listens for these messages on the Shell channel,
1098 The Kernel listens for these messages on the Shell channel,
1082 and the Frontend listens for them on the IOPub channel.
1099 and the Frontend listens for them on the IOPub channel.
1083
1100
1084 .. versionadded:: 2.0
1085
1086 Opening a Comm
1101 Opening a Comm
1087 --------------
1102 --------------
1088
1103
1089 Opening a Comm produces a ``comm_open`` message, to be sent to the other side::
1104 Opening a Comm produces a ``comm_open`` message, to be sent to the other side::
1090
1105
1091 {
1106 {
1092 'comm_id' : 'u-u-i-d',
1107 'comm_id' : 'u-u-i-d',
1093 'target_name' : 'my_comm',
1108 'target_name' : 'my_comm',
1094 'data' : {}
1109 'data' : {}
1095 }
1110 }
1096
1111
1097 Every Comm has an ID and a target name.
1112 Every Comm has an ID and a target name.
1098 The code handling the message on the receiving side is responsible for maintaining a mapping
1113 The code handling the message on the receiving side is responsible for maintaining a mapping
1099 of target_name keys to constructors.
1114 of target_name keys to constructors.
1100 After a ``comm_open`` message has been sent,
1115 After a ``comm_open`` message has been sent,
1101 there should be a corresponding Comm instance on both sides.
1116 there should be a corresponding Comm instance on both sides.
1102 The ``data`` key is always a dict and can be any extra JSON information used in initialization of the comm.
1117 The ``data`` key is always a dict and can be any extra JSON information used in initialization of the comm.
1103
1118
1104 If the ``target_name`` key is not found on the receiving side,
1119 If the ``target_name`` key is not found on the receiving side,
1105 then it should immediately reply with a ``comm_close`` message to avoid an inconsistent state.
1120 then it should immediately reply with a ``comm_close`` message to avoid an inconsistent state.
1106
1121
1107 Comm Messages
1122 Comm Messages
1108 -------------
1123 -------------
1109
1124
1110 Comm messages are one-way communications to update comm state,
1125 Comm messages are one-way communications to update comm state,
1111 used for synchronizing widget state, or simply requesting actions of a comm's counterpart.
1126 used for synchronizing widget state, or simply requesting actions of a comm's counterpart.
1112
1127
1113 Essentially, each comm pair defines their own message specification implemented inside the ``data`` dict.
1128 Essentially, each comm pair defines their own message specification implemented inside the ``data`` dict.
1114
1129
1115 There are no expected replies (of course, one side can send another ``comm_msg`` in reply).
1130 There are no expected replies (of course, one side can send another ``comm_msg`` in reply).
1116
1131
1117 Message type: ``comm_msg``::
1132 Message type: ``comm_msg``::
1118
1133
1119 {
1134 {
1120 'comm_id' : 'u-u-i-d',
1135 'comm_id' : 'u-u-i-d',
1121 'data' : {}
1136 'data' : {}
1122 }
1137 }
1123
1138
1124 Tearing Down Comms
1139 Tearing Down Comms
1125 ------------------
1140 ------------------
1126
1141
1127 Since comms live on both sides, when a comm is destroyed the other side must be notified.
1142 Since comms live on both sides, when a comm is destroyed the other side must be notified.
1128 This is done with a ``comm_close`` message.
1143 This is done with a ``comm_close`` message.
1129
1144
1130 Message type: ``comm_close``::
1145 Message type: ``comm_close``::
1131
1146
1132 {
1147 {
1133 'comm_id' : 'u-u-i-d',
1148 'comm_id' : 'u-u-i-d',
1134 'data' : {}
1149 'data' : {}
1135 }
1150 }
1136
1151
1137 Output Side Effects
1152 Output Side Effects
1138 -------------------
1153 -------------------
1139
1154
1140 Since comm messages can execute arbitrary user code,
1155 Since comm messages can execute arbitrary user code,
1141 handlers should set the parent header and publish status busy / idle,
1156 handlers should set the parent header and publish status busy / idle,
1142 just like an execute request.
1157 just like an execute request.
1143
1158
1144
1159
1145 ToDo
1160 ToDo
1146 ====
1161 ====
1147
1162
1148 Missing things include:
1163 Missing things include:
1149
1164
1150 * Important: finish thinking through the payload concept and API.
1165 * Important: finish thinking through the payload concept and API.
1151
1166
1152 * Important: ensure that we have a good solution for magics like %edit. It's
1167 * Important: ensure that we have a good solution for magics like %edit. It's
1153 likely that with the payload concept we can build a full solution, but not
1168 likely that with the payload concept we can build a full solution, but not
1154 100% clear yet.
1169 100% clear yet.
1155
1170
1156 .. include:: ../links.txt
1171 .. include:: ../links.txt
General Comments 0
You need to be logged in to leave comments. Login now