[Commits] (vajda) - added Item.onItemDelete() hook

commits at osafoundation.org commits at osafoundation.org
Wed Feb 2 12:15:55 PST 2005


Commit by: vajda
Modified files:
chandler/repository/item/Item.py 1.192 1.193
chandler/repository/item/ItemError.py 1.5 1.6
chandler/repository/item/Monitors.py 1.7 1.8
chandler/repository/schema/Cloud.py 1.22 1.23
chandler/repository/tests/TestDelete.py 1.2 1.3

Log message:
   - added Item.onItemDelete() hook
   - first pass at cloud-based deletion


ViewCVS links:
http://cvs.osafoundation.org/index.cgi/chandler/repository/item/Item.py.diff?r1=text&tr1=1.192&r2=text&tr2=1.193
http://cvs.osafoundation.org/index.cgi/chandler/repository/item/ItemError.py.diff?r1=text&tr1=1.5&r2=text&tr2=1.6
http://cvs.osafoundation.org/index.cgi/chandler/repository/item/Monitors.py.diff?r1=text&tr1=1.7&r2=text&tr2=1.8
http://cvs.osafoundation.org/index.cgi/chandler/repository/schema/Cloud.py.diff?r1=text&tr1=1.22&r2=text&tr2=1.23
http://cvs.osafoundation.org/index.cgi/chandler/repository/tests/TestDelete.py.diff?r1=text&tr1=1.2&r2=text&tr2=1.3

Index: chandler/repository/schema/Cloud.py
diff -u chandler/repository/schema/Cloud.py:1.22 chandler/repository/schema/Cloud.py:1.23
--- chandler/repository/schema/Cloud.py:1.22	Fri Jan 21 11:16:07 2005
+++ chandler/repository/schema/Cloud.py	Wed Feb  2 12:15:52 2005
@@ -1,12 +1,13 @@
 
-__revision__  = "$Revision: 1.22 $"
-__date__      = "$Date: 2005/01/21 19:16:07 $"
+__revision__  = "$Revision: 1.23 $"
+__date__      = "$Date: 2005/02/02 20:15:52 $"
 __copyright__ = "Copyright (c) 2004 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
 import re
 
 from repository.item.Item import Item
+from repository.item.ItemError import RecursiveDeleteError
 from repository.item.RefCollections import RefList
 from repository.item.PersistentCollections import PersistentCollection
 from repository.remote.CloudFilter import CloudFilter, EndpointFilter
@@ -161,6 +162,54 @@
                 
         return results
 
+    def deleteItems(self, item, recursive=False, cloudAlias=None):
+        """
+        Delete all items in the cloud.
+
+        Items are first gathered as documented in L{getItems}. They are then
+        deleted as follows:
+
+            - items in the result set returned by L{getItems} are deleted.
+
+            - references to items in the C{references} dictionary upon
+              returning from L{getItems}, that is, references to items that
+              are not considered part of the cloud but are nonetheless
+              referenced by items in it are removed.
+
+        It is an error to delete an item with children unless C{recursive}
+        is set to C{True}.
+
+        @param item: the entry point of the cloud.
+        @type item: an C{Item<repository.item.Item.Item>} instance
+        @param recursive: C{True} to recursively delete the items' children
+        too, C{False} otherwise (the default).
+        @type recursive: boolean
+        @param cloudAlias: the optional alias name to use for C{byCloud}
+        policy endpoints where the cloud is unspecified.
+        @type cloudAlias: a string
+        @return: the list of all item copies considered part of the cloud.
+        """
+
+        items = {}
+        references = {}
+        deleting = self.getItems(item, cloudAlias, items, references)
+
+        def deleteItem(item):
+            if not (item.isDeleted() or item.isDeleting()):
+                if recursive:
+                    item.delete(recursive=True, deletePolicy='remove')
+                else:
+                    if item.hasChildren():
+                        for child in item.iterChildren():
+                            if child._uuid in items:
+                                deleteItem(child)
+                            else:
+                                raise RecursiveDeleteError, item
+                    item.delete(deletePolicy='remove')
+
+        for item in deleting:
+            deleteItem(item)
+
     def getAttributeEndpoints(self, attrName, index=0, cloudAlias=None):
 
         endpoints = []

Index: chandler/repository/item/ItemError.py
diff -u chandler/repository/item/ItemError.py:1.5 chandler/repository/item/ItemError.py:1.6
--- chandler/repository/item/ItemError.py:1.5	Tue Jan 11 14:11:59 2005
+++ chandler/repository/item/ItemError.py	Wed Feb  2 12:15:52 2005
@@ -1,6 +1,6 @@
 
-__revision__  = "$Revision: 1.5 $"
-__date__      = "$Date: 2005/01/11 22:11:59 $"
+__revision__  = "$Revision: 1.6 $"
+__date__      = "$Date: 2005/02/02 20:15:52 $"
 __copyright__ = "Copyright (c) 2003-2004 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -55,6 +55,13 @@
                               self.args[1])
 
 
+class RecursiveDeleteError(ValueError, ItemError):
+    'Item %s has children, delete must be recursive'
+
+    def __str__(self):
+        return self.__doc__ %(self.getItem()._repr_())
+
+
 class NoSuchItemInCollectionError(ValueError, ItemError):
     "Item %s: no item %s in collection on attribute '%s'"
 

Index: chandler/repository/item/Monitors.py
diff -u chandler/repository/item/Monitors.py:1.7 chandler/repository/item/Monitors.py:1.8
--- chandler/repository/item/Monitors.py:1.7	Fri Jan 28 15:45:11 2005
+++ chandler/repository/item/Monitors.py	Wed Feb  2 12:15:52 2005
@@ -1,6 +1,6 @@
 
-__revision__  = "$Revision: 1.7 $"
-__date__      = "$Date: 2005/01/28 23:45:11 $"
+__revision__  = "$Revision: 1.8 $"
+__date__      = "$Date: 2005/02/02 20:15:52 $"
 __copyright__ = "Copyright (c) 2004 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -13,11 +13,8 @@
 
         if not view.isRefCounted():
             self.setPinned()
-        Monitors.instances[view] = self
 
-        if 'monitoring' not in self._values:
-            self.setAttributeValue('monitoring', { 'set': {} },
-                                   _attrDict=self._values)
+        Monitors.instances[view] = self
 
     def getInstance(cls, view):
 
@@ -73,4 +70,4 @@
 # recursive import prevention
 #
 
-Item._invokeMonitors = Monitors.invoke
+Item._monitorsClass = Monitors

Index: chandler/repository/item/Item.py
diff -u chandler/repository/item/Item.py:1.192 chandler/repository/item/Item.py:1.193
--- chandler/repository/item/Item.py:1.192	Fri Jan 28 15:45:11 2005
+++ chandler/repository/item/Item.py	Wed Feb  2 12:15:52 2005
@@ -1,6 +1,6 @@
 
-__revision__  = "$Revision: 1.192 $"
-__date__      = "$Date: 2005/01/28 23:45:11 $"
+__revision__  = "$Revision: 1.193 $"
+__date__      = "$Date: 2005/02/02 20:15:52 $"
 __copyright__ = "Copyright (c) 2003-2004 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -1267,8 +1267,7 @@
                 assert attrDict is not None
                 attrDict._setDirty(attribute)
                 if not noMonitors:
-                    # Item._invokeMonitors is defined in Monitors.py
-                    Item._invokeMonitors('set', self, attribute)
+                    Item._monitorsClass.invoke('set', self, attribute)
                 
             self._lastAccess = Item._countAccess()
             if self._status & Item.DIRTY == 0:
@@ -1406,42 +1405,71 @@
 
         return item
 
-    def delete(self, recursive=False):
+    def delete(self, recursive=False, deletePolicy=None, cloudAlias=None):
         """
         Delete this item.
 
+        By default, an attribute's deletePolicy aspect is C{remove} for
+        bi-directional references.
+
         If this item has references to other items and the C{deletePolicy}
         aspect of the attributes containing them is C{cascade} then these
-        other items are deleted too.
+        other items are deleted too when their count of counted references
+        is zero. References in an attribute are counted when the countPolicy
+        of the attribute is C{count}. It is C{none} by default.
+
+        Attribute delete policies can be overriden with a
+        L{Cloud<repository.schema.Cloud.Cloud>} instance to drive the delete
+        operation by using the C{cloudAlias} argument.
 
         It is an error to delete an item with children unless C{recursive}
         is set to C{True}.
 
+        If this item has an C{onItemDelete} method defined, it is invoked
+        before the item's deletion process is started.
+
+        @param deletePolicy: an optional deletePolicy to override the reference
+        attributes delete policies with.
+        @type deletePolicy: a string
+        @param cloudAlias: the optional alias name of a cloud in the item's
+        kind clouds list.
+        @type cloudAlias: a string
         @param recursive: C{True} to recursively delete this item's children
         too, C{False} otherwise (the default).
         @type recursive: boolean
         """
 
-        if not self._status & (Item.DELETED | Item.DELETING):
+        if cloudAlias is not None:
+            clouds = self._kind.getClouds(cloudAlias)
+            for cloud in clouds:
+                cloud.deleteItems(self, recursive, cloudAlias)
+            
+        elif not self._status & (Item.DELETED | Item.DELETING):
 
             if self._status & Item.STALE:
                 raise StaleItemError, self
 
             if not recursive and self.hasChildren():
-                raise ValueError, 'item %s has children, delete must be recursive' %(self)
+                raise RecursiveDeleteError, self
+
+            view = self.getRepositoryView()
+
+            if hasattr(type(self), 'onItemDelete'):
+                self.onItemDelete(view)
 
             self.setDirty(Item.NDIRTY)
             self._status |= Item.DELETING
             others = []
 
             for child in self.iterChildren():
-                child.delete(True)
+                child.delete(recursive=True, deletePolicy=deletePolicy)
 
             self._values.clear()
 
             for name in self._references.keys():
-                policy = self.getAttributeAspect(name, 'deletePolicy',
-                                                 default='remove')
+                policy = (deletePolicy or
+                          self.getAttributeAspect(name, 'deletePolicy',
+                                                  default='remove'))
                 if policy == 'cascade':
                     value = self._references._getRef(name)
                     if value is not None:
@@ -1452,10 +1480,7 @@
                     
                 self.removeAttributeValue(name, _attrDict=self._references)
 
-            parent = self.itsParent
-            view = self.getRepositoryView()
-            
-            parent._removeItem(self)
+            self.itsParent._removeItem(self)
             self._setRoot(None, view)
 
             self._status |= Item.DELETED | Item.STALE
@@ -1463,7 +1488,7 @@
 
             for other in others:
                 if other.refCount(counted=True) == 0:
-                    other.delete()
+                    other.delete(recursive=recursive, deletePolicy=deletePolicy)
 
             self._kind = None
             

Index: chandler/repository/tests/TestDelete.py
diff -u chandler/repository/tests/TestDelete.py:1.2 chandler/repository/tests/TestDelete.py:1.3
--- chandler/repository/tests/TestDelete.py:1.2	Sat Jan 15 22:12:52 2005
+++ chandler/repository/tests/TestDelete.py	Wed Feb  2 12:15:53 2005
@@ -2,8 +2,8 @@
 Test deletion of items
 """
 
-__revision__  = "$Revision: 1.2 $"
-__date__      = "$Date: 2005/01/16 06:12:52 $"
+__revision__  = "$Revision: 1.3 $"
+__date__      = "$Date: 2005/02/02 20:15:53 $"
 __copyright__ = "Copyright (c) 2003-2004 Open Source Applications Foundation"
 __license__   = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
 
@@ -29,6 +29,7 @@
     def testDeleteItemsInCollection(self):
 
         tools.timing.reset()
+
         self._reopenRepository()
         k = self.rep.findPath('//CineGuide/KHepburn')
         for m in k.movies:
@@ -44,6 +45,20 @@
 
         tools.timing.results(verbose=False)
 
+    def testCloudDelete(self):
+
+        tools.timing.reset()
+
+        k = self.rep.findPath('//CineGuide/KHepburn')
+        k.delete(cloudAlias='remote')
+        self.rep.commit()
+        self.rep.check()
+        self._reopenRepository()
+        self.rep.check()
+
+        tools.timing.results(verbose=False)
+        
+
 if __name__ == "__main__":
 #    import hotshot
 #    profiler = hotshot.Profile('/tmp/TestItems.hotshot')



More information about the Commits mailing list