##// END OF EJS Templates
Expose ConfigManager one level up the hierarchy...
Expose ConfigManager one level up the hierarchy Because `from IPython.html.services.config import ConfigManager` is long enough.

File last commit:

r18835:b7c85f43 merge
r19162:ee8f49f3
Show More
manager.py
380 lines | 11.6 KiB | text/x-python | PythonLexer
MinRK
rename notebooks service to contents service...
r17524 """A base class for contents managers."""
Brian Granger
Refactoring notebook managers and adding Azure backed storage....
r8180
MinRK
rename notebooks service to contents service...
r17524 # Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
Brian Granger
Refactoring notebook managers and adding Azure backed storage....
r8180
Thomas Kluyver
Make hidden directories configurable
r15525 from fnmatch import fnmatch
Konrad Hinsen
Move method increment_filename from FileNotebookManager to NotebookManager...
r15292 import itertools
MinRK
add dialogs for failed save/load...
r18249 import json
Brian Granger
Fixing minor things for the Azure backed nb storage.
r8181 import os
Min RK
adjustments to filename increment...
r18813 import re
Brian Granger
Refactoring notebook managers and adding Azure backed storage....
r8180
MinRK
support deleting empty directories...
r17530 from tornado.web import HTTPError
Brian Granger
Refactoring notebook managers and adding Azure backed storage....
r8180 from IPython.config.configurable import LoggingConfigurable
MinRK
don't use nbformat.current in IPython.html...
r18607 from IPython.nbformat import sign, validate, ValidationError
from IPython.nbformat.v4 import new_notebook
Thomas Kluyver
Make hidden directories configurable
r15525 from IPython.utils.traitlets import Instance, Unicode, List
Brian Granger
Refactoring notebook managers and adding Azure backed storage....
r8180
Min RK
adjustments to filename increment...
r18813 copy_pat = re.compile(r'\-Copy\d*\.')
Brian Granger
Refactoring notebook managers and adding Azure backed storage....
r8180
MinRK
rename notebooks service to contents service...
r17524 class ContentsManager(LoggingConfigurable):
MinRK
updates per review...
r17535 """Base class for serving files and directories.
This serves any text or binary file,
as well as directories,
with special handling for JSON notebook documents.
Most APIs take a path argument,
which is always an API-style unicode path,
and always refers to a directory.
- unicode, not url-escaped
- '/'-separated
- leading and trailing '/' will be stripped
- if unspecified, path defaults to '',
indicating the root path.
"""
MinRK
mv services/notebooks services/contents
r17523
MinRK
add nbformat.sign.NotebookNotary
r14857 notary = Instance(sign.NotebookNotary)
def _notary_default(self):
return sign.NotebookNotary(parent=self)
MinRK
mv services/notebooks services/contents
r17523
MinRK
contents service review...
r17529 hide_globs = List(Unicode, [
u'__pycache__', '*.pyc', '*.pyo',
'.DS_Store', '*.so', '*.dylib', '*~',
], config=True, help="""
Thomas Kluyver
Make hidden directories configurable
r15525 Glob patterns to hide in file and directory listings.
""")
MinRK
updates per review...
r17535 untitled_notebook = Unicode("Untitled", config=True,
help="The base name used when creating untitled notebooks."
)
untitled_file = Unicode("untitled", config=True,
help="The base name used when creating untitled files."
)
untitled_directory = Unicode("Untitled Folder", config=True,
help="The base name used when creating untitled directories."
)
MinRK
rename notebooks service to contents service...
r17524 # ContentsManager API part 1: methods that must be
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 # implemented in subclasses.
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 def dir_exists(self, path):
MinRK
adjust definition of 'path' in notebooks...
r13067 """Does the API-style path (directory) actually exist?
MinRK
mv services/notebooks services/contents
r17523
MinRK
updates per review...
r17535 Like os.path.isdir
MinRK
move os_path to FileNBMan...
r13070 Override this method in subclasses.
MinRK
mv services/notebooks services/contents
r17523
Paul Ivanov
cleaning up named_notebook_path
r13026 Parameters
----------
MinRK
adjust definition of 'path' in notebooks...
r13067 path : string
MinRK
trust method docstrings
r15664 The path to check
MinRK
mv services/notebooks services/contents
r17523
Paul Ivanov
cleaning up named_notebook_path
r13026 Returns
-------
MinRK
adjust definition of 'path' in notebooks...
r13067 exists : bool
Whether the path does indeed exist.
Paul Ivanov
cleaning up named_notebook_path
r13026 """
MinRK
move os_path to FileNBMan...
r13070 raise NotImplementedError
Brian E. Granger
Creating and testing IPython.html.utils.is_hidden.
r15097
def is_hidden(self, path):
"""Does the API style path correspond to a hidden directory or file?
MinRK
mv services/notebooks services/contents
r17523
Brian E. Granger
Creating and testing IPython.html.utils.is_hidden.
r15097 Parameters
----------
path : string
The path to check. This is an API path (`/` separated,
MinRK
rename notebooks service to contents service...
r17524 relative to root dir).
MinRK
mv services/notebooks services/contents
r17523
Brian E. Granger
Creating and testing IPython.html.utils.is_hidden.
r15097 Returns
-------
MinRK
updates per review...
r17535 hidden : bool
Brian E. Granger
Creating and testing IPython.html.utils.is_hidden.
r15097 Whether the path is hidden.
MinRK
mv services/notebooks services/contents
r17523
Brian E. Granger
Creating and testing IPython.html.utils.is_hidden.
r15097 """
raise NotImplementedError
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 def file_exists(self, path=''):
"""Does a file exist at the given path?
MinRK
updates per review...
r17535
Like os.path.isfile
Override this method in subclasses.
Konrad Hinsen
Add method notebook_exists to NotebookManager....
r15291
Parameters
----------
name : string
MinRK
contents service review...
r17529 The name of the file you are checking.
Konrad Hinsen
Add method notebook_exists to NotebookManager....
r15291 path : string
MinRK
contents service review...
r17529 The relative path to the file's directory (with '/' as separator)
Konrad Hinsen
Add method notebook_exists to NotebookManager....
r15291
Returns
-------
MinRK
updates per review...
r17535 exists : bool
Whether the file exists.
Konrad Hinsen
Add method notebook_exists to NotebookManager....
r15291 """
raise NotImplementedError('must be implemented in a subclass')
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 def exists(self, path):
Min RK
address review in contents service...
r18758 """Does a file or directory exist at the given path?
Brian Granger
Refactoring notebook managers and adding Azure backed storage....
r8180
MinRK
updates per review...
r17535 Like os.path.exists
Brian Granger
Refactoring notebook managers and adding Azure backed storage....
r8180
MinRK
updates per review...
r17535 Parameters
----------
path : string
The relative path to the file's directory (with '/' as separator)
Brian Granger
Refactoring notebook managers and adding Azure backed storage....
r8180
MinRK
updates per review...
r17535 Returns
-------
exists : bool
Whether the target exists.
Brian Granger
Refactoring notebook managers and adding Azure backed storage....
r8180 """
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 return self.file_exists(path) or self.dir_exists(path)
Brian Granger
Refactoring notebook managers and adding Azure backed storage....
r8180
Thomas Kluyver
Rename get_model() to get()
r18791 def get(self, path, content=True, type_=None, format=None):
MinRK
contents service review...
r17529 """Get the model of a file or directory with or without content."""
Brian Granger
Refactoring notebook managers and adding Azure backed storage....
r8180 raise NotImplementedError('must be implemented in a subclass')
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 def save(self, model, path):
MinRK
contents service review...
r17529 """Save the file or directory and return the model with no content."""
Zachary Sailer
refactoring of nbmanager and filenbmanager...
r13046 raise NotImplementedError('must be implemented in a subclass')
Brian Granger
Refactoring notebook managers and adding Azure backed storage....
r8180
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 def update(self, model, path):
MinRK
updates per review...
r17535 """Update the file or directory and return the model with no content.
For use in PATCH requests, to enable renaming a file without
re-uploading its contents. Only used for renaming at the moment.
"""
Brian Granger
Refactoring notebook managers and adding Azure backed storage....
r8180 raise NotImplementedError('must be implemented in a subclass')
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 def delete(self, path):
"""Delete file or directory by path."""
Brian Granger
Refactoring notebook managers and adding Azure backed storage....
r8180 raise NotImplementedError('must be implemented in a subclass')
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 def create_checkpoint(self, path):
MinRK
contents service review...
r17529 """Create a checkpoint of the current state of a file
MinRK
mv services/notebooks services/contents
r17523
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 Returns a checkpoint_id for the new checkpoint.
"""
raise NotImplementedError("must be implemented in a subclass")
MinRK
mv services/notebooks services/contents
r17523
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 def list_checkpoints(self, path):
MinRK
contents service review...
r17529 """Return a list of checkpoints for a given file"""
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 return []
MinRK
mv services/notebooks services/contents
r17523
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 def restore_checkpoint(self, checkpoint_id, path):
MinRK
contents service review...
r17529 """Restore a file from one of its checkpoints"""
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 raise NotImplementedError("must be implemented in a subclass")
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 def delete_checkpoint(self, checkpoint_id, path):
MinRK
contents service review...
r17529 """delete a checkpoint for a file"""
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 raise NotImplementedError("must be implemented in a subclass")
MinRK
mv services/notebooks services/contents
r17523
MinRK
rename notebooks service to contents service...
r17524 # ContentsManager API part 2: methods that have useable default
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 # implementations, but can be overridden in subclasses.
MinRK
updates per review...
r17535 def info_string(self):
return "Serving contents"
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 def get_kernel_path(self, path, model=None):
Min RK
address review in contents service...
r18758 """Return the API path for the kernel
KernelManagers can turn this value into a filesystem path,
or ignore it altogether.
"""
Dale Jung
API: Allow NotebookManagers to control kernel startup dir. #5468
r16052 return path
Min RK
adjustments to filename increment...
r18813 def increment_filename(self, filename, path='', insert=''):
MinRK
rename notebooks service to contents service...
r17524 """Increment a filename until it is unique.
MinRK
mv services/notebooks services/contents
r17523
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 Parameters
----------
MinRK
rename notebooks service to contents service...
r17524 filename : unicode
The name of a file, including extension
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 path : unicode
MinRK
updates per review...
r17535 The API path of the target's directory
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293
Returns
-------
name : unicode
MinRK
rename notebooks service to contents service...
r17524 A filename that is unique, based on the input filename.
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 """
path = path.strip('/')
MinRK
rename notebooks service to contents service...
r17524 basename, ext = os.path.splitext(filename)
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 for i in itertools.count():
Min RK
adjustments to filename increment...
r18813 if i:
insert_i = '{}{}'.format(insert, i)
else:
insert_i = ''
name = u'{basename}{insert}{ext}'.format(basename=basename,
insert=insert_i, ext=ext)
Min RK
address review in contents service...
r18758 if not self.exists(u'{}/{}'.format(path, name)):
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 break
return name
MinRK
add dialogs for failed save/load...
r18249 def validate_notebook_model(self, model):
"""Add failed-validation message to model"""
try:
MinRK
don't use nbformat.current in IPython.html...
r18607 validate(model['content'])
except ValidationError as e:
Min RK
unicode!
r18754 model['message'] = u'Notebook Validation failed: {}:\n{}'.format(
MinRK
add dialogs for failed save/load...
r18249 e.message, json.dumps(e.instance, indent=1, default=lambda obj: '<UNKNOWN>'),
)
return model
Min RK
split ContentsManager.new, add ContentsManager.new_untitled
r18759
def new_untitled(self, path='', type='', ext=''):
"""Create a new untitled file or directory in path
path must be a directory
File extension can be specified.
Use `new` to create files with a fully specified path (including filename).
"""
path = path.strip('/')
if not self.dir_exists(path):
raise HTTPError(404, 'No such directory: %s' % path)
model = {}
if type:
model['type'] = type
if ext == '.ipynb':
model.setdefault('type', 'notebook')
else:
model.setdefault('type', 'file')
Min RK
adjustments to filename increment...
r18813 insert = ''
Min RK
split ContentsManager.new, add ContentsManager.new_untitled
r18759 if model['type'] == 'directory':
untitled = self.untitled_directory
Min RK
adjustments to filename increment...
r18813 insert = ' '
Min RK
split ContentsManager.new, add ContentsManager.new_untitled
r18759 elif model['type'] == 'notebook':
untitled = self.untitled_notebook
ext = '.ipynb'
elif model['type'] == 'file':
untitled = self.untitled_file
else:
raise HTTPError(400, "Unexpected model type: %r" % model['type'])
Min RK
adjustments to filename increment...
r18813 name = self.increment_filename(untitled + ext, path, insert=insert)
Min RK
split ContentsManager.new, add ContentsManager.new_untitled
r18759 path = u'{0}/{1}'.format(path, name)
return self.new(model, path)
def new(self, model=None, path=''):
Min RK
address review in contents service...
r18758 """Create a new file or directory and return its model with no content.
Min RK
split ContentsManager.new, add ContentsManager.new_untitled
r18759 To create a new untitled entity in a directory, use `new_untitled`.
Min RK
address review in contents service...
r18758 """
MinRK
ensure 'path' never has leading or trailing slash in nbmanager...
r13078 path = path.strip('/')
Zachary Sailer
refactoring of nbmanager and filenbmanager...
r13046 if model is None:
model = {}
Min RK
address review in contents service...
r18758
Min RK
split ContentsManager.new, add ContentsManager.new_untitled
r18759 if path.endswith('.ipynb'):
Min RK
address review in contents service...
r18758 model.setdefault('type', 'notebook')
Min RK
split ContentsManager.new, add ContentsManager.new_untitled
r18759 else:
model.setdefault('type', 'file')
Min RK
address review in contents service...
r18758
# no content, not a directory, so fill out new-file model
if 'content' not in model and model['type'] != 'directory':
if model['type'] == 'notebook':
MinRK
don't use nbformat.current in IPython.html...
r18607 model['content'] = new_notebook()
MinRK
updates per review...
r17532 model['format'] = 'json'
MinRK
add support and tests for uploading and saving regular files
r17527 else:
model['content'] = ''
MinRK
updates per review...
r17532 model['type'] = 'file'
model['format'] = 'text'
Min RK
address review in contents service...
r18758
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 model = self.save(model, path)
Zachary Sailer
refactoring of nbmanager and filenbmanager...
r13046 return model
Brian Granger
Refactoring notebook managers and adding Azure backed storage....
r8180
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 def copy(self, from_path, to_path=None):
MinRK
rename notebooks service to contents service...
r17524 """Copy an existing file and return its new model.
MinRK
mv services/notebooks services/contents
r17523
Min RK
address review in contents service...
r18758 If to_path not specified, it will be the parent directory of from_path.
If to_path is a directory, filename will increment `from_path-Copy#.ext`.
MinRK
updates per review...
r17535
Min RK
address review in contents service...
r18758 from_path must be a full path to a file.
MinRK
allow specifying destination in copy_notebook
r13123 """
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 path = from_path.strip('/')
if '/' in path:
from_dir, from_name = path.rsplit('/', 1)
MinRK
updates per review...
r17535 else:
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 from_dir = ''
from_name = path
Thomas Kluyver
Rename get_model() to get()
r18791 model = self.get(path)
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 model.pop('path', None)
model.pop('name', None)
MinRK
support deleting empty directories...
r17530 if model['type'] == 'directory':
raise HTTPError(400, "Can't copy directories")
MinRK
Remove separate 'path', 'name' in Contents API...
r18749
if not to_path:
to_path = from_dir
if self.dir_exists(to_path):
Min RK
adjustments to filename increment...
r18813 name = copy_pat.sub(u'.', from_name)
to_name = self.increment_filename(name, to_path, insert='-Copy')
Min RK
unicode!
r18754 to_path = u'{0}/{1}'.format(to_path, to_name)
MinRK
Remove separate 'path', 'name' in Contents API...
r18749
model = self.save(model, to_path)
Zachary Sailer
refactoring of nbmanager and filenbmanager...
r13046 return model
MinRK
mv services/notebooks services/contents
r17523
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 def log_info(self):
self.log.info(self.info_string())
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 def trust_notebook(self, path):
MinRK
trust method docstrings
r15664 """Explicitly trust a notebook
MinRK
mv services/notebooks services/contents
r17523
MinRK
trust method docstrings
r15664 Parameters
----------
path : string
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 The path of a notebook
MinRK
Add Trust Notebook to File menu
r15655 """
Thomas Kluyver
Rename get_model() to get()
r18791 model = self.get(path)
MinRK
Add Trust Notebook to File menu
r15655 nb = model['content']
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 self.log.warn("Trusting notebook %s", path)
MinRK
Add Trust Notebook to File menu
r15655 self.notary.mark_cells(nb, True)
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 self.save(model, path)
MinRK
mv services/notebooks services/contents
r17523
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 def check_and_sign(self, nb, path=''):
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 """Check for trusted cells, and sign the notebook.
MinRK
mv services/notebooks services/contents
r17523
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 Called as a part of saving notebooks.
MinRK
mv services/notebooks services/contents
r17523
MinRK
trust method docstrings
r15664 Parameters
----------
nb : dict
MinRK
restore ability to sign v3 notebooks
r18612 The notebook dict
MinRK
trust method docstrings
r15664 path : string
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 The notebook's path (for logging)
MinRK
add checkpoint API to FileNBManager
r10497 """
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 if self.notary.check_cells(nb):
self.notary.sign(nb)
else:
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 self.log.warn("Saving untrusted notebook %s", path)
MinRK
mv services/notebooks services/contents
r17523
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 def mark_trusted_cells(self, nb, path=''):
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 """Mark cells as trusted if the notebook signature matches.
MinRK
mv services/notebooks services/contents
r17523
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 Called as a part of loading notebooks.
MinRK
mv services/notebooks services/contents
r17523
MinRK
trust method docstrings
r15664 Parameters
----------
nb : dict
MinRK
don't use nbformat.current in IPython.html...
r18607 The notebook object (in current nbformat)
MinRK
trust method docstrings
r15664 path : string
Min RK
address review in contents service...
r18758 The notebook's path (for logging)
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 """
trusted = self.notary.check_signature(nb)
if not trusted:
MinRK
Remove separate 'path', 'name' in Contents API...
r18749 self.log.warn("Notebook %s is not trusted", path)
Konrad Hinsen
Rearrange the NotebookManager methods for clarity...
r15293 self.notary.mark_cells(nb, trusted)
Brian Granger
Fixing minor things for the Azure backed nb storage.
r8181
Thomas Kluyver
Make hidden directories configurable
r15525 def should_list(self, name):
"""Should this file/directory name be displayed in a listing?"""
return not any(fnmatch(name, glob) for glob in self.hide_globs)