[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/OFS/ServiceManager - IBindingAware.py:1.1.2.1 IServiceManager.py:1.1.2.6 ServiceManager.py:1.1.2.11 hooks.py:1.1.2.6 service-manager.zcml:1.1.2.5

Gary Poster garyposter@earthlink.net
Fri, 17 May 2002 13:16:15 -0400


Update of /cvs-repository/Zope3/lib/python/Zope/App/OFS/ServiceManager
In directory cvs.zope.org:/tmp/cvs-serv15153/App/OFS/ServiceManager

Modified Files:
      Tag: Zope-3x-branch
	IServiceManager.py ServiceManager.py hooks.py 
	service-manager.zcml 
Added Files:
      Tag: Zope-3x-branch
	IBindingAware.py 
Log Message:
1) Fixed some of my own (wrapping) errors in CA and Traversal
2) added IBindingAware interface for services that need to know when they are bound and unbound to a local service manager
3) in subscribables, made event_types into event_type (YAGNI)
4) in subscribables, added ability to unsubscribe per subscription, not just whole-hog
5) in subscribables, added ability to query subscribable for subscriptions of a given subscriber
6) made ISubscribable extremely verbose, to hopefully describe exactly what's going on (see it for more smaller changes)
7) added ISubscriptionAware interface for objects that need to know when they have been subscribed and unsubscribed
8) built out local event service; once there are some views and once I have some more robust tests this *prototype* should by ready to fly.  Note that it is currently a standard service that can be added to any service manager, and thus the design does attempt to address many of the nested service manager issues.
9) as part of this, created the first indirect subscriber (all placeful
subscriptions will usually need to use indirect subscribers in order to retain their context when events are fired): PathSubscriber
10) removed an endless loop between local service managers and  ZopeSecurityPolicy in which both needed the other to function: ZopeSecurityPolicy now explicitly asks for adapters from the global service manager
11) unintentionally retained some of the "default=ComponentLookupError"-type argument signatures from my sandbox, but only within Container and Folder; I won't worry about undoing it though (unless I am otherwise requested) since it seems these interfaces are due for a dict-like overhaul anyway.

Also, if anyone needs a local event service setup for other tests (like the ObjectHub, for instance) see the LocalEventService/tests/EventSetup.py

more tests on the way for the local event service, and for the changes to the subscribable interface



=== Added File Zope3/lib/python/Zope/App/OFS/ServiceManager/IBindingAware.py ===
##############################################################################
#
# 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: IBindingAware.py,v 1.1.2.1 2002/05/17 17:15:44 poster Exp $
"""

from Interface import Interface

class IBindingAware(Interface):
    
    def bound(name):
        """Called when an immediately-containing service manager binds this object to
        perform the named service"""
    
    def unbound(name):
        """Called when an immediately-containing service manager unbinds this object
        from performing the named service"""

=== Zope3/lib/python/Zope/App/OFS/ServiceManager/IServiceManager.py 1.1.2.5 => 1.1.2.6 ===
 from Interface import Interface
 from Zope.ComponentArchitecture.IServiceManager import IServiceManager as \
-  IServiceService # fix once this package is changed to LocalServiceManager
+  IGlobalServiceManager # fix once this package is changed to LocalServiceManager
 from Zope.App.OFS.Container.IContainer import IContainer
 
-class IServiceManager(IServiceService, IContainer):
+class IServiceManager(IGlobalServiceManager, IContainer):
     """
     Service Managers act as containers for Services.
     
@@ -33,10 +33,14 @@
     """
 
     def bindService(serviceName, serviceComponentName):
-        """provide a service implementation"""
+        """provide a service implementation.  If the named object
+        implements IBindingAware, the wrapped object is notified as per
+        that interface"""
 
     def unbindService(serviceName):
-        """no longer provide a service implementation"""
+        """no longer provide a service implementation.  If the named
+        object implements IBindingAware, the wrapped object is notified
+        as per that interface"""
 
     def getBoundService(name):
         """retrieve a bound service implimentation


=== Zope3/lib/python/Zope/App/OFS/ServiceManager/ServiceManager.py 1.1.2.10 => 1.1.2.11 ===
 from Zope.App.OFS.Container.BTreeContainer import BTreeContainer
 from Zope.Proxy.ProxyIntrospection import removeAllProxies
+from IBindingAware import IBindingAware
 
 class ServiceManager(BTreeContainer):
 
@@ -72,7 +73,8 @@
 
         if service:
             return ContextWrapper(wrapped_self.getObject(service),
-                                  wrapped_self, name=name)
+                                  wrapped_self, name=service) # we want
+        # to traverse by component name, not service name
 
         return getNextService(wrapped_self, name)
 
@@ -88,15 +90,17 @@
         clean_self=removeAllProxies(wrapped_self)
 
         # This could raise a KeyError if we don't have this component
-        serviceComponent = removeAllProxies(
-             wrapped_self.getObject(
-                 serviceComponentName
-                 )
-             )
+        clean_serviceComponent = wrapped_self.getObject(
+            serviceComponentName
+           )
+        wrapped_serviceComponent=ContextWrapper(
+            clean_serviceComponent,
+            wrapped_self,
+            name=serviceComponentName)
 
         for name,interface in wrapped_self.getServiceDefinitions():
             if name == serviceName:
-                if not interface.isImplementedBy(serviceComponent):
+                if not interface.isImplementedBy(clean_serviceComponent):
                     raise InvalidService(serviceName,
                                          serviceComponentName,
                                          interface)
@@ -104,22 +108,40 @@
 
         # Services are added to the Manager through the Folder interface
         # self.setObject(name, component)
+        
+        if IBindingAware.isImplementedBy(clean_serviceComponent):
+            wrapped_serviceComponent.bound(serviceName)
+
+        clean_self.__bindings[serviceName] = serviceComponentName
 
         # trigger persistence
         clean_self.__bindings = clean_self.__bindings
 
-        clean_self.__bindings[serviceName] = serviceComponentName
-
     bindService=ContextMethod(bindService) # needed because of call to
-    # getServiceDefinitions
+    # getServiceDefinitions, as well as IBindingAware stuff
 
-    def unbindService(self, serviceName):
+    def unbindService(wrapped_self, serviceName):
         """ see IServiceManager Interface """
+        clean_self=removeAllProxies(wrapped_self)
+        serviceComponentName=clean_self.__bindings[serviceName]
+        
+        clean_serviceComponent = wrapped_self.getObject(
+            serviceComponentName
+           )
+        wrapped_serviceComponent=ContextWrapper(
+            clean_serviceComponent,
+            wrapped_self,
+            name=serviceComponentName)
+        
+        if IBindingAware.isImplementedBy(clean_serviceComponent):
+            wrapped_serviceComponent.unbound(serviceName)
 
-        # trigger persistence
-        self.__bindings = self.__bindings
+        del clean_self.__bindings[serviceName]
 
-        del self.__bindings[serviceName]
+        # trigger persistence
+        clean_self.__bindings = clean_self.__bindings
+    
+    unbindService=ContextMethod(unbindService)
 
 
     def delObject(self, name):


=== Zope3/lib/python/Zope/App/OFS/ServiceManager/hooks.py 1.1.2.5 => 1.1.2.6 ===
         if IServiceManagerContainer.isImplementedBy(
             clean_context) and clean_context.hasServiceManager():
-            return context.getServiceManager()
+            return ContextWrapper(context.getServiceManager(), context, name="Services;etc")
         context = getWrapperContainer(context)
     return serviceManager
 
@@ -47,7 +47,7 @@
     if context is serviceManager: return None
     context=getWrapperContainer(context)
     while context and not \
-          IServiceManagerContainer.isImplementedBy(context):
+          IServiceManagerContainer.isImplementedBy(removeAllProxies(context)):
         context=getWrapperContainer(context) # we should be
     # able to rely on the first step getting us a
     # ServiceManagerContainer


=== Zope3/lib/python/Zope/App/OFS/ServiceManager/service-manager.zcml 1.1.2.4 => 1.1.2.5 ===
 >
 
-<security:protectClass name="Zope.App.OFS.ServiceManager."
-   permission_id="Zope.ManageServices"
-   interface="Zope.App.OFS.ServiceManager.IServiceManager." 
-   />
+<security:protectClass name="Zope.App.OFS.ServiceManager+"
+   permission_id="Zope.Public">
+   
+    <security:protect
+               interface="Zope.App.OFS.Container.IContainer.IReadContainer"
+               permission_id="Zope.Public" />
+    <security:protect
+               interface="Zope.App.OFS.Container.IContainer.IWriteContainer"
+               permission_id="Zope.ManageServices" />
+   
+   <security:protect
+               interface="Zope.App.OFS.ServiceManager.IServiceManager+"
+               permission_id="Zope.ManageServices" />
+    
+   </security:protectClass>
 
 <include package="Zope.App.OFS.ServiceManager.Views" file="views.zcml" />