mirror of
https://github.com/jupyter/notebook.git
synced 2024-12-15 04:00:34 +08:00
support deleting empty directories
can’t copy directories
This commit is contained in:
parent
260afd76ae
commit
93b300adda
@ -357,7 +357,13 @@ class FileContentsManager(ContentsManager):
|
||||
"""Delete file by name and path."""
|
||||
path = path.strip('/')
|
||||
os_path = self._get_os_path(name, path)
|
||||
if not os.path.isfile(os_path):
|
||||
rm = os.unlink
|
||||
if os.path.isdir(os_path):
|
||||
listing = os.listdir(os_path)
|
||||
# don't delete non-empty directories (checkpoints dir doesn't count)
|
||||
if listing and listing != ['.ipynb_checkpoints']:
|
||||
raise web.HTTPError(400, u'Directory %s not empty' % os_path)
|
||||
elif not os.path.isfile(os_path):
|
||||
raise web.HTTPError(404, u'File does not exist: %s' % os_path)
|
||||
|
||||
# clear checkpoints
|
||||
@ -368,8 +374,12 @@ class FileContentsManager(ContentsManager):
|
||||
self.log.debug("Unlinking checkpoint %s", cp_path)
|
||||
os.unlink(cp_path)
|
||||
|
||||
self.log.debug("Unlinking file %s", os_path)
|
||||
os.unlink(os_path)
|
||||
if os.path.isdir(os_path):
|
||||
self.log.debug("Removing directory %s", os_path)
|
||||
shutil.rmtree(os_path)
|
||||
else:
|
||||
self.log.debug("Unlinking file %s", os_path)
|
||||
rm(os_path)
|
||||
|
||||
def rename(self, old_name, old_path, new_name, new_path):
|
||||
"""Rename a file."""
|
||||
|
@ -7,6 +7,8 @@ from fnmatch import fnmatch
|
||||
import itertools
|
||||
import os
|
||||
|
||||
from tornado.web import HTTPError
|
||||
|
||||
from IPython.config.configurable import LoggingConfigurable
|
||||
from IPython.nbformat import current, sign
|
||||
from IPython.utils.traitlets import Instance, Unicode, List
|
||||
@ -187,6 +189,8 @@ class ContentsManager(LoggingConfigurable):
|
||||
"""
|
||||
path = path.strip('/')
|
||||
model = self.get_model(from_name, path)
|
||||
if model['type'] == 'directory':
|
||||
raise HTTPError(400, "Can't copy directories")
|
||||
if not to_name:
|
||||
base, ext = os.path.splitext(from_name)
|
||||
copy_name = u'{0}-Copy{1}'.format(base, ext)
|
||||
|
@ -69,6 +69,9 @@ class API(object):
|
||||
def upload(self, name, body, path='/'):
|
||||
return self._req('PUT', url_path_join(path, name), body)
|
||||
|
||||
def mkdir(self, name, path='/'):
|
||||
return self._req('PUT', url_path_join(path, name), json.dumps({'type': 'directory'}))
|
||||
|
||||
def copy(self, copy_from, copy_to, path='/'):
|
||||
body = json.dumps({'copy_from':copy_from})
|
||||
return self._req('PUT', url_path_join(path, copy_to), body)
|
||||
@ -299,9 +302,7 @@ class APITest(NotebookTestBase):
|
||||
self._check_created(resp, u'Upload tést.ipynb', u'å b')
|
||||
|
||||
def test_mkdir(self):
|
||||
model = {'type': 'directory'}
|
||||
resp = self.api.upload(u'New ∂ir', path=u'å b',
|
||||
body=json.dumps(model))
|
||||
resp = self.api.mkdir(u'New ∂ir', path=u'å b')
|
||||
self._check_created(resp, u'New ∂ir', u'å b', type='directory')
|
||||
|
||||
def test_upload_txt(self):
|
||||
@ -362,6 +363,11 @@ class APITest(NotebookTestBase):
|
||||
resp = self.api.copy(u'ç d.ipynb', u'cøpy.ipynb', path=u'å b')
|
||||
self._check_created(resp, u'cøpy.ipynb', u'å b')
|
||||
|
||||
def test_copy_dir_400(self):
|
||||
# can't copy directories
|
||||
with assert_http_error(400):
|
||||
resp = self.api.copy(u'å b', u'å c')
|
||||
|
||||
def test_delete(self):
|
||||
for d, name in self.dirs_nbs:
|
||||
resp = self.api.delete('%s.ipynb' % name, d)
|
||||
@ -371,6 +377,20 @@ class APITest(NotebookTestBase):
|
||||
nbs = notebooks_only(self.api.list(d).json())
|
||||
self.assertEqual(len(nbs), 0)
|
||||
|
||||
def test_delete_dirs(self):
|
||||
# depth-first delete everything, so we don't try to delete empty directories
|
||||
for name in sorted(self.dirs + ['/'], key=len, reverse=True):
|
||||
listing = self.api.list(name).json()['content']
|
||||
for model in listing:
|
||||
self.api.delete(model['name'], model['path'])
|
||||
listing = self.api.list('/').json()['content']
|
||||
self.assertEqual(listing, [])
|
||||
|
||||
def test_delete_non_empty_dir(self):
|
||||
"""delete non-empty dir raises 400"""
|
||||
with assert_http_error(400):
|
||||
self.api.delete(u'å b')
|
||||
|
||||
def test_rename(self):
|
||||
resp = self.api.rename('a.ipynb', 'foo', 'z.ipynb')
|
||||
self.assertEqual(resp.headers['Location'].split('/')[-1], 'z.ipynb')
|
||||
|
Loading…
Reference in New Issue
Block a user