[Zope-Checkins] SVN: Zope/branches/philikon-zope32-integration/ Zope now sends Zope 3 events when objects are added or removed from

Florent Guillaume fg at nuxeo.com
Mon Oct 31 15:09:40 EST 2005


Log message for revision 39784:
  Zope now sends Zope 3 events when objects are added or removed from
  standard containers. manage_afterAdd, manage_beforeDelete and
  manage_afterClone are now deprecated. See
  lib/python/Products/Five/tests/event.txt for details.
  
  This requires Five 1.3 (included in Zope 2.9).
  
  

Changed:
  U   Zope/branches/philikon-zope32-integration/doc/CHANGES.txt
  U   Zope/branches/philikon-zope32-integration/lib/python/OFS/Application.py
  U   Zope/branches/philikon-zope32-integration/lib/python/OFS/CopySupport.py
  U   Zope/branches/philikon-zope32-integration/lib/python/OFS/ObjectManager.py
  U   Zope/branches/philikon-zope32-integration/lib/python/OFS/OrderSupport.py
  U   Zope/branches/philikon-zope32-integration/lib/python/OFS/SimpleItem.py
  U   Zope/branches/philikon-zope32-integration/lib/python/Products/BTreeFolder2/BTreeFolder2.py

-=-
Modified: Zope/branches/philikon-zope32-integration/doc/CHANGES.txt
===================================================================
--- Zope/branches/philikon-zope32-integration/doc/CHANGES.txt	2005-10-31 20:04:14 UTC (rev 39783)
+++ Zope/branches/philikon-zope32-integration/doc/CHANGES.txt	2005-10-31 20:09:39 UTC (rev 39784)
@@ -26,6 +26,11 @@
 
     Features added
 
+      - Zope now sends Zope 3 events when objects are added or removed
+        from standard containers. manage_afterAdd, manage_beforeDelete
+        and manage_afterClone are now deprecated. See
+        lib/python/Products/Five/tests/event.txt for details.
+
       - Zope now utilizes ZODB 3.6.  It had previously used
         ZODB 3.4.  As a result, the DBTab package was removed, as
         ZODB 3.6 has multidatabase support that makes DBTab

Modified: Zope/branches/philikon-zope32-integration/lib/python/OFS/Application.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/OFS/Application.py	2005-10-31 20:04:14 UTC (rev 39783)
+++ Zope/branches/philikon-zope32-integration/lib/python/OFS/Application.py	2005-10-31 20:09:39 UTC (rev 39784)
@@ -459,6 +459,10 @@
             from Products.Sessions.BrowserIdManager import BrowserIdManager
             bid = BrowserIdManager('browser_id_manager', 'Browser Id Manager')
             app._setObject('browser_id_manager', bid)
+            # FIXME explicitely call manage_afterAdd, as sometimes
+            # events are initialized too late
+            browser_id_manager = app.browser_id_manager
+            browser_id_manager.manage_afterAdd(browser_id_manager, app)
             app._setInitializerFlag('browser_id_manager')
             self.commit('Added browser_id_manager')
 
@@ -475,6 +479,10 @@
                 path='/temp_folder/session_data',
                 requestName='SESSION')
             app._setObject('session_data_manager', sdm)
+            # FIXME explicitely call manage_afterAdd, as sometimes
+            # events are initialized too late
+            session_data_manager = app.session_data_manager
+            session_data_manager.manage_afterAdd(session_data_manager, app)
             app._setInitializerFlag('session_data_manager')
             self.commit('Added session_data_manager')
 
@@ -523,6 +531,10 @@
             from Products.SiteErrorLog.SiteErrorLog import SiteErrorLog
             error_log = SiteErrorLog()
             app._setObject('error_log', error_log)
+            # FIXME explicitely call manage_afterAdd, as sometimes
+            # events are initialized too late
+            error_log = app.error_log
+            error_log.manage_afterAdd(error_log, app)
             app._setInitializerFlag('error_log')
             self.commit('Added site error_log at /error_log')
 

Modified: Zope/branches/philikon-zope32-integration/lib/python/OFS/CopySupport.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/OFS/CopySupport.py	2005-10-31 20:04:14 UTC (rev 39783)
+++ Zope/branches/philikon-zope32-integration/lib/python/OFS/CopySupport.py	2005-10-31 20:09:39 UTC (rev 39784)
@@ -30,6 +30,11 @@
 from webdav.Lockable import ResourceLockedError
 from zExceptions import Unauthorized, BadRequest
 from zope.interface import implements
+from zope.event import notify
+from zope.app.event.objectevent import ObjectCopiedEvent
+from zope.app.container.contained import ObjectMovedEvent
+from Products.Five.event import ObjectWillBeMovedEvent
+from Products.Five.event import FiveObjectClonedEvent
 
 from OFS.interfaces import ICopyContainer
 from OFS.interfaces import ICopySource
@@ -154,85 +159,123 @@
         If calling manage_pasteObjects from python code, pass the result of a
         previous call to manage_cutObjects or manage_copyObjects as the first
         argument.
+
+        Also sends IObjectCopiedEvent and IFiveObjectClonedEvent
+        or IObjectWillBeMovedEvent and IObjectMovedEvent.
         """
-        cp=None
+        # Done here to avoid circular imports
+        from Products.Five.subscribers import maybeCallDeprecated
+
         if cb_copy_data is not None:
-            cp=cb_copy_data
+            cp = cb_copy_data
+        elif REQUEST is not None and REQUEST.has_key('__cp'):
+            cp = REQUEST['__cp']
         else:
-            if REQUEST and REQUEST.has_key('__cp'):
-                cp=REQUEST['__cp']
+            cp = None
         if cp is None:
             raise CopyError, eNoData
 
-        try:    cp=_cb_decode(cp)
-        except: raise CopyError, eInvalid
+        try:
+            op, mdatas = _cb_decode(cp)
+        except:
+            raise CopyError, eInvalid
 
-        oblist=[]
-        op=cp[0]
+        oblist = []
         app = self.getPhysicalRoot()
-        result = []
-
-        for mdata in cp[1]:
+        for mdata in mdatas:
             m = Moniker.loadMoniker(mdata)
-            try: ob = m.bind(app)
-            except: raise CopyError, eNotFound
+            try:
+                ob = m.bind(app)
+            except ConflictError:
+                raise
+            except:
+                raise CopyError, eNotFound
             self._verifyObjectPaste(ob, validate_src=op+1)
             oblist.append(ob)
 
-        if op==0:
+        result = []
+        if op == 0:
             # Copy operation
             for ob in oblist:
+                orig_id = ob.getId()
                 if not ob.cb_isCopyable():
-                    raise CopyError, eNotSupported % escape(ob.getId())
-                try:    ob._notifyOfCopyTo(self, op=0)
-                except: raise CopyError, MessageDialog(
-                    title='Copy Error',
-                    message=sys.exc_info()[1],
-                    action ='manage_main')
-                ob=ob._getCopy(self)
-                orig_id=ob.getId()
-                id=self._get_id(ob.getId())
-                result.append({'id':orig_id, 'new_id':id})
+                    raise CopyError, eNotSupported % escape(orig_id)
+
+                try:
+                    ob._notifyOfCopyTo(self, op=0)
+                except ConflictError:
+                    raise
+                except:
+                    raise CopyError, MessageDialog(
+                        title="Copy Error",
+                        message=sys.exc_info()[1],
+                        action='manage_main')
+
+                id = self._get_id(orig_id)
+                result.append({'id': orig_id, 'new_id': id})
+
+                ob = ob._getCopy(self)
                 ob._setId(id)
+                notify(ObjectCopiedEvent(ob))
+
                 self._setObject(id, ob)
                 ob = self._getOb(id)
-                ob._postCopy(self, op=0)
-                ob.manage_afterClone(ob)
                 ob.wl_clearLocks()
 
+                ob._postCopy(self, op=0)
+
+                maybeCallDeprecated('manage_afterClone', ob)
+
+                notify(FiveObjectClonedEvent(ob))
+
             if REQUEST is not None:
                 return self.manage_main(self, REQUEST, update_menu=1,
                                         cb_dataValid=1)
 
-        if op==1:
+        elif op == 1:
             # Move operation
             for ob in oblist:
-                id=ob.getId()
+                orig_id = ob.getId()
                 if not ob.cb_isMoveable():
-                    raise CopyError, eNotSupported % escape(id)
-                try:    ob._notifyOfCopyTo(self, op=1)
-                except: raise CopyError, MessageDialog(
-                    title='Move Error',
-                    message=sys.exc_info()[1],
-                    action ='manage_main')
+                    raise CopyError, eNotSupported % escape(orig_id)
+
+                try:
+                    ob._notifyOfCopyTo(self, op=1)
+                except ConflictError:
+                    raise
+                except:
+                    raise CopyError, MessageDialog(
+                        title="Move Error",
+                        message=sys.exc_info()[1],
+                        action='manage_main')
+
                 if not sanity_check(self, ob):
-                    raise CopyError, 'This object cannot be pasted into itself'
+                    raise CopyError, "This object cannot be pasted into itself"
 
+                orig_container = aq_parent(aq_inner(ob))
+                if aq_base(orig_container) is aq_base(self):
+                    id = orig_id
+                else:
+                    id = self._get_id(orig_id)
+                result.append({'id': orig_id, 'new_id': id})
+
+                notify(ObjectWillBeMovedEvent(ob, orig_container, orig_id,
+                                              self, id))
+
                 # try to make ownership explicit so that it gets carried
                 # along to the new location if needed.
                 ob.manage_changeOwnershipType(explicit=1)
 
-                aq_parent(aq_inner(ob))._delObject(id)
+                orig_container._delObject(orig_id, suppress_events=True)
                 ob = aq_base(ob)
-                orig_id=id
-                id=self._get_id(id)
-                result.append({'id':orig_id, 'new_id':id })
+                ob._setId(id)
 
-                ob._setId(id)
-                self._setObject(id, ob, set_owner=0)
-                ob=self._getOb(id)
+                self._setObject(id, ob, set_owner=0, suppress_events=True)
+                ob = self._getOb(id)
+
+                notify(ObjectMovedEvent(ob, orig_container, orig_id, self, id))
+
                 ob._postCopy(self, op=1)
-
                 # try to make ownership implicit if possible
                 ob.manage_changeOwnershipType(explicit=0)
 
@@ -243,6 +286,7 @@
                 REQUEST['__cp'] = None
                 return self.manage_main(self, REQUEST, update_menu=1,
                                         cb_dataValid=0)
+
         return result
 
     manage_renameForm=Globals.DTMLFile('dtml/renameForm', globals())
@@ -259,31 +303,48 @@
         return None
 
     def manage_renameObject(self, id, new_id, REQUEST=None):
-        """Rename a particular sub-object"""
-        try: self._checkId(new_id)
-        except: raise CopyError, MessageDialog(
-                      title='Invalid Id',
-                      message=sys.exc_info()[1],
-                      action ='manage_main')
-        ob=self._getOb(id)
+        """Rename a particular sub-object.
+        """
+        try:
+            self._checkId(new_id)
+        except:
+            raise CopyError, MessageDialog(
+                title='Invalid Id',
+                message=sys.exc_info()[1],
+                action ='manage_main')
+
+        ob = self._getOb(id)
+
         if ob.wl_isLocked():
-            raise ResourceLockedError, 'Object "%s" is locked via WebDAV' % ob.getId()
+            raise ResourceLockedError, ('Object "%s" is locked via WebDAV'
+                                        % ob.getId())
         if not ob.cb_isMoveable():
             raise CopyError, eNotSupported % escape(id)
         self._verifyObjectPaste(ob)
-        try:    ob._notifyOfCopyTo(self, op=1)
-        except: raise CopyError, MessageDialog(
-                      title='Rename Error',
-                      message=sys.exc_info()[1],
-                      action ='manage_main')
-        self._delObject(id)
+
+        try:
+            ob._notifyOfCopyTo(self, op=1)
+        except ConflictError:
+            raise
+        except:
+            raise CopyError, MessageDialog(
+                title="Rename Error",
+                message=sys.exc_info()[1],
+                action ='manage_main')
+
+        notify(ObjectWillBeMovedEvent(ob, self, id, self, new_id))
+
+        self._delObject(id, suppress_events=True)
         ob = aq_base(ob)
         ob._setId(new_id)
 
         # Note - because a rename always keeps the same context, we
         # can just leave the ownership info unchanged.
-        self._setObject(new_id, ob, set_owner=0)
+        self._setObject(new_id, ob, set_owner=0, suppress_events=True)
         ob = self._getOb(new_id)
+
+        notify(ObjectMovedEvent(ob, self, id, self, new_id))
+
         ob._postCopy(self, op=1)
 
         if REQUEST is not None:
@@ -296,26 +357,46 @@
     # Because it's still a "management" function.
     manage_clone__roles__=None
     def manage_clone(self, ob, id, REQUEST=None):
-        # Clone an object, creating a new object with the given id.
+        """Clone an object, creating a new object with the given id.
+        """
+        # Done here to avoid circular imports
+        from Products.Five.subscribers import maybeCallDeprecated
+
         if not ob.cb_isCopyable():
             raise CopyError, eNotSupported % escape(ob.getId())
-        try: self._checkId(id)
-        except: raise CopyError, MessageDialog(
-                      title='Invalid Id',
-                      message=sys.exc_info()[1],
-                      action ='manage_main')
+        try:
+            self._checkId(id)
+        except:
+            raise CopyError, MessageDialog(
+                title='Invalid Id',
+                message=sys.exc_info()[1],
+                action ='manage_main')
+
         self._verifyObjectPaste(ob)
-        try:    ob._notifyOfCopyTo(self, op=0)
-        except: raise CopyError, MessageDialog(
-                      title='Clone Error',
-                      message=sys.exc_info()[1],
-                      action ='manage_main')
-        ob=ob._getCopy(self)
+
+        try:
+            ob._notifyOfCopyTo(self, op=0)
+        except ConflictError:
+            raise
+        except:
+            raise CopyError, MessageDialog(
+                title="Clone Error",
+                message=sys.exc_info()[1],
+                action='manage_main')
+
+        ob = ob._getCopy(self)
         ob._setId(id)
+        notify(ObjectCopiedEvent(ob))
+
         self._setObject(id, ob)
-        ob=self._getOb(id)
+        ob = self._getOb(id)
+
         ob._postCopy(self, op=0)
-        ob.manage_afterClone(ob)
+
+        maybeCallDeprecated('manage_afterClone', ob)
+
+        notify(FiveObjectClonedEvent(ob))
+
         return ob
 
     def cb_dataValid(self):

Modified: Zope/branches/philikon-zope32-integration/lib/python/OFS/ObjectManager.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/OFS/ObjectManager.py	2005-10-31 20:04:14 UTC (rev 39783)
+++ Zope/branches/philikon-zope32-integration/lib/python/OFS/ObjectManager.py	2005-10-31 20:09:39 UTC (rev 39784)
@@ -15,6 +15,7 @@
 $Id$
 """
 
+import warnings
 import marshal
 import sys, fnmatch, copy, os, re
 from cgi import escape
@@ -42,6 +43,11 @@
 import CopySupport
 from interfaces import IObjectManager
 from Traversable import Traversable
+from zope.event import notify
+from zope.app.container.contained import ObjectAddedEvent
+from zope.app.container.contained import ObjectRemovedEvent
+from Products.Five.event import ObjectWillBeAddedEvent
+from Products.Five.event import ObjectWillBeRemovedEvent
 
 
 # the name BadRequestException is relied upon by 3rd-party code
@@ -266,90 +272,99 @@
             raise AttributeError, id
         return default
 
-    def _setObject(self, id, object, roles=None, user=None, set_owner=1):
-        v=self._checkId(id)
-        if v is not None: id=v
-        try:    t=object.meta_type
-        except: t=None
+    def _setObject(self, id, object, roles=None, user=None, set_owner=1,
+                   suppress_events=False):
+        """Set an object into this container.
 
+        Also sends IObjectWillBeAddedEvent and IObjectAddedEvent.
+        """
+        # Done here to avoid circular imports
+        from Products.Five.subscribers import maybeCallDeprecated
+
+        ob = object # better name, keep original function signature
+        v = self._checkId(id)
+        if v is not None:
+            id = v
+        t = getattr(ob, 'meta_type', None)
+
         # If an object by the given id already exists, remove it.
         for object_info in self._objects:
             if object_info['id'] == id:
                 self._delObject(id)
                 break
 
-        self._objects=self._objects+({'id':id,'meta_type':t},)
-        self._setOb(id,object)
-        object=self._getOb(id)
+        if not suppress_events:
+            notify(ObjectWillBeAddedEvent(ob, self, id))
 
+        self._objects = self._objects + ({'id': id, 'meta_type': t},)
+        self._setOb(id, ob)
+        ob = self._getOb(id)
+
         if set_owner:
-            object.manage_fixupOwnershipAfterAdd()
+            # TODO: eventify manage_fixupOwnershipAfterAdd
+            # This will be called for a copy/clone, or a normal _setObject.
+            ob.manage_fixupOwnershipAfterAdd()
 
             # Try to give user the local role "Owner", but only if
             # no local roles have been set on the object yet.
-            if hasattr(object, '__ac_local_roles__'):
-                if object.__ac_local_roles__ is None:
-                    user=getSecurityManager().getUser()
-                    if user is not None:
-                        userid=user.getId()
-                        if userid is not None:
-                            object.manage_setLocalRoles(userid, ['Owner'])
+            if getattr(ob, '__ac_local_roles__', _marker) is None:
+                user = getSecurityManager().getUser()
+                if user is not None:
+                    userid = user.getId()
+                    if userid is not None:
+                        ob.manage_setLocalRoles(userid, ['Owner'])
 
-        object.manage_afterAdd(object, self)
+        if not suppress_events:
+            notify(ObjectAddedEvent(ob, self, id))
+
+        maybeCallDeprecated('manage_afterAdd', ob, self)
+
         return id
 
     def manage_afterAdd(self, item, container):
-        for object in self.objectValues():
-            try: s=object._p_changed
-            except: s=0
-            if hasattr(aq_base(object), 'manage_afterAdd'):
-                object.manage_afterAdd(item, container)
-            if s is None: object._p_deactivate()
+        # Don't do recursion anymore, a subscriber does that.
+        warnings.warn(
+            "%s.manage_afterAdd is deprecated and will be removed in "
+            "Zope 2.11, you should use an IObjectAddedEvent "
+            "subscriber instead." % self.__class__.__name__,
+            DeprecationWarning, stacklevel=2)
+    manage_afterAdd.__five_method__ = True
 
     def manage_afterClone(self, item):
-        for object in self.objectValues():
-            try: s=object._p_changed
-            except: s=0
-            if hasattr(aq_base(object), 'manage_afterClone'):
-                object.manage_afterClone(item)
-            if s is None: object._p_deactivate()
+        # Don't do recursion anymore, a subscriber does that.
+        warnings.warn(
+            "%s.manage_afterClone is deprecated and will be removed in "
+            "Zope 2.11, you should use an IFiveObjectClonedEvent "
+            "subscriber instead." % self.__class__.__name__,
+            DeprecationWarning, stacklevel=2)
+    manage_afterClone.__five_method__ = True
 
     def manage_beforeDelete(self, item, container):
-        for object in self.objectValues():
-            try: s=object._p_changed
-            except: s=0
-            try:
-                if hasattr(aq_base(object), 'manage_beforeDelete'):
-                    object.manage_beforeDelete(item, container)
-            except BeforeDeleteException, ob:
-                raise
-            except ConflictError:
-                raise
-            except:
-                LOG('Zope',ERROR,'manage_beforeDelete() threw',
-                    error=sys.exc_info())
-                # In debug mode when non-Manager, let exceptions propagate.
-                if getConfiguration().debug_mode:
-                    if not getSecurityManager().getUser().has_role('Manager'):
-                        raise
-            if s is None: object._p_deactivate()
+        # Don't do recursion anymore, a subscriber does that.
+        warnings.warn(
+            "%s.manage_beforeDelete is deprecated and will be removed in "
+            "Zope 2.11, you should use an IObjectWillBeRemovedEvent "
+            "subscriber instead." % self.__class__.__name__,
+            DeprecationWarning, stacklevel=2)
+    manage_beforeDelete.__five_method__ = True
 
-    def _delObject(self, id, dp=1):
-        object=self._getOb(id)
-        try:
-            object.manage_beforeDelete(object, self)
-        except BeforeDeleteException, ob:
-            raise
-        except ConflictError:
-            raise
-        except:
-            LOG('Zope', ERROR, '_delObject() threw',
-                error=sys.exc_info())
-            # In debug mode when non-Manager, let exceptions propagate.
-            if getConfiguration().debug_mode:
-                if not getSecurityManager().getUser().has_role('Manager'):
-                    raise
-        self._objects=tuple(filter(lambda i,n=id: i['id']!=n, self._objects))
+    def _delObject(self, id, dp=1, suppress_events=False):
+        """Delete an object from this container.
+
+        Also sends IObjectWillBeRemovedEvent and IObjectRemovedEvent.
+        """
+        # Done here to avoid circular imports
+        from Products.Five.subscribers import maybeCallDeprecated
+
+        ob = self._getOb(id)
+
+        maybeCallDeprecated('manage_beforeDelete', ob, self)
+
+        if not suppress_events:
+            notify(ObjectWillBeRemovedEvent(ob, self, id))
+
+        self._objects = tuple([i for i in self._objects
+                               if i['id'] != id])
         self._delOb(id)
 
         # Indicate to the object that it has been deleted. This is
@@ -357,9 +372,14 @@
         # tolerate failure here because the object being deleted could
         # be a Broken object, and it is not possible to set attributes
         # on Broken objects.
-        try:    object._v__object_deleted__ = 1
-        except: pass
+        try:
+            ob._v__object_deleted__ = 1
+        except:
+            pass
 
+        if not suppress_events:
+            notify(ObjectRemovedEvent(ob, self, id))
+
     def objectIds(self, spec=None):
         # Returns a list of subobject ids of the current object.
         # If 'spec' is specified, returns objects whose meta_type

Modified: Zope/branches/philikon-zope32-integration/lib/python/OFS/OrderSupport.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/OFS/OrderSupport.py	2005-10-31 20:04:14 UTC (rev 39783)
+++ Zope/branches/philikon-zope32-integration/lib/python/OFS/OrderSupport.py	2005-10-31 20:09:39 UTC (rev 39784)
@@ -30,7 +30,7 @@
 from ObjectManager import ObjectManager
 
 
-class OrderSupport:
+class OrderSupport(object):
 
     """ Ordered container mixin class.
 
@@ -251,13 +251,12 @@
     #   Override Inherited Method of ObjectManager Subclass
     #
 
-    _old_manage_renameObject = ObjectManager.inheritedAttribute(
-                                                        'manage_renameObject')
     def manage_renameObject(self, id, new_id, REQUEST=None):
         """ Rename a particular sub-object without changing its position.
         """
         old_position = self.getObjectPosition(id)
-        result = self._old_manage_renameObject(id, new_id, REQUEST)
+        result = super(OrderSupport, self).manage_renameObject(id, new_id,
+                                                               REQUEST)
         self.moveObjectToPosition(new_id, old_position)
         return result
 

Modified: Zope/branches/philikon-zope32-integration/lib/python/OFS/SimpleItem.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/OFS/SimpleItem.py	2005-10-31 20:04:14 UTC (rev 39783)
+++ Zope/branches/philikon-zope32-integration/lib/python/OFS/SimpleItem.py	2005-10-31 20:09:39 UTC (rev 39784)
@@ -20,6 +20,7 @@
 $Id$
 """
 
+import warnings
 import marshal, re, sys, time
 
 import AccessControl.Role, AccessControl.Owned, App.Common
@@ -60,13 +61,28 @@
     isTopLevelPrincipiaApplicationObject=0
 
     def manage_afterAdd(self, item, container):
-        pass
+        warnings.warn(
+            "%s.manage_afterAdd is deprecated and will be removed in "
+            "Zope 2.11, you should use an IObjectAddedEvent "
+            "subscriber instead." % self.__class__.__name__,
+            DeprecationWarning, stacklevel=2)
+    manage_afterAdd.__five_method__ = True
 
     def manage_beforeDelete(self, item, container):
-        pass
+        warnings.warn(
+            "%s.manage_beforeDelete is deprecated and will be removed in "
+            "Zope 2.11, you should use an IObjectWillBeRemovedEvent "
+            "subscriber instead." % self.__class__.__name__,
+            DeprecationWarning, stacklevel=2)
+    manage_beforeDelete.__five_method__ = True
 
     def manage_afterClone(self, item):
-        pass
+        warnings.warn(
+            "%s.manage_afterClone is deprecated and will be removed in "
+            "Zope 2.11, you should use an IFiveObjectClonedEvent "
+            "subscriber instead." % self.__class__.__name__,
+            DeprecationWarning, stacklevel=2)
+    manage_afterClone.__five_method__ = True
 
     # Direct use of the 'id' attribute is deprecated - use getId()
     id=''

Modified: Zope/branches/philikon-zope32-integration/lib/python/Products/BTreeFolder2/BTreeFolder2.py
===================================================================
--- Zope/branches/philikon-zope32-integration/lib/python/Products/BTreeFolder2/BTreeFolder2.py	2005-10-31 20:04:14 UTC (rev 39783)
+++ Zope/branches/philikon-zope32-integration/lib/python/Products/BTreeFolder2/BTreeFolder2.py	2005-10-31 20:09:39 UTC (rev 39784)
@@ -37,6 +37,11 @@
      view_management_screens
 from zLOG import LOG, INFO, ERROR, WARNING
 from Products.ZCatalog.Lazy import LazyMap
+from zope.event import notify
+from zope.app.container.contained import ObjectAddedEvent
+from zope.app.container.contained import ObjectRemovedEvent
+from Products.Five.event import ObjectWillBeAddedEvent
+from Products.Five.event import ObjectWillBeRemovedEvent
 
 
 manage_addBTreeFolderForm = DTMLFile('folderAdd', globals())
@@ -404,48 +409,65 @@
                                         'it is already in use.' % id)
 
 
-    def _setObject(self, id, object, roles=None, user=None, set_owner=1):
-        v=self._checkId(id)
-        if v is not None: id=v
+    def _setObject(self, id, object, roles=None, user=None, set_owner=1,
+                   suppress_events=False):
+        # Done here to avoid circular imports
+        from Products.Five.subscribers import maybeCallDeprecated
 
+        ob = object # better name, keep original function signature
+        v = self._checkId(id)
+        if v is not None:
+            id = v
+
         # If an object by the given id already exists, remove it.
         if self.has_key(id):
             self._delObject(id)
 
-        self._setOb(id, object)
-        object = self._getOb(id)
+        if not suppress_events:
+            notify(ObjectWillBeAddedEvent(ob, self, id))
 
+        self._setOb(id, ob)
+        ob = self._getOb(id)
+
         if set_owner:
-            object.manage_fixupOwnershipAfterAdd()
+            # TODO: eventify manage_fixupOwnershipAfterAdd
+            # This will be called for a copy/clone, or a normal _setObject.
+            ob.manage_fixupOwnershipAfterAdd()
 
             # Try to give user the local role "Owner", but only if
             # no local roles have been set on the object yet.
-            if hasattr(object, '__ac_local_roles__'):
-                if object.__ac_local_roles__ is None:
-                    user=getSecurityManager().getUser()
-                    if user is not None:
-                        userid=user.getId()
-                        if userid is not None:
-                            object.manage_setLocalRoles(userid, ['Owner'])
+            if getattr(ob, '__ac_local_roles__', _marker) is None:
+                user = getSecurityManager().getUser()
+                if user is not None:
+                    userid = user.getId()
+                    if userid is not None:
+                        ob.manage_setLocalRoles(userid, ['Owner'])
 
-        object.manage_afterAdd(object, self)
+        if not suppress_events:
+            notify(ObjectAddedEvent(ob, self, id))
+
+        maybeCallDeprecated('manage_afterAdd', ob, self)
+
         return id
 
 
-    def _delObject(self, id, dp=1):
-        object = self._getOb(id)
-        try:
-            object.manage_beforeDelete(object, self)
-        except BeforeDeleteException, ob:
-            raise
-        except ConflictError:
-            raise
-        except:
-            LOG('Zope', ERROR, 'manage_beforeDelete() threw',
-                error=sys.exc_info())
+    def _delObject(self, id, dp=1, suppress_events=False):
+        # Done here to avoid circular imports
+        from Products.Five.subscribers import maybeCallDeprecated
+
+        ob = self._getOb(id)
+
+        maybeCallDeprecated('manage_beforeDelete', ob, self)
+
+        if not suppress_events:
+            notify(ObjectWillBeRemovedEvent(ob, self, id))
+
         self._delOb(id)
 
+        if not suppress_events:
+            notify(ObjectRemovedEvent(ob, self, id))
 
+
     # Aliases for mapping-like access.
     __len__ = objectCount
     keys = objectIds



More information about the Zope-Checkins mailing list