[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/OFS/Services/AddableService - Addable.py:1.1.2.2 GlobalAddableService.py:1.1.2.2 IAddable.py:1.1.2.2 IAddableService.py:1.1.2.2 __init__.py:1.1.2.2 addable-service.zcml:1.1.2.2

Gary Poster garyposter@earthlink.net
Mon, 29 Apr 2002 19:20:36 -0400


Update of /cvs-repository/Zope3/lib/python/Zope/App/OFS/Services/AddableService
In directory cvs.zope.org:/tmp/cvs-serv1556/App/OFS/Services/AddableService

Modified Files:
      Tag: Zope-3x-branch
	Addable.py GlobalAddableService.py IAddable.py 
	IAddableService.py __init__.py addable-service.zcml 
Log Message:
ComponentArchitecture reorganization; addition of for_container; addition of IWriteContainer.isAddable.

good news: all tests pass; bad news: after the new security system, my changes have some problems.  I had to punt on the default contents view of all folders for instance--hasServiceManager is causing a problem for some reason I couldn't divine, even with Shane's Checker tool.  I commented out the offending code on the contents.pt just to keep things up.

I tagged before committing: gary_CA-reorganization

changes more in depth (as I understand it, all or most approved :-) ):

(in ComponentArchitecture:)
 * changing implementation names to Global* (i.e., AdapterService becomes 
GlobalAdapterService) and giving each its own file (many are clumped together 
in hooks.py)
 * removing hooks.py in ComponentArchitecture, putting all functions in appropriate module above (i.e. getAdapter will be in the adapter module)
 * largely removing indirection (_hook) except for getService and 
getNextService
 * changing IServiceService.py to IServiceManager
 * changing Service.py to GlobalServiceManager.py (and class name too)
 * removing "provide*" functions (i.e., provideAdapter, provideUtility, etc.) 
and "defineService" from the __init__.py imports
 * change all global services to classes with appropriate methods as per 
interfaces
 * update all tests 
 * remove all of the "provide*" functions from the interfaces
 * renamed IComponentArchitecture to IPlacefulComponentArchitecture (hereafter IPCA), after long discussion with SteveA 
 * list Resources as one of core CA services in IPlacefulComponentArchitecture
 * build actual IPCA interface, not just import of service interfaces (because we want IPCA to be placeful, but the service interfaces do not need to be)
 * place functions implementing ICA actually in __init__
 * explicitly setting up services in zcml
 * created Global service interfaces, and placed the "provides" and "set" and "define" functions there: however, to keep the main interfaces clean and clear, I placed these global interfaces in the same file as the global implementations, hoping to clarify that these are not reusable interfaces but descriptive, one-time interfaces
 * built PlacefulSetup in Zope.ComponentArchitecture.tests for more specific CleanUp (a subclass).  PlacefulSetup is in the tests folder of the local ServiceManager.  AddableSetup also is available, in the AddableService tests.

(elsewhere in Zope3)
 * built for_container in addables
 * built isAddable for containers (after discussion with Jim, we decided an addable "contains" attribute in the zcml might not be the way to go.  I chose the isAddable approach for a number of reasons)
 * addableservice does some more checks in getting the addable list, pertinent to the above and to whether it can find the appropriate factories
 * a few more tests: a start of one in the local event service, and some more here and there

I'm sorry to add to the confusion of the big security changes, but I needed to either trash these changes or commit them: I'm a bit out of time for the moment.  If all else fails, again, I did tag the previous version.



=== Zope3/lib/python/Zope/App/OFS/Services/AddableService/Addable.py 1.1.2.1 => 1.1.2.2 ===
     __implements__=IAddable
 
-    def __init__(self, id, title, description, icon=None, marker_interface=None):
+    def __init__(self, id, title, description,
+                 for_container=None,
+                 creation_markers=None, icon=None):
         self.__id = id
         self.title = title
         self.description = description
         self.icon = icon
-        if marker_interface:
+        self.for_container=for_container
+        if creation_markers:
             if hasattr(self, "__implements__"): 
                 # not checking to see if already there...
-                self.__implements__ = marker_interface, self.__implements__
-            else: self.__implements__=marker_interface
+                self.__implements__ = creation_markers, self.__implements__
+            else: self.__implements__=creation_markers
 
     def __getid(self): return self.__id
     
     id=property(__getid)
     
-    def __eq__(self, other):
+    def __eq__(self, other): # here basically just for unit tests...
+        if not IAddable.isImplementedBy(other):
+            return 0
         try:
             i, t, d = other.id, other.title, other.description
         except AttributeError:
             return 0
         
         return self.id == i and self.title == t and self.description == d
+    
+    def __repr__(self): # and for debugging
+        return "<Addable %s (%s)>" % (self.__id, self.title)
 
     


=== Zope3/lib/python/Zope/App/OFS/Services/AddableService/GlobalAddableService.py 1.1.2.1 => 1.1.2.2 ===
 $Id$
 """
-from Zope.ComponentArchitecture import getService
+from Zope.ComponentArchitecture import getService, getFactoryInterfaces, \
+     ComponentLookupError
 from IAddableService import IAddableService
 from Addable import Addable
+from Zope.App.OFS.Container.IContainer import IWriteContainer
+from Zope.Proxy.ProxyIntrospection import removeAllProxies
+
+class IGlobalAddableService(IAddableService):
+    
+    def provideAddable(self, id, title, description, for_container=None,
+                       creation_markers=None):
+        """adds addable to service, associated with id (used in
+        factory service for the class)
+        
+        for_container is interface or interface tuple indicating type of
+        container to which this addable can be added (any match in list
+        is sufficient, including subclasses)
+        
+        creation_markers are marker interfaces to which one can associate
+        views for this addable (for pre-creation views)
+        
+        raises DuplicateError if id is already used in this service"""
+
+def multi_implement_check(interface, object):
+    if type(interface) is tuple:
+        for inter in interface:
+            if multi_implement_check(inter, object):
+                return 1
+        return 0
+    return interface.isImplementedBy(object)
 
 class GlobalAddableService: # file system
     
-    __implements__=IAddableService
+    __implements__=IGlobalAddableService
 
-    def provideAddable(self, id, title, description, marker_interface=None):
-        self.__reg.append(Addable(id, title, description, marker_interface=marker_interface))
+    def provideAddable(self, id, title, description, for_container=None,
+                       creation_markers=None):
+        self.__reg.append(Addable(id, title, description, 
+                                  for_container=for_container, 
+                                  creation_markers=creation_markers))
 
     def getAddables(self, ob):
-        return self.__reg[:]
+        clean_object=removeAllProxies(ob)
+        addables=[]
+        for addable in self.__reg:
+            for_c=addable.for_container
+            if not for_c or multi_implement_check(for_c, clean_object):
+                try:
+                    inter=getFactoryInterfaces(ob, addable.id)
+                except ComponentLookupError:
+                    continue
+                if IWriteContainer.isImplementedBy(clean_object) and not \
+                   ob.isAddable(inter):
+                    continue
+                addables.append(addable)
+        return addables
     
     def _clear(self):
         self.__reg = []


=== Zope3/lib/python/Zope/App/OFS/Services/AddableService/IAddable.py 1.1.2.1 => 1.1.2.2 ===
         
         read-write""")
+    
+    for_container = Attribute(
+        """the interfaces of objects that can contain this addable""")
 
     


=== Zope3/lib/python/Zope/App/OFS/Services/AddableService/IAddableService.py 1.1.2.1 => 1.1.2.2 ===
 class IAddableService(Interface):
     """The common denominator for all addables services.  Addables are
-    the """
+    the Zope-specific front end for the factory service.  The
+    functionality relies on the factory service and on the IContainer
+    interface"""
     
     def getAddables(container):
-        """returns the addables available from this service for the
-        service's context, as limited by what factory names are also
-        available in the same context, and as further limited by what
-        addables and factories are registered to be added to the
-        interfaces implemented by the container"""
-    
-    def provideAddable(name, addable):
-        """adds addable to service, associated with name
+        """returns the addables available from this service and its
+        parents for the service's context.
         
-        raises DuplicateError if name is already used in this service"""
+        By default, it is limited by what factory names are also
+        available in the same context; and further limited by what
+        addables and factories are registered to be added to the
+        interfaces implemented by the container; and, if the container
+        implements IWriteContainer, further limited by what interfaces
+        the container supports in its getAddableInterfaces method."""
 


=== Zope3/lib/python/Zope/App/OFS/Services/AddableService/__init__.py 1.1.2.1 => 1.1.2.2 ===
 ##############################################################################
 """ Addables """
-from hooks import getAddableContent, getAddableServices
\ No newline at end of file
+
+from Zope.ComponentArchitecture import getService
+
+def getAddableContent(wrapped_container):
+    """return the list of content addables for the given container"""
+    return getService(wrapped_container, 
+                      'AddableContent').getAddables(wrapped_container)
+
+def getAddableServices(wrapped_container):
+    """return the list  of service addables for the given container"""
+    return getService(wrapped_container,
+                      'AddableServices').getAddables(wrapped_container)
\ No newline at end of file


=== Zope3/lib/python/Zope/App/OFS/Services/AddableService/addable-service.zcml 1.1.2.1 => 1.1.2.2 ===
          component='.GlobalAddableService.addableServices' />
 
-<hookable module=".hooks" name="getAddableContent" />
-<hookable module=".hooks" name="getAddableServices" />
-
 </zopeConfigure>