##// END OF EJS Templates
Finishing the DirectView widget and adding an example notebook.
Brian Granger -
Show More
@@ -0,0 +1,255 b''
1 {
2 "metadata": {
3 "name": "direct_view_widget"
4 },
5 "nbformat": 3,
6 "worksheets": [
7 {
8 "cells": [
9 {
10 "cell_type": "heading",
11 "level": 1,
12 "source": [
13 "Direct View Widget"
14 ]
15 },
16 {
17 "cell_type": "markdown",
18 "source": [
19 "IPython has a JavaScript widget for interacting with an IPython parallel engine interactively in the Notebook. This Notebook shows how this widget can be used."
20 ]
21 },
22 {
23 "cell_type": "code",
24 "input": [
25 "from IPython.frontend.html.notebook.widgets import directview",
26 "from IPython.parallel import Client"
27 ],
28 "language": "python",
29 "outputs": [],
30 "prompt_number": 4
31 },
32 {
33 "cell_type": "markdown",
34 "source": [
35 "Let's create a `Client` and build a `DirectView` containing all of the engines:"
36 ]
37 },
38 {
39 "cell_type": "code",
40 "input": [
41 "c = Client()",
42 "dv = c[:]"
43 ],
44 "language": "python",
45 "outputs": [],
46 "prompt_number": 5
47 },
48 {
49 "cell_type": "markdown",
50 "source": [
51 "To interact with the engines we simply pass the `DirectView` instance to the `interact` function. The resulting widget has an embedded notebook cell, but any code entered into the embedded cell is run on the engines you choose. The engines are now full blown IPython kernels so you can enter arbitrary Python/IPython code and even make plots on the engines."
52 ]
53 },
54 {
55 "cell_type": "code",
56 "input": [
57 "directview.interact(dv)"
58 ],
59 "language": "python",
60 "outputs": [
61 {
62 "javascript": [
63 "//----------------------------------------------------------------------------",
64 "// Copyright (C) 2008-2012 The IPython Development Team",
65 "//",
66 "// Distributed under the terms of the BSD License. The full license is in",
67 "// the file COPYING, distributed as part of this software.",
68 "//----------------------------------------------------------------------------",
69 "",
70 "//============================================================================",
71 "// EngineInteract",
72 "//============================================================================",
73 "",
74 "var key = IPython.utils.keycodes;",
75 "",
76 "",
77 "var DirectViewWidget = function (selector, kernel, targets) {",
78 " // The kernel doesn't have to be set at creation time, in that case",
79 " // it will be null and set_kernel has to be called later.",
80 " this.selector = selector;",
81 " this.element = $(selector);",
82 " this.kernel = kernel || null;",
83 " this.code_mirror = null;",
84 " this.targets = targets;",
85 " this.create_element();",
86 "};",
87 "",
88 "",
89 "DirectViewWidget.prototype.create_element = function () {",
90 " this.element.addClass('cell border-box-sizing code_cell vbox');",
91 " this.element.attr('tabindex','2');",
92 " this.element.css('padding-right',0);",
93 "",
94 " var control = $('<div/>').addClass('dv_control').height('30px');",
95 " var control_label = $('<span/>').html('Select engine(s) to run code on interactively: ');",
96 " control_label.css('line-height','30px');",
97 " var select = $('<select/>').addClass('dv_select ui-widget ui-widget-content');",
98 " select.css('font-size','85%').css('margin-bottom','5px');",
99 " var n = this.targets.length;",
100 " select.append($('<option/>').html('all').attr('value','all'));",
101 " for (var i=0; i<n; i++) {",
102 " select.append($('<option/>').html(this.targets[i]).attr('value',this.targets[i]))",
103 " }",
104 " control.append(control_label).append(select);",
105 "",
106 " var input = $('<div></div>').addClass('input hbox');",
107 " var input_area = $('<div/>').addClass('input_area box-flex1');",
108 " this.code_mirror = CodeMirror(input_area.get(0), {",
109 " indentUnit : 4,",
110 " mode: 'python',",
111 " theme: 'ipython',",
112 " onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)",
113 " });",
114 " input.append(input_area);",
115 " var output = $('<div></div>');",
116 "",
117 "",
118 " this.element.append(control).append(input).append(output);",
119 "\tthis.output_area = new IPython.OutputArea(output, false);",
120 "",
121 "};",
122 "",
123 "",
124 "DirectViewWidget.prototype.handle_codemirror_keyevent = function (editor, event) {",
125 " // This method gets called in CodeMirror's onKeyDown/onKeyPress",
126 " // handlers and is used to provide custom key handling. Its return",
127 " // value is used to determine if CodeMirror should ignore the event:",
128 " // true = ignore, false = don't ignore.",
129 " ",
130 " var that = this;",
131 " var cur = editor.getCursor();",
132 "",
133 " if (event.keyCode === key.ENTER && event.shiftKey && event.type === 'keydown') {",
134 " // Always ignore shift-enter in CodeMirror as we handle it.",
135 " event.stop();",
136 " that.execute();",
137 " return true;",
138 " } else if (event.keyCode === key.UP && event.type === 'keydown') {",
139 " event.stop();",
140 " return false;",
141 " } else if (event.keyCode === key.DOWN && event.type === 'keydown') {",
142 " event.stop();",
143 " return false;",
144 " } else if (event.keyCode === key.BACKSPACE && event.type == 'keydown') {",
145 " // If backspace and the line ends with 4 spaces, remove them.",
146 " var line = editor.getLine(cur.line);",
147 " var ending = line.slice(-4);",
148 " if (ending === ' ') {",
149 " editor.replaceRange('',",
150 " {line: cur.line, ch: cur.ch-4},",
151 " {line: cur.line, ch: cur.ch}",
152 " );",
153 " event.stop();",
154 " return true;",
155 " } else {",
156 " return false;",
157 " };",
158 " };",
159 "",
160 " return false;",
161 "};",
162 "",
163 "",
164 "// Kernel related calls.",
165 "",
166 "",
167 "DirectViewWidget.prototype.set_kernel = function (kernel) {",
168 " this.kernel = kernel;",
169 "}",
170 "",
171 "",
172 "DirectViewWidget.prototype.execute = function () {",
173 " this.output_area.clear_output(true, true, true);",
174 " this.element.addClass(\"running\");",
175 " var callbacks = {",
176 " 'execute_reply': $.proxy(this._handle_execute_reply, this),",
177 " 'output': $.proxy(this.output_area.handle_output, this.output_area),",
178 " 'clear_output': $.proxy(this.output_area.handle_clear_output, this.output_area),",
179 " };",
180 " var target = this.element.find('.dv_select option:selected').attr('value');",
181 " if (target === 'all') {",
182 " target = '\"all\"';",
183 " }",
184 " var code = '__widget_b32c0bd12a804f69b0e6445ef57c08d9.execute(\"\"\"'+this.get_text()+'\"\"\",targets='+target+')';",
185 " var msg_id = this.kernel.execute(code, callbacks, {silent: false});",
186 " this.clear_input();",
187 " this.code_mirror.focus();",
188 "};",
189 "",
190 "",
191 "DirectViewWidget.prototype._handle_execute_reply = function (content) {",
192 " this.element.removeClass(\"running\");",
193 " // this.dirty = true;",
194 "}",
195 "",
196 "// Basic cell manipulation.",
197 "",
198 "",
199 "DirectViewWidget.prototype.select_all = function () {",
200 " var start = {line: 0, ch: 0};",
201 " var nlines = this.code_mirror.lineCount();",
202 " var last_line = this.code_mirror.getLine(nlines-1);",
203 " var end = {line: nlines-1, ch: last_line.length};",
204 " this.code_mirror.setSelection(start, end);",
205 "};",
206 "",
207 "",
208 "DirectViewWidget.prototype.clear_input = function () {",
209 " this.code_mirror.setValue('');",
210 "};",
211 "",
212 "",
213 "DirectViewWidget.prototype.get_text = function () {",
214 " return this.code_mirror.getValue();",
215 "};",
216 "",
217 "",
218 "DirectViewWidget.prototype.set_text = function (code) {",
219 " return this.code_mirror.setValue(code);",
220 "};",
221 "",
222 "container.show();",
223 "var widget = $('<div/>')",
224 "// When templating over a JSON string, we must use single quotes.",
225 "var targets = '[0,1,2,3]';",
226 "targets = $.parseJSON(targets);",
227 "var eiw = new DirectViewWidget(widget, IPython.notebook.kernel, targets);",
228 "element.append(widget);",
229 "element.css('padding',0);",
230 "setTimeout(function () {",
231 " eiw.code_mirror.refresh();",
232 " eiw.code_mirror.focus();",
233 "}, 1);",
234 "",
235 ""
236 ],
237 "output_type": "display_data",
238 "text": [
239 "<IPython.core.display.Javascript at 0x107d35fd0>"
240 ]
241 },
242 {
243 "output_type": "pyout",
244 "prompt_number": 6,
245 "text": [
246 "<IPython.frontend.html.notebook.widgets.directview.DirectViewWidget at 0x107eb9890>"
247 ]
248 }
249 ],
250 "prompt_number": 6
251 }
252 ]
253 }
254 ]
255 } No newline at end of file
@@ -120,8 +120,6 b' DirectViewWidget.prototype.execute = function () {'
120 target = '"all"';
120 target = '"all"';
121 }
121 }
122 var code = '%(widget_var)s.execute("""'+this.get_text()+'""",targets='+target+')';
122 var code = '%(widget_var)s.execute("""'+this.get_text()+'""",targets='+target+')';
123 console.log(code);
124 console.log(this.get_text());
125 var msg_id = this.kernel.execute(code, callbacks, {silent: false});
123 var msg_id = this.kernel.execute(code, callbacks, {silent: false});
126 this.clear_input();
124 this.clear_input();
127 this.code_mirror.focus();
125 this.code_mirror.focus();
@@ -53,22 +53,9 b' class DirectViewWidget(JavascriptWidget):'
53 def execute(self, code, targets='all'):
53 def execute(self, code, targets='all'):
54 if targets == 'all':
54 if targets == 'all':
55 targets = self.targets
55 targets = self.targets
56 ar = self.dv.execute(code,block=False,targets=targets)
56 result = self.dv.execute(code,silent=False,block=False,targets=targets)
57 ar.wait()
57 result.wait()
58 metadata = ar.metadata
58 result.display_outputs()
59 if isinstance(metadata, (list,tuple)):
60 for md in metadata:
61 self.publish_md(md)
62 elif isinstance(metadata, dict):
63 self.publish_md(metadata)
64
65 def publish_md(self, md):
66 if md['stdout']:
67 publish_pretty(md['stdout'],{'engine_id':md['engine_id']})
68 if md['stderr']:
69 publish_pretty(md['stderr'],{'engine_id':md['engine_id']})
70 if md['pyerr']:
71 publish_pretty(md['pyerr'],{'engine_id':md['engine_id']})
72
59
73
60
74 def interact(dv):
61 def interact(dv):
General Comments 0
You need to be logged in to leave comments. Login now