##// END OF EJS Templates
proper '.py' and '.ipynb' download files
Zachary Sailer -
Show More
@@ -1,199 +1,204 b''
1 1 """Tornado handlers for the notebooks web service.
2 2
3 3 Authors:
4 4
5 5 * Brian Granger
6 6 """
7 7
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2008-2011 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18
19 19 from tornado import web
20 20 import ast
21 21
22 22 from zmq.utils import jsonapi
23 23
24 24 from IPython.utils.jsonutil import date_default
25 25
26 26 from ...base.handlers import IPythonHandler
27 27
28 28 #-----------------------------------------------------------------------------
29 29 # Notebook web service handlers
30 30 #-----------------------------------------------------------------------------
31 31
32 32
33 33 class NotebookRootHandler(IPythonHandler):
34 34
35 35 @web.authenticated
36 36 def get(self):
37 37 nbm = self.notebook_manager
38 38 km = self.kernel_manager
39 39 notebooks = nbm.list_notebooks("")
40 40 self.finish(jsonapi.dumps(notebooks))
41 41
42 42 @web.authenticated
43 43 def post(self):
44 44 nbm = self.notebook_manager
45 45 notebook_name = nbm.new_notebook()
46 46 model = nbm.notebook_model(notebook_name)
47 47 self.set_header('Location', '{0}api/notebooks/{1}'.format(self.base_project_url, notebook_name))
48 48 self.finish(jsonapi.dumps(model))
49 49
50 50
51 51 class NotebookRootRedirect(IPythonHandler):
52 52
53 53 @authenticate_unless_readonly
54 54 def get(self):
55 55 self.redirect("/api/notebooks")
56 56
57 57
58 58 class NotebookHandler(IPythonHandler):
59 59
60 60 SUPPORTED_METHODS = ('GET', 'PUT', 'PATCH', 'DELETE')
61 61
62 62 @web.authenticated
63 63 def get(self, notebook_path):
64 64 nbm = self.notebook_manager
65 65 name, path = nbm.named_notebook_path(notebook_path)
66 66
67 67 if name == None:
68 68 notebooks = nbm.list_notebooks(path)
69 69 self.finish(jsonapi.dumps(notebooks))
70 70 else:
71 71 format = self.get_argument('format', default='json')
72 download = self.get_argument('download', default='False')
72 73 model = nbm.notebook_model(name,path)
73 74 last_mod, representation, name = nbm.get_notebook(name, path, format)
74
75 if format == u'json':
76 self.set_header('Content-Type', 'application/json')
77 self.set_header('Content-Disposition','attachment; filename="%s.ipynb"' % name)
78 elif format == u'py':
79 self.set_header('Content-Type', 'application/x-python')
80 self.set_header('Content-Disposition','attachment; filename="%s.py"' % name)
81 #self.set_header('Last-Modified', last_mod)
82 self.finish(jsonapi.dumps(model))
75 self.set_header('Last-Modified', last_mod)
76
77 if download == 'True':
78 if format == u'json':
79 self.set_header('Content-Type', 'application/json')
80 self.set_header('Content-Disposition','attachment; filename="%s.ipynb"' % name)
81 self.finish(representation)
82 elif format == u'py':
83 self.set_header('Content-Type', 'application/x-python')
84 self.set_header('Content-Disposition','attachment; filename="%s.py"' % name)
85 self.finish(representation)
86 else:
87 self.finish(jsonapi.dumps(model))
83 88
84 89 @web.authenticated
85 90 def patch(self, notebook_path):
86 91 nbm = self.notebook_manager
87 92 notebook_name, notebook_path = nbm.named_notebook_path(notebook_path)
88 93 data = jsonapi.loads(self.request.body)
89 94 model = nbm.change_notebook(data, notebook_name, notebook_path)
90 95 self.finish(jsonapi.dumps(model))
91 96
92 97 @web.authenticated
93 98 def put(self, notebook_path):
94 99 nbm = self.notebook_manager
95 100 notebook_name, notebook_path = nbm.named_notebook_path(notebook_path)
96 101 if notebook_name == None:
97 102 body = self.request.body.strip()
98 103 format = self.get_argument('format', default='json')
99 104 name = self.get_argument('name', default=None)
100 105 if body:
101 106 notebook_name = nbm.save_new_notebook(body, notebook_path=notebook_path, name=name, format=format)
102 107 else:
103 108 notebook_name = nbm.new_notebook(notebook_path=notebook_path)
104 109 if notebook_path==None:
105 110 self.set_header('Location', nbm.notebook_dir + '/'+ notebook_name)
106 111 else:
107 112 self.set_header('Location', nbm.notebook_dir + '/'+ notebook_path + '/' + notebook_name)
108 113 model = nbm.notebook_model(notebook_name, notebook_path)
109 114 self.finish(jsonapi.dumps(model))
110 115 else:
111 116 format = self.get_argument('format', default='json')
112 117 name = self.get_argument('name', default=None)
113 118 nbm.save_notebook(self.request.body, notebook_path=notebook_path, name=name, format=format)
114 119 model = nbm.notebook_model(notebook_name, notebook_path)
115 120 self.set_status(204)
116 121 self.finish(jsonapi.dumps(model))
117 122
118 123 @web.authenticated
119 124 def delete(self, notebook_path):
120 125 nbm = self.notebook_manager
121 126 name, path = nbm.named_notebook_path(notebook_path)
122 127 nbm.delete_notebook(name, path)
123 128 self.set_status(204)
124 129 self.finish()
125 130
126 131
127 132 class NotebookCheckpointsHandler(IPythonHandler):
128 133
129 134 SUPPORTED_METHODS = ('GET', 'POST')
130 135
131 136 @web.authenticated
132 137 def get(self, notebook_path):
133 138 """get lists checkpoints for a notebook"""
134 139 nbm = self.notebook_manager
135 140 name, path = nbm.named_notebook_path(notebook_path)
136 141 checkpoints = nbm.list_checkpoints(name, path)
137 142 data = jsonapi.dumps(checkpoints, default=date_default)
138 143 self.finish(data)
139 144
140 145 @web.authenticated
141 146 def post(self, notebook_path):
142 147 """post creates a new checkpoint"""
143 148 nbm = self.notebook_manager
144 149 name, path = nbm.named_notebook_path(notebook_path)
145 150 checkpoint = nbm.create_checkpoint(name, path)
146 151 data = jsonapi.dumps(checkpoint, default=date_default)
147 152 if path == None:
148 153 self.set_header('Location', '{0}notebooks/{1}/checkpoints/{2}'.format(
149 154 self.base_project_url, name, checkpoint['checkpoint_id']
150 155 ))
151 156 else:
152 157 self.set_header('Location', '{0}notebooks/{1}/{2}/checkpoints/{3}'.format(
153 158 self.base_project_url, path, name, checkpoint['checkpoint_id']
154 159 ))
155 160 self.finish(data)
156 161
157 162
158 163 class ModifyNotebookCheckpointsHandler(IPythonHandler):
159 164
160 165 SUPPORTED_METHODS = ('POST', 'DELETE')
161 166
162 167 @web.authenticated
163 168 def post(self, notebook_path, checkpoint_id):
164 169 """post restores a notebook from a checkpoint"""
165 170 nbm = self.notebook_manager
166 171 name, path = nbm.named_notebook_path(notebook_path)
167 172 nbm.restore_checkpoint(name, checkpoint_id, path)
168 173 self.set_status(204)
169 174 self.finish()
170 175
171 176 @web.authenticated
172 177 def delete(self, notebook_path, checkpoint_id):
173 178 """delete clears a checkpoint for a given notebook"""
174 179 nbm = self.notebook_manager
175 180 name, path = nbm.named_notebook_path(notebook_path)
176 181 nbm.delete_checkpoint(name, checkpoint_id, path)
177 182 self.set_status(204)
178 183 self.finish()
179 184
180 185 #-----------------------------------------------------------------------------
181 186 # URL to handler mappings
182 187 #-----------------------------------------------------------------------------
183 188
184 189
185 190 _notebook_path_regex = r"(?P<notebook_path>.+)"
186 191 _checkpoint_id_regex = r"(?P<checkpoint_id>[\w-]+)"
187 192
188 193 default_handlers = [
189 194 (r"api/notebooks/%s/checkpoints" % _notebook_path_regex, NotebookCheckpointsHandler),
190 195 (r"api/notebooks/%s/checkpoints/%s" % (_notebook_path_regex, _checkpoint_id_regex),
191 196 ModifyNotebookCheckpointsHandler),
192 197 (r"api/notebooks/%s" % _notebook_path_regex, NotebookHandler),
193 198 (r"api/notebooks/", NotebookRootRedirect),
194 199 (r"api/notebooks", NotebookRootHandler),
195 200 ]
196 201
197 202
198 203
199 204
@@ -1,285 +1,285 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // MenuBar
10 10 //============================================================================
11 11
12 12 /**
13 13 * @module IPython
14 14 * @namespace IPython
15 15 * @submodule MenuBar
16 16 */
17 17
18 18
19 19 var IPython = (function (IPython) {
20 20 "use strict";
21 21
22 22 /**
23 23 * A MenuBar Class to generate the menubar of IPython notebook
24 24 * @Class MenuBar
25 25 *
26 26 * @constructor
27 27 *
28 28 *
29 29 * @param selector {string} selector for the menubar element in DOM
30 30 * @param {object} [options]
31 31 * @param [options.baseProjectUrl] {String} String to use for the
32 32 * Base Project url, default would be to inspect
33 33 * $('body').data('baseProjectUrl');
34 34 * does not support change for now is set through this option
35 35 */
36 36 var MenuBar = function (selector, options) {
37 37 var options = options || {};
38 38 if(options.baseProjectUrl!= undefined){
39 39 this._baseProjectUrl = options.baseProjectUrl;
40 40 }
41 41 this.selector = selector;
42 42 if (this.selector !== undefined) {
43 43 this.element = $(selector);
44 44 this.style();
45 45 this.bind_events();
46 46 }
47 47 };
48 48
49 49 MenuBar.prototype.baseProjectUrl = function(){
50 50 return this._baseProjectUrl || $('body').data('baseProjectUrl');
51 51 };
52 52
53 53 MenuBar.prototype.notebookPath = function() {
54 54 var path = $('body').data('notebookPath');
55 55 if (path != 'None') {
56 56 if (path[path.length-1] != '/') {
57 57 path = path.substring(0,path.length);
58 58 };
59 59 return path;
60 60 } else {
61 61 return '';
62 62 }
63 63 };
64 64
65 65 MenuBar.prototype.style = function () {
66 66 this.element.addClass('border-box-sizing');
67 67 this.element.find("li").click(function (event, ui) {
68 68 // The selected cell loses focus when the menu is entered, so we
69 69 // re-select it upon selection.
70 70 var i = IPython.notebook.get_selected_index();
71 71 IPython.notebook.select(i);
72 72 }
73 73 );
74 74 };
75 75
76 76
77 77 MenuBar.prototype.bind_events = function () {
78 78 // File
79 79 var that = this;
80 80 this.element.find('#new_notebook').click(function () {
81 81 window.open(that.baseProjectUrl() + 'notebooks/' + that.notebookPath() +'new');
82 82 });
83 83 this.element.find('#open_notebook').click(function () {
84 84 window.open(that.baseProjectUrl() + 'tree/' + that.notebookPath());
85 85 });
86 86 this.element.find('#copy_notebook').click(function () {
87 87 var notebook_name = IPython.notebook.get_notebook_name();
88 88 var url = that.baseProjectUrl() + 'notebooks/' + that.notebookPath() + notebook_name + '/copy';
89 89 window.open(url,'_blank');
90 90 return false;
91 91 });
92 92 this.element.find('#download_ipynb').click(function () {
93 93 var notebook_name = IPython.notebook.get_notebook_name();
94 var url = that.baseProjectUrl() + 'api/notebooks/' +
95 notebook_name + '?format=json';
94 var url = that.baseProjectUrl() + 'api/notebooks/' + that.notebookPath() +
95 notebook_name + '?format=json'+ '&download=True';
96 96 window.location.assign(url);
97 97 });
98 98 this.element.find('#download_py').click(function () {
99 99 var notebook_name = IPython.notebook.get_notebook_name();
100 var url = that.baseProjectUrl() + 'api/notebooks/' +
101 notebook_name + '?format=py';
100 var url = that.baseProjectUrl() + 'api/notebooks/' + that.notebookPath() +
101 notebook_name + '?format=py' + '&download=True';
102 102 window.location.assign(url);
103 103 });
104 104 this.element.find('#rename_notebook').click(function () {
105 105 IPython.save_widget.rename_notebook();
106 106 });
107 107 this.element.find('#save_checkpoint').click(function () {
108 108 IPython.notebook.save_checkpoint();
109 109 });
110 110 this.element.find('#restore_checkpoint').click(function () {
111 111 });
112 112 this.element.find('#kill_and_exit').click(function () {
113 113 IPython.notebook.session.delete_session();
114 114 setTimeout(function(){window.close();}, 500);
115 115 });
116 116 // Edit
117 117 this.element.find('#cut_cell').click(function () {
118 118 IPython.notebook.cut_cell();
119 119 });
120 120 this.element.find('#copy_cell').click(function () {
121 121 IPython.notebook.copy_cell();
122 122 });
123 123 this.element.find('#delete_cell').click(function () {
124 124 IPython.notebook.delete_cell();
125 125 });
126 126 this.element.find('#undelete_cell').click(function () {
127 127 IPython.notebook.undelete();
128 128 });
129 129 this.element.find('#split_cell').click(function () {
130 130 IPython.notebook.split_cell();
131 131 });
132 132 this.element.find('#merge_cell_above').click(function () {
133 133 IPython.notebook.merge_cell_above();
134 134 });
135 135 this.element.find('#merge_cell_below').click(function () {
136 136 IPython.notebook.merge_cell_below();
137 137 });
138 138 this.element.find('#move_cell_up').click(function () {
139 139 IPython.notebook.move_cell_up();
140 140 });
141 141 this.element.find('#move_cell_down').click(function () {
142 142 IPython.notebook.move_cell_down();
143 143 });
144 144 this.element.find('#select_previous').click(function () {
145 145 IPython.notebook.select_prev();
146 146 });
147 147 this.element.find('#select_next').click(function () {
148 148 IPython.notebook.select_next();
149 149 });
150 150 this.element.find('#edit_nb_metadata').click(function () {
151 151 IPython.notebook.edit_metadata();
152 152 });
153 153
154 154 // View
155 155 this.element.find('#toggle_header').click(function () {
156 156 $('div#header').toggle();
157 157 IPython.layout_manager.do_resize();
158 158 });
159 159 this.element.find('#toggle_toolbar').click(function () {
160 160 $('div#maintoolbar').toggle();
161 161 IPython.layout_manager.do_resize();
162 162 });
163 163 // Insert
164 164 this.element.find('#insert_cell_above').click(function () {
165 165 IPython.notebook.insert_cell_above('code');
166 166 });
167 167 this.element.find('#insert_cell_below').click(function () {
168 168 IPython.notebook.insert_cell_below('code');
169 169 });
170 170 // Cell
171 171 this.element.find('#run_cell').click(function () {
172 172 IPython.notebook.execute_selected_cell();
173 173 });
174 174 this.element.find('#run_cell_in_place').click(function () {
175 175 IPython.notebook.execute_selected_cell({terminal:true});
176 176 });
177 177 this.element.find('#run_all_cells').click(function () {
178 178 IPython.notebook.execute_all_cells();
179 179 }).attr('title', 'Run all cells in the notebook');
180 180 this.element.find('#run_all_cells_above').click(function () {
181 181 IPython.notebook.execute_cells_above();
182 182 }).attr('title', 'Run all cells above (but not including) this cell');
183 183 this.element.find('#run_all_cells_below').click(function () {
184 184 IPython.notebook.execute_cells_below();
185 185 }).attr('title', 'Run this cell and all cells below it');
186 186 this.element.find('#to_code').click(function () {
187 187 IPython.notebook.to_code();
188 188 });
189 189 this.element.find('#to_markdown').click(function () {
190 190 IPython.notebook.to_markdown();
191 191 });
192 192 this.element.find('#to_raw').click(function () {
193 193 IPython.notebook.to_raw();
194 194 });
195 195 this.element.find('#to_heading1').click(function () {
196 196 IPython.notebook.to_heading(undefined, 1);
197 197 });
198 198 this.element.find('#to_heading2').click(function () {
199 199 IPython.notebook.to_heading(undefined, 2);
200 200 });
201 201 this.element.find('#to_heading3').click(function () {
202 202 IPython.notebook.to_heading(undefined, 3);
203 203 });
204 204 this.element.find('#to_heading4').click(function () {
205 205 IPython.notebook.to_heading(undefined, 4);
206 206 });
207 207 this.element.find('#to_heading5').click(function () {
208 208 IPython.notebook.to_heading(undefined, 5);
209 209 });
210 210 this.element.find('#to_heading6').click(function () {
211 211 IPython.notebook.to_heading(undefined, 6);
212 212 });
213 213 this.element.find('#toggle_output').click(function () {
214 214 IPython.notebook.toggle_output();
215 215 });
216 216 this.element.find('#collapse_all_output').click(function () {
217 217 IPython.notebook.collapse_all_output();
218 218 });
219 219 this.element.find('#scroll_all_output').click(function () {
220 220 IPython.notebook.scroll_all_output();
221 221 });
222 222 this.element.find('#expand_all_output').click(function () {
223 223 IPython.notebook.expand_all_output();
224 224 });
225 225 this.element.find('#clear_all_output').click(function () {
226 226 IPython.notebook.clear_all_output();
227 227 });
228 228 // Kernel
229 229 this.element.find('#int_kernel').click(function () {
230 230 IPython.notebook.session.interrupt_kernel();
231 231 });
232 232 this.element.find('#restart_kernel').click(function () {
233 233 IPython.notebook.restart_kernel();
234 234 });
235 235 // Help
236 236 this.element.find('#keyboard_shortcuts').click(function () {
237 237 IPython.quick_help.show_keyboard_shortcuts();
238 238 });
239 239
240 240 this.update_restore_checkpoint(null);
241 241
242 242 $([IPython.events]).on('checkpoints_listed.Notebook', function (event, data) {
243 243 that.update_restore_checkpoint(IPython.notebook.checkpoints);
244 244 });
245 245
246 246 $([IPython.events]).on('checkpoint_created.Notebook', function (event, data) {
247 247 that.update_restore_checkpoint(IPython.notebook.checkpoints);
248 248 });
249 249 };
250 250
251 251 MenuBar.prototype.update_restore_checkpoint = function(checkpoints) {
252 252 var ul = this.element.find("#restore_checkpoint").find("ul");
253 253 ul.empty();
254 254 if (! checkpoints || checkpoints.length == 0) {
255 255 ul.append(
256 256 $("<li/>")
257 257 .addClass("disabled")
258 258 .append(
259 259 $("<a/>")
260 260 .text("No checkpoints")
261 261 )
262 262 );
263 263 return;
264 264 };
265 265
266 266 checkpoints.map(function (checkpoint) {
267 267 var d = new Date(checkpoint.last_modified);
268 268 ul.append(
269 269 $("<li/>").append(
270 270 $("<a/>")
271 271 .attr("href", "#")
272 272 .text(d.format("mmm dd HH:MM:ss"))
273 273 .click(function () {
274 274 IPython.notebook.restore_checkpoint_dialog(checkpoint);
275 275 })
276 276 )
277 277 );
278 278 });
279 279 };
280 280
281 281 IPython.MenuBar = MenuBar;
282 282
283 283 return IPython;
284 284
285 285 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now