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