##// END OF EJS Templates
Fix to if test
Thomas Kluyver -
Show More
@@ -1,349 +1,349 b''
1 """A notebook manager that uses the local file system for storage.
1 """A notebook manager that uses the local file system for storage.
2
2
3 Authors:
3 Authors:
4
4
5 * Brian Granger
5 * Brian Granger
6 """
6 """
7
7
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2011 The IPython Development Team
9 # Copyright (C) 2011 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 import datetime
19 import datetime
20 import io
20 import io
21 import os
21 import os
22 import glob
22 import glob
23 import shutil
23 import shutil
24
24
25 from unicodedata import normalize
25 from unicodedata import normalize
26
26
27 from tornado import web
27 from tornado import web
28
28
29 from .nbmanager import NotebookManager
29 from .nbmanager import NotebookManager
30 from IPython.nbformat import current
30 from IPython.nbformat import current
31 from IPython.utils.traitlets import Unicode, Dict, Bool, TraitError
31 from IPython.utils.traitlets import Unicode, Dict, Bool, TraitError
32 from IPython.utils import tz
32 from IPython.utils import tz
33
33
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35 # Classes
35 # Classes
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37
37
38 class FileNotebookManager(NotebookManager):
38 class FileNotebookManager(NotebookManager):
39
39
40 save_script = Bool(False, config=True,
40 save_script = Bool(False, config=True,
41 help="""Automatically create a Python script when saving the notebook.
41 help="""Automatically create a Python script when saving the notebook.
42
42
43 For easier use of import, %run and %load across notebooks, a
43 For easier use of import, %run and %load across notebooks, a
44 <notebook-name>.py script will be created next to any
44 <notebook-name>.py script will be created next to any
45 <notebook-name>.ipynb on each save. This can also be set with the
45 <notebook-name>.ipynb on each save. This can also be set with the
46 short `--script` flag.
46 short `--script` flag.
47 """
47 """
48 )
48 )
49
49
50 checkpoint_dir = Unicode(config=True,
50 checkpoint_dir = Unicode(config=True,
51 help="""The location in which to keep notebook checkpoints
51 help="""The location in which to keep notebook checkpoints
52
52
53 By default, it is notebook-dir/.ipynb_checkpoints
53 By default, it is notebook-dir/.ipynb_checkpoints
54 """
54 """
55 )
55 )
56 def _checkpoint_dir_default(self):
56 def _checkpoint_dir_default(self):
57 return os.path.join(self.notebook_dir, '.ipynb_checkpoints')
57 return os.path.join(self.notebook_dir, '.ipynb_checkpoints')
58
58
59 def _checkpoint_dir_changed(self, name, old, new):
59 def _checkpoint_dir_changed(self, name, old, new):
60 """do a bit of validation of the checkpoint dir"""
60 """do a bit of validation of the checkpoint dir"""
61 if not os.path.isabs(new):
61 if not os.path.isabs(new):
62 # If we receive a non-absolute path, make it absolute.
62 # If we receive a non-absolute path, make it absolute.
63 abs_new = os.path.abspath(new)
63 abs_new = os.path.abspath(new)
64 self.checkpoint_dir = abs_new
64 self.checkpoint_dir = abs_new
65 return
65 return
66 if os.path.exists(new) and not os.path.isdir(new):
66 if os.path.exists(new) and not os.path.isdir(new):
67 raise TraitError("checkpoint dir %r is not a directory" % new)
67 raise TraitError("checkpoint dir %r is not a directory" % new)
68 if not os.path.exists(new):
68 if not os.path.exists(new):
69 self.log.info("Creating checkpoint dir %s", new)
69 self.log.info("Creating checkpoint dir %s", new)
70 try:
70 try:
71 os.mkdir(new)
71 os.mkdir(new)
72 except:
72 except:
73 raise TraitError("Couldn't create checkpoint dir %r" % new)
73 raise TraitError("Couldn't create checkpoint dir %r" % new)
74
74
75 filename_ext = Unicode(u'.ipynb')
75 filename_ext = Unicode(u'.ipynb')
76
76
77
77
78 def get_notebook_names(self, path):
78 def get_notebook_names(self, path):
79 """List all notebook names in the notebook dir."""
79 """List all notebook names in the notebook dir."""
80 names = glob.glob(os.path.join(self.notebook_dir, path,
80 names = glob.glob(os.path.join(self.notebook_dir, path,
81 '*' + self.filename_ext))
81 '*' + self.filename_ext))
82 names = [os.path.basename(name)
82 names = [os.path.basename(name)
83 for name in names]
83 for name in names]
84 return names
84 return names
85
85
86 def list_notebooks(self, path):
86 def list_notebooks(self, path):
87 """List all notebooks in the notebook dir."""
87 """List all notebooks in the notebook dir."""
88 notebook_names = self.get_notebook_names(path)
88 notebook_names = self.get_notebook_names(path)
89 notebook_mapping = []
89 notebook_mapping = []
90 for name in notebook_names:
90 for name in notebook_names:
91 model = self.notebook_model(name, path, content=False)
91 model = self.notebook_model(name, path, content=False)
92 notebook_mapping.append(model)
92 notebook_mapping.append(model)
93 return notebook_mapping
93 return notebook_mapping
94
94
95 def change_notebook(self, data, notebook_name, notebook_path=None):
95 def change_notebook(self, data, notebook_name, notebook_path=None):
96 """Changes notebook"""
96 """Changes notebook"""
97 changes = data.keys()
97 changes = data.keys()
98 response = 200
98 response = 200
99 for change in changes:
99 for change in changes:
100 full_path = self.get_path(notebook_name, notebook_path)
100 full_path = self.get_path(notebook_name, notebook_path)
101 if change == "name":
101 if change == "name":
102 new_path = self.get_path(data['name'], notebook_path)
102 new_path = self.get_path(data['name'], notebook_path)
103 if os.path.isfile(new_path) == False:
103 if not os.path.isfile(new_path):
104 os.rename(full_path,
104 os.rename(full_path,
105 self.get_path(data['name'], notebook_path))
105 self.get_path(data['name'], notebook_path))
106 notebook_name = data['name']
106 notebook_name = data['name']
107 else:
107 else:
108 response = 409
108 response = 409
109 if change == "path":
109 if change == "path":
110 new_path = self.get_path(data['name'], data['path'])
110 new_path = self.get_path(data['name'], data['path'])
111 stutil.move(full_path, new_path)
111 stutil.move(full_path, new_path)
112 notebook_path = data['path']
112 notebook_path = data['path']
113 if change == "content":
113 if change == "content":
114 self.save_notebook(data, notebook_name, notebook_path)
114 self.save_notebook(data, notebook_name, notebook_path)
115 model = self.notebook_model(notebook_name, notebook_path)
115 model = self.notebook_model(notebook_name, notebook_path)
116 return model, response
116 return model, response
117
117
118 def notebook_exists(self, notebook_path):
118 def notebook_exists(self, notebook_path):
119 """Does a notebook exist?"""
119 """Does a notebook exist?"""
120 return os.path.isfile(notebook_path)
120 return os.path.isfile(notebook_path)
121
121
122 def get_path(self, notebook_name, notebook_path=None):
122 def get_path(self, notebook_name, notebook_path=None):
123 """Return a full path to a notebook given its notebook_name."""
123 """Return a full path to a notebook given its notebook_name."""
124 return self.get_path_by_name(notebook_name, notebook_path)
124 return self.get_path_by_name(notebook_name, notebook_path)
125
125
126 def get_path_by_name(self, name, notebook_path=None):
126 def get_path_by_name(self, name, notebook_path=None):
127 """Return a full path to a notebook given its name."""
127 """Return a full path to a notebook given its name."""
128 filename = name #+ self.filename_ext
128 filename = name #+ self.filename_ext
129 if notebook_path == None:
129 if notebook_path == None:
130 path = os.path.join(self.notebook_dir, filename)
130 path = os.path.join(self.notebook_dir, filename)
131 else:
131 else:
132 path = os.path.join(self.notebook_dir, notebook_path, filename)
132 path = os.path.join(self.notebook_dir, notebook_path, filename)
133 return path
133 return path
134
134
135 def read_notebook_object_from_path(self, path):
135 def read_notebook_object_from_path(self, path):
136 """read a notebook object from a path"""
136 """read a notebook object from a path"""
137 info = os.stat(path)
137 info = os.stat(path)
138 last_modified = tz.utcfromtimestamp(info.st_mtime)
138 last_modified = tz.utcfromtimestamp(info.st_mtime)
139 with open(path,'r') as f:
139 with open(path,'r') as f:
140 s = f.read()
140 s = f.read()
141 try:
141 try:
142 # v1 and v2 and json in the .ipynb files.
142 # v1 and v2 and json in the .ipynb files.
143 nb = current.reads(s, u'json')
143 nb = current.reads(s, u'json')
144 except ValueError as e:
144 except ValueError as e:
145 msg = u"Unreadable Notebook: %s" % e
145 msg = u"Unreadable Notebook: %s" % e
146 raise web.HTTPError(400, msg, reason=msg)
146 raise web.HTTPError(400, msg, reason=msg)
147 return last_modified, nb
147 return last_modified, nb
148
148
149 def read_notebook_object(self, notebook_name, notebook_path=None):
149 def read_notebook_object(self, notebook_name, notebook_path=None):
150 """Get the Notebook representation of a notebook by notebook_name."""
150 """Get the Notebook representation of a notebook by notebook_name."""
151 path = self.get_path(notebook_name, notebook_path)
151 path = self.get_path(notebook_name, notebook_path)
152 if not os.path.isfile(path):
152 if not os.path.isfile(path):
153 raise web.HTTPError(404, u'Notebook does not exist: %s' % notebook_name)
153 raise web.HTTPError(404, u'Notebook does not exist: %s' % notebook_name)
154 last_modified, nb = self.read_notebook_object_from_path(path)
154 last_modified, nb = self.read_notebook_object_from_path(path)
155 # Always use the filename as the notebook name.
155 # Always use the filename as the notebook name.
156 # Eventually we will get rid of the notebook name in the metadata
156 # Eventually we will get rid of the notebook name in the metadata
157 # but for now, that name is just an empty string. Until the notebooks
157 # but for now, that name is just an empty string. Until the notebooks
158 # web service knows about names in URLs we still pass the name
158 # web service knows about names in URLs we still pass the name
159 # back to the web app using the metadata though.
159 # back to the web app using the metadata though.
160 nb.metadata.name = os.path.splitext(os.path.basename(path))[0]
160 nb.metadata.name = os.path.splitext(os.path.basename(path))[0]
161 return last_modified, nb
161 return last_modified, nb
162
162
163 def write_notebook_object(self, nb, notebook_name=None, notebook_path=None, new_name= None):
163 def write_notebook_object(self, nb, notebook_name=None, notebook_path=None, new_name= None):
164 """Save an existing notebook object by notebook_name."""
164 """Save an existing notebook object by notebook_name."""
165 if new_name == None:
165 if new_name == None:
166 try:
166 try:
167 new_name = normalize('NFC', nb.metadata.name)
167 new_name = normalize('NFC', nb.metadata.name)
168 except AttributeError:
168 except AttributeError:
169 raise web.HTTPError(400, u'Missing notebook name')
169 raise web.HTTPError(400, u'Missing notebook name')
170
170
171 new_path = notebook_path
171 new_path = notebook_path
172 old_name = notebook_name
172 old_name = notebook_name
173 old_checkpoints = self.list_checkpoints(old_name)
173 old_checkpoints = self.list_checkpoints(old_name)
174
174
175 path = self.get_path_by_name(new_name, new_path)
175 path = self.get_path_by_name(new_name, new_path)
176
176
177 # Right before we save the notebook, we write an empty string as the
177 # Right before we save the notebook, we write an empty string as the
178 # notebook name in the metadata. This is to prepare for removing
178 # notebook name in the metadata. This is to prepare for removing
179 # this attribute entirely post 1.0. The web app still uses the metadata
179 # this attribute entirely post 1.0. The web app still uses the metadata
180 # name for now.
180 # name for now.
181 nb.metadata.name = u''
181 nb.metadata.name = u''
182
182
183 try:
183 try:
184 self.log.debug("Autosaving notebook %s", path)
184 self.log.debug("Autosaving notebook %s", path)
185 with open(path,'w') as f:
185 with open(path,'w') as f:
186 current.write(nb, f, u'json')
186 current.write(nb, f, u'json')
187 except Exception as e:
187 except Exception as e:
188 raise web.HTTPError(400, u'Unexpected error while autosaving notebook: %s' % e)
188 raise web.HTTPError(400, u'Unexpected error while autosaving notebook: %s' % e)
189
189
190 # save .py script as well
190 # save .py script as well
191 if self.save_script:
191 if self.save_script:
192 pypath = os.path.splitext(path)[0] + '.py'
192 pypath = os.path.splitext(path)[0] + '.py'
193 self.log.debug("Writing script %s", pypath)
193 self.log.debug("Writing script %s", pypath)
194 try:
194 try:
195 with io.open(pypath,'w', encoding='utf-8') as f:
195 with io.open(pypath,'w', encoding='utf-8') as f:
196 current.write(nb, f, u'py')
196 current.write(nb, f, u'py')
197 except Exception as e:
197 except Exception as e:
198 raise web.HTTPError(400, u'Unexpected error while saving notebook as script: %s' % e)
198 raise web.HTTPError(400, u'Unexpected error while saving notebook as script: %s' % e)
199
199
200 if old_name != None:
200 if old_name != None:
201 # remove old files if the name changed
201 # remove old files if the name changed
202 if old_name != new_name:
202 if old_name != new_name:
203 # remove renamed original, if it exists
203 # remove renamed original, if it exists
204 old_path = self.get_path_by_name(old_name, notebook_path)
204 old_path = self.get_path_by_name(old_name, notebook_path)
205 if os.path.isfile(old_path):
205 if os.path.isfile(old_path):
206 self.log.debug("unlinking notebook %s", old_path)
206 self.log.debug("unlinking notebook %s", old_path)
207 os.unlink(old_path)
207 os.unlink(old_path)
208
208
209 # cleanup old script, if it exists
209 # cleanup old script, if it exists
210 if self.save_script:
210 if self.save_script:
211 old_pypath = os.path.splitext(old_path)[0] + '.py'
211 old_pypath = os.path.splitext(old_path)[0] + '.py'
212 if os.path.isfile(old_pypath):
212 if os.path.isfile(old_pypath):
213 self.log.debug("unlinking script %s", old_pypath)
213 self.log.debug("unlinking script %s", old_pypath)
214 os.unlink(old_pypath)
214 os.unlink(old_pypath)
215
215
216 # rename checkpoints to follow file
216 # rename checkpoints to follow file
217 for cp in old_checkpoints:
217 for cp in old_checkpoints:
218 checkpoint_id = cp['checkpoint_id']
218 checkpoint_id = cp['checkpoint_id']
219 old_cp_path = self.get_checkpoint_path_by_name(old_name, checkpoint_id)
219 old_cp_path = self.get_checkpoint_path_by_name(old_name, checkpoint_id)
220 new_cp_path = self.get_checkpoint_path_by_name(new_name, checkpoint_id)
220 new_cp_path = self.get_checkpoint_path_by_name(new_name, checkpoint_id)
221 if os.path.isfile(old_cp_path):
221 if os.path.isfile(old_cp_path):
222 self.log.debug("renaming checkpoint %s -> %s", old_cp_path, new_cp_path)
222 self.log.debug("renaming checkpoint %s -> %s", old_cp_path, new_cp_path)
223 os.rename(old_cp_path, new_cp_path)
223 os.rename(old_cp_path, new_cp_path)
224
224
225 return new_name
225 return new_name
226
226
227 def delete_notebook(self, notebook_name, notebook_path):
227 def delete_notebook(self, notebook_name, notebook_path):
228 """Delete notebook by notebook_name."""
228 """Delete notebook by notebook_name."""
229 nb_path = self.get_path(notebook_name, notebook_path)
229 nb_path = self.get_path(notebook_name, notebook_path)
230 if not os.path.isfile(nb_path):
230 if not os.path.isfile(nb_path):
231 raise web.HTTPError(404, u'Notebook does not exist: %s' % notebook_name)
231 raise web.HTTPError(404, u'Notebook does not exist: %s' % notebook_name)
232
232
233 # clear checkpoints
233 # clear checkpoints
234 for checkpoint in self.list_checkpoints(notebook_name):
234 for checkpoint in self.list_checkpoints(notebook_name):
235 checkpoint_id = checkpoint['checkpoint_id']
235 checkpoint_id = checkpoint['checkpoint_id']
236 path = self.get_checkpoint_path(notebook_name, checkpoint_id)
236 path = self.get_checkpoint_path(notebook_name, checkpoint_id)
237 self.log.debug(path)
237 self.log.debug(path)
238 if os.path.isfile(path):
238 if os.path.isfile(path):
239 self.log.debug("unlinking checkpoint %s", path)
239 self.log.debug("unlinking checkpoint %s", path)
240 os.unlink(path)
240 os.unlink(path)
241
241
242 self.log.debug("unlinking notebook %s", nb_path)
242 self.log.debug("unlinking notebook %s", nb_path)
243 os.unlink(nb_path)
243 os.unlink(nb_path)
244
244
245 def increment_filename(self, basename, notebook_path=None):
245 def increment_filename(self, basename, notebook_path=None):
246 """Return a non-used filename of the form basename<int>.
246 """Return a non-used filename of the form basename<int>.
247
247
248 This searches through the filenames (basename0, basename1, ...)
248 This searches through the filenames (basename0, basename1, ...)
249 until is find one that is not already being used. It is used to
249 until is find one that is not already being used. It is used to
250 create Untitled and Copy names that are unique.
250 create Untitled and Copy names that are unique.
251 """
251 """
252 i = 0
252 i = 0
253 while True:
253 while True:
254 name = u'%s%i.ipynb' % (basename,i)
254 name = u'%s%i.ipynb' % (basename,i)
255 path = self.get_path_by_name(name, notebook_path)
255 path = self.get_path_by_name(name, notebook_path)
256 if not os.path.isfile(path):
256 if not os.path.isfile(path):
257 break
257 break
258 else:
258 else:
259 i = i+1
259 i = i+1
260 return name
260 return name
261
261
262 # Checkpoint-related utilities
262 # Checkpoint-related utilities
263
263
264 def get_checkpoint_path_by_name(self, name, checkpoint_id, notebook_path=None):
264 def get_checkpoint_path_by_name(self, name, checkpoint_id, notebook_path=None):
265 """Return a full path to a notebook checkpoint, given its name and checkpoint id."""
265 """Return a full path to a notebook checkpoint, given its name and checkpoint id."""
266 filename = u"{name}-{checkpoint_id}{ext}".format(
266 filename = u"{name}-{checkpoint_id}{ext}".format(
267 name=name,
267 name=name,
268 checkpoint_id=checkpoint_id,
268 checkpoint_id=checkpoint_id,
269 ext=self.filename_ext,
269 ext=self.filename_ext,
270 )
270 )
271 if notebook_path ==None:
271 if notebook_path ==None:
272 path = os.path.join(self.checkpoint_dir, filename)
272 path = os.path.join(self.checkpoint_dir, filename)
273 else:
273 else:
274 path = os.path.join(notebook_path, self.checkpoint_dir, filename)
274 path = os.path.join(notebook_path, self.checkpoint_dir, filename)
275 return path
275 return path
276
276
277 def get_checkpoint_path(self, notebook_name, checkpoint_id, notebook_path=None):
277 def get_checkpoint_path(self, notebook_name, checkpoint_id, notebook_path=None):
278 """find the path to a checkpoint"""
278 """find the path to a checkpoint"""
279 name = notebook_name
279 name = notebook_name
280 return self.get_checkpoint_path_by_name(name, checkpoint_id, notebook_path)
280 return self.get_checkpoint_path_by_name(name, checkpoint_id, notebook_path)
281
281
282 def get_checkpoint_info(self, notebook_name, checkpoint_id, notebook_path=None):
282 def get_checkpoint_info(self, notebook_name, checkpoint_id, notebook_path=None):
283 """construct the info dict for a given checkpoint"""
283 """construct the info dict for a given checkpoint"""
284 path = self.get_checkpoint_path(notebook_name, checkpoint_id, notebook_path)
284 path = self.get_checkpoint_path(notebook_name, checkpoint_id, notebook_path)
285 stats = os.stat(path)
285 stats = os.stat(path)
286 last_modified = tz.utcfromtimestamp(stats.st_mtime)
286 last_modified = tz.utcfromtimestamp(stats.st_mtime)
287 info = dict(
287 info = dict(
288 checkpoint_id = checkpoint_id,
288 checkpoint_id = checkpoint_id,
289 last_modified = last_modified,
289 last_modified = last_modified,
290 )
290 )
291
291
292 return info
292 return info
293
293
294 # public checkpoint API
294 # public checkpoint API
295
295
296 def create_checkpoint(self, notebook_name, notebook_path=None):
296 def create_checkpoint(self, notebook_name, notebook_path=None):
297 """Create a checkpoint from the current state of a notebook"""
297 """Create a checkpoint from the current state of a notebook"""
298 nb_path = self.get_path(notebook_name, notebook_path)
298 nb_path = self.get_path(notebook_name, notebook_path)
299 # only the one checkpoint ID:
299 # only the one checkpoint ID:
300 checkpoint_id = u"checkpoint"
300 checkpoint_id = u"checkpoint"
301 cp_path = self.get_checkpoint_path(notebook_name, checkpoint_id, notebook_path)
301 cp_path = self.get_checkpoint_path(notebook_name, checkpoint_id, notebook_path)
302 self.log.debug("creating checkpoint for notebook %s", notebook_name)
302 self.log.debug("creating checkpoint for notebook %s", notebook_name)
303 if not os.path.exists(self.checkpoint_dir):
303 if not os.path.exists(self.checkpoint_dir):
304 os.mkdir(self.checkpoint_dir)
304 os.mkdir(self.checkpoint_dir)
305 shutil.copy2(nb_path, cp_path)
305 shutil.copy2(nb_path, cp_path)
306
306
307 # return the checkpoint info
307 # return the checkpoint info
308 return self.get_checkpoint_info(notebook_name, checkpoint_id, notebook_path)
308 return self.get_checkpoint_info(notebook_name, checkpoint_id, notebook_path)
309
309
310 def list_checkpoints(self, notebook_name, notebook_path=None):
310 def list_checkpoints(self, notebook_name, notebook_path=None):
311 """list the checkpoints for a given notebook
311 """list the checkpoints for a given notebook
312
312
313 This notebook manager currently only supports one checkpoint per notebook.
313 This notebook manager currently only supports one checkpoint per notebook.
314 """
314 """
315 checkpoint_id = "checkpoint"
315 checkpoint_id = "checkpoint"
316 path = self.get_checkpoint_path(notebook_name, checkpoint_id, notebook_path)
316 path = self.get_checkpoint_path(notebook_name, checkpoint_id, notebook_path)
317 if not os.path.exists(path):
317 if not os.path.exists(path):
318 return []
318 return []
319 else:
319 else:
320 return [self.get_checkpoint_info(notebook_name, checkpoint_id, notebook_path)]
320 return [self.get_checkpoint_info(notebook_name, checkpoint_id, notebook_path)]
321
321
322
322
323 def restore_checkpoint(self, notebook_name, checkpoint_id, notebook_path=None):
323 def restore_checkpoint(self, notebook_name, checkpoint_id, notebook_path=None):
324 """restore a notebook to a checkpointed state"""
324 """restore a notebook to a checkpointed state"""
325 self.log.info("restoring Notebook %s from checkpoint %s", notebook_name, checkpoint_id)
325 self.log.info("restoring Notebook %s from checkpoint %s", notebook_name, checkpoint_id)
326 nb_path = self.get_path(notebook_name, notebook_path)
326 nb_path = self.get_path(notebook_name, notebook_path)
327 cp_path = self.get_checkpoint_path(notebook_name, checkpoint_id, notebook_path)
327 cp_path = self.get_checkpoint_path(notebook_name, checkpoint_id, notebook_path)
328 if not os.path.isfile(cp_path):
328 if not os.path.isfile(cp_path):
329 self.log.debug("checkpoint file does not exist: %s", cp_path)
329 self.log.debug("checkpoint file does not exist: %s", cp_path)
330 raise web.HTTPError(404,
330 raise web.HTTPError(404,
331 u'Notebook checkpoint does not exist: %s-%s' % (notebook_name, checkpoint_id)
331 u'Notebook checkpoint does not exist: %s-%s' % (notebook_name, checkpoint_id)
332 )
332 )
333 # ensure notebook is readable (never restore from an unreadable notebook)
333 # ensure notebook is readable (never restore from an unreadable notebook)
334 last_modified, nb = self.read_notebook_object_from_path(cp_path)
334 last_modified, nb = self.read_notebook_object_from_path(cp_path)
335 shutil.copy2(cp_path, nb_path)
335 shutil.copy2(cp_path, nb_path)
336 self.log.debug("copying %s -> %s", cp_path, nb_path)
336 self.log.debug("copying %s -> %s", cp_path, nb_path)
337
337
338 def delete_checkpoint(self, notebook_name, checkpoint_id, notebook_path=None):
338 def delete_checkpoint(self, notebook_name, checkpoint_id, notebook_path=None):
339 """delete a notebook's checkpoint"""
339 """delete a notebook's checkpoint"""
340 path = self.get_checkpoint_path(notebook_name, checkpoint_id, notebook_path)
340 path = self.get_checkpoint_path(notebook_name, checkpoint_id, notebook_path)
341 if not os.path.isfile(path):
341 if not os.path.isfile(path):
342 raise web.HTTPError(404,
342 raise web.HTTPError(404,
343 u'Notebook checkpoint does not exist: %s-%s' % (notebook_name, checkpoint_id)
343 u'Notebook checkpoint does not exist: %s-%s' % (notebook_name, checkpoint_id)
344 )
344 )
345 self.log.debug("unlinking %s", path)
345 self.log.debug("unlinking %s", path)
346 os.unlink(path)
346 os.unlink(path)
347
347
348 def info_string(self):
348 def info_string(self):
349 return "Serving notebooks from local directory: %s" % self.notebook_dir
349 return "Serving notebooks from local directory: %s" % self.notebook_dir
General Comments 0
You need to be logged in to leave comments. Login now