##// END OF EJS Templates
update contents per further review...
MinRK -
Show More
@@ -265,6 +265,11 b" flags['no-mathjax']=("
265 """
265 """
266 )
266 )
267
267
268 # Add notebook manager flags
269 flags.update(boolean_flag('script', 'FileContentsManager.save_script',
270 'DEPRECATED, IGNORED',
271 'DEPRECATED, IGNORED'))
272
268 aliases = dict(base_aliases)
273 aliases = dict(base_aliases)
269
274
270 aliases.update({
275 aliases.update({
@@ -17,20 +17,27 b' from IPython.utils.path import ensure_dir_exists'
17 from IPython.utils.traitlets import Unicode, Bool, TraitError
17 from IPython.utils.traitlets import Unicode, Bool, TraitError
18 from IPython.utils.py3compat import getcwd
18 from IPython.utils.py3compat import getcwd
19 from IPython.utils import tz
19 from IPython.utils import tz
20 from IPython.html.utils import is_hidden, to_os_path
20 from IPython.html.utils import is_hidden, to_os_path, url_path_join
21
21
22
22
23 class FileContentsManager(ContentsManager):
23 class FileContentsManager(ContentsManager):
24
24
25 root_dir = Unicode(getcwd(), config=True)
25 root_dir = Unicode(getcwd(), config=True)
26
26
27 save_script = Bool(False, config=True, help='DEPRECATED, IGNORED')
28 def _save_script_changed(self):
29 self.log.warn("""
30 Automatically saving notebooks as scripts has been removed.
31 Use `ipython nbconvert --to python [notebook]` instead.
32 """)
33
27 def _root_dir_changed(self, name, old, new):
34 def _root_dir_changed(self, name, old, new):
28 """Do a bit of validation of the root_dir."""
35 """Do a bit of validation of the root_dir."""
29 if not os.path.isabs(new):
36 if not os.path.isabs(new):
30 # If we receive a non-absolute path, make it absolute.
37 # If we receive a non-absolute path, make it absolute.
31 self.root_dir = os.path.abspath(new)
38 self.root_dir = os.path.abspath(new)
32 return
39 return
33 if not os.path.exists(new) or not os.path.isdir(new):
40 if not os.path.isdir(new):
34 raise TraitError("%r is not a directory" % new)
41 raise TraitError("%r is not a directory" % new)
35
42
36 checkpoint_dir = Unicode('.ipynb_checkpoints', config=True,
43 checkpoint_dir = Unicode('.ipynb_checkpoints', config=True,
@@ -70,7 +77,7 b' class FileContentsManager(ContentsManager):'
70 API path to be evaluated relative to root_dir.
77 API path to be evaluated relative to root_dir.
71 """
78 """
72 if name is not None:
79 if name is not None:
73 path = path + '/' + name
80 path = url_path_join(path, name)
74 return to_os_path(path, self.root_dir)
81 return to_os_path(path, self.root_dir)
75
82
76 def path_exists(self, path):
83 def path_exists(self, path):
@@ -177,11 +184,15 b' class FileContentsManager(ContentsManager):'
177 """
184 """
178 os_path = self._get_os_path(name, path)
185 os_path = self._get_os_path(name, path)
179
186
187 four_o_four = u'directory does not exist: %r' % os_path
188
180 if not os.path.isdir(os_path):
189 if not os.path.isdir(os_path):
181 raise web.HTTPError(404, u'directory does not exist: %r' % os_path)
190 raise web.HTTPError(404, four_o_four)
182 elif is_hidden(os_path, self.root_dir):
191 elif is_hidden(os_path, self.root_dir):
183 self.log.info("Refusing to serve hidden directory, via 404 Error")
192 self.log.info("Refusing to serve hidden directory %r, via 404 Error",
184 raise web.HTTPError(404, u'directory does not exist: %r' % os_path)
193 os_path
194 )
195 raise web.HTTPError(404, four_o_four)
185
196
186 if name is None:
197 if name is None:
187 if '/' in path:
198 if '/' in path:
@@ -212,14 +223,13 b' class FileContentsManager(ContentsManager):'
212 model['type'] = 'file'
223 model['type'] = 'file'
213 if content:
224 if content:
214 os_path = self._get_os_path(name, path)
225 os_path = self._get_os_path(name, path)
226 with io.open(os_path, 'rb') as f:
227 bcontent = f.read()
215 try:
228 try:
216 with io.open(os_path, 'r', encoding='utf-8') as f:
229 model['content'] = bcontent.decode('utf8')
217 model['content'] = f.read()
218 except UnicodeError as e:
230 except UnicodeError as e:
219 with io.open(os_path, 'rb') as f:
231 model['content'] = base64.encodestring(bcontent).decode('ascii')
220 bcontent = f.read()
232 model['format'] = 'base64'
221 model['content'] = base64.encodestring(bcontent).decode('ascii')
222 model['format'] = 'base64'
223 else:
233 else:
224 model['format'] = 'text'
234 model['format'] = 'text'
225 return model
235 return model
@@ -307,10 +317,14 b' class FileContentsManager(ContentsManager):'
307
317
308 def _save_directory(self, os_path, model, name='', path=''):
318 def _save_directory(self, os_path, model, name='', path=''):
309 """create a directory"""
319 """create a directory"""
320 if is_hidden(os_path, self.root_dir):
321 raise web.HTTPError(400, u'Cannot create hidden directory %r' % os_path)
310 if not os.path.exists(os_path):
322 if not os.path.exists(os_path):
311 os.mkdir(os_path)
323 os.mkdir(os_path)
312 elif not os.path.isdir(os_path):
324 elif not os.path.isdir(os_path):
313 raise web.HTTPError(400, u'Not a directory: %s' % (os_path))
325 raise web.HTTPError(400, u'Not a directory: %s' % (os_path))
326 else:
327 self.log.debug("Directory %r already exists", os_path)
314
328
315 def save(self, model, name='', path=''):
329 def save(self, model, name='', path=''):
316 """Save the file model and return the model with no content."""
330 """Save the file model and return the model with no content."""
@@ -372,7 +386,7 b' class FileContentsManager(ContentsManager):'
372 if os.path.isdir(os_path):
386 if os.path.isdir(os_path):
373 listing = os.listdir(os_path)
387 listing = os.listdir(os_path)
374 # don't delete non-empty directories (checkpoints dir doesn't count)
388 # don't delete non-empty directories (checkpoints dir doesn't count)
375 if listing and listing != ['.ipynb_checkpoints']:
389 if listing and listing != [self.checkpoint_dir]:
376 raise web.HTTPError(400, u'Directory %s not empty' % os_path)
390 raise web.HTTPError(400, u'Directory %s not empty' % os_path)
377 elif not os.path.isfile(os_path):
391 elif not os.path.isfile(os_path):
378 raise web.HTTPError(404, u'File does not exist: %s' % os_path)
392 raise web.HTTPError(404, u'File does not exist: %s' % os_path)
@@ -303,6 +303,10 b' class APITest(NotebookTestBase):'
303 resp = self.api.mkdir(u'New ∂ir', path=u'å b')
303 resp = self.api.mkdir(u'New ∂ir', path=u'å b')
304 self._check_created(resp, u'New ∂ir', u'å b', type='directory')
304 self._check_created(resp, u'New ∂ir', u'å b', type='directory')
305
305
306 def test_mkdir_hidden_400(self):
307 with assert_http_error(400):
308 resp = self.api.mkdir(u'.hidden', path=u'å b')
309
306 def test_upload_txt(self):
310 def test_upload_txt(self):
307 body = u'ünicode téxt'
311 body = u'ünicode téxt'
308 model = {
312 model = {
@@ -382,7 +382,20 b' define(['
382 if (file_ext === '.ipynb') {
382 if (file_ext === '.ipynb') {
383 model.type = 'notebook';
383 model.type = 'notebook';
384 model.format = 'json';
384 model.format = 'json';
385 model.content = JSON.parse(filedata);
385 try {
386 model.content = JSON.parse(filedata);
387 } catch (e) {
388 dialog.modal({
389 title : 'Cannot upload invalid Notebook',
390 body : "The error was: " + e,
391 buttons : {'OK' : {
392 'class' : 'btn-primary',
393 click: function () {
394 item.remove();
395 }
396 }}
397 });
398 }
386 content_type = 'application/json';
399 content_type = 'application/json';
387 } else {
400 } else {
388 model.type = 'file';
401 model.type = 'file';
@@ -113,6 +113,9 b" def is_hidden(abs_path, abs_root=''):"
113 # check UF_HIDDEN on any location up to root
113 # check UF_HIDDEN on any location up to root
114 path = abs_path
114 path = abs_path
115 while path and path.startswith(abs_root) and path != abs_root:
115 while path and path.startswith(abs_root) and path != abs_root:
116 if not os.path.exists(path):
117 path = os.path.dirname(path)
118 continue
116 try:
119 try:
117 # may fail on Windows junctions
120 # may fail on Windows junctions
118 st = os.stat(path)
121 st = os.stat(path)
@@ -3,4 +3,4 b''
3 which supports all kinds of files.
3 which supports all kinds of files.
4 - The Dashboard now lists all files, not just notebooks and directories.
4 - The Dashboard now lists all files, not just notebooks and directories.
5 - The ``--script`` hook for saving notebooks to Python scripts is removed,
5 - The ``--script`` hook for saving notebooks to Python scripts is removed,
6 use ``ipython nbconvert --to python [notebook]`` instead.
6 use :samp:`ipython nbconvert --to python {notebook}` instead.
General Comments 0
You need to be logged in to leave comments. Login now