[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/ Added an event
handler that dispatches object-location events to subobjects.
Jim Fulton
jim at zope.com
Fri May 28 17:58:44 EDT 2004
Log message for revision 25108:
Added an event handler that dispatches object-location events to subobjects.
-=-
Modified: Zope3/trunk/src/zope/app/component/metadirectives.py
===================================================================
--- Zope3/trunk/src/zope/app/component/metadirectives.py 2004-05-28 21:39:53 UTC (rev 25107)
+++ Zope3/trunk/src/zope/app/component/metadirectives.py 2004-05-28 21:58:44 UTC (rev 25108)
@@ -201,7 +201,7 @@
title=u"Interfaces or classes that this subscriber depends on",
description=u"This should be a list of interfaces or classes",
required=True,
- value_type=GlobalObject()
+ value_type=GlobalObject(missing_value = object()),
)
permission = Permission(
Modified: Zope3/trunk/src/zope/app/container/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/container/configure.zcml 2004-05-28 21:39:53 UTC (rev 25107)
+++ Zope3/trunk/src/zope/app/container/configure.zcml 2004-05-28 21:58:44 UTC (rev 25108)
@@ -48,6 +48,15 @@
for="zope.app.container.interfaces.IObjectRemovedEvent"
/>
+ <subscriber
+ for="zope.app.location.interfaces.ILocation
+ zope.app.container.interfaces.IObjectMovedEvent"
+ factory=".contained.dispatchToSublocations"
+ >
+ Handler dispatches moved events to sublocations of the original object.
+ </subscriber>
+
+
<content class=".constraints.ItemTypePrecondition">
<allow interface=".constraints.IItemTypePrecondition" />
</content>
Modified: Zope3/trunk/src/zope/app/container/contained.py
===================================================================
--- Zope3/trunk/src/zope/app/container/contained.py 2004-05-28 21:39:53 UTC (rev 25107)
+++ Zope3/trunk/src/zope/app/container/contained.py 2004-05-28 21:58:44 UTC (rev 25108)
@@ -15,6 +15,7 @@
$Id$
"""
+
from zope.proxy import getProxiedObject
from zope.exceptions import DuplicationError
from zope.security.checker import selectChecker, CombinedChecker
@@ -25,6 +26,7 @@
from zope.interface.declarations import ObjectSpecification
from zope.interface import providedBy
+from zope.app import zapi
from zope.app.exception.interfaces import UserError
from zope.app.event.objectevent import ObjectEvent, modified
from zope.event import notify
@@ -34,7 +36,7 @@
from zope.app.container.interfaces import IObjectAddedEvent
from zope.app.container.interfaces import IObjectMovedEvent
from zope.app.container.interfaces import IObjectRemovedEvent
-from zope.app.location.interfaces import ILocation
+from zope.app.location.interfaces import ILocation, ISublocations
from zope.app.container._zope_app_container_contained import ContainedProxyBase
from zope.app.container._zope_app_container_contained import getProxiedObject
@@ -82,7 +84,101 @@
oldName = object.__name__
ObjectMovedEvent.__init__(self, object, oldParent, oldName, None, None)
+def dispatchToSublocations(object, event):
+ """Dispatch an event to sublocations of a given object
+ When a move event happens for an object, it's important to
+ notify subobjects as well.
+
+ We do this based on locations.
+
+ Suppose, for example, that we define some location objects.
+
+
+ >>> class L:
+ ... zope.interface.implements(ILocation)
+ ... def __init__(self, name):
+ ... self.__name__ = name
+ ... self.__parent__ = None
+ ... def __repr__(self):
+ ... return '%s(%s)' % (
+ ... self.__class__.__name__, str(self.__name__))
+
+ >>> class C(L):
+ ... zope.interface.implements(ISublocations)
+ ... def __init__(self, name, *subs):
+ ... L.__init__(self, name)
+ ... self.subs = subs
+ ... for sub in subs:
+ ... sub.__parent__ = self
+ ... def sublocations(self):
+ ... return self.subs
+
+ >>> c = C(1,
+ ... C(11,
+ ... L(111),
+ ... L(112),
+ ... ),
+ ... C(12,
+ ... L(121),
+ ... L(122),
+ ... L(123),
+ ... L(124),
+ ... ),
+ ... L(13),
+ ... )
+
+ Now, if we call the dispatcher, it should call event handlers
+ for all of the objects.
+
+ Lets create an event handler that records the objects it sees:
+
+ >>> seen = []
+ >>> def handler(ob, event):
+ ... seen.append((ob, event.object))
+
+ Note that we record the the object the handler is called on as
+ well as the event object:
+
+ Now we'll register it:
+
+ >>> from zope.app.tests import ztapi
+ >>> ztapi.handle([None, IObjectMovedEvent], handler)
+
+ We also register our dispatcher:
+
+ >>> ztapi.handle([None, IObjectMovedEvent], dispatchToSublocations)
+
+ We can then call the dispatcher for the root object:
+
+ >>> event = ObjectRemovedEvent(c)
+ >>> dispatchToSublocations(c, event)
+
+ Now, we should have seen all of the subobjects:
+
+ >>> seenreprs = map(repr, seen)
+ >>> seenreprs.sort()
+ >>> seenreprs
+ ['(C(11), C(1))', '(C(12), C(1))', '(L(111), C(1))',""" \
+ """ '(L(112), C(1))', '(L(121), C(1))', '(L(122), C(1))',""" \
+ """ '(L(123), C(1))', '(L(124), C(1))', '(L(13), C(1))']
+
+ We see that we get entries for each of the subobjects and
+ that,for each entry, the event object is top object.
+
+ This suggests that location event handlers need to be aware that
+ the objects they are called on and the event objects could be
+ different.
+
+ """
+ subs = ISublocations(object, None)
+ if subs is not None:
+ for sub in subs.sublocations():
+ for ignored in zapi.subscribers((sub, event), None):
+ pass # They do work in the adapter fetch
+
+
+
def containedEvent(object, container, name=None):
"""Establish the containment of the object in the container
Modified: Zope3/trunk/src/zope/app/location/interfaces.py
===================================================================
--- Zope3/trunk/src/zope/app/location/interfaces.py 2004-05-28 21:39:53 UTC (rev 25107)
+++ Zope3/trunk/src/zope/app/location/interfaces.py 2004-05-28 21:58:44 UTC (rev 25108)
@@ -28,3 +28,15 @@
description=u"The parent can be traversed with this name to "
u"get the object."
)
+
+class ISublocations(Interface):
+ """Provide access to sublocations
+ """
+
+ def sublocations():
+ """Return sublocations
+
+ An iterablt of objects who's __parent__ is the object
+ providing the interface is returned.
+
+ """
More information about the Zope3-Checkins
mailing list