[z3-checkins] r19705 - in z3/Five/branch/Five-1.2: . bbb tests

efge at codespeak.net efge at codespeak.net
Thu Nov 10 15:00:28 CET 2005


Author: efge
Date: Thu Nov 10 15:00:27 2005
New Revision: 19705

Modified:
   z3/Five/branch/Five-1.2/bbb/OFS_subscribers.py
   z3/Five/branch/Five-1.2/event.py
   z3/Five/branch/Five-1.2/tests/event.txt
   z3/Five/branch/Five-1.2/tests/test_event.py
Log:
Updates to compatibility mode to make recursion work better.

Keep in sync with what will be in Five 1.3 in a few minutes.



Modified: z3/Five/branch/Five-1.2/bbb/OFS_subscribers.py
==============================================================================
--- z3/Five/branch/Five-1.2/bbb/OFS_subscribers.py	(original)
+++ z3/Five/branch/Five-1.2/bbb/OFS_subscribers.py	Thu Nov 10 15:00:27 2005
@@ -17,15 +17,15 @@
 $Id$
 """
 
-##################################################
-
+import warnings
 import sys
+
 from zLOG import LOG, ERROR
+from Acquisition import aq_base
 from App.config import getConfiguration
 from AccessControl import getSecurityManager
 from ZODB.POSException import ConflictError
 from OFS.ObjectManager import BeforeDeleteException
-from Products.Five.fiveconfigure import isFiveMethod
 from zope.app.container.contained import dispatchToSublocations
 from OFS_interfaces import IObjectManager
 
@@ -33,36 +33,42 @@
 deprecatedManageAddDeleteClasses = []
 
 
-def hasDeprecatedMethods(ob):
-    """Do we need to call the deprecated methods?
+def compatibilityCall(method_name, *args):
+    """Call a method if events have not been setup yet.
+
+    This is the case for some unit tests that have not been converted to
+    use the component architecture.
     """
-    for class_ in deprecatedManageAddDeleteClasses:
-        if isinstance(ob, class_):
-            return True
-    return False
-
-def maybeCallDeprecated(method_name, ob, *args):
-    """Call a deprecated method, if the framework doesn't call it already.
-    """
-    if hasDeprecatedMethods(ob):
-        # Already deprecated through zcml
-        return
-    method = getattr(ob, method_name)
-    if isFiveMethod(method):
-        # Monkey-patched method
-        return
     if deprecatedManageAddDeleteClasses:
-        # Not deprecated through zcml and directives fully loaded
-        class_ = ob.__class__
-        warnings.warn(
-            "Calling %s.%s.%s is deprecated when using Five, "
-            "instead use event subscribers or "
-            "mark the class with <five:deprecatedManageAddDelete/>"
-            % (class_.__module__, class_.__name__, method_name),
-            DeprecationWarning)
-    # Note that calling the method can lead to incorrect behavior
-    # but in the most common case that's better than not calling it.
-    method(ob, *args)
+        # Events initialized, don't do compatibility call
+        return
+    if method_name == 'manage_afterAdd':
+        callManageAfterAdd(*args)
+    elif method_name == 'manage_beforeDelete':
+        callManageBeforeDelete(*args)
+    else:
+        callManageAfterClone(*args)
+
+def maybeWarnDeprecated(ob, method_name):
+    """Send a warning if a method is deprecated.
+    """
+    if not deprecatedManageAddDeleteClasses:
+        # Directives not fully loaded
+        return
+    for cls in deprecatedManageAddDeleteClasses:
+        if isinstance(ob, cls):
+            # Already deprecated through zcml
+            return
+    if getattr(getattr(ob, method_name), '__five_method__', False):
+        # Method knows it's deprecated
+        return
+    class_ = ob.__class__
+    warnings.warn(
+        "%s.%s.%s is deprecated and will be removed in Zope 2.11, "
+        "you should use event subscribers instead, and meanwhile "
+        "mark the class with <five:deprecatedManageAddDelete/>"
+        % (class_.__module__, class_.__name__, method_name),
+        DeprecationWarning)
 
 
 ##################################################
@@ -95,15 +101,13 @@
     if IObjectManager.providedBy(ob):
         dispatchToSublocations(ob, event)
     # Next, do the manage_beforeDelete dance
-    if hasDeprecatedMethods(ob):
-        callManageBeforeDelete(ob, event)
+    callManageBeforeDelete(ob, event.object, event.oldParent)
 
 def dispatchObjectMovedEvent(ob, event):
     """Multi-subscriber for IItem + IObjectMovedEvent.
     """
     # First, do the manage_afterAdd dance
-    if hasDeprecatedMethods(ob):
-        callManageAfterAdd(ob, event)
+    callManageAfterAdd(ob, event.object, event.newParent)
     # Next, dispatch to sublocations
     if IObjectManager.providedBy(ob):
         dispatchToSublocations(ob, event)
@@ -112,31 +116,32 @@
     """Multi-subscriber for IItem + IObjectClonedEvent.
     """
     # First, do the manage_afterClone dance
-    if hasDeprecatedMethods(ob):
-        callManageAfterClone(ob, event)
+    callManageAfterClone(ob, event.object)
     # Next, dispatch to sublocations
     if IObjectManager.providedBy(ob):
         dispatchToSublocations(ob, event)
 
 
-def callManageAfterAdd(ob, event):
+def callManageAfterAdd(ob, item, container):
     """Compatibility subscriber for manage_afterAdd.
     """
-    container = event.newParent
     if container is None:
-        # this is a remove
         return
-    ob.manage_afterAdd(event.object, container)
+    if getattr(aq_base(ob), 'manage_afterAdd', None) is None:
+        return
+    maybeWarnDeprecated(ob, 'manage_afterAdd')
+    ob.manage_afterAdd(item, container)
 
-def callManageBeforeDelete(ob, event):
+def callManageBeforeDelete(ob, item, container):
     """Compatibility subscriber for manage_beforeDelete.
     """
-    container = event.oldParent
     if container is None:
-        # this is an add
         return
+    if getattr(aq_base(ob), 'manage_beforeDelete', None) is None:
+        return
+    maybeWarnDeprecated(ob, 'manage_beforeDelete')
     try:
-        ob.manage_beforeDelete(event.object, container)
+        ob.manage_beforeDelete(item, container)
     except BeforeDeleteException:
         raise
     except ConflictError:
@@ -148,7 +153,10 @@
             if not getSecurityManager().getUser().has_role('Manager'):
                 raise
 
-def callManageAfterClone(ob, event):
+def callManageAfterClone(ob, item):
     """Compatibility subscriber for manage_afterClone.
     """
-    ob.manage_afterClone(event.object)
+    if getattr(aq_base(ob), 'manage_afterClone', None) is None:
+        return
+    maybeWarnDeprecated(ob, 'manage_afterClone')
+    ob.manage_afterClone(item)

Modified: z3/Five/branch/Five-1.2/event.py
==============================================================================
--- z3/Five/branch/Five-1.2/event.py	(original)
+++ z3/Five/branch/Five-1.2/event.py	Thu Nov 10 15:00:27 2005
@@ -40,8 +40,7 @@
 from OFS.event import ObjectWillBeRemovedEvent
 from OFS.event import ObjectClonedEvent
 from OFS.subscribers import deprecatedManageAddDeleteClasses
-from OFS.subscribers import hasDeprecatedMethods
-from OFS.subscribers import maybeCallDeprecated
+from OFS.subscribers import compatibilityCall
 from Products.Five.fiveconfigure import isFiveMethod
 
 
@@ -130,7 +129,7 @@
     if not suppress_events:
         notify(ObjectAddedEvent(ob, self, id))
 
-    maybeCallDeprecated('manage_afterAdd', ob, self)
+    compatibilityCall('manage_afterAdd', ob, ob, self)
 
     return id
 
@@ -171,7 +170,7 @@
     if not suppress_events:
         notify(ObjectAddedEvent(ob, self, id))
 
-    maybeCallDeprecated('manage_afterAdd', ob, self)
+    compatibilityCall('manage_afterAdd', ob, ob, self)
 
     return id
 
@@ -184,7 +183,7 @@
     """
     ob = self._getOb(id)
 
-    maybeCallDeprecated('manage_beforeDelete', ob, self)
+    compatibilityCall('manage_beforeDelete', ob, ob, self)
 
     if not suppress_events:
         notify(ObjectWillBeRemovedEvent(ob, self, id))
@@ -211,7 +210,7 @@
 def BT_delObject(self, id, dp=1, suppress_events=False):
     ob = self._getOb(id)
 
-    maybeCallDeprecated('manage_beforeDelete', ob, self)
+    compatibilityCall('manage_beforeDelete', ob, ob, self)
 
     if not suppress_events:
         notify(ObjectWillBeRemovedEvent(ob, self, id))
@@ -340,7 +339,7 @@
 
             ob._postCopy(self, op=0)
 
-            maybeCallDeprecated('manage_afterClone', ob)
+            compatibilityCall('manage_afterClone', ob, ob)
 
             notify(ObjectClonedEvent(ob))
 
@@ -440,7 +439,7 @@
 
     ob._postCopy(self, op=0)
 
-    maybeCallDeprecated('manage_afterClone', ob)
+    compatibilityCall('manage_afterClone', ob, ob)
 
     notify(ObjectClonedEvent(ob))
 

Modified: z3/Five/branch/Five-1.2/tests/event.txt
==============================================================================
--- z3/Five/branch/Five-1.2/tests/event.txt	(original)
+++ z3/Five/branch/Five-1.2/tests/event.txt	Thu Nov 10 15:00:27 2005
@@ -47,12 +47,12 @@
   >>> app = MyApp('')
   >>> root['app'] = app
   >>> folder = MyFolder('folder')
-  >>> app._setObject('folder', folder)
+  >>> app._setObject('folder', folder) # doctest: +NORMALIZE_WHITESPACE
   old manage_afterAdd folder folder
   'folder'
   >>> folder = app.folder
   >>> btfolder = MyBTreeFolder('btfolder')
-  >>> app._setObject('btfolder', btfolder)
+  >>> app._setObject('btfolder', btfolder) # doctest: +NORMALIZE_WHITESPACE
   old manage_afterAdd btfolder btfolder
   'btfolder'
 
@@ -187,31 +187,63 @@
   >>> from Products.Five.event import doMonkies, undoMonkies
   >>> doMonkies()
 
+We need at least one fake deprecated method to tell the compatibility
+framework that component architecture is initialized::
+
+  >>> from Products.Five.eventconfigure import setDeprecatedManageAddDelete
+  >>> class C(object): pass
+  >>> setDeprecatedManageAddDelete(C)
+
 Old class
 ---------
 
 If we use an instance of an old class for which we haven't specified
 anything, events are sent and the manage_afterAdd & co methods are
-called but in a "compatibility" way.
-
-Because the bases classes of Zope have been changed to not recurse
-except through the event framework, unexpected behavior may happen
-(however a warning will be sent)::
+called, but with a deprecation warning::
 
+  >>> sub = MyFolder('sub')
+  >>> folder._setObject('sub', sub)
+  ObjectWillBeAddedEvent sub
+  ObjectAddedEvent sub
+  old manage_afterAdd sub sub folder
+  'sub'
+  >>> sub = folder.sub
   >>> ob = MyContent('dog')
-  >>> folder._setObject('dog', ob)
+  >>> sub._setObject('dog', ob)
   ObjectWillBeAddedEvent dog
   ObjectAddedEvent dog
-  old manage_afterAdd dog dog folder
+  old manage_afterAdd dog dog sub
   'dog'
 
-And when we delete the object, manage_beforeDelete is also called and
-events are sent::
+And when we rename the subfolder, manage_beforeDelete is also called
+bottom-up and events are sent::
 
-  >>> folder.manage_delObjects('dog')
-  old manage_beforeDelete dog dog folder
-  ObjectWillBeRemovedEvent dog
-  ObjectRemovedEvent dog
+  >>> folder.manage_renameObject('sub', 'marine')
+  ObjectWillBeMovedEvent sub
+  ObjectWillBeMovedEvent dog
+  old manage_beforeDelete dog sub folder
+  old manage_beforeDelete sub sub folder
+  ObjectMovedEvent marine
+  old manage_afterAdd marine marine folder
+  ObjectMovedEvent dog
+  old manage_afterAdd dog marine folder
+
+Same thing for clone::
+
+  >>> res = folder.manage_clone(folder.marine, 'tank')
+  ObjectCopiedEvent tank
+  ObjectWillBeAddedEvent tank
+  ObjectWillBeAddedEvent dog
+  ObjectAddedEvent tank
+  old manage_afterAdd tank tank folder
+  ObjectAddedEvent dog
+  old manage_afterAdd dog tank folder
+  ObjectClonedEvent tank
+  old manage_afterClone tank tank
+  ObjectClonedEvent dog
+  old manage_afterClone dog tank
+  >>> res.getId()
+  'tank'
 
 Old class with deprecatedManageAddDelete
 ----------------------------------------
@@ -466,7 +498,7 @@
 OrderedFolder has the same renaming behavior than before::
 
   >>> ofolder = MyOrderedFolder('ofolder')
-  >>> app._setObject('ofolder', ofolder)
+  >>> app._setObject('ofolder', ofolder) # doctest: +NORMALIZE_WHITESPACE
   ObjectWillBeAddedEvent ofolder
   ObjectAddedEvent ofolder
   old manage_afterAdd ofolder ofolder

Modified: z3/Five/branch/Five-1.2/tests/test_event.py
==============================================================================
--- z3/Five/branch/Five-1.2/tests/test_event.py	(original)
+++ z3/Five/branch/Five-1.2/tests/test_event.py	Thu Nov 10 15:00:27 2005
@@ -41,13 +41,16 @@
         print 'old manage_afterAdd %s %s %s' % (self.getId(), item.getId(),
                                                 container.getId())
         super(NotifyBase, self).manage_afterAdd(item, container)
+    manage_afterAdd.__five_method__ = True # Shut up deprecation warnings
     def manage_beforeDelete(self, item, container):
         super(NotifyBase, self).manage_beforeDelete(item, container)
         print 'old manage_beforeDelete %s %s %s' % (self.getId(), item.getId(),
                                                     container.getId())
+    manage_beforeDelete.__five_method__ = True # Shut up deprecation warnings
     def manage_afterClone(self, item):
         print 'old manage_afterClone %s %s' % (self.getId(), item.getId())
         super(NotifyBase, self).manage_afterClone(item)
+    manage_afterClone.__five_method__ = True # Shut up deprecation warnings
 
 class MyApp(Folder):
     def getPhysicalRoot(self):
@@ -78,8 +81,8 @@
 
 
 def test_suite():
-    from Testing.ZopeTestCase import ZopeDocFileSuite
-    return ZopeDocFileSuite('event.txt', package="Products.Five.tests")
+    from zope.testing.doctest import DocFileSuite
+    return DocFileSuite('event.txt', package="Products.Five.tests")
 
 if __name__ == '__main__':
     framework()


More information about the z3-checkins mailing list