[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/OFS/Services/LocalEventService - IPathSubscriber.py:1.2 LocalEventChannel.py:1.2 LocalEventService.py:1.2 LocalServiceSubscribable.py:1.2 LocalSubscribable.py:1.2 LocalSubscriptionAware.py:1.2 PathSubscriber.py:1.2 __init__.py:1.2 localEventService.zcml:1.2
Jim Fulton
jim@zope.com
Mon, 10 Jun 2002 19:28:41 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/App/OFS/Services/LocalEventService
In directory cvs.zope.org:/tmp/cvs-serv17445/lib/python/Zope/App/OFS/Services/LocalEventService
Added Files:
IPathSubscriber.py LocalEventChannel.py LocalEventService.py
LocalServiceSubscribable.py LocalSubscribable.py
LocalSubscriptionAware.py PathSubscriber.py __init__.py
localEventService.zcml
Log Message:
Merged Zope-3x-branch into newly forked Zope3 CVS Tree.
=== Zope3/lib/python/Zope/App/OFS/Services/LocalEventService/IPathSubscriber.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+from Interface.Attribute import Attribute
+from Zope.Event.ISubscriber import IIndirectSubscriber
+
+
+class IPathSubscriber(IIndirectSubscriber):
+
+ def __init__(wrapped_subscriber):
+ """creates new PathSubscriber for the given wrapped_subscriber"""
+
+ subscriber_path = Attribute(
+ """the slash-delineated absolute url to the subscriber"""
+ )
\ No newline at end of file
=== Zope3/lib/python/Zope/App/OFS/Services/LocalEventService/LocalEventChannel.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from LocalSubscribable import LocalSubscribable
+from Zope.Event.IEventChannel import IEventChannel
+from Zope.ContextWrapper import ContextMethod
+from Zope.Proxy.ProxyIntrospection import removeAllProxies
+from Zope.Proxy.ContextWrapper import ContextWrapper
+
+class LocalEventChannel(LocalSubscribable):
+
+ __implements__ = IEventChannel
+
+ def notify(wrapped_self, event):
+ clean_self=removeAllProxies(wrapped_self)
+
+ subscriptionses = clean_self._registry.getAllForObject(event)
+
+ for subscriptions in subscriptionses:
+
+ for subscriber,filter in subscriptions:
+ if filter is not None and not filter(event):
+ continue
+ ContextWrapper(subscriber, wrapped_self).notify(event)
+
+ notify=ContextMethod(notify)
+
+
+
+
=== Zope3/lib/python/Zope/App/OFS/Services/LocalEventService/LocalEventService.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from Zope.Event.IEventService import IEventService
+from Zope.Event.ISubscriptionAware import ISubscriptionAware
+from Zope.Event.ISubscriber import ISubscriber
+from LocalServiceSubscribable import LocalServiceSubscribable
+from Zope.ComponentArchitecture import getNextService, getAdapter, getService
+from Zope.App.OFS.Services.ServiceManager.IBindingAware import IBindingAware
+from Zope.ContextWrapper import ContextMethod
+from Zope.Proxy.ProxyIntrospection import removeAllProxies
+from Zope.Proxy.ContextWrapper import ContextWrapper
+from PathSubscriber import PathSubscriber
+from Zope.App.Traversing.ITraverser import ITraverser
+from LocalSubscriptionAware import LocalSubscriptionAware
+from Interface.Attribute import Attribute
+from Zope.Event.GlobalEventService import eventService
+from Zope.Event.IEvent import IEvent
+
+class ILocalEventService(
+ IEventService, ISubscriber, IBindingAware, ISubscriptionAware):
+
+ def isPromotableEvent(event):
+ """a hook. Returns a true value if, when publishing an
+ event, the event should also be promoted to the
+ next (higher) level of event service, and a false value
+ otherwise. The default implementation is to always return
+ true."""
+
+ subscribeOnBind=Attribute(
+ """if true, event service will subscribe
+ to the parent event service on binding, unless the parent
+ service is the global event service""")
+
+class LocalEventService(LocalServiceSubscribable, LocalSubscriptionAware):
+
+ __implements__ = ILocalEventService
+
+ _serviceName="Events" # used by LocalServiceSubscribable
+
+ subscribeOnBind=1
+
+ def __init__(self):
+ LocalServiceSubscribable.__init__(self)
+ LocalSubscriptionAware.__init__(self)
+
+ def isPromotableEvent(self, event):
+ "see ILocalEventService"
+ return 1
+
+ def publishEvent(wrapped_self, event):
+ "see IEventService"
+ clean_self=removeAllProxies(wrapped_self)
+
+ subscriptionses = clean_self._registry.getAllForObject(event)
+
+ for subscriptions in subscriptionses:
+
+ for subscriber,filter in subscriptions:
+ if filter is not None and not filter(event):
+ continue
+ ContextWrapper(subscriber, wrapped_self).notify(event)
+ publishedEvents=getattr(clean_self, "_v_publishedEvents", None)
+ if publishedEvents is None:
+ publishedEvents=clean_self._v_publishedEvents=[event]
+ else: publishedEvents.append(event)
+ if(clean_self.isPromotableEvent(event)):
+ getNextService(wrapped_self, 'Events').publishEvent(event)
+ publishedEvents.remove(event)
+
+ publishEvent=ContextMethod(publishEvent)
+
+ def notify(wrapped_self, event):
+ "see ISubscriber"
+ clean_self=removeAllProxies(wrapped_self)
+ publishedEvents=getattr(clean_self, "_v_publishedEvents", None)
+ if publishedEvents is None or event not in publishedEvents:
+
+ subscriptionses = clean_self._registry.getAllForObject(event)
+
+ for subscriptions in subscriptionses:
+
+ for subscriber,filter in subscriptions:
+ if filter is not None and not filter(event):
+ continue
+ ContextWrapper(subscriber, wrapped_self).notify(event)
+
+ notify=ContextMethod(notify)
+
+
+ def bound(wrapped_self, name):
+ "see IBindingAware"
+ clean_self=removeAllProxies(wrapped_self)
+ if clean_self.subscribeOnBind:
+ es=getNextService(wrapped_self, name)
+ if es is not eventService: # if we really want the top-level
+ # placeful event service to receive events from the
+ # global event service we're going to have to
+ # set something special up--something that subscribes
+ # every startup...
+ es.subscribe(PathSubscriber(wrapped_self))
+
+ bound=ContextMethod(bound)
+
+ def unbound(wrapped_self, name):
+ "see IBindingAware"
+ clean_self=removeAllProxies(wrapped_self)
+ subscriber=PathSubscriber(wrapped_self)
+ clean_self._v_unbinding=1
+ for subscription in clean_self._subscriptions:
+ subscribable=getAdapter(
+ wrapped_self, ITraverser).traverse(subscription[0])
+ subscribable.unsubscribe(subscriber)
+ clean_self._subscriptions=()
+ for subscriber in clean_self._subscribers:
+ clean_self.__unsubscribeAllFromSelf(wrapped_self, subscriber[0])
+ clean_self._v_unbinding=None
+
+ unbound=ContextMethod(unbound)
+
+ def __unsubscribeAllFromSelf(clean_self, wrapped_self, subscriber):
+ """this is *not* an interface function, and should not be used
+ outside of this class"""
+
+ wrapped_subscriber=ContextWrapper(subscriber, wrapped_self)
+
+ for subscriber_index in range(len(clean_self._subscribers)):
+ sub=clean_self._subscribers[subscriber_index]
+ if sub[0]==subscriber:
+ ev_set=sub[1]
+ break
+ else:
+ raise NotFoundError(subscriber)
+ do_alert=ISubscriptionAware.isImplementedBy(subscriber)
+ for ev_type in ev_set:
+ subscriptions = clean_self._registry.getJustForType(ev_type)
+ subs=subscriptions[:]
+ subscriptions[:] = []
+ for sub in subs:
+ if sub[0] == subscriber: # deleted (not added back)
+ if do_alert:
+ wrapped_subscriber.unsubscribedFrom(
+ wrapped_self, ev_type or IEvent, sub[1])
+ # IEvent switch is to make optimization transparent
+ else: # kept (added back)
+ subscriptions.append(sub)
+ del clean_self._subscribers[subscriber_index]
+ clean_self._registry=clean_self._registry #trigger persistence
+
+ def unsubscribedFrom(wrapped_self, subscribable, event_type, filter):
+ "see ISubscriptionAware"
+ clean_self=removeAllProxies(wrapped_self)
+ if getattr(clean_self, "_v_unbinding", None) is None:
+ # we presumably have been unsubscribed from a higher-level
+ # event service because that event service is unbinding
+ # itself: we need to remove the higher level event service
+ # from our subscriptions list and try to find another event
+ # service to which to attach
+ LocalSubscriptionAware.unsubscribedFrom(
+ clean_self, subscribable, event_type, filter)
+ clean_subscribable=removeAllProxies(subscribable)
+ if IEventService.isImplementedBy(removeAllProxies(clean_subscribable)):
+ context=getService(wrapped_self, "Events")
+ # we do this instead of getNextService because the order
+ # of unbinding and notification of unbinding is not
+ # guaranteed
+ while removeAllProxies(context) in (
+ clean_subscribable, clean_self):
+ context=getNextService(context, "Events")
+ # XXX as usual, we *must not* be working with a global service;
+ # this probably should raise an error if service is global
+ # service...
+ # that leaves replacing top level event services an
+ # interesting question, however
+ context.subscribe(PathSubscriber(wrapped_self))
+
+ unsubscribedFrom=ContextMethod(unsubscribedFrom)
+
+
=== Zope3/lib/python/Zope/App/OFS/Services/LocalEventService/LocalServiceSubscribable.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from Zope.ComponentArchitecture.IToIRegistry import TypeRegistry
+from Zope.Exceptions import NotFoundError
+from Zope.Event.ISubscriptionAware import ISubscriptionAware
+from Zope.Event.IEvent import IEvent
+from Zope.ContextWrapper import ContextMethod
+from Zope.Proxy.ProxyIntrospection import removeAllProxies
+from Zope.Proxy.ContextWrapper import ContextWrapper
+from LocalSubscribable import LocalSubscribable
+from Persistence import Persistent
+from Zope.ComponentArchitecture import getNextService
+
+class LocalServiceSubscribable(LocalSubscribable, Persistent):
+ """a local mix-in for services"""
+
+ _serviceName=None # replace me
+
+ def unsubscribe(wrapped_self, subscriber, event_type=None, filter=None):
+ subscriber=removeAllProxies(subscriber) # might be wrapped, might not
+
+ clean_self=removeAllProxies(wrapped_self)
+ wrapped_subscriber=ContextWrapper(subscriber, wrapped_self)
+
+ for subscriber_index in range(len(clean_self._subscribers)):
+ sub=clean_self._subscribers[subscriber_index]
+ if sub[0]==subscriber:
+ ev_set=sub[1]
+ break
+ else:
+ # raise NotFoundError(subscriber)
+ getNextService(wrapped_self, clean_self._serviceName).unsubscribe(
+ subscriber, event_type, filter)
+ return
+
+
+ do_alert=ISubscriptionAware.isImplementedBy(subscriber)
+
+ if event_type:
+ ev_type=event_type
+ if event_type is IEvent:
+ ev_type=None # handle optimization
+ if ev_type not in ev_set:
+ getNextService(
+ wrapped_self, clean_self._serviceName).unsubscribe(
+ subscriber, event_type, filter)
+ else:
+ subscriptions = clean_self._registry.getJustForType(ev_type)
+ try:
+ subscriptions.remove((subscriber, filter))
+ except ValueError:
+ raise NotFoundError(subscriber, event_type, filter)
+ if do_alert:
+ wrapped_subscriber.unsubscribedFrom(
+ self, event_type, filter)
+ if len(ev_set)==1:
+ for sub in subscriptions:
+ if sub[0]==subscriber:
+ break
+ else:
+ del clean_self._subscribers[subscriber_index]
+ else:
+ for ev_type in ev_set:
+ subscriptions = clean_self._registry.getJustForType(ev_type)
+ subs=subscriptions[:]
+ subscriptions[:] = []
+ for sub in subs:
+ if sub[0] == subscriber: # deleted (not added back)
+ if do_alert:
+ wrapped_subscriber.unsubscribedFrom(
+ wrapped_self, ev_type or IEvent, sub[1])
+ # IEvent switch is to make optimization transparent
+ else: # kept (added back)
+ subscriptions.append(sub)
+ del clean_self._subscribers[subscriber_index]
+ getNextService(wrapped_self, clean_self._serviceName).unsubscribe(
+ subscriber, event_type, filter)
+ clean_self._registry=clean_self._registry #trigger persistence
+
+ unsubscribe=ContextMethod(unsubscribe)
+
+ def listSubscriptions(wrapped_self, subscriber, event_type=None):
+ subscriber=removeAllProxies(subscriber) # might be wrapped, might not
+
+ clean_self=removeAllProxies(wrapped_self)
+ result=LocalSubscribable.listSubscriptions(
+ clean_self, subscriber, event_type)
+ result.extend(getNextService(
+ wrapped_self, clean_self._serviceName).listSubscriptions(
+ subscriber, event_type))
+ return result
+
+ listSubscriptions=ContextMethod(listSubscriptions)
=== Zope3/lib/python/Zope/App/OFS/Services/LocalEventService/LocalSubscribable.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from Zope.ComponentArchitecture.IToIRegistry import TypeRegistry
+from Zope.Exceptions import NotFoundError
+from Zope.Event.ISubscriptionAware import ISubscriptionAware
+from Zope.Event.IEvent import IEvent
+from Zope.ContextWrapper import ContextMethod
+from Zope.Proxy.ProxyIntrospection import removeAllProxies
+from Zope.Proxy.ContextWrapper import ContextWrapper
+from Zope.Event.Subscribable import Subscribable
+from Persistence import Persistent
+
+class LocalSubscribable(Subscribable, Persistent):
+ """a local mix-in"""
+
+ def subscribe(wrapped_self, subscriber, event_type=IEvent, filter=None):
+ subscriber=removeAllProxies(subscriber) # might be wrapped, might not
+
+ clean_self=removeAllProxies(wrapped_self)
+ wrapped_subscriber=ContextWrapper(subscriber, wrapped_self)
+
+ if ISubscriptionAware.isImplementedBy(subscriber):
+ wrapped_subscriber.subscribedTo(wrapped_self, event_type, filter)
+
+ ev_type=event_type
+ if ev_type is IEvent: ev_type=None # optimization
+
+ subscribers = clean_self._registry.getJustForType(ev_type)
+ if subscribers is None:
+ subscribers = []
+ clean_self._registry.register(ev_type, subscribers)
+ subscribers.append((subscriber, filter))
+
+ subs = clean_self._subscribers
+ for sub in subs:
+ if sub[0]==subscriber:
+ sub[1][ev_type]=1
+ break
+ else:
+ subs.append((subscriber,{ev_type:1}))
+
+ clean_self._registry=clean_self._registry #trigger persistence
+
+
+ subscribe=ContextMethod(subscribe)
+
+ def unsubscribe(wrapped_self, subscriber, event_type=None, filter=None):
+ subscriber=removeAllProxies(subscriber) # might be wrapped, might not
+
+ clean_self=removeAllProxies(wrapped_self)
+ wrapped_subscriber=ContextWrapper(subscriber, wrapped_self)
+
+ for subscriber_index in range(len(clean_self._subscribers)):
+ sub=clean_self._subscribers[subscriber_index]
+ if sub[0]==subscriber:
+ ev_set=sub[1]
+ break
+ else:
+ raise NotFoundError(subscriber)
+
+
+ do_alert=ISubscriptionAware.isImplementedBy(subscriber)
+
+ if event_type:
+ ev_type=event_type
+ if event_type is IEvent:
+ ev_type=None # handle optimization
+ if ev_type not in ev_set:
+ raise NotFoundError(subscriber, event_type, filter)
+ subscriptions = clean_self._registry.getJustForType(ev_type)
+ if not subscriptions:
+ raise NotFoundError(subscriber, event_type, filter)
+ try:
+ subscriptions.remove((subscriber, filter))
+ except ValueError:
+ raise NotFoundError(subscriber, event_type, filter)
+ if do_alert:
+ wrapped_subscriber.unsubscribedFrom(self, event_type, filter)
+ if len(ev_set)==1:
+ for sub in subscriptions:
+ if sub[0]==subscriber:
+ break
+ else:
+ del clean_self._subscribers[subscriber_index]
+ else:
+ for ev_type in ev_set:
+ subscriptions = clean_self._registry.getJustForType(ev_type)
+ subs=subscriptions[:]
+ subscriptions[:] = []
+ for sub in subs:
+ if sub[0] == subscriber: # deleted (not added back)
+ if do_alert:
+ wrapped_subscriber.unsubscribedFrom(
+ wrapped_self, ev_type or IEvent, sub[1])
+ # IEvent switch is to make optimization transparent
+ else: # kept (added back)
+ subscriptions.append(sub)
+ del clean_self._subscribers[subscriber_index]
+ clean_self._registry=clean_self._registry #trigger persistence
+
+ unsubscribe=ContextMethod(unsubscribe)
=== Zope3/lib/python/Zope/App/OFS/Services/LocalEventService/LocalSubscriptionAware.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+from Zope.Event.ISubscriptionAware import ISubscriptionAware
+from Zope.Proxy.ProxyIntrospection import removeAllProxies
+from Zope.ComponentArchitecture import getAdapter
+from Zope.App.Traversing.ITraverser import ITraverser
+
+
+class LocalSubscriptionAware:
+ # a mix-in
+
+ __implements__=ISubscriptionAware
+
+ def __init__(self):
+ self._subscriptions=()
+
+ def subscribedTo(self, subscribable, event_type, filter):
+ #subscribable_path=getAdapter(
+ # subscribable, ITraverser).getPhysicalPath()
+ subscribable_path="/%s" % "/".join(getAdapter(
+ subscribable, ITraverser).getPhysicalPath())
+ # XXX right now the conversion to a string is necessary because
+ # the tuple path returned by the Traverser does not include an
+ # empty initial space to represent the root
+ if (subscribable_path, event_type, filter) not in self._subscriptions:
+ self._subscriptions+=((subscribable_path,event_type, filter),)
+
+ def unsubscribedFrom(self, subscribable, event_type, filter):
+ subscribable_path="/%s" % "/".join(getAdapter(
+ subscribable, ITraverser).getPhysicalPath())
+ sub=list(self._subscriptions)
+ sub.remove((subscribable_path, event_type, filter))
+ self._subscriptions=tuple(sub)
+
+
+
\ No newline at end of file
=== Zope3/lib/python/Zope/App/OFS/Services/LocalEventService/PathSubscriber.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from Zope.ComponentArchitecture import getAdapter
+from Zope.App.Traversing.ITraverser import ITraverser
+from Zope.Event.ISubscriptionAware import ISubscriptionAware
+from Zope.Proxy.ProxyIntrospection import removeAllProxies
+from IPathSubscriber import IPathSubscriber
+from Interface import Attribute
+
+from Zope.ContextWrapper import ContextMethod
+
+
+class PathSubscriber:
+
+ __implements__=IPathSubscriber, ISubscriptionAware
+
+ def __init__(self, wrapped_subscriber):
+ self.subscriber_path="/%s" % "/".join(getAdapter(
+ wrapped_subscriber, ITraverser).getPhysicalPath())
+ # XXX right now the conversion to a string is necessary because
+ # the tuple path returned by the Traverser does not include an
+ # empty initial space to represent the root
+ self.__alert_subscription=ISubscriptionAware.isImplementedBy(
+ removeAllProxies(wrapped_subscriber) )
+
+ def __eq__(self, other):
+ return IPathSubscriber.isImplementedBy(other) and \
+ other.subscriber_path==self.subscriber_path
+
+ def __getSubscriber(self, wrapped_self):
+ return getAdapter(wrapped_self, ITraverser).traverse(
+ self.subscriber_path)
+
+ def notify(wrapped_self, event):
+ removeAllProxies(wrapped_self).__getSubscriber(
+ wrapped_self).notify(event)
+
+ notify=ContextMethod(notify)
+
+ def subscribedTo(wrapped_self, subscribable, event_type, filter):
+ clean_self=removeAllProxies(wrapped_self)
+ if clean_self.__alert_subscription:
+ clean_self.__getSubscriber(wrapped_self).subscribedTo(
+ subscribable, event_type, filter )
+
+ subscribedTo=ContextMethod(subscribedTo)
+
+ def unsubscribedFrom(wrapped_self, subscribable, event_type, filter):
+ clean_self=removeAllProxies(wrapped_self)
+ if clean_self.__alert_subscription:
+ clean_self.__getSubscriber(wrapped_self).unsubscribedFrom(
+ subscribable, event_type, filter )
+
+ unsubscribedFrom=ContextMethod(unsubscribedFrom)
+
\ No newline at end of file
=== Zope3/lib/python/Zope/App/OFS/Services/LocalEventService/__init__.py 1.1 => 1.2 ===
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Local Event Service"""
+
+
=== Zope3/lib/python/Zope/App/OFS/Services/LocalEventService/localEventService.zcml 1.1 => 1.2 ===
+ xmlns='http://namespaces.zope.org/zope'
+ xmlns:security='http://namespaces.zope.org/security'
+ xmlns:zmi='http://namespaces.zope.org/zmi'
+ xmlns:browser='http://namespaces.zope.org/browser'
+ xmlns:service='http://namespaces.zope.org/service'
+>
+
+ <content class='.LocalEventService.'>
+ <security:require
+ permission="Zope.View"
+ attributes="publishEvent notify" />
+ <security:require
+ permission="Zope.ManageServices"
+ attributes="bound unbound subscribe unsubscribe subscribeOnBind
+ unsubscribedFrom subscribedTo" />
+ </content>
+
+ <service:factoryFromClass
+ id='Events'
+ class='.LocalEventService.'
+ permission='Zope.ManageServices'
+ title='Events'
+ description='An event service: use sparingly' />
+
+ <include package=".Views"
+ file="views.zcml" />
+
+</zopeConfigure>