mirror of
https://github.com/jupyter/notebook.git
synced 2025-03-19 13:20:36 +08:00
Allow specifying format when getting files from contents API
This commit is contained in:
parent
e453b160b1
commit
b5a6cb7da1
@ -209,11 +209,15 @@ class FileContentsManager(ContentsManager):
|
||||
|
||||
return model
|
||||
|
||||
def _file_model(self, path, content=True):
|
||||
def _file_model(self, path, content=True, format=None):
|
||||
"""Build a model for a file
|
||||
|
||||
if content is requested, include the file contents.
|
||||
UTF-8 text files will be unicode, binary files will be base64-encoded.
|
||||
|
||||
format:
|
||||
If 'text', the contents will be decoded as UTF-8.
|
||||
If 'base64', the raw bytes contents will be encoded as base64.
|
||||
If not specified, try to decode as UTF-8, and fall back to base64
|
||||
"""
|
||||
model = self._base_model(path)
|
||||
model['type'] = 'file'
|
||||
@ -224,13 +228,20 @@ class FileContentsManager(ContentsManager):
|
||||
raise web.HTTPError(400, "Cannot get content of non-file %s" % os_path)
|
||||
with io.open(os_path, 'rb') as f:
|
||||
bcontent = f.read()
|
||||
try:
|
||||
model['content'] = bcontent.decode('utf8')
|
||||
except UnicodeError as e:
|
||||
|
||||
if format != 'base64':
|
||||
try:
|
||||
model['content'] = bcontent.decode('utf8')
|
||||
except UnicodeError as e:
|
||||
if format == 'text':
|
||||
raise web.HTTPError(400, "%s is not UTF-8 encoded" % path)
|
||||
else:
|
||||
model['format'] = 'text'
|
||||
|
||||
if model['content'] is None:
|
||||
model['content'] = base64.encodestring(bcontent).decode('ascii')
|
||||
model['format'] = 'base64'
|
||||
else:
|
||||
model['format'] = 'text'
|
||||
|
||||
return model
|
||||
|
||||
|
||||
@ -255,7 +266,7 @@ class FileContentsManager(ContentsManager):
|
||||
self.validate_notebook_model(model)
|
||||
return model
|
||||
|
||||
def get_model(self, path, content=True, type_=None):
|
||||
def get_model(self, path, content=True, type_=None, format=None):
|
||||
""" Takes a path for an entity and returns its model
|
||||
|
||||
Parameters
|
||||
@ -267,6 +278,9 @@ class FileContentsManager(ContentsManager):
|
||||
type_ : str, optional
|
||||
The requested type - 'file', 'notebook', or 'directory'.
|
||||
Will raise HTTPError 406 if the content doesn't match.
|
||||
format : str, optional
|
||||
The requested format for file contents. 'text' or 'base64'.
|
||||
Ignored if this returns a notebook or directory model.
|
||||
|
||||
Returns
|
||||
-------
|
||||
@ -291,7 +305,7 @@ class FileContentsManager(ContentsManager):
|
||||
if type_ == 'directory':
|
||||
raise web.HTTPError(400,
|
||||
u'%s is not a directory')
|
||||
model = self._file_model(path, content=content)
|
||||
model = self._file_model(path, content=content, format=format)
|
||||
return model
|
||||
|
||||
def _save_notebook(self, os_path, model, path=''):
|
||||
|
@ -62,7 +62,11 @@ class ContentsHandler(IPythonHandler):
|
||||
if type_ not in {None, 'directory', 'file', 'notebook'}:
|
||||
raise web.HTTPError(400, u'Type %r is invalid' % type_)
|
||||
|
||||
model = self.contents_manager.get_model(path=path, type_=type_)
|
||||
format = self.get_query_argument('format', default=None)#
|
||||
if format not in {None, 'text', 'base64'}:
|
||||
raise web.HTTPError(400, u'Format %r is invalid' % format)
|
||||
|
||||
model = self.contents_manager.get_model(path=path, type_=type_, format=format)
|
||||
if model['type'] == 'directory':
|
||||
# group listing by type, then by name (case-insensitive)
|
||||
# FIXME: sorting should be done in the frontends
|
||||
|
@ -135,7 +135,7 @@ class ContentsManager(LoggingConfigurable):
|
||||
"""
|
||||
return self.file_exists(path) or self.dir_exists(path)
|
||||
|
||||
def get_model(self, path, content=True, type_=None):
|
||||
def get_model(self, path, content=True, type_=None, format=None):
|
||||
"""Get the model of a file or directory with or without content."""
|
||||
raise NotImplementedError('must be implemented in a subclass')
|
||||
|
||||
|
@ -46,9 +46,14 @@ class API(object):
|
||||
def list(self, path='/'):
|
||||
return self._req('GET', path)
|
||||
|
||||
def read(self, path, type_=None):
|
||||
def read(self, path, type_=None, format=None):
|
||||
query = []
|
||||
if type_ is not None:
|
||||
path += '?type=' + type_
|
||||
query.append('type=' + type_)
|
||||
if format is not None:
|
||||
query.append('format=' + format)
|
||||
if query:
|
||||
path += '?' + '&'.join(query)
|
||||
return self._req('GET', path)
|
||||
|
||||
def create_untitled(self, path='/', ext='.ipynb'):
|
||||
@ -245,6 +250,10 @@ class APITest(NotebookTestBase):
|
||||
with assert_http_error(404):
|
||||
self.api.read('foo/q.txt')
|
||||
|
||||
# Specifying format=text should fail on a non-UTF-8 file
|
||||
with assert_http_error(400):
|
||||
self.api.read('foo/bar/baz.blob', type_='file', format='text')
|
||||
|
||||
def test_get_binary_file_contents(self):
|
||||
for d, name in self.dirs_nbs:
|
||||
path = url_path_join(d, name + '.blob')
|
||||
|
@ -165,6 +165,9 @@ class TestContentsManager(TestCase):
|
||||
self.assertEqual(nb_as_file['format'], 'text')
|
||||
self.assertNotIsInstance(nb_as_file['content'], dict)
|
||||
|
||||
nb_as_bin_file = cm.get_model(path, content=True, type_='file', format='base64')
|
||||
self.assertEqual(nb_as_bin_file['format'], 'base64')
|
||||
|
||||
# Test in sub-directory
|
||||
sub_dir = '/foo/'
|
||||
self.make_dir(cm.root_dir, 'foo')
|
||||
|
Loading…
x
Reference in New Issue
Block a user