##// END OF EJS Templates
Merge pull request #6915 from minrk/contents-no-0...
Thomas Kluyver -
r18835:b7c85f43 merge
parent child Browse files
Show More
@@ -7,6 +7,7 b' from fnmatch import fnmatch'
7 import itertools
7 import itertools
8 import json
8 import json
9 import os
9 import os
10 import re
10
11
11 from tornado.web import HTTPError
12 from tornado.web import HTTPError
12
13
@@ -15,6 +16,7 b' from IPython.nbformat import sign, validate, ValidationError'
15 from IPython.nbformat.v4 import new_notebook
16 from IPython.nbformat.v4 import new_notebook
16 from IPython.utils.traitlets import Instance, Unicode, List
17 from IPython.utils.traitlets import Instance, Unicode, List
17
18
19 copy_pat = re.compile(r'\-Copy\d*\.')
18
20
19 class ContentsManager(LoggingConfigurable):
21 class ContentsManager(LoggingConfigurable):
20 """Base class for serving files and directories.
22 """Base class for serving files and directories.
@@ -188,7 +190,7 b' class ContentsManager(LoggingConfigurable):'
188 """
190 """
189 return path
191 return path
190
192
191 def increment_filename(self, filename, path=''):
193 def increment_filename(self, filename, path='', insert=''):
192 """Increment a filename until it is unique.
194 """Increment a filename until it is unique.
193
195
194 Parameters
196 Parameters
@@ -206,8 +208,12 b' class ContentsManager(LoggingConfigurable):'
206 path = path.strip('/')
208 path = path.strip('/')
207 basename, ext = os.path.splitext(filename)
209 basename, ext = os.path.splitext(filename)
208 for i in itertools.count():
210 for i in itertools.count():
209 name = u'{basename}{i}{ext}'.format(basename=basename, i=i,
211 if i:
210 ext=ext)
212 insert_i = '{}{}'.format(insert, i)
213 else:
214 insert_i = ''
215 name = u'{basename}{insert}{ext}'.format(basename=basename,
216 insert=insert_i, ext=ext)
211 if not self.exists(u'{}/{}'.format(path, name)):
217 if not self.exists(u'{}/{}'.format(path, name)):
212 break
218 break
213 return name
219 return name
@@ -244,8 +250,10 b' class ContentsManager(LoggingConfigurable):'
244 else:
250 else:
245 model.setdefault('type', 'file')
251 model.setdefault('type', 'file')
246
252
253 insert = ''
247 if model['type'] == 'directory':
254 if model['type'] == 'directory':
248 untitled = self.untitled_directory
255 untitled = self.untitled_directory
256 insert = ' '
249 elif model['type'] == 'notebook':
257 elif model['type'] == 'notebook':
250 untitled = self.untitled_notebook
258 untitled = self.untitled_notebook
251 ext = '.ipynb'
259 ext = '.ipynb'
@@ -254,7 +262,7 b' class ContentsManager(LoggingConfigurable):'
254 else:
262 else:
255 raise HTTPError(400, "Unexpected model type: %r" % model['type'])
263 raise HTTPError(400, "Unexpected model type: %r" % model['type'])
256
264
257 name = self.increment_filename(untitled + ext, path)
265 name = self.increment_filename(untitled + ext, path, insert=insert)
258 path = u'{0}/{1}'.format(path, name)
266 path = u'{0}/{1}'.format(path, name)
259 return self.new(model, path)
267 return self.new(model, path)
260
268
@@ -309,9 +317,8 b' class ContentsManager(LoggingConfigurable):'
309 if not to_path:
317 if not to_path:
310 to_path = from_dir
318 to_path = from_dir
311 if self.dir_exists(to_path):
319 if self.dir_exists(to_path):
312 base, ext = os.path.splitext(from_name)
320 name = copy_pat.sub(u'.', from_name)
313 copy_name = u'{0}-Copy{1}'.format(base, ext)
321 to_name = self.increment_filename(name, to_path, insert='-Copy')
314 to_name = self.increment_filename(copy_name, to_path)
315 to_path = u'{0}/{1}'.format(to_path, to_name)
322 to_path = u'{0}/{1}'.format(to_path, to_name)
316
323
317 model = self.save(model, to_path)
324 model = self.save(model, to_path)
@@ -291,7 +291,7 b' class APITest(NotebookTestBase):'
291
291
292 def test_create_untitled(self):
292 def test_create_untitled(self):
293 resp = self.api.create_untitled(path=u'å b')
293 resp = self.api.create_untitled(path=u'å b')
294 self._check_created(resp, u'å b/Untitled0.ipynb')
294 self._check_created(resp, u'å b/Untitled.ipynb')
295
295
296 # Second time
296 # Second time
297 resp = self.api.create_untitled(path=u'å b')
297 resp = self.api.create_untitled(path=u'å b')
@@ -299,13 +299,13 b' class APITest(NotebookTestBase):'
299
299
300 # And two directories down
300 # And two directories down
301 resp = self.api.create_untitled(path='foo/bar')
301 resp = self.api.create_untitled(path='foo/bar')
302 self._check_created(resp, 'foo/bar/Untitled0.ipynb')
302 self._check_created(resp, 'foo/bar/Untitled.ipynb')
303
303
304 def test_create_untitled_txt(self):
304 def test_create_untitled_txt(self):
305 resp = self.api.create_untitled(path='foo/bar', ext='.txt')
305 resp = self.api.create_untitled(path='foo/bar', ext='.txt')
306 self._check_created(resp, 'foo/bar/untitled0.txt', type='file')
306 self._check_created(resp, 'foo/bar/untitled.txt', type='file')
307
307
308 resp = self.api.read(path='foo/bar/untitled0.txt')
308 resp = self.api.read(path='foo/bar/untitled.txt')
309 model = resp.json()
309 model = resp.json()
310 self.assertEqual(model['type'], 'file')
310 self.assertEqual(model['type'], 'file')
311 self.assertEqual(model['format'], 'text')
311 self.assertEqual(model['format'], 'text')
@@ -320,15 +320,15 b' class APITest(NotebookTestBase):'
320
320
321 def test_mkdir_untitled(self):
321 def test_mkdir_untitled(self):
322 resp = self.api.mkdir_untitled(path=u'å b')
322 resp = self.api.mkdir_untitled(path=u'å b')
323 self._check_created(resp, u'å b/Untitled Folder0', type='directory')
323 self._check_created(resp, u'å b/Untitled Folder', type='directory')
324
324
325 # Second time
325 # Second time
326 resp = self.api.mkdir_untitled(path=u'å b')
326 resp = self.api.mkdir_untitled(path=u'å b')
327 self._check_created(resp, u'å b/Untitled Folder1', type='directory')
327 self._check_created(resp, u'å b/Untitled Folder 1', type='directory')
328
328
329 # And two directories down
329 # And two directories down
330 resp = self.api.mkdir_untitled(path='foo/bar')
330 resp = self.api.mkdir_untitled(path='foo/bar')
331 self._check_created(resp, 'foo/bar/Untitled Folder0', type='directory')
331 self._check_created(resp, 'foo/bar/Untitled Folder', type='directory')
332
332
333 def test_mkdir(self):
333 def test_mkdir(self):
334 path = u'å b/New ∂ir'
334 path = u'å b/New ∂ir'
@@ -390,15 +390,25 b' class APITest(NotebookTestBase):'
390 self.assertEqual(data['content']['nbformat'], 4)
390 self.assertEqual(data['content']['nbformat'], 4)
391
391
392 def test_copy(self):
392 def test_copy(self):
393 resp = self.api.copy(u'å b/ç d.ipynb', u'unicodé')
393 resp = self.api.copy(u'å b/ç d.ipynb', u'å b')
394 self._check_created(resp, u'unicodé/ç d-Copy0.ipynb')
394 self._check_created(resp, u'å b/ç d-Copy1.ipynb')
395
395
396 resp = self.api.copy(u'å b/ç d.ipynb', u'å b')
396 resp = self.api.copy(u'å b/ç d.ipynb', u'å b')
397 self._check_created(resp, u'å b/ç d-Copy0.ipynb')
397 self._check_created(resp, u'å b/ç d-Copy2.ipynb')
398
398
399 def test_copy_copy(self):
400 resp = self.api.copy(u'å b/ç d.ipynb', u'å b')
401 self._check_created(resp, u'å b/ç d-Copy1.ipynb')
402
403 resp = self.api.copy(u'å b/ç d-Copy1.ipynb', u'å b')
404 self._check_created(resp, u'å b/ç d-Copy2.ipynb')
405
399 def test_copy_path(self):
406 def test_copy_path(self):
400 resp = self.api.copy(u'foo/a.ipynb', u'å b')
407 resp = self.api.copy(u'foo/a.ipynb', u'å b')
401 self._check_created(resp, u'å b/a-Copy0.ipynb')
408 self._check_created(resp, u'å b/a.ipynb')
409
410 resp = self.api.copy(u'foo/a.ipynb', u'å b')
411 self._check_created(resp, u'å b/a-Copy1.ipynb')
402
412
403 def test_copy_put_400(self):
413 def test_copy_put_400(self):
404 with assert_http_error(400):
414 with assert_http_error(400):
@@ -121,8 +121,8 b' class TestContentsManager(TestCase):'
121 self.assertIn('path', model)
121 self.assertIn('path', model)
122 self.assertIn('type', model)
122 self.assertIn('type', model)
123 self.assertEqual(model['type'], 'notebook')
123 self.assertEqual(model['type'], 'notebook')
124 self.assertEqual(model['name'], 'Untitled0.ipynb')
124 self.assertEqual(model['name'], 'Untitled.ipynb')
125 self.assertEqual(model['path'], 'Untitled0.ipynb')
125 self.assertEqual(model['path'], 'Untitled.ipynb')
126
126
127 # Test in sub-directory
127 # Test in sub-directory
128 model = cm.new_untitled(type='directory')
128 model = cm.new_untitled(type='directory')
@@ -131,8 +131,8 b' class TestContentsManager(TestCase):'
131 self.assertIn('path', model)
131 self.assertIn('path', model)
132 self.assertIn('type', model)
132 self.assertIn('type', model)
133 self.assertEqual(model['type'], 'directory')
133 self.assertEqual(model['type'], 'directory')
134 self.assertEqual(model['name'], 'Untitled Folder0')
134 self.assertEqual(model['name'], 'Untitled Folder')
135 self.assertEqual(model['path'], 'Untitled Folder0')
135 self.assertEqual(model['path'], 'Untitled Folder')
136 sub_dir = model['path']
136 sub_dir = model['path']
137
137
138 model = cm.new_untitled(path=sub_dir)
138 model = cm.new_untitled(path=sub_dir)
@@ -141,8 +141,8 b' class TestContentsManager(TestCase):'
141 self.assertIn('path', model)
141 self.assertIn('path', model)
142 self.assertIn('type', model)
142 self.assertIn('type', model)
143 self.assertEqual(model['type'], 'file')
143 self.assertEqual(model['type'], 'file')
144 self.assertEqual(model['name'], 'untitled0')
144 self.assertEqual(model['name'], 'untitled')
145 self.assertEqual(model['path'], '%s/untitled0' % sub_dir)
145 self.assertEqual(model['path'], '%s/untitled' % sub_dir)
146
146
147 def test_get(self):
147 def test_get(self):
148 cm = self.contents_manager
148 cm = self.contents_manager
@@ -177,7 +177,7 b' class TestContentsManager(TestCase):'
177 self.assertIn('name', model2)
177 self.assertIn('name', model2)
178 self.assertIn('path', model2)
178 self.assertIn('path', model2)
179 self.assertIn('content', model2)
179 self.assertIn('content', model2)
180 self.assertEqual(model2['name'], 'Untitled0.ipynb')
180 self.assertEqual(model2['name'], 'Untitled.ipynb')
181 self.assertEqual(model2['path'], '{0}/{1}'.format(sub_dir.strip('/'), name))
181 self.assertEqual(model2['path'], '{0}/{1}'.format(sub_dir.strip('/'), name))
182
182
183 # Test getting directory model
183 # Test getting directory model
@@ -291,8 +291,8 b' class TestContentsManager(TestCase):'
291 assert isinstance(model, dict)
291 assert isinstance(model, dict)
292 self.assertIn('name', model)
292 self.assertIn('name', model)
293 self.assertIn('path', model)
293 self.assertIn('path', model)
294 self.assertEqual(model['name'], 'Untitled0.ipynb')
294 self.assertEqual(model['name'], 'Untitled.ipynb')
295 self.assertEqual(model['path'], 'foo/Untitled0.ipynb')
295 self.assertEqual(model['path'], 'foo/Untitled.ipynb')
296
296
297 def test_delete(self):
297 def test_delete(self):
298 cm = self.contents_manager
298 cm = self.contents_manager
@@ -315,12 +315,16 b' class TestContentsManager(TestCase):'
315
315
316 # copy with unspecified name
316 # copy with unspecified name
317 copy = cm.copy(path)
317 copy = cm.copy(path)
318 self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy0.ipynb'))
318 self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy1.ipynb'))
319
319
320 # copy with specified name
320 # copy with specified name
321 copy2 = cm.copy(path, u'å b/copy 2.ipynb')
321 copy2 = cm.copy(path, u'å b/copy 2.ipynb')
322 self.assertEqual(copy2['name'], u'copy 2.ipynb')
322 self.assertEqual(copy2['name'], u'copy 2.ipynb')
323 self.assertEqual(copy2['path'], u'å b/copy 2.ipynb')
323 self.assertEqual(copy2['path'], u'å b/copy 2.ipynb')
324 # copy with specified path
325 copy2 = cm.copy(path, u'/')
326 self.assertEqual(copy2['name'], name)
327 self.assertEqual(copy2['path'], name)
324
328
325 def test_trust_notebook(self):
329 def test_trust_notebook(self):
326 cm = self.contents_manager
330 cm = self.contents_manager
General Comments 0
You need to be logged in to leave comments. Login now