From b7c85f43feb2eaae3d9be358a4f8f1dac289e0ff 2014-11-13 22:04:00
From: Thomas Kluyver <takowl@gmail.com>
Date: 2014-11-13 22:04:00
Subject: [PATCH] Merge pull request #6915 from minrk/contents-no-0

use Untitled instead of Untitled0
---

diff --git a/IPython/html/services/contents/manager.py b/IPython/html/services/contents/manager.py
index bbd6ede..491401f 100644
--- a/IPython/html/services/contents/manager.py
+++ b/IPython/html/services/contents/manager.py
@@ -7,6 +7,7 @@ from fnmatch import fnmatch
 import itertools
 import json
 import os
+import re
 
 from tornado.web import HTTPError
 
@@ -15,6 +16,7 @@ from IPython.nbformat import sign, validate, ValidationError
 from IPython.nbformat.v4 import new_notebook
 from IPython.utils.traitlets import Instance, Unicode, List
 
+copy_pat = re.compile(r'\-Copy\d*\.')
 
 class ContentsManager(LoggingConfigurable):
     """Base class for serving files and directories.
@@ -188,7 +190,7 @@ class ContentsManager(LoggingConfigurable):
         """
         return path
 
-    def increment_filename(self, filename, path=''):
+    def increment_filename(self, filename, path='', insert=''):
         """Increment a filename until it is unique.
 
         Parameters
@@ -206,8 +208,12 @@ class ContentsManager(LoggingConfigurable):
         path = path.strip('/')
         basename, ext = os.path.splitext(filename)
         for i in itertools.count():
-            name = u'{basename}{i}{ext}'.format(basename=basename, i=i,
-                                                ext=ext)
+            if i:
+                insert_i = '{}{}'.format(insert, i)
+            else:
+                insert_i = ''
+            name = u'{basename}{insert}{ext}'.format(basename=basename,
+                insert=insert_i, ext=ext)
             if not self.exists(u'{}/{}'.format(path, name)):
                 break
         return name
@@ -244,8 +250,10 @@ class ContentsManager(LoggingConfigurable):
         else:
             model.setdefault('type', 'file')
         
+        insert = ''
         if model['type'] == 'directory':
             untitled = self.untitled_directory
+            insert = ' '
         elif model['type'] == 'notebook':
             untitled = self.untitled_notebook
             ext = '.ipynb'
@@ -254,7 +262,7 @@ class ContentsManager(LoggingConfigurable):
         else:
             raise HTTPError(400, "Unexpected model type: %r" % model['type'])
         
-        name = self.increment_filename(untitled + ext, path)
+        name = self.increment_filename(untitled + ext, path, insert=insert)
         path = u'{0}/{1}'.format(path, name)
         return self.new(model, path)
     
@@ -309,9 +317,8 @@ class ContentsManager(LoggingConfigurable):
         if not to_path:
             to_path = from_dir
         if self.dir_exists(to_path):
-            base, ext = os.path.splitext(from_name)
-            copy_name = u'{0}-Copy{1}'.format(base, ext)
-            to_name = self.increment_filename(copy_name, to_path)
+            name = copy_pat.sub(u'.', from_name)
+            to_name = self.increment_filename(name, to_path, insert='-Copy')
             to_path = u'{0}/{1}'.format(to_path, to_name)
         
         model = self.save(model, to_path)
diff --git a/IPython/html/services/contents/tests/test_contents_api.py b/IPython/html/services/contents/tests/test_contents_api.py
index d73a4c2..bda7c77 100644
--- a/IPython/html/services/contents/tests/test_contents_api.py
+++ b/IPython/html/services/contents/tests/test_contents_api.py
@@ -291,7 +291,7 @@ class APITest(NotebookTestBase):
 
     def test_create_untitled(self):
         resp = self.api.create_untitled(path=u'å b')
-        self._check_created(resp, u'å b/Untitled0.ipynb')
+        self._check_created(resp, u'å b/Untitled.ipynb')
 
         # Second time
         resp = self.api.create_untitled(path=u'å b')
@@ -299,13 +299,13 @@ class APITest(NotebookTestBase):
 
         # And two directories down
         resp = self.api.create_untitled(path='foo/bar')
-        self._check_created(resp, 'foo/bar/Untitled0.ipynb')
+        self._check_created(resp, 'foo/bar/Untitled.ipynb')
 
     def test_create_untitled_txt(self):
         resp = self.api.create_untitled(path='foo/bar', ext='.txt')
-        self._check_created(resp, 'foo/bar/untitled0.txt', type='file')
+        self._check_created(resp, 'foo/bar/untitled.txt', type='file')
 
-        resp = self.api.read(path='foo/bar/untitled0.txt')
+        resp = self.api.read(path='foo/bar/untitled.txt')
         model = resp.json()
         self.assertEqual(model['type'], 'file')
         self.assertEqual(model['format'], 'text')
@@ -320,15 +320,15 @@ class APITest(NotebookTestBase):
 
     def test_mkdir_untitled(self):
         resp = self.api.mkdir_untitled(path=u'å b')
-        self._check_created(resp, u'å b/Untitled Folder0', type='directory')
+        self._check_created(resp, u'å b/Untitled Folder', type='directory')
 
         # Second time
         resp = self.api.mkdir_untitled(path=u'å b')
-        self._check_created(resp, u'å b/Untitled Folder1', type='directory')
+        self._check_created(resp, u'å b/Untitled Folder 1', type='directory')
 
         # And two directories down
         resp = self.api.mkdir_untitled(path='foo/bar')
-        self._check_created(resp, 'foo/bar/Untitled Folder0', type='directory')
+        self._check_created(resp, 'foo/bar/Untitled Folder', type='directory')
 
     def test_mkdir(self):
         path = u'å b/New ∂ir'
@@ -390,15 +390,25 @@ class APITest(NotebookTestBase):
         self.assertEqual(data['content']['nbformat'], 4)
 
     def test_copy(self):
-        resp = self.api.copy(u'å b/ç d.ipynb', u'unicodé')
-        self._check_created(resp, u'unicodé/ç d-Copy0.ipynb')
+        resp = self.api.copy(u'å b/ç d.ipynb', u'å b')
+        self._check_created(resp, u'å b/ç d-Copy1.ipynb')
         
         resp = self.api.copy(u'å b/ç d.ipynb', u'å b')
-        self._check_created(resp, u'å b/ç d-Copy0.ipynb')
-
+        self._check_created(resp, u'å b/ç d-Copy2.ipynb')
+    
+    def test_copy_copy(self):
+        resp = self.api.copy(u'å b/ç d.ipynb', u'å b')
+        self._check_created(resp, u'å b/ç d-Copy1.ipynb')
+        
+        resp = self.api.copy(u'å b/ç d-Copy1.ipynb', u'å b')
+        self._check_created(resp, u'å b/ç d-Copy2.ipynb')
+    
     def test_copy_path(self):
         resp = self.api.copy(u'foo/a.ipynb', u'å b')
-        self._check_created(resp, u'å b/a-Copy0.ipynb')
+        self._check_created(resp, u'å b/a.ipynb')
+        
+        resp = self.api.copy(u'foo/a.ipynb', u'å b')
+        self._check_created(resp, u'å b/a-Copy1.ipynb')
 
     def test_copy_put_400(self):
         with assert_http_error(400):
diff --git a/IPython/html/services/contents/tests/test_manager.py b/IPython/html/services/contents/tests/test_manager.py
index be78499..647578c 100644
--- a/IPython/html/services/contents/tests/test_manager.py
+++ b/IPython/html/services/contents/tests/test_manager.py
@@ -121,8 +121,8 @@ class TestContentsManager(TestCase):
         self.assertIn('path', model)
         self.assertIn('type', model)
         self.assertEqual(model['type'], 'notebook')
-        self.assertEqual(model['name'], 'Untitled0.ipynb')
-        self.assertEqual(model['path'], 'Untitled0.ipynb')
+        self.assertEqual(model['name'], 'Untitled.ipynb')
+        self.assertEqual(model['path'], 'Untitled.ipynb')
 
         # Test in sub-directory
         model = cm.new_untitled(type='directory')
@@ -131,8 +131,8 @@ class TestContentsManager(TestCase):
         self.assertIn('path', model)
         self.assertIn('type', model)
         self.assertEqual(model['type'], 'directory')
-        self.assertEqual(model['name'], 'Untitled Folder0')
-        self.assertEqual(model['path'], 'Untitled Folder0')
+        self.assertEqual(model['name'], 'Untitled Folder')
+        self.assertEqual(model['path'], 'Untitled Folder')
         sub_dir = model['path']
         
         model = cm.new_untitled(path=sub_dir)
@@ -141,8 +141,8 @@ class TestContentsManager(TestCase):
         self.assertIn('path', model)
         self.assertIn('type', model)
         self.assertEqual(model['type'], 'file')
-        self.assertEqual(model['name'], 'untitled0')
-        self.assertEqual(model['path'], '%s/untitled0' % sub_dir)
+        self.assertEqual(model['name'], 'untitled')
+        self.assertEqual(model['path'], '%s/untitled' % sub_dir)
 
     def test_get(self):
         cm = self.contents_manager
@@ -177,7 +177,7 @@ class TestContentsManager(TestCase):
         self.assertIn('name', model2)
         self.assertIn('path', model2)
         self.assertIn('content', model2)
-        self.assertEqual(model2['name'], 'Untitled0.ipynb')
+        self.assertEqual(model2['name'], 'Untitled.ipynb')
         self.assertEqual(model2['path'], '{0}/{1}'.format(sub_dir.strip('/'), name))
 
         # Test getting directory model
@@ -291,8 +291,8 @@ class TestContentsManager(TestCase):
         assert isinstance(model, dict)
         self.assertIn('name', model)
         self.assertIn('path', model)
-        self.assertEqual(model['name'], 'Untitled0.ipynb')
-        self.assertEqual(model['path'], 'foo/Untitled0.ipynb')
+        self.assertEqual(model['name'], 'Untitled.ipynb')
+        self.assertEqual(model['path'], 'foo/Untitled.ipynb')
 
     def test_delete(self):
         cm = self.contents_manager
@@ -315,12 +315,16 @@ class TestContentsManager(TestCase):
 
         # copy with unspecified name
         copy = cm.copy(path)
-        self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy0.ipynb'))
+        self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy1.ipynb'))
 
         # copy with specified name
         copy2 = cm.copy(path, u'å b/copy 2.ipynb')
         self.assertEqual(copy2['name'], u'copy 2.ipynb')
         self.assertEqual(copy2['path'], u'å b/copy 2.ipynb')
+        # copy with specified path
+        copy2 = cm.copy(path, u'/')
+        self.assertEqual(copy2['name'], name)
+        self.assertEqual(copy2['path'], name)
 
     def test_trust_notebook(self):
         cm = self.contents_manager