[Zope3-checkins] SVN: Zope3/trunk/ #356 : Copy and Paste does not handle exceptions raised by __setitem__

Julien Anguenot ja at nuxeo.com
Fri Jun 17 13:43:11 EDT 2005


Log message for revision 30831:
  #356 : Copy and Paste does not handle exceptions raised by __setitem__

Changed:
  U   Zope3/trunk/doc/CHANGES.txt
  U   Zope3/trunk/doc/TODO.txt
  U   Zope3/trunk/src/zope/app/authentication/browser/ftests.py
  U   Zope3/trunk/src/zope/app/authentication/principalfolder.py
  U   Zope3/trunk/src/zope/app/container/browser/contents.py

-=-
Modified: Zope3/trunk/doc/CHANGES.txt
===================================================================
--- Zope3/trunk/doc/CHANGES.txt	2005-06-17 17:19:15 UTC (rev 30830)
+++ Zope3/trunk/doc/CHANGES.txt	2005-06-17 17:43:11 UTC (rev 30831)
@@ -614,6 +614,9 @@
 
     Bug Fixes
 
+      - Fix #356 : Copy and Paste does not handle exceptions raised by
+        __setitem__
+
       - Made different key reference implementations comparable:IKeyReference
         interface is extended by an additional key_type_id attribute.
 

Modified: Zope3/trunk/doc/TODO.txt
===================================================================
--- Zope3/trunk/doc/TODO.txt	2005-06-17 17:19:15 UTC (rev 30830)
+++ Zope3/trunk/doc/TODO.txt	2005-06-17 17:43:11 UTC (rev 30831)
@@ -39,8 +39,6 @@
 
   * 344: PAU registration error
 
-  * 356: Copy and Paste does not handle exceptions raised by __setitem__
-
   * 372: WidgetInputError.doc is broken
 
   * 373: Adding objects requires permission zope.app.dublincore.change
@@ -53,4 +51,4 @@
 
 
 Bugs starting with * represent bugs that must be fixed for the 3.0.x branch as
-well.
+well .

Modified: Zope3/trunk/src/zope/app/authentication/browser/ftests.py
===================================================================
--- Zope3/trunk/src/zope/app/authentication/browser/ftests.py	2005-06-17 17:19:15 UTC (rev 30830)
+++ Zope3/trunk/src/zope/app/authentication/browser/ftests.py	2005-06-17 17:43:11 UTC (rev 30831)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2004 Zope Corporation and Contributors.
+# Copyright (c) 2004-2005 Zope Corporation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -17,14 +17,108 @@
 """
 import unittest
 
+from zope.app.testing import ztapi
+from zope.app.testing import functional
+
+import transaction
+
+from zope.interface import implements, Interface, directlyProvides
+from zope.app import copypastemove
+
+from zope.app.authentication.principalfolder import PrincipalFolder
+from zope.app.authentication.principalfolder import Principal
+from zope.app.authentication.principalfolder import IInternalPrincipal
+
+from zope.app.exception.interfaces import UserError
+
+class FunkTest(functional.BrowserTestCase):
+
+    def test_copypaste_duplicated_id_object(self):
+        
+        root = self.getRootFolder()
+
+        # Create a principal Folder
+        root['pf'] = PrincipalFolder()
+        pf = root['pf']
+
+        # Create a principal with p1 as login
+        principal = Principal('p1')
+        principal.login = 'p1'
+        directlyProvides(principal, IInternalPrincipal)
+
+        pf['p1'] = principal
+        
+        transaction.commit()
+        self.assertEqual(len(pf.keys()), 1)
+        #raise str([x for x in pf.keys()])
+
+        response = self.publish('/pf/@@contents.html',
+                                basic='mgr:mgrpw',
+                                form={'ids': [u'p1'],
+                                      'container_copy_button': u'Copy'})
+        self.assertEqual(response.getStatus(), 302)
+
+
+        # Try to paste the file
+        try:
+            response = self.publish('/pf/@@contents.html',
+                                    basic='mgr:mgrpw',
+                                    form={'container_paste_button': ''})
+        except UserError, e:
+            self.assertEqual(
+                str(e),
+                "The given name(s) [u'p1'] is / are already being used")
+        else:
+            # test failed !
+            self.asserEqual(1, 0)
+
+    def test_cutpaste_duplicated_id_object(self):
+
+        root = self.getRootFolder()
+
+        # Create a principal Folder
+        root['pf'] = PrincipalFolder()
+        pf = root['pf']
+
+        # Create a principal with p1 as login
+        principal = Principal('p1')
+        principal.login = 'p1'
+        directlyProvides(principal, IInternalPrincipal)
+
+        pf['p1'] = principal
+        
+        transaction.commit()
+        self.assertEqual(len(pf.keys()), 1)
+        #raise str([x for x in pf.keys()])
+
+        response = self.publish('/pf/@@contents.html',
+                                basic='mgr:mgrpw',
+                                form={'ids': [u'p1'],
+                                      'container_cut_button': u'Cut'})
+        self.assertEqual(response.getStatus(), 302)
+
+
+        # Try to paste the file
+        try:
+            response = self.publish('/pf/@@contents.html',
+                                    basic='mgr:mgrpw',
+                                    form={'container_paste_button': ''})
+        except UserError, e:
+            self.assertEqual(
+                str(e),
+                "The given name(s) [u'p1'] is / are already being used")
+        else:
+            # test failed !
+            self.asserEqual(1, 0)
+            
 def test_suite():
-    from zope.app.testing import functional
     return unittest.TestSuite((
         functional.FunctionalDocFileSuite('principalfolder.txt'),
         functional.FunctionalDocFileSuite('groupfolder.txt'),
         functional.FunctionalDocFileSuite(
             'group_searching_with_empty_string.txt'),
         functional.FunctionalDocFileSuite('special-groups.txt'),
+        unittest.makeSuite(FunkTest),
         ))
 
 if __name__ == '__main__':

Modified: Zope3/trunk/src/zope/app/authentication/principalfolder.py
===================================================================
--- Zope3/trunk/src/zope/app/authentication/principalfolder.py	2005-06-17 17:19:15 UTC (rev 30830)
+++ Zope3/trunk/src/zope/app/authentication/principalfolder.py	2005-06-17 17:43:11 UTC (rev 30831)
@@ -25,6 +25,7 @@
 from zope.publisher.interfaces import IRequest
 from zope.security.interfaces import IGroupAwarePrincipal
 
+from zope.app.container.interfaces import DuplicateIDError
 from zope.app.container.contained import Contained
 from zope.app.container.constraints import contains, containers
 from zope.app.container.btree import BTreeContainer
@@ -186,10 +187,34 @@
         self.__id_by_login[principal.login] = principal.__name__
 
     def __setitem__(self, id, principal):
-        """Add principal information."""
+        """Add principal information.
+
+        Create a Principal Folder
+
+            >>> pf = PrincipalFolder()
+
+        Create a principal with 1 as id
+        Add a login attr since __setitem__ is in need of one
+        
+            >>> principal = Principal(1)
+            >>> principal.login = 1
+
+        Add the principal within the Principal Folder
+
+            >>> pf.__setitem__(u'1', principal)
+
+        Try to add another principal with the same id.
+        It should raise a DuplicateIDError
+
+            >>> try:
+            ...     pf.__setitem__(u'1', principal)
+            ... except DuplicateIDError, e:
+            ...     pass
+            >>>
+        """
         # A user with the new login already exists
         if principal.login in self.__id_by_login:
-            raise ValueError, 'Principal Login already taken!'
+            raise DuplicateIDError, 'Principal Login already taken!'
 
         super(PrincipalFolder, self).__setitem__(id, principal)
         self.__id_by_login[principal.login] = id

Modified: Zope3/trunk/src/zope/app/container/browser/contents.py
===================================================================
--- Zope3/trunk/src/zope/app/container/browser/contents.py	2005-06-17 17:19:15 UTC (rev 30830)
+++ Zope3/trunk/src/zope/app/container/browser/contents.py	2005-06-17 17:43:11 UTC (rev 30831)
@@ -19,6 +19,7 @@
 
 import urllib
 
+from zope.app.exception.interfaces import UserError
 from zope.app.traversing.interfaces import TraversalError
 from zope.security.interfaces import Unauthorized
 from zope.security import checkPermission
@@ -39,6 +40,7 @@
 from zope.app.container.browser.adding import Adding
 from zope.app.container.interfaces import IContainer
 from zope.app.container.interfaces import IContainerNamesContainer
+from zope.app.container.interfaces import DuplicateIDError
 
 class Contents(BrowserView):
 
@@ -365,26 +367,45 @@
         clipboard = getPrincipalClipboard(self.request)
         items = clipboard.getContents()
         moved = False
+        not_pasteable_ids = []
         for item in items:
+            duplicated_id = False
             try:
                 obj = zapi.traverse(target, item['target'])
             except TraversalError:
                 pass
             else:
                 if item['action'] == 'cut':
-                    mover = IObjectMover(obj)
-                    mover.moveTo(target)
-                    moved = True
+                    try:
+                        mover = IObjectMover(obj)
+                        mover.moveTo(target)
+                        moved = True
+                    except DuplicateIDError:
+                        duplicated_id = True
                 elif item['action'] == 'copy':
-                    copier = IObjectCopier(obj)
-                    copier.copyTo(target)
+                    try:
+                        copier = IObjectCopier(obj)
+                        copier.copyTo(target)
+                    except DuplicateIDError:
+                        duplicated_id = True
                 else:
                     raise
 
+            if duplicated_id:
+                not_pasteable_ids.append(zapi.getName(obj))                
+
         if moved:
             # Clear the clipboard if we do a move, but not if we only do a copy
             clipboard.clearContents()
 
+        if not_pasteable_ids != []:
+            # Show the ids of objects that can't be pasted because
+            # their ids are already taken.
+            # XXX Can't we add a 'copy_of' or something as a prefix
+            # instead of raising an exception ?
+            raise UserError(
+                _("The given name(s) %s is / are already being used" %(
+                str(not_pasteable_ids))))
 
     def hasClipboardContents(self):
         """ interogates the `PrinicipalAnnotation` to see if



More information about the Zope3-Checkins mailing list