[Zope3-checkins] CVS: Zope3/src/zope/app/services - event.py:1.14
Steve Alexander
steve@cat-box.net
Tue, 18 Feb 2003 10:19:23 -0500
Update of /cvs-repository/Zope3/src/zope/app/services
In directory cvs.zope.org:/tmp/cvs-serv5632/src/zope/app/services
Modified Files:
event.py
Log Message:
Fixed bug in event service where it was subscribing three times
to its parent event service. This was revealed by a unit test when the
erroneous 'Subscriptions' service id was replaced with the symbolic
constant. One bug had hidden the other. Symbolic service names are a
good idea.
=== Zope3/src/zope/app/services/event.py 1.13 => 1.14 ===
--- Zope3/src/zope/app/services/event.py:1.13 Fri Feb 14 18:06:08 2003
+++ Zope3/src/zope/app/services/event.py Tue Feb 18 10:19:22 2003
@@ -85,8 +85,7 @@
hubGet = getService(wrapped_self, HubIds).getObject
pathGet = getAdapter(wrapped_self, ITraverser).traverse
- badSubscribers = {}
-
+ badSubscribers = {} # using a dict as a set
for subscriptions in subscriptionsForEvent:
for subscriber,filter in subscriptions:
if filter is not None and not filter(event):
@@ -95,13 +94,13 @@
try:
obj = hubGet(subscriber)
except NotFoundError:
- badSubscribers[subscriber] = 1
+ badSubscribers[subscriber] = None
continue
else:
try:
obj = pathGet(subscriber)
except NotFoundError:
- badSubscribers[subscriber] = 1
+ badSubscribers[subscriber] = None
continue
# Get an ISubscriber adapter in the context of the object
# This is probably the right context to use.
@@ -112,7 +111,7 @@
# adding this subscriber to badSubscribers is inappropriate.
getAdapter(obj, ISubscriber).notify(event)
- for subscriber in badSubscribers.keys():
+ for subscriber in badSubscribers:
# XXX this ought to be logged
clean_self.unsubscribe(subscriber)
@@ -147,7 +146,7 @@
# the name of the service that this object is providing, or
# None if unbound
- _subscribeToServiceName = "Subscriptions"
+ _subscribeToServiceName = Subscription
_subscribeToServiceInterface = IEvent
_subscribeToServiceFilter = None
@@ -165,10 +164,14 @@
# this and the unbound code must be conditional for the
# pertinent service that should trigger event subscription
clean_self = removeAllProxies(wrapped_self)
- clean_self._serviceName = name # for LocalServiceSubscribable
+ clean_self._serviceName = name # for ServiceSubscribable
if clean_self.subscribeOnBind:
es = queryService(wrapped_self, clean_self._subscribeToServiceName)
if es is not None:
+ if removeAllProxies(es) is clean_self:
+ es = queryNextService(
+ wrapped_self, clean_self._subscribeToServiceName)
+ if es is not None:
es.subscribe(
wrapped_self,
clean_self._subscribeToServiceInterface,
@@ -178,7 +181,9 @@
def unbound(wrapped_self, name):
"See IBindingAware"
- # see comment in "bound" above
+ # Note: if a component is used for more than one service then
+ # this and the unbound code must be conditional for the
+ # pertinent service that should trigger event subscription
clean_self = removeAllProxies(wrapped_self)
@@ -314,32 +319,34 @@
def publish(wrapped_self, event):
"see IEventPublisher"
clean_self = removeAllProxies(wrapped_self)
- clean_self._notify(wrapped_self, 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).publish(event)
- publishedEvents.remove(event)
+ publishedEvents = getattr(clean_self, "_v_publishedEvents", [])
+ clean_self._v_publishedEvents = publishedEvents
+ publishedEvents.append(event)
+ try:
+ clean_self._notify(wrapped_self, event)
+ if clean_self.isPromotableEvent(event):
+ getNextService(wrapped_self, Events).publish(event)
+ finally:
+ publishedEvents.remove(event)
publish = ContextMethod(publish)
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:
+ publishedEvents = getattr(clean_self, "_v_publishedEvents", [])
+ if event not in publishedEvents:
clean_self._notify(wrapped_self, event)
notify = ContextMethod(notify)
def bound(wrapped_self, name):
"See IBindingAware"
- ContextSuper(EventService, wrapped_self).bound(name)
+ # An event service is bound as Subscription and as Events.
+ # We only want to subscribe to the next event service when we're bound
+ # as Subscription
if name == Subscription:
clean_self = removeAllProxies(wrapped_self)
- clean_self._serviceName = name # for LocalServiceSubscribable
+ clean_self._serviceName = name # for ServiceSubscribable
if clean_self.subscribeOnBind:
try:
es = getNextService(wrapped_self, Subscription)
@@ -351,6 +358,9 @@
def unbound(wrapped_self, name):
"See IBindingAware"
+ # An event service is bound as Subscription and as Events.
+ # We only want to unsubscribe from the next event service when
+ # we're unbound as Subscription
if name == Subscription:
clean_self = removeAllProxies(wrapped_self)
clean_self._v_unbinding = True