##// END OF EJS Templates
mv services/notebooks services/contents
MinRK -
Show More
1 NO CONTENT: file renamed from IPython/html/services/notebooks/__init__.py to IPython/html/services/contents/__init__.py
NO CONTENT: file renamed from IPython/html/services/notebooks/__init__.py to IPython/html/services/contents/__init__.py
@@ -27,10 +27,10 b' def sort_key(item):'
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28
28
29 class FileNotebookManager(NotebookManager):
29 class FileNotebookManager(NotebookManager):
30
30
31 save_script = Bool(False, config=True,
31 save_script = Bool(False, config=True,
32 help="""Automatically create a Python script when saving the notebook.
32 help="""Automatically create a Python script when saving the notebook.
33
33
34 For easier use of import, %run and %load across notebooks, a
34 For easier use of import, %run and %load across notebooks, a
35 <notebook-name>.py script will be created next to any
35 <notebook-name>.py script will be created next to any
36 <notebook-name>.ipynb on each save. This can also be set with the
36 <notebook-name>.ipynb on each save. This can also be set with the
@@ -38,7 +38,7 b' class FileNotebookManager(NotebookManager):'
38 """
38 """
39 )
39 )
40 notebook_dir = Unicode(getcwd(), config=True)
40 notebook_dir = Unicode(getcwd(), config=True)
41
41
42 def _notebook_dir_changed(self, name, old, new):
42 def _notebook_dir_changed(self, name, old, new):
43 """Do a bit of validation of the notebook dir."""
43 """Do a bit of validation of the notebook dir."""
44 if not os.path.isabs(new):
44 if not os.path.isabs(new):
@@ -47,19 +47,19 b' class FileNotebookManager(NotebookManager):'
47 return
47 return
48 if not os.path.exists(new) or not os.path.isdir(new):
48 if not os.path.exists(new) or not os.path.isdir(new):
49 raise TraitError("notebook dir %r is not a directory" % new)
49 raise TraitError("notebook dir %r is not a directory" % new)
50
50
51 checkpoint_dir = Unicode('.ipynb_checkpoints', config=True,
51 checkpoint_dir = Unicode('.ipynb_checkpoints', config=True,
52 help="""The directory name in which to keep notebook checkpoints
52 help="""The directory name in which to keep notebook checkpoints
53
53
54 This is a path relative to the notebook's own directory.
54 This is a path relative to the notebook's own directory.
55
55
56 By default, it is .ipynb_checkpoints
56 By default, it is .ipynb_checkpoints
57 """
57 """
58 )
58 )
59
59
60 def _copy(self, src, dest):
60 def _copy(self, src, dest):
61 """copy src to dest
61 """copy src to dest
62
62
63 like shutil.copy2, but log errors in copystat
63 like shutil.copy2, but log errors in copystat
64 """
64 """
65 shutil.copyfile(src, dest)
65 shutil.copyfile(src, dest)
@@ -67,7 +67,7 b' class FileNotebookManager(NotebookManager):'
67 shutil.copystat(src, dest)
67 shutil.copystat(src, dest)
68 except OSError as e:
68 except OSError as e:
69 self.log.debug("copystat on %s failed", dest, exc_info=True)
69 self.log.debug("copystat on %s failed", dest, exc_info=True)
70
70
71 def get_notebook_names(self, path=''):
71 def get_notebook_names(self, path=''):
72 """List all notebook names in the notebook dir and path."""
72 """List all notebook names in the notebook dir and path."""
73 path = path.strip('/')
73 path = path.strip('/')
@@ -80,13 +80,13 b' class FileNotebookManager(NotebookManager):'
80
80
81 def path_exists(self, path):
81 def path_exists(self, path):
82 """Does the API-style path (directory) actually exist?
82 """Does the API-style path (directory) actually exist?
83
83
84 Parameters
84 Parameters
85 ----------
85 ----------
86 path : string
86 path : string
87 The path to check. This is an API path (`/` separated,
87 The path to check. This is an API path (`/` separated,
88 relative to base notebook-dir).
88 relative to base notebook-dir).
89
89
90 Returns
90 Returns
91 -------
91 -------
92 exists : bool
92 exists : bool
@@ -98,18 +98,18 b' class FileNotebookManager(NotebookManager):'
98
98
99 def is_hidden(self, path):
99 def is_hidden(self, path):
100 """Does the API style path correspond to a hidden directory or file?
100 """Does the API style path correspond to a hidden directory or file?
101
101
102 Parameters
102 Parameters
103 ----------
103 ----------
104 path : string
104 path : string
105 The path to check. This is an API path (`/` separated,
105 The path to check. This is an API path (`/` separated,
106 relative to base notebook-dir).
106 relative to base notebook-dir).
107
107
108 Returns
108 Returns
109 -------
109 -------
110 exists : bool
110 exists : bool
111 Whether the path is hidden.
111 Whether the path is hidden.
112
112
113 """
113 """
114 path = path.strip('/')
114 path = path.strip('/')
115 os_path = self._get_os_path(path=path)
115 os_path = self._get_os_path(path=path)
@@ -204,13 +204,13 b' class FileNotebookManager(NotebookManager):'
204 def list_notebooks(self, path):
204 def list_notebooks(self, path):
205 """Returns a list of dictionaries that are the standard model
205 """Returns a list of dictionaries that are the standard model
206 for all notebooks in the relative 'path'.
206 for all notebooks in the relative 'path'.
207
207
208 Parameters
208 Parameters
209 ----------
209 ----------
210 path : str
210 path : str
211 the URL path that describes the relative path for the
211 the URL path that describes the relative path for the
212 listed notebooks
212 listed notebooks
213
213
214 Returns
214 Returns
215 -------
215 -------
216 notebooks : list of dicts
216 notebooks : list of dicts
@@ -225,7 +225,7 b' class FileNotebookManager(NotebookManager):'
225
225
226 def get_notebook(self, name, path='', content=True):
226 def get_notebook(self, name, path='', content=True):
227 """ Takes a path and name for a notebook and returns its model
227 """ Takes a path and name for a notebook and returns its model
228
228
229 Parameters
229 Parameters
230 ----------
230 ----------
231 name : str
231 name : str
@@ -233,11 +233,11 b' class FileNotebookManager(NotebookManager):'
233 path : str
233 path : str
234 the URL path that describes the relative path for
234 the URL path that describes the relative path for
235 the notebook
235 the notebook
236
236
237 Returns
237 Returns
238 -------
238 -------
239 model : dict
239 model : dict
240 the notebook model. If contents=True, returns the 'contents'
240 the notebook model. If contents=True, returns the 'contents'
241 dict in the model as well.
241 dict in the model as well.
242 """
242 """
243 path = path.strip('/')
243 path = path.strip('/')
@@ -284,9 +284,9 b' class FileNotebookManager(NotebookManager):'
284 # Save the notebook file
284 # Save the notebook file
285 os_path = self._get_os_path(new_name, new_path)
285 os_path = self._get_os_path(new_name, new_path)
286 nb = current.to_notebook_json(model['content'])
286 nb = current.to_notebook_json(model['content'])
287
287
288 self.check_and_sign(nb, new_name, new_path)
288 self.check_and_sign(nb, new_name, new_path)
289
289
290 if 'name' in nb['metadata']:
290 if 'name' in nb['metadata']:
291 nb['metadata']['name'] = u''
291 nb['metadata']['name'] = u''
292 try:
292 try:
@@ -325,7 +325,7 b' class FileNotebookManager(NotebookManager):'
325 os_path = self._get_os_path(name, path)
325 os_path = self._get_os_path(name, path)
326 if not os.path.isfile(os_path):
326 if not os.path.isfile(os_path):
327 raise web.HTTPError(404, u'Notebook does not exist: %s' % os_path)
327 raise web.HTTPError(404, u'Notebook does not exist: %s' % os_path)
328
328
329 # clear checkpoints
329 # clear checkpoints
330 for checkpoint in self.list_checkpoints(name, path):
330 for checkpoint in self.list_checkpoints(name, path):
331 checkpoint_id = checkpoint['id']
331 checkpoint_id = checkpoint['id']
@@ -333,7 +333,7 b' class FileNotebookManager(NotebookManager):'
333 if os.path.isfile(cp_path):
333 if os.path.isfile(cp_path):
334 self.log.debug("Unlinking checkpoint %s", cp_path)
334 self.log.debug("Unlinking checkpoint %s", cp_path)
335 os.unlink(cp_path)
335 os.unlink(cp_path)
336
336
337 self.log.debug("Unlinking notebook %s", os_path)
337 self.log.debug("Unlinking notebook %s", os_path)
338 os.unlink(os_path)
338 os.unlink(os_path)
339
339
@@ -343,7 +343,7 b' class FileNotebookManager(NotebookManager):'
343 new_path = new_path.strip('/')
343 new_path = new_path.strip('/')
344 if new_name == old_name and new_path == old_path:
344 if new_name == old_name and new_path == old_path:
345 return
345 return
346
346
347 new_os_path = self._get_os_path(new_name, new_path)
347 new_os_path = self._get_os_path(new_name, new_path)
348 old_os_path = self._get_os_path(old_name, old_path)
348 old_os_path = self._get_os_path(old_name, old_path)
349
349
@@ -375,9 +375,9 b' class FileNotebookManager(NotebookManager):'
375 # Move the .py script
375 # Move the .py script
376 if self.save_script:
376 if self.save_script:
377 shutil.move(old_py_path, new_py_path)
377 shutil.move(old_py_path, new_py_path)
378
378
379 # Checkpoint-related utilities
379 # Checkpoint-related utilities
380
380
381 def get_checkpoint_path(self, checkpoint_id, name, path=''):
381 def get_checkpoint_path(self, checkpoint_id, name, path=''):
382 """find the path to a checkpoint"""
382 """find the path to a checkpoint"""
383 path = path.strip('/')
383 path = path.strip('/')
@@ -404,9 +404,9 b' class FileNotebookManager(NotebookManager):'
404 last_modified = last_modified,
404 last_modified = last_modified,
405 )
405 )
406 return info
406 return info
407
407
408 # public checkpoint API
408 # public checkpoint API
409
409
410 def create_checkpoint(self, name, path=''):
410 def create_checkpoint(self, name, path=''):
411 """Create a checkpoint from the current state of a notebook"""
411 """Create a checkpoint from the current state of a notebook"""
412 path = path.strip('/')
412 path = path.strip('/')
@@ -416,13 +416,13 b' class FileNotebookManager(NotebookManager):'
416 cp_path = self.get_checkpoint_path(checkpoint_id, name, path)
416 cp_path = self.get_checkpoint_path(checkpoint_id, name, path)
417 self.log.debug("creating checkpoint for notebook %s", name)
417 self.log.debug("creating checkpoint for notebook %s", name)
418 self._copy(nb_path, cp_path)
418 self._copy(nb_path, cp_path)
419
419
420 # return the checkpoint info
420 # return the checkpoint info
421 return self.get_checkpoint_model(checkpoint_id, name, path)
421 return self.get_checkpoint_model(checkpoint_id, name, path)
422
422
423 def list_checkpoints(self, name, path=''):
423 def list_checkpoints(self, name, path=''):
424 """list the checkpoints for a given notebook
424 """list the checkpoints for a given notebook
425
425
426 This notebook manager currently only supports one checkpoint per notebook.
426 This notebook manager currently only supports one checkpoint per notebook.
427 """
427 """
428 path = path.strip('/')
428 path = path.strip('/')
@@ -432,8 +432,8 b' class FileNotebookManager(NotebookManager):'
432 return []
432 return []
433 else:
433 else:
434 return [self.get_checkpoint_model(checkpoint_id, name, path)]
434 return [self.get_checkpoint_model(checkpoint_id, name, path)]
435
435
436
436
437 def restore_checkpoint(self, checkpoint_id, name, path=''):
437 def restore_checkpoint(self, checkpoint_id, name, path=''):
438 """restore a notebook to a checkpointed state"""
438 """restore a notebook to a checkpointed state"""
439 path = path.strip('/')
439 path = path.strip('/')
@@ -450,7 +450,7 b' class FileNotebookManager(NotebookManager):'
450 current.read(f, u'json')
450 current.read(f, u'json')
451 self._copy(cp_path, nb_path)
451 self._copy(cp_path, nb_path)
452 self.log.debug("copying %s -> %s", cp_path, nb_path)
452 self.log.debug("copying %s -> %s", cp_path, nb_path)
453
453
454 def delete_checkpoint(self, checkpoint_id, name, path=''):
454 def delete_checkpoint(self, checkpoint_id, name, path=''):
455 """delete a notebook's checkpoint"""
455 """delete a notebook's checkpoint"""
456 path = path.strip('/')
456 path = path.strip('/')
@@ -461,7 +461,7 b' class FileNotebookManager(NotebookManager):'
461 )
461 )
462 self.log.debug("unlinking %s", cp_path)
462 self.log.debug("unlinking %s", cp_path)
463 os.unlink(cp_path)
463 os.unlink(cp_path)
464
464
465 def info_string(self):
465 def info_string(self):
466 return "Serving notebooks from local directory: %s" % self.notebook_dir
466 return "Serving notebooks from local directory: %s" % self.notebook_dir
467
467
@@ -38,7 +38,7 b' class NotebookHandler(IPythonHandler):'
38
38
39 def notebook_location(self, name, path=''):
39 def notebook_location(self, name, path=''):
40 """Return the full URL location of a notebook based.
40 """Return the full URL location of a notebook based.
41
41
42 Parameters
42 Parameters
43 ----------
43 ----------
44 name : unicode
44 name : unicode
@@ -57,7 +57,7 b' class NotebookHandler(IPythonHandler):'
57 self.set_header('Location', location)
57 self.set_header('Location', location)
58 self.set_header('Last-Modified', model['last_modified'])
58 self.set_header('Last-Modified', model['last_modified'])
59 self.finish(json.dumps(model, default=date_default))
59 self.finish(json.dumps(model, default=date_default))
60
60
61 @web.authenticated
61 @web.authenticated
62 @json_errors
62 @json_errors
63 def get(self, path='', name=None):
63 def get(self, path='', name=None):
@@ -99,10 +99,10 b' class NotebookHandler(IPythonHandler):'
99 raise web.HTTPError(400, u'JSON body missing')
99 raise web.HTTPError(400, u'JSON body missing')
100 model = nbm.update_notebook(model, name, path)
100 model = nbm.update_notebook(model, name, path)
101 self._finish_model(model)
101 self._finish_model(model)
102
102
103 def _copy_notebook(self, copy_from, path, copy_to=None):
103 def _copy_notebook(self, copy_from, path, copy_to=None):
104 """Copy a notebook in path, optionally specifying the new name.
104 """Copy a notebook in path, optionally specifying the new name.
105
105
106 Only support copying within the same directory.
106 Only support copying within the same directory.
107 """
107 """
108 self.log.info(u"Copying notebook from %s/%s to %s/%s",
108 self.log.info(u"Copying notebook from %s/%s to %s/%s",
@@ -112,23 +112,23 b' class NotebookHandler(IPythonHandler):'
112 model = self.notebook_manager.copy_notebook(copy_from, copy_to, path)
112 model = self.notebook_manager.copy_notebook(copy_from, copy_to, path)
113 self.set_status(201)
113 self.set_status(201)
114 self._finish_model(model)
114 self._finish_model(model)
115
115
116 def _upload_notebook(self, model, path, name=None):
116 def _upload_notebook(self, model, path, name=None):
117 """Upload a notebook
117 """Upload a notebook
118
118
119 If name specified, create it in path/name.
119 If name specified, create it in path/name.
120 """
120 """
121 self.log.info(u"Uploading notebook to %s/%s", path, name or '')
121 self.log.info(u"Uploading notebook to %s/%s", path, name or '')
122 if name:
122 if name:
123 model['name'] = name
123 model['name'] = name
124
124
125 model = self.notebook_manager.create_notebook(model, path)
125 model = self.notebook_manager.create_notebook(model, path)
126 self.set_status(201)
126 self.set_status(201)
127 self._finish_model(model)
127 self._finish_model(model)
128
128
129 def _create_empty_notebook(self, path, name=None):
129 def _create_empty_notebook(self, path, name=None):
130 """Create an empty notebook in path
130 """Create an empty notebook in path
131
131
132 If name specified, create it in path/name.
132 If name specified, create it in path/name.
133 """
133 """
134 self.log.info(u"Creating new notebook in %s/%s", path, name or '')
134 self.log.info(u"Creating new notebook in %s/%s", path, name or '')
@@ -138,7 +138,7 b' class NotebookHandler(IPythonHandler):'
138 model = self.notebook_manager.create_notebook(model, path=path)
138 model = self.notebook_manager.create_notebook(model, path=path)
139 self.set_status(201)
139 self.set_status(201)
140 self._finish_model(model)
140 self._finish_model(model)
141
141
142 def _save_notebook(self, model, path, name):
142 def _save_notebook(self, model, path, name):
143 """Save an existing notebook."""
143 """Save an existing notebook."""
144 self.log.info(u"Saving notebook at %s/%s", path, name)
144 self.log.info(u"Saving notebook at %s/%s", path, name)
@@ -149,26 +149,26 b' class NotebookHandler(IPythonHandler):'
149 else:
149 else:
150 location = False
150 location = False
151 self._finish_model(model, location)
151 self._finish_model(model, location)
152
152
153 @web.authenticated
153 @web.authenticated
154 @json_errors
154 @json_errors
155 def post(self, path='', name=None):
155 def post(self, path='', name=None):
156 """Create a new notebook in the specified path.
156 """Create a new notebook in the specified path.
157
157
158 POST creates new notebooks. The server always decides on the notebook name.
158 POST creates new notebooks. The server always decides on the notebook name.
159
159
160 POST /api/notebooks/path
160 POST /api/notebooks/path
161 New untitled notebook in path. If content specified, upload a
161 New untitled notebook in path. If content specified, upload a
162 notebook, otherwise start empty.
162 notebook, otherwise start empty.
163 POST /api/notebooks/path?copy=OtherNotebook.ipynb
163 POST /api/notebooks/path?copy=OtherNotebook.ipynb
164 New copy of OtherNotebook in path
164 New copy of OtherNotebook in path
165 """
165 """
166
166
167 if name is not None:
167 if name is not None:
168 raise web.HTTPError(400, "Only POST to directories. Use PUT for full names.")
168 raise web.HTTPError(400, "Only POST to directories. Use PUT for full names.")
169
169
170 model = self.get_json_body()
170 model = self.get_json_body()
171
171
172 if model is not None:
172 if model is not None:
173 copy_from = model.get('copy_from')
173 copy_from = model.get('copy_from')
174 if copy_from:
174 if copy_from:
@@ -184,10 +184,10 b' class NotebookHandler(IPythonHandler):'
184 @json_errors
184 @json_errors
185 def put(self, path='', name=None):
185 def put(self, path='', name=None):
186 """Saves the notebook in the location specified by name and path.
186 """Saves the notebook in the location specified by name and path.
187
187
188 PUT is very similar to POST, but the requester specifies the name,
188 PUT is very similar to POST, but the requester specifies the name,
189 whereas with POST, the server picks the name.
189 whereas with POST, the server picks the name.
190
190
191 PUT /api/notebooks/path/Name.ipynb
191 PUT /api/notebooks/path/Name.ipynb
192 Save notebook at ``path/Name.ipynb``. Notebook structure is specified
192 Save notebook at ``path/Name.ipynb``. Notebook structure is specified
193 in `content` key of JSON request body. If content is not specified,
193 in `content` key of JSON request body. If content is not specified,
@@ -197,7 +197,7 b' class NotebookHandler(IPythonHandler):'
197 """
197 """
198 if name is None:
198 if name is None:
199 raise web.HTTPError(400, "Only PUT to full names. Use POST for directories.")
199 raise web.HTTPError(400, "Only PUT to full names. Use POST for directories.")
200
200
201 model = self.get_json_body()
201 model = self.get_json_body()
202 if model:
202 if model:
203 copy_from = model.get('copy_from')
203 copy_from = model.get('copy_from')
@@ -223,9 +223,9 b' class NotebookHandler(IPythonHandler):'
223
223
224
224
225 class NotebookCheckpointsHandler(IPythonHandler):
225 class NotebookCheckpointsHandler(IPythonHandler):
226
226
227 SUPPORTED_METHODS = ('GET', 'POST')
227 SUPPORTED_METHODS = ('GET', 'POST')
228
228
229 @web.authenticated
229 @web.authenticated
230 @json_errors
230 @json_errors
231 def get(self, path='', name=None):
231 def get(self, path='', name=None):
@@ -234,7 +234,7 b' class NotebookCheckpointsHandler(IPythonHandler):'
234 checkpoints = nbm.list_checkpoints(name, path)
234 checkpoints = nbm.list_checkpoints(name, path)
235 data = json.dumps(checkpoints, default=date_default)
235 data = json.dumps(checkpoints, default=date_default)
236 self.finish(data)
236 self.finish(data)
237
237
238 @web.authenticated
238 @web.authenticated
239 @json_errors
239 @json_errors
240 def post(self, path='', name=None):
240 def post(self, path='', name=None):
@@ -250,9 +250,9 b' class NotebookCheckpointsHandler(IPythonHandler):'
250
250
251
251
252 class ModifyNotebookCheckpointsHandler(IPythonHandler):
252 class ModifyNotebookCheckpointsHandler(IPythonHandler):
253
253
254 SUPPORTED_METHODS = ('POST', 'DELETE')
254 SUPPORTED_METHODS = ('POST', 'DELETE')
255
255
256 @web.authenticated
256 @web.authenticated
257 @json_errors
257 @json_errors
258 def post(self, path, name, checkpoint_id):
258 def post(self, path, name, checkpoint_id):
@@ -261,7 +261,7 b' class ModifyNotebookCheckpointsHandler(IPythonHandler):'
261 nbm.restore_checkpoint(checkpoint_id, name, path)
261 nbm.restore_checkpoint(checkpoint_id, name, path)
262 self.set_status(204)
262 self.set_status(204)
263 self.finish()
263 self.finish()
264
264
265 @web.authenticated
265 @web.authenticated
266 @json_errors
266 @json_errors
267 def delete(self, path, name, checkpoint_id):
267 def delete(self, path, name, checkpoint_id):
@@ -270,7 +270,7 b' class ModifyNotebookCheckpointsHandler(IPythonHandler):'
270 nbm.delete_checkpoint(checkpoint_id, name, path)
270 nbm.delete_checkpoint(checkpoint_id, name, path)
271 self.set_status(204)
271 self.set_status(204)
272 self.finish()
272 self.finish()
273
273
274 #-----------------------------------------------------------------------------
274 #-----------------------------------------------------------------------------
275 # URL to handler mappings
275 # URL to handler mappings
276 #-----------------------------------------------------------------------------
276 #-----------------------------------------------------------------------------
@@ -285,4 +285,3 b' default_handlers = ['
285 (r"/api/notebooks%s" % notebook_path_regex, NotebookHandler),
285 (r"/api/notebooks%s" % notebook_path_regex, NotebookHandler),
286 (r"/api/notebooks%s" % path_regex, NotebookHandler),
286 (r"/api/notebooks%s" % path_regex, NotebookHandler),
287 ]
287 ]
288
@@ -32,11 +32,11 b' from IPython.utils.traitlets import Instance, Unicode, List'
32 class NotebookManager(LoggingConfigurable):
32 class NotebookManager(LoggingConfigurable):
33
33
34 filename_ext = Unicode(u'.ipynb')
34 filename_ext = Unicode(u'.ipynb')
35
35
36 notary = Instance(sign.NotebookNotary)
36 notary = Instance(sign.NotebookNotary)
37 def _notary_default(self):
37 def _notary_default(self):
38 return sign.NotebookNotary(parent=self)
38 return sign.NotebookNotary(parent=self)
39
39
40 hide_globs = List(Unicode, [u'__pycache__'], config=True, help="""
40 hide_globs = List(Unicode, [u'__pycache__'], config=True, help="""
41 Glob patterns to hide in file and directory listings.
41 Glob patterns to hide in file and directory listings.
42 """)
42 """)
@@ -46,14 +46,14 b' class NotebookManager(LoggingConfigurable):'
46
46
47 def path_exists(self, path):
47 def path_exists(self, path):
48 """Does the API-style path (directory) actually exist?
48 """Does the API-style path (directory) actually exist?
49
49
50 Override this method in subclasses.
50 Override this method in subclasses.
51
51
52 Parameters
52 Parameters
53 ----------
53 ----------
54 path : string
54 path : string
55 The path to check
55 The path to check
56
56
57 Returns
57 Returns
58 -------
58 -------
59 exists : bool
59 exists : bool
@@ -63,18 +63,18 b' class NotebookManager(LoggingConfigurable):'
63
63
64 def is_hidden(self, path):
64 def is_hidden(self, path):
65 """Does the API style path correspond to a hidden directory or file?
65 """Does the API style path correspond to a hidden directory or file?
66
66
67 Parameters
67 Parameters
68 ----------
68 ----------
69 path : string
69 path : string
70 The path to check. This is an API path (`/` separated,
70 The path to check. This is an API path (`/` separated,
71 relative to base notebook-dir).
71 relative to base notebook-dir).
72
72
73 Returns
73 Returns
74 -------
74 -------
75 exists : bool
75 exists : bool
76 Whether the path is hidden.
76 Whether the path is hidden.
77
77
78 """
78 """
79 raise NotImplementedError
79 raise NotImplementedError
80
80
@@ -104,7 +104,7 b' class NotebookManager(LoggingConfigurable):'
104 # no longer listed by the notebook web service.
104 # no longer listed by the notebook web service.
105 def get_dir_model(self, name, path=''):
105 def get_dir_model(self, name, path=''):
106 """Get the directory model given a directory name and its API style path.
106 """Get the directory model given a directory name and its API style path.
107
107
108 The keys in the model should be:
108 The keys in the model should be:
109 * name
109 * name
110 * path
110 * path
@@ -145,15 +145,15 b' class NotebookManager(LoggingConfigurable):'
145
145
146 def create_checkpoint(self, name, path=''):
146 def create_checkpoint(self, name, path=''):
147 """Create a checkpoint of the current state of a notebook
147 """Create a checkpoint of the current state of a notebook
148
148
149 Returns a checkpoint_id for the new checkpoint.
149 Returns a checkpoint_id for the new checkpoint.
150 """
150 """
151 raise NotImplementedError("must be implemented in a subclass")
151 raise NotImplementedError("must be implemented in a subclass")
152
152
153 def list_checkpoints(self, name, path=''):
153 def list_checkpoints(self, name, path=''):
154 """Return a list of checkpoints for a given notebook"""
154 """Return a list of checkpoints for a given notebook"""
155 return []
155 return []
156
156
157 def restore_checkpoint(self, checkpoint_id, name, path=''):
157 def restore_checkpoint(self, checkpoint_id, name, path=''):
158 """Restore a notebook from one of its checkpoints"""
158 """Restore a notebook from one of its checkpoints"""
159 raise NotImplementedError("must be implemented in a subclass")
159 raise NotImplementedError("must be implemented in a subclass")
@@ -161,7 +161,7 b' class NotebookManager(LoggingConfigurable):'
161 def delete_checkpoint(self, checkpoint_id, name, path=''):
161 def delete_checkpoint(self, checkpoint_id, name, path=''):
162 """delete a checkpoint for a notebook"""
162 """delete a checkpoint for a notebook"""
163 raise NotImplementedError("must be implemented in a subclass")
163 raise NotImplementedError("must be implemented in a subclass")
164
164
165 def info_string(self):
165 def info_string(self):
166 return "Serving notebooks"
166 return "Serving notebooks"
167
167
@@ -174,7 +174,7 b' class NotebookManager(LoggingConfigurable):'
174
174
175 def increment_filename(self, basename, path=''):
175 def increment_filename(self, basename, path=''):
176 """Increment a notebook filename without the .ipynb to make it unique.
176 """Increment a notebook filename without the .ipynb to make it unique.
177
177
178 Parameters
178 Parameters
179 ----------
179 ----------
180 basename : unicode
180 basename : unicode
@@ -206,14 +206,14 b' class NotebookManager(LoggingConfigurable):'
206 model['content'] = current.new_notebook(metadata=metadata)
206 model['content'] = current.new_notebook(metadata=metadata)
207 if 'name' not in model:
207 if 'name' not in model:
208 model['name'] = self.increment_filename('Untitled', path)
208 model['name'] = self.increment_filename('Untitled', path)
209
209
210 model['path'] = path
210 model['path'] = path
211 model = self.save_notebook(model, model['name'], model['path'])
211 model = self.save_notebook(model, model['name'], model['path'])
212 return model
212 return model
213
213
214 def copy_notebook(self, from_name, to_name=None, path=''):
214 def copy_notebook(self, from_name, to_name=None, path=''):
215 """Copy an existing notebook and return its new model.
215 """Copy an existing notebook and return its new model.
216
216
217 If to_name not specified, increment `from_name-Copy#.ipynb`.
217 If to_name not specified, increment `from_name-Copy#.ipynb`.
218 """
218 """
219 path = path.strip('/')
219 path = path.strip('/')
@@ -224,13 +224,13 b' class NotebookManager(LoggingConfigurable):'
224 model['name'] = to_name
224 model['name'] = to_name
225 model = self.save_notebook(model, to_name, path)
225 model = self.save_notebook(model, to_name, path)
226 return model
226 return model
227
227
228 def log_info(self):
228 def log_info(self):
229 self.log.info(self.info_string())
229 self.log.info(self.info_string())
230
230
231 def trust_notebook(self, name, path=''):
231 def trust_notebook(self, name, path=''):
232 """Explicitly trust a notebook
232 """Explicitly trust a notebook
233
233
234 Parameters
234 Parameters
235 ----------
235 ----------
236 name : string
236 name : string
@@ -243,12 +243,12 b' class NotebookManager(LoggingConfigurable):'
243 self.log.warn("Trusting notebook %s/%s", path, name)
243 self.log.warn("Trusting notebook %s/%s", path, name)
244 self.notary.mark_cells(nb, True)
244 self.notary.mark_cells(nb, True)
245 self.save_notebook(model, name, path)
245 self.save_notebook(model, name, path)
246
246
247 def check_and_sign(self, nb, name, path=''):
247 def check_and_sign(self, nb, name, path=''):
248 """Check for trusted cells, and sign the notebook.
248 """Check for trusted cells, and sign the notebook.
249
249
250 Called as a part of saving notebooks.
250 Called as a part of saving notebooks.
251
251
252 Parameters
252 Parameters
253 ----------
253 ----------
254 nb : dict
254 nb : dict
@@ -262,12 +262,12 b' class NotebookManager(LoggingConfigurable):'
262 self.notary.sign(nb)
262 self.notary.sign(nb)
263 else:
263 else:
264 self.log.warn("Saving untrusted notebook %s/%s", path, name)
264 self.log.warn("Saving untrusted notebook %s/%s", path, name)
265
265
266 def mark_trusted_cells(self, nb, name, path=''):
266 def mark_trusted_cells(self, nb, name, path=''):
267 """Mark cells as trusted if the notebook signature matches.
267 """Mark cells as trusted if the notebook signature matches.
268
268
269 Called as a part of loading notebooks.
269 Called as a part of loading notebooks.
270
270
271 Parameters
271 Parameters
272 ----------
272 ----------
273 nb : dict
273 nb : dict
1 NO CONTENT: file renamed from IPython/html/services/notebooks/tests/__init__.py to IPython/html/services/contents/tests/__init__.py
NO CONTENT: file renamed from IPython/html/services/notebooks/tests/__init__.py to IPython/html/services/contents/tests/__init__.py
@@ -55,7 +55,7 b' class TestFileNotebookManager(TestCase):'
55 path = fm._get_os_path('test.ipynb', '////')
55 path = fm._get_os_path('test.ipynb', '////')
56 fs_path = os.path.join(fm.notebook_dir, 'test.ipynb')
56 fs_path = os.path.join(fm.notebook_dir, 'test.ipynb')
57 self.assertEqual(path, fs_path)
57 self.assertEqual(path, fs_path)
58
58
59 def test_checkpoint_subdir(self):
59 def test_checkpoint_subdir(self):
60 subd = u'sub ∂ir'
60 subd = u'sub ∂ir'
61 cp_name = 'test-cp.ipynb'
61 cp_name = 'test-cp.ipynb'
@@ -68,10 +68,10 b' class TestFileNotebookManager(TestCase):'
68 self.assertNotEqual(cp_dir, cp_subdir)
68 self.assertNotEqual(cp_dir, cp_subdir)
69 self.assertEqual(cp_dir, os.path.join(nbdir, fm.checkpoint_dir, cp_name))
69 self.assertEqual(cp_dir, os.path.join(nbdir, fm.checkpoint_dir, cp_name))
70 self.assertEqual(cp_subdir, os.path.join(nbdir, subd, fm.checkpoint_dir, cp_name))
70 self.assertEqual(cp_subdir, os.path.join(nbdir, subd, fm.checkpoint_dir, cp_name))
71
71
72
72
73 class TestNotebookManager(TestCase):
73 class TestNotebookManager(TestCase):
74
74
75 def setUp(self):
75 def setUp(self):
76 self._temp_dir = TemporaryDirectory()
76 self._temp_dir = TemporaryDirectory()
77 self.td = self._temp_dir.name
77 self.td = self._temp_dir.name
@@ -79,10 +79,10 b' class TestNotebookManager(TestCase):'
79 notebook_dir=self.td,
79 notebook_dir=self.td,
80 log=logging.getLogger()
80 log=logging.getLogger()
81 )
81 )
82
82
83 def tearDown(self):
83 def tearDown(self):
84 self._temp_dir.cleanup()
84 self._temp_dir.cleanup()
85
85
86 def make_dir(self, abs_path, rel_path):
86 def make_dir(self, abs_path, rel_path):
87 """make subdirectory, rel_path is the relative path
87 """make subdirectory, rel_path is the relative path
88 to that directory from the location where the server started"""
88 to that directory from the location where the server started"""
@@ -91,27 +91,27 b' class TestNotebookManager(TestCase):'
91 os.makedirs(os_path)
91 os.makedirs(os_path)
92 except OSError:
92 except OSError:
93 print("Directory already exists: %r" % os_path)
93 print("Directory already exists: %r" % os_path)
94
94
95 def add_code_cell(self, nb):
95 def add_code_cell(self, nb):
96 output = current.new_output("display_data", output_javascript="alert('hi');")
96 output = current.new_output("display_data", output_javascript="alert('hi');")
97 cell = current.new_code_cell("print('hi')", outputs=[output])
97 cell = current.new_code_cell("print('hi')", outputs=[output])
98 if not nb.worksheets:
98 if not nb.worksheets:
99 nb.worksheets.append(current.new_worksheet())
99 nb.worksheets.append(current.new_worksheet())
100 nb.worksheets[0].cells.append(cell)
100 nb.worksheets[0].cells.append(cell)
101
101
102 def new_notebook(self):
102 def new_notebook(self):
103 nbm = self.notebook_manager
103 nbm = self.notebook_manager
104 model = nbm.create_notebook()
104 model = nbm.create_notebook()
105 name = model['name']
105 name = model['name']
106 path = model['path']
106 path = model['path']
107
107
108 full_model = nbm.get_notebook(name, path)
108 full_model = nbm.get_notebook(name, path)
109 nb = full_model['content']
109 nb = full_model['content']
110 self.add_code_cell(nb)
110 self.add_code_cell(nb)
111
111
112 nbm.save_notebook(full_model, name, path)
112 nbm.save_notebook(full_model, name, path)
113 return nb, name, path
113 return nb, name, path
114
114
115 def test_create_notebook(self):
115 def test_create_notebook(self):
116 nm = self.notebook_manager
116 nm = self.notebook_manager
117 # Test in root directory
117 # Test in root directory
@@ -158,7 +158,7 b' class TestNotebookManager(TestCase):'
158 self.assertIn('content', model2)
158 self.assertIn('content', model2)
159 self.assertEqual(model2['name'], 'Untitled0.ipynb')
159 self.assertEqual(model2['name'], 'Untitled0.ipynb')
160 self.assertEqual(model2['path'], sub_dir.strip('/'))
160 self.assertEqual(model2['path'], sub_dir.strip('/'))
161
161
162 def test_update_notebook(self):
162 def test_update_notebook(self):
163 nm = self.notebook_manager
163 nm = self.notebook_manager
164 # Create a notebook
164 # Create a notebook
@@ -184,7 +184,7 b' class TestNotebookManager(TestCase):'
184 model = nm.create_notebook(None, sub_dir)
184 model = nm.create_notebook(None, sub_dir)
185 name = model['name']
185 name = model['name']
186 path = model['path']
186 path = model['path']
187
187
188 # Change the name in the model for rename
188 # Change the name in the model for rename
189 model['name'] = 'test_in_sub.ipynb'
189 model['name'] = 'test_in_sub.ipynb'
190 model = nm.update_notebook(model, name, path)
190 model = nm.update_notebook(model, name, path)
@@ -193,7 +193,7 b' class TestNotebookManager(TestCase):'
193 self.assertIn('path', model)
193 self.assertIn('path', model)
194 self.assertEqual(model['name'], 'test_in_sub.ipynb')
194 self.assertEqual(model['name'], 'test_in_sub.ipynb')
195 self.assertEqual(model['path'], sub_dir.strip('/'))
195 self.assertEqual(model['path'], sub_dir.strip('/'))
196
196
197 # Make sure the old name is gone
197 # Make sure the old name is gone
198 self.assertRaises(HTTPError, nm.get_notebook, name, path)
198 self.assertRaises(HTTPError, nm.get_notebook, name, path)
199
199
@@ -255,50 +255,50 b' class TestNotebookManager(TestCase):'
255 nm = self.notebook_manager
255 nm = self.notebook_manager
256 # Create a notebook
256 # Create a notebook
257 nb, name, path = self.new_notebook()
257 nb, name, path = self.new_notebook()
258
258
259 # Delete the notebook
259 # Delete the notebook
260 nm.delete_notebook(name, path)
260 nm.delete_notebook(name, path)
261
261
262 # Check that a 'get' on the deleted notebook raises and error
262 # Check that a 'get' on the deleted notebook raises and error
263 self.assertRaises(HTTPError, nm.get_notebook, name, path)
263 self.assertRaises(HTTPError, nm.get_notebook, name, path)
264
264
265 def test_copy_notebook(self):
265 def test_copy_notebook(self):
266 nm = self.notebook_manager
266 nm = self.notebook_manager
267 path = u'å b'
267 path = u'å b'
268 name = u'nb √.ipynb'
268 name = u'nb √.ipynb'
269 os.mkdir(os.path.join(nm.notebook_dir, path))
269 os.mkdir(os.path.join(nm.notebook_dir, path))
270 orig = nm.create_notebook({'name' : name}, path=path)
270 orig = nm.create_notebook({'name' : name}, path=path)
271
271
272 # copy with unspecified name
272 # copy with unspecified name
273 copy = nm.copy_notebook(name, path=path)
273 copy = nm.copy_notebook(name, path=path)
274 self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy0.ipynb'))
274 self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy0.ipynb'))
275
275
276 # copy with specified name
276 # copy with specified name
277 copy2 = nm.copy_notebook(name, u'copy 2.ipynb', path=path)
277 copy2 = nm.copy_notebook(name, u'copy 2.ipynb', path=path)
278 self.assertEqual(copy2['name'], u'copy 2.ipynb')
278 self.assertEqual(copy2['name'], u'copy 2.ipynb')
279
279
280 def test_trust_notebook(self):
280 def test_trust_notebook(self):
281 nbm = self.notebook_manager
281 nbm = self.notebook_manager
282 nb, name, path = self.new_notebook()
282 nb, name, path = self.new_notebook()
283
283
284 untrusted = nbm.get_notebook(name, path)['content']
284 untrusted = nbm.get_notebook(name, path)['content']
285 assert not nbm.notary.check_cells(untrusted)
285 assert not nbm.notary.check_cells(untrusted)
286
286
287 # print(untrusted)
287 # print(untrusted)
288 nbm.trust_notebook(name, path)
288 nbm.trust_notebook(name, path)
289 trusted = nbm.get_notebook(name, path)['content']
289 trusted = nbm.get_notebook(name, path)['content']
290 # print(trusted)
290 # print(trusted)
291 assert nbm.notary.check_cells(trusted)
291 assert nbm.notary.check_cells(trusted)
292
292
293 def test_mark_trusted_cells(self):
293 def test_mark_trusted_cells(self):
294 nbm = self.notebook_manager
294 nbm = self.notebook_manager
295 nb, name, path = self.new_notebook()
295 nb, name, path = self.new_notebook()
296
296
297 nbm.mark_trusted_cells(nb, name, path)
297 nbm.mark_trusted_cells(nb, name, path)
298 for cell in nb.worksheets[0].cells:
298 for cell in nb.worksheets[0].cells:
299 if cell.cell_type == 'code':
299 if cell.cell_type == 'code':
300 assert not cell.trusted
300 assert not cell.trusted
301
301
302 nbm.trust_notebook(name, path)
302 nbm.trust_notebook(name, path)
303 nb = nbm.get_notebook(name, path)['content']
303 nb = nbm.get_notebook(name, path)['content']
304 for cell in nb.worksheets[0].cells:
304 for cell in nb.worksheets[0].cells:
@@ -308,11 +308,11 b' class TestNotebookManager(TestCase):'
308 def test_check_and_sign(self):
308 def test_check_and_sign(self):
309 nbm = self.notebook_manager
309 nbm = self.notebook_manager
310 nb, name, path = self.new_notebook()
310 nb, name, path = self.new_notebook()
311
311
312 nbm.mark_trusted_cells(nb, name, path)
312 nbm.mark_trusted_cells(nb, name, path)
313 nbm.check_and_sign(nb, name, path)
313 nbm.check_and_sign(nb, name, path)
314 assert not nbm.notary.check_signature(nb)
314 assert not nbm.notary.check_signature(nb)
315
315
316 nbm.trust_notebook(name, path)
316 nbm.trust_notebook(name, path)
317 nb = nbm.get_notebook(name, path)['content']
317 nb = nbm.get_notebook(name, path)['content']
318 nbm.mark_trusted_cells(nb, name, path)
318 nbm.mark_trusted_cells(nb, name, path)
@@ -163,7 +163,7 b' class APITest(NotebookTestBase):'
163 expected = [ u'a.ipynb', u'b.ipynb', u'name with spaces.ipynb', u'unicodé.ipynb']
163 expected = [ u'a.ipynb', u'b.ipynb', u'name with spaces.ipynb', u'unicodé.ipynb']
164 expected = { normalize('NFC', name) for name in expected }
164 expected = { normalize('NFC', name) for name in expected }
165 self.assertEqual(nbnames, expected)
165 self.assertEqual(nbnames, expected)
166
166
167 nbs = notebooks_only(self.nb_api.list('ordering').json())
167 nbs = notebooks_only(self.nb_api.list('ordering').json())
168 nbnames = [n['name'] for n in nbs]
168 nbnames = [n['name'] for n in nbs]
169 expected = ['A.ipynb', 'b.ipynb', 'C.ipynb']
169 expected = ['A.ipynb', 'b.ipynb', 'C.ipynb']
@@ -344,4 +344,3 b' class APITest(NotebookTestBase):'
344 self.assertEqual(r.status_code, 204)
344 self.assertEqual(r.status_code, 204)
345 cps = self.nb_api.get_checkpoints('a.ipynb', 'foo').json()
345 cps = self.nb_api.get_checkpoints('a.ipynb', 'foo').json()
346 self.assertEqual(cps, [])
346 self.assertEqual(cps, [])
347
General Comments 0
You need to be logged in to leave comments. Login now