[Zope3-checkins] CVS: Zope3/src/zope/app - copypastemove.py:1.13

Kiran Jonnalagadda jace at pobox.com
Wed Dec 10 08:07:53 EST 2003


Update of /cvs-repository/Zope3/src/zope/app
In directory cvs.zope.org:/tmp/cvs-serv29773/src/zope/app

Modified Files:
	copypastemove.py 
Log Message:
Copy/Move now checks constraints and preconditions, instead of just
expecting the source's and target's class to be the same.


=== Zope3/src/zope/app/copypastemove.py 1.12 => 1.13 ===
--- Zope3/src/zope/app/copypastemove.py:1.12	Mon Nov  3 23:04:28 2003
+++ Zope3/src/zope/app/copypastemove.py	Wed Dec 10 08:07:53 2003
@@ -29,6 +29,9 @@
 from zope.interface import implements
 from zope.exceptions import NotFoundError, DuplicationError
 from zope.proxy import removeAllProxies
+from zope.component.exceptions import ComponentLookupError
+from zope.app.container.constraints import checkObject
+from zope.interface import Invalid
 
 class ObjectMover:
     """Adapter for moving objects between containers
@@ -65,7 +68,9 @@
     >>> mover.moveableTo(container2)
     1
     >>> mover.moveableTo({})
-    0
+    Traceback (most recent call last):
+    ...
+    TypeError: Container is not a valid Zope container.
 
     Of course, once we've decided we can move an object, we can use
     the mover to do so:
@@ -77,7 +82,7 @@
     [u'foo']
     >>> ob.__parent__ is container2
     1
-    
+
     We can also specify a name:
 
     >>> mover.moveTo(container2, u'bar')
@@ -99,15 +104,67 @@
     [u'splat', u'splat_']
     >>> ob.__name__
     u'splat_'
-    
+
 
     If we try to move to an invalid container, we'll get an error:
 
     >>> mover.moveTo({})
     Traceback (most recent call last):
     ...
-    TypeError: Can only move objects between like containers
-        
+    TypeError: Container is not a valid Zope container.
+
+
+    Do a test for preconditions:
+
+    >>> import zope.interface
+    >>> import zope.schema
+    >>> def preNoZ(container, name, ob):
+    ...     "Silly precondition example"
+    ...     if name.startswith("Z"):
+    ...         raise zope.interface.Invalid("Invalid name.")
+
+    >>> class I1(zope.interface.Interface):
+    ...     def __setitem__(name, on):
+    ...         "Add an item"
+    ...     __setitem__.precondition = preNoZ
+
+    >>> from zope.app.interfaces.container import IContainer
+    >>> class C1:
+    ...     zope.interface.implements(I1, IContainer)
+    ...     def __repr__(self):
+    ...         return 'C1'
+
+    >>> from zope.app.container.constraints import checkObject
+    >>> container3 = C1()
+    >>> mover.moveableTo(container3, 'ZDummy')
+    0
+    >>> mover.moveableTo(container3, 'newName')
+    1
+
+    And a test for constraints:
+
+    >>> def con1(container):
+    ...     "silly container constraint"
+    ...     if not hasattr(container, 'x'):
+    ...         return False
+    ...     return True
+    ...
+    >>> class I2(zope.interface.Interface):
+    ...     __parent__ = zope.schema.Field(constraint = con1)
+    ...
+    >>> class constrainedObject:
+    ...     zope.interface.implements(I2)
+    ...     def __init__(self):
+    ...         self.__name__ = 'constrainedObject'
+    ...
+    >>> cO = constrainedObject()
+    >>> mover2 = ObjectMover(cO)
+    >>> mover2.moveableTo(container)
+    0
+    >>> container.x = 1
+    >>> mover2.moveableTo(container)
+    1
+
     """
 
     implements(IObjectMover)
@@ -124,17 +181,12 @@
         obj = self.context
         container = obj.__parent__
 
-        # XXX Only allow moving between the same types of containers for
-        # now, until we can properly implement containment constraints:
-        if target.__class__ != container.__class__:
-            raise TypeError(
-                _("Can only move objects between like containers")
-                )
-        
         orig_name = obj.__name__
         if new_name is None:
             new_name = orig_name
 
+        checkObject(target, new_name, obj)
+
         if target is container and new_name == orig_name:
             # Nothing to do
             return
@@ -158,7 +210,13 @@
         Returns True if it can be moved there. Otherwise, returns
         false.
         '''
-        return self.context.__parent__.__class__ == target.__class__ 
+        if name is None:
+            name = self.context.__name__
+        try:
+            checkObject(target, name, self.context)
+        except Invalid:
+            return 0
+        return 1
 
 class ObjectCopier:
     """Adapter for copying objects between containers
@@ -195,7 +253,9 @@
     >>> copier.copyableTo(container2)
     1
     >>> copier.copyableTo({})
-    0
+    Traceback (most recent call last):
+    ...
+    TypeError: Container is not a valid Zope container.
 
     Of course, once we've decided we can copy an object, we can use
     the copier to do so:
@@ -213,7 +273,7 @@
     1
     >>> container2[u'foo'].__name__
     u'foo'
-    
+
     We can also specify a name:
 
     >>> copier.copyTo(container2, u'bar')
@@ -241,15 +301,66 @@
     [u'bar', u'bar_', u'foo']
     >>> container2[u'bar_'].__name__
     u'bar_'
-    
+
 
     If we try to copy to an invalid container, we'll get an error:
 
     >>> copier.copyTo({})
     Traceback (most recent call last):
     ...
-    TypeError: Can only copy objects to like containers
-        
+    TypeError: Container is not a valid Zope container.
+
+    Do a test for preconditions:
+
+    >>> import zope.interface
+    >>> import zope.schema
+    >>> def preNoZ(container, name, ob):
+    ...     "Silly precondition example"
+    ...     if name.startswith("Z"):
+    ...         raise zope.interface.Invalid("Invalid name.")
+
+    >>> class I1(zope.interface.Interface):
+    ...     def __setitem__(name, on):
+    ...         "Add an item"
+    ...     __setitem__.precondition = preNoZ
+
+    >>> from zope.app.interfaces.container import IContainer
+    >>> class C1:
+    ...     zope.interface.implements(I1, IContainer)
+    ...     def __repr__(self):
+    ...         return 'C1'
+
+    >>> from zope.app.container.constraints import checkObject
+    >>> container3 = C1()
+    >>> copier.copyableTo(container3, 'ZDummy')
+    0
+    >>> copier.copyableTo(container3, 'newName')
+    1
+
+    And a test for constraints:
+
+    >>> def con1(container):
+    ...     "silly container constraint"
+    ...     if not hasattr(container, 'x'):
+    ...         return False
+    ...     return True
+    ...
+    >>> class I2(zope.interface.Interface):
+    ...     __parent__ = zope.schema.Field(constraint = con1)
+    ...
+    >>> class constrainedObject:
+    ...     zope.interface.implements(I2)
+    ...     def __init__(self):
+    ...         self.__name__ = 'constrainedObject'
+    ...
+    >>> cO = constrainedObject()
+    >>> copier2 = ObjectCopier(cO)
+    >>> copier2.copyableTo(container)
+    0
+    >>> container.x = 1
+    >>> copier2.copyableTo(container)
+    1
+
     """
 
     implements(IObjectCopier)
@@ -271,17 +382,12 @@
         obj = self.context
         container = obj.__parent__
 
-        # XXX Only allow moving between the same types of containers for
-        # now, until we can properly implement containment constraints:
-        if target.__class__ != container.__class__:
-            raise TypeError(
-                _("Can only copy objects to like containers")
-                )
-
         orig_name = obj.__name__
         if new_name is None:
             new_name = orig_name
 
+        checkObject(target, new_name, obj)
+
         chooser = zapi.getAdapter(target, INameChooser)
         new_name = chooser.chooseName(new_name, obj)
 
@@ -302,7 +408,13 @@
         Returns True if it can be copied there. Otherwise, returns
         False.
         '''
-        return self.context.__parent__.__class__ == target.__class__ 
+        if name is None:
+            name = self.context.__name__
+        try:
+            checkObject(target, name, self.context)
+        except Invalid:
+            return 0
+        return 1
 
 
 class PrincipalClipboard:




More information about the Zope3-Checkins mailing list