[Zope3-checkins] SVN: Zope3/branches/srichter-blow-services/src/zope/app/ Made the first registration-related tests pass. See the TXT files in

Stephan Richter srichter at cosmos.phy.tufts.edu
Thu Dec 23 13:26:32 EST 2004


Log message for revision 28692:
  Made the first registration-related tests pass. See the TXT files in 
  zope.app.component.
  
  Along the way I noticed that there are many circular imports in all of 
  this code. I think that my refactorings will improve the situation.
  
  

Changed:
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/__init__.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/adapter.py
  A   Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/__init__.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/adapter/__init__.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/adapter/adapter.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/localservice.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/registration/registration.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/site/browser/__init__.py
  A   Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/tests/
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/utility/utility.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/contentdirective.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/hooks.py
  A   Zope3/branches/srichter-blow-services/src/zope/app/component/interfaces/
  A   Zope3/branches/srichter-blow-services/src/zope/app/component/interfaces/__init__.py
  A   Zope3/branches/srichter-blow-services/src/zope/app/component/interfaces/registration.py
  D   Zope3/branches/srichter-blow-services/src/zope/app/component/interfaces.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/metaconfigure.py
  A   Zope3/branches/srichter-blow-services/src/zope/app/component/registration.py
  A   Zope3/branches/srichter-blow-services/src/zope/app/component/registration.txt
  U   Zope3/branches/srichter-blow-services/src/zope/app/component/site.py
  A   Zope3/branches/srichter-blow-services/src/zope/app/component/statusproperty.txt
  D   Zope3/branches/srichter-blow-services/src/zope/app/component/tests/service.py
  A   Zope3/branches/srichter-blow-services/src/zope/app/component/tests/test_registration.py
  U   Zope3/branches/srichter-blow-services/src/zope/app/publication/zopepublication.py

-=-
Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/__init__.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/__init__.py	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/__init__.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -17,7 +17,30 @@
 """
 __docformat__ = "reStructuredText"
 
+##############################################################################
+# BBB: Backward Compatiblity 12/23/2004
 
+import sys
+import zope.app
+from zope.app.component.bbb import registration
+sys.modules['zope.app.registration'] = registration
+zope.app.registration = registration
+from zope.app.component.bbb import localservice
+sys.modules['zope.app.component.localservice'] = localservice
+from zope.app.component.bbb import site
+sys.modules['zope.app.site'] = site
+zope.app.site = site
+from zope.app.component.bbb import adapter
+sys.modules['zope.app.adapter'] = adapter
+zope.app.adapter = adapter
+from zope.app.component.bbb import utility
+sys.modules['zope.app.utility'] = utility
+zope.app.utility = utility
+
+##############################################################################
+
+
+
 _marker = object()
 
 def getNextUtility(context, interface, name=''):

Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/adapter.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/adapter.py	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/adapter.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -16,26 +16,26 @@
 $Id$
 """
 __docformat__ = 'restructuredtext' 
-
+import sys
 from persistent.dict import PersistentDict
 from persistent import Persistent
-from zope.app import zapi
-from zope.app.registration.registration import NotifyingRegistrationStack
+
+import zope.component.adapter
+import zope.interface
+import zope.schema
 from zope.interface.adapter import adapterImplied, Default
 from zope.interface.adapter import Surrogate, AdapterRegistry
 from zope.security.proxy import removeSecurityProxy
-import sys
+
 import zope.app.component.localservice
 import zope.app.container.contained
-import zope.app.registration.interfaces
 import zope.app.site.interfaces
-import zope.app.registration
 import zope.component.interfaces
-import zope.component.adapter
-import zope.interface
-import zope.schema
+from zope.app import zapi
+from zope.app.component.interfaces.registration import IRegistry
 from zope.app.i18n import ZopeMessageIDFactory as _
 
+
 class LocalSurrogate(Surrogate):
     """Local surrogates
 
@@ -61,20 +61,18 @@
         self.adapters = adapters
         Surrogate.clean(self)
 
+
 class LocalAdapterRegistry(AdapterRegistry, Persistent):
-    """Local/persistent surrogate registry
-    """
+    """Local/persistent surrogate registry"""
 
-    zope.interface.implements(
-        zope.app.registration.interfaces.IRegistry,
-        )
+    zope.interface.implements(IRegistry)
     
     _surrogateClass = LocalSurrogate
 
     # Next local registry, may be None
-    next = None
+    nextRegistry = None
 
-    subs = ()
+    subRegistries = ()
 
     def __init__(self, base, next=None):
 
@@ -82,11 +80,11 @@
         self.base = base
 
         self.adapters = {}
-        self.stacks = PersistentDict()
+        self.registrations = PersistentDict()
         AdapterRegistry.__init__(self)
-        self.setNext(next)
+        self.setNextRegistry(next)
 
-    def setNext(self, next, base=None):
+    def setNextRegistry(self, next, base=None):
         if base is not None:
             self.base = base
         if self.next is not None:
@@ -96,10 +94,10 @@
         self.next = next
         self.adaptersChanged()
 
-    def addSub(self, sub):
+    def addSubRegistry(self, sub):
         self.subs += (sub, )
 
-    def removeSub(self, sub):
+    def removeSubRegistry(self, sub):
         self.subs = tuple([s for s in self.subs if s is not sub])
 
     def __getstate__(self):
@@ -119,34 +117,6 @@
     def baseFor(self, spec):
         return self.base.get(spec)
 
-    def queryRegistrationsFor(self, registration, default=None):
-        stacks = self.stacks.get(registration.required)
-        if stacks:
-            stack = stacks.get((False, registration.with, registration.name,
-                                registration.provided))
-            if stack is not None:
-                return stack
-
-        return default
-
-    _stackType = NotifyingRegistrationStack
-
-    def createRegistrationsFor(self, registration):
-        stacks = self.stacks.get(registration.required)
-        if stacks is None:
-            stacks = PersistentDict()
-            self.stacks[registration.required] = stacks
-
-        key = (False, registration.with, registration.name,
-               registration.provided)
-        stack = stacks.get(key)
-        if stack is None:
-            stack = self._stackType(self)
-            stacks[key] = stack
-
-        return stack
-
-
     def _updateAdaptersFromLocalData(self, adapters):
         for required, stacks in self.stacks.iteritems():
             if required is None:
@@ -168,7 +138,7 @@
                     
                     radapters[key] = removeSecurityProxy(registration.factory)
 
-    def adaptersChanged(self, *args):
+    def adaptersChanged(self):
 
         adapters = {}
         if self.next is not None:
@@ -187,8 +157,6 @@
             for sub in self.subs:
                 sub.adaptersChanged()
 
-    notifyActivated = notifyDeactivated = adaptersChanged
-
     def baseChanged(self):
         """Someone changed the base service
 

Added: Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/__init__.py
===================================================================

Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/adapter/__init__.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/adapter/__init__.py	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/adapter/__init__.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -16,7 +16,7 @@
 $Id$
 """
 
-from zope.app.adapter.adapter import IAdapterRegistration
-from zope.app.adapter.adapter import LocalAdapterRegistry
-from zope.app.adapter.adapter import LocalAdapterBasedService
+from zope.app.component.bbb.adapter.adapter import IAdapterRegistration
+from zope.app.component.bbb.adapter.adapter import LocalAdapterRegistry
+from zope.app.component.bbb.adapter.adapter import LocalAdapterBasedService
 

Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/adapter/adapter.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/adapter/adapter.py	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/adapter/adapter.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -29,7 +29,6 @@
 import zope.app.container.contained
 import zope.app.registration.interfaces
 import zope.app.site.interfaces
-import zope.app.registration
 import zope.component.interfaces
 import zope.component.adapter
 import zope.interface

Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/localservice.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/localservice.py	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/localservice.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -21,7 +21,7 @@
 from zope.component.exceptions import ComponentLookupError
 from zope.component.service import serviceManager
 from zope.component.interfaces import IServiceService
-from zope.app.site.interfaces import ISite, ISiteManager
+from zope.app.component.bbb.site.interfaces import ISite, ISiteManager
 from zope.testing.cleanup import addCleanUp
 from zope.app.component.hooks import setSite
 from zope.component.service import IGlobalServiceManager

Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/registration/registration.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/registration/registration.py	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/registration/registration.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -29,7 +29,7 @@
 
 from zope.app import zapi
 from zope.app.annotation.interfaces import IAttributeAnnotatable
-from zope.app.component.localservice import getLocalServices
+#from zope.app.component.localservice import getLocalServices
 from zope.app.container.contained import Contained
 from zope.app.container.contained import setitem, contained, uncontained
 from zope.app.copypastemove import ObjectCopier

Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/site/browser/__init__.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/site/browser/__init__.py	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/site/browser/__init__.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -23,7 +23,7 @@
 from zope.app.registration.interfaces import UnregisteredStatus
 from zope.app.registration.interfaces import RegisteredStatus
 from zope.app.registration.interfaces import ActiveStatus
-from zope.app.site.interfaces import ILocalService
+from zope.app.component.bbb.site.interfaces import ILocalService
 from zope.app.utility.interfaces import ILocalUtility
 from zope.app.site.service import ServiceRegistration
 from zope.app.publisher.browser import BrowserView

Copied: Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/tests (from rev 28677, Zope3/branches/srichter-blow-services/src/zope/app/component/tests)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/utility/utility.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/utility/utility.py	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/utility/utility.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -27,8 +27,8 @@
 from zope.app.adapter.adapter import LocalAdapterService
 from zope.app.component.localservice import queryNextService
 from zope.app.registration.registration import ComponentRegistration
-from zope.app.utility.interfaces import ILocalUtilityService
-from zope.app.utility.interfaces import IUtilityRegistration
+from interfaces import ILocalUtilityService
+from interfaces import IUtilityRegistration
 
 class LocalUtilityService(UtilityService, LocalAdapterService):
     """Local Utility Service

Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/contentdirective.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/contentdirective.py	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/contentdirective.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -18,15 +18,20 @@
 __docformat__ = 'restructuredtext'
 
 from types import ModuleType
+from persistent.interfaces import IPersistent
+from zope.component.factory import Factory
 from zope.interface import classImplements
 from zope.schema.interfaces import IField
 from zope.configuration.exceptions import ConfigurationError
 
 from zope.app import zapi
-from zope.component.factory import Factory
-from zope.app.security.protectclass \
-    import protectLikeUnto, protectName, protectSetAttribute
+from zope.app.annotation.interfaces import IAttributeAnnotatable
 from zope.app.component.interface import provideInterface
+from zope.app.component.interfaces import ILocalUtility
+from zope.app.location.interfaces import ILocation
+from zope.app.security.protectclass import protectLikeUnto, protectName
+from zope.app.security.protectclass import protectSetAttribute
+
 from metaconfigure import factory
 
 PublicPermission = 'zope.Public'
@@ -175,3 +180,59 @@
         # so addable names must also act as if they were all in the
         # same namespace, despite the service/content division
         factory(_context, factoryObj, id, title, description)
+
+
+class LocalUtilityDirective(ContentDirective):
+    r"""localUtility directive handler.
+
+    Examples:
+
+      >>> from zope.interface import implements
+      >>> class LU1(object):
+      ...     pass
+
+      >>> class LU2(LU1):
+      ...     implements(ILocation)
+
+      >>> class LU3(LU1):
+      ...     __parent__ = None
+
+      >>> class LU4(LU2):
+      ...     implements(IPersistent)
+
+      >>> dir = LocalUtilityDirective(None, LU4)
+      >>> IAttributeAnnotatable.implementedBy(LU4)
+      True
+      >>> ILocalUtility.implementedBy(LU4)
+      True
+
+      >>> LocalUtilityDirective(None, LU3)
+      Traceback (most recent call last):
+      ...
+      ConfigurationError: Class `LU3` does not implement `IPersistent`.
+
+      >>> LocalUtilityDirective(None, LU2)
+      Traceback (most recent call last):
+      ...
+      ConfigurationError: Class `LU2` does not implement `IPersistent`.
+
+      >>> LocalUtilityDirective(None, LU1)
+      Traceback (most recent call last):
+      ...
+      ConfigurationError: Class `LU1` does not implement `ILocation`.
+    """
+
+    def __init__(self, _context, class_):
+        if not ILocation.implementedBy(class_) and \
+               not hasattr(class_, '__parent__'):
+            raise ConfigurationError, \
+                  'Class `%s` does not implement `ILocation`.' %class_.__name__
+
+        if not IPersistent.implementedBy(class_):
+            raise ConfigurationError, \
+                 'Class `%s` does not implement `IPersistent`.' %class_.__name__
+
+        classImplements(class_, IAttributeAnnotatable)
+        classImplements(class_, ILocalUtility)
+
+        super(LocalUtilityDirective, self).__init__(_context, class_)

Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/hooks.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/hooks.py	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/hooks.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -18,7 +18,7 @@
 __docformat__ = 'restructuredtext'
 
 import zope.component
-from zope.app.site.interfaces import ISite
+from zope.app.component.interfaces import ISite
 from zope.component.exceptions import ComponentLookupError
 from zope.security.proxy import removeSecurityProxy
 from zope.app.traversing.interfaces import IContainmentRoot
@@ -41,7 +41,7 @@
 
 class SiteInfo(zope.thread.local):
     site = None
-    services = serviceManager
+    #services = serviceManager
 
     def adapter_hook(self):
         services = self.services

Copied: Zope3/branches/srichter-blow-services/src/zope/app/component/interfaces/__init__.py (from rev 28687, Zope3/branches/srichter-blow-services/src/zope/app/component/interfaces.py)
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/interfaces.py	2004-12-22 17:17:53 UTC (rev 28687)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/interfaces/__init__.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -0,0 +1,237 @@
+##############################################################################
+#
+# Copyright (c) 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Interfaces for the Local Component Architecture
+
+$Id$
+"""
+import zope.interface
+import zope.schema
+from zope.component.interfaces import ISiteManager
+from zope.app.container.interfaces import IContainer
+from zope.app.container.constraints import ContainerTypesConstraint
+from zope.app.container.constraints import ItemTypePrecondition
+from zope.app.i18n import ZopeMessageIDFactory as _
+import registration
+
+class IComponentManager(zope.interface.Interface):
+
+    def queryComponent(type=None, filter=None, all=0):
+        """Return all components that match the given type and filter
+
+        The objects are returned a sequence of mapping objects with keys:
+
+        path -- The component path
+
+        component -- The component
+
+        all -- A flag indicating whether all component managers in
+               this place should be queried, or just the local one.
+        """
+
+class IBindingAware(zope.interface.Interface):
+
+    def bound(name):
+        """Inform a service component that it is providing a service
+
+        Called when an immediately-containing service manager binds
+        this object to perform the named service.
+        """
+
+    def unbound(name):
+        """Inform a service component that it is no longer providing a service
+
+        Called when an immediately-containing service manager unbinds
+        this object from performing the named service.
+        """
+
+class IPossibleSite(zope.interface.Interface):
+    """An object that could be a site
+    """
+
+    def setSiteManager(sitemanager):
+        """Sets the service manager for this object.
+        """
+
+    def getSiteManager():
+        """Returns the service manager contained in this object.
+
+        If there isn't a service manager, raise a component lookup.
+        """
+
+class ISite(IPossibleSite):
+    """Marker interface to indicate that we have a site
+    """
+
+class ILocalSiteManager(ISiteManager, IComponentManager,
+                        registration.IRegistry):
+    """Service Managers act as containers for Services.
+
+    If a Service Manager is asked for a service, it checks for those it
+    contains before using a context-based lookup to find another service
+    manager to delegate to.  If no other service manager is found they defer
+    to the ComponentArchitecture ServiceManager which contains file based
+    services.
+    """
+
+    def queryRegistrations(name, default=None):
+        """Return an IRegistrationRegistry for the registration name.
+
+        queryRegistrationsFor(cfg, default) is equivalent to
+        queryRegistrations(cfg.name, default)
+        """
+
+    def createRegistrationsFor(registration):
+        """Create and return an IRegistrationRegistry for the registration
+        name.
+
+        createRegistrationsFor(cfg, default) is equivalent to
+        createRegistrations(cfg.name, default)
+        """
+
+    def listRegistrationNames():
+        """Return a list of all registered registration names.
+        """
+
+    def queryActiveComponent(name, default=None):
+        """Finds the registration registry for a given name, checks if it has
+        an active registration, and if so, returns its component.  Otherwise
+        returns default.
+        """
+
+    def addSubsite(subsite):
+        """Add a subsite of the site
+
+        Local sites are connected in a tree. Each site knows about
+        its containing sites and its subsites.
+        """
+
+    next = zope.interface.Attribute('The site that this site is a subsite of.')
+
+    def findModule(name):
+        """Find the module of the given name.
+
+        If the module can be find in the folder or a parent folder
+        (within the site manager), then return it, otherwise, delegate
+        to the module service.
+
+        This must return None when the module is not found.
+
+        """
+
+    def resolve(name):
+        """Resolve a dotted object name.
+
+        A dotted object name is a dotted module name and an object
+        name within the module.
+
+        TODO: We really should switch to using some other character than
+        a dot for the delimiter between the module and the object
+        name.
+
+        """
+
+class ISiteManagementFolder(registration.IRegisterableContainer,
+                            IContainer):
+    """Component and component registration containers."""
+
+    __parent__ = zope.schema.Field(
+        constraint = ContainerTypesConstraint(
+            ISiteManager,
+            registration.IRegisterableContainer,
+            ),
+        )
+
+class ISiteManagementFolders(IContainer, IComponentManager):
+    """A collection of ISiteManagementFolder objects.
+
+    An ISiteManagementFolders object supports simple containment as
+    well as package query and lookup.
+    
+    """
+
+class ILocalUtility(registration.IRegisterable):
+    """Local utility marker.
+
+    A marker interface that indicates that a component can be used as
+    a local utility.
+
+    Utilities should usually also declare they implement
+    IAttributeAnnotatable, so that the standard adapter to
+    IRegistered can be used; otherwise, they must provide
+    another way to be adaptable to IRegistered.
+    """
+
+
+
+
+
+class IAdapterRegistration(registration.IRegistration):
+
+    required = zope.schema.Choice(
+        title = _(u"For interface"),
+        description = _(u"The interface of the objects being adapted"),
+        vocabulary="Interfaces",
+        readonly = True)
+
+    provided = zope.schema.Choice(
+        title = _(u"Provided interface"),
+        description = _(u"The interface provided"),
+        vocabulary="Interfaces",
+        readonly = True,
+        required = True)
+
+    name = zope.schema.TextLine(
+        title=_(u"Name"),
+        readonly=True,
+        required=False,
+        )
+
+    factoryName = zope.schema.BytesLine(
+        title=_(u"The dotted name of a factory for creating the adapter"),
+        readonly = True,
+        required = True,
+        )
+
+    permission = zope.schema.Choice(
+        title=_(u"The permission required for use"),
+        vocabulary="Permission Ids",
+        readonly=False,
+        required=False,
+        )
+        
+    factory = zope.interface.Attribute(
+        _("Factory to be called to construct the component")
+        )
+
+class IUtilityRegistration(registration.IComponentRegistration):
+    """Utility registration object.
+
+    This is keyed off name (which may be empty) and interface. It inherits the
+    `component` property.
+    """
+
+    name = zope.schema.TextLine(
+        title=_("Register As"),
+        description=_("The name that is registered"),
+        readonly=True,
+        required=True,
+        )
+
+    interface = zope.schema.Choice(
+        title=_("Provided interface"),
+        description=_("The interface provided by the utility"),
+        vocabulary="Utility Component Interfaces",
+        readonly=True,
+        required=True,
+        )

Copied: Zope3/branches/srichter-blow-services/src/zope/app/component/interfaces/registration.py (from rev 28687, Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/registration/interfaces.py)
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/registration/interfaces.py	2004-12-22 17:17:53 UTC (rev 28687)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/interfaces/registration.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -0,0 +1,188 @@
+##############################################################################
+#
+# Copyright (c) 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Interfaces for objects supporting registration
+
+$Id$
+"""
+import zope.component.interfaces
+from zope.interface import Interface, Attribute, implements
+from zope.schema import TextLine, Field, Choice, Dict
+from zope.schema.interfaces import ITextLine, IField
+
+from zope.app.annotation.interfaces import IAnnotatable
+from zope.app.annotation.interfaces import IAttributeAnnotatable
+from zope.app.container.interfaces import IContainerNamesContainer
+from zope.app.container.interfaces import IContained, IContainer
+from zope.app.container.constraints import contains, containers
+from zope.app.event.interfaces import IObjectEvent
+from zope.app.i18n import ZopeMessageIDFactory as _
+
+InactiveStatus = _('Inactive')
+ActiveStatus = _('Active')
+
+
+class IRegistrationEvent(IObjectEvent):
+    """An event that involves a registration"""
+
+class IRegistrationActivatedEvent(IRegistrationEvent):
+    """This event is fired, when a component's registration is activated."""
+
+class IRegistrationDeactivatedEvent(IRegistrationEvent):
+    """This event is fired, when a component's registration is deactivated."""
+
+
+class IRegistration(Interface):
+    """Registration object
+
+    A registration object represents a specific registration
+    decision, such as registering an adapter or defining a permission.
+
+    In addition to the attributes or methods defined here,
+    registration objects will include additional attributes
+    identifying how they should be used. For example, a service
+    registration will provide a service type. An adapter
+    registration will specify a used-for interface and a provided
+    interface.
+    """
+
+    status = Choice(
+        title=_("Registration status"),
+        values=(InactiveStatus, ActiveStatus),
+        default=InactiveStatus
+        )
+
+class IComponent(IField):
+    """A component path
+
+    This is just the interface for the ComponentPath field below.  We'll use
+    this as the basis for looking up an appropriate widget.
+    """
+
+class Component(Field):
+    """A component path
+
+    Values of the field are absolute unicode path strings that can be
+    traversed to get an object.
+    """
+    implements(IComponent)
+
+
+class IComponentRegistration(IRegistration):
+    """Registration object that uses a component path and a permission."""
+
+    permission = Choice(
+        title=_("The permission needed to use the component"),
+        vocabulary="Permissions",
+        required=False,
+        )
+
+    component = Component(
+        title=_("Registration Component"),
+        description=_("The component the registration is for."),
+        required=True)
+
+    def getInterface(self):
+        """Return the interface the component provides through this
+        registration.
+
+        If no interface was specified, return `None`.
+
+        The interface will be used to produce a proxy for the component, if
+        the `permission` is specified.
+        """
+
+
+class IRegistry(zope.component.interfaces.IRegistry):
+    """A component that can be configured using a registration manager."""
+
+    def register(registration):
+        """Register a component with the registry using a registration.
+
+        Once the registration is added to the registry, it will be active. If
+        the registration is already registered with the registry, this method
+        will quietly return.
+        """
+
+    def unregister(registration):
+        """Unregister a component from the registry.
+
+        Unregistering a registration automatically makes the component
+        inactive. If the registration is not registered, this method will
+        quietly return.
+        """
+
+    def registered(registration):
+        """Determine whether a registration is registered with the registry.
+
+        The method will return a Boolean value.
+        """
+
+
+class IRegistrationManager(IContainerNamesContainer):
+    """Manage Registrations"""
+
+    def addRegistration(registration):
+        """Add a registration to the manager.
+
+        The function will automatically choose a name as which the
+        registration will be known. The name of the registration inside this
+        manager is returned.
+        """
+
+
+class IRegisterableContainer(IContainer):
+    """Containers with registration managers
+
+    These are site-management folders of one sort or another.
+
+    The container allows clients to access the registration manager
+    without knowing it's name.
+
+    The registration manager container *also* supports local-module
+    lookup.
+    """
+
+    registrationManager = Field(
+        title=_("Registration Manager"),
+        description=_("The registration manager keeps track of all component "
+                    "registrations."))
+
+
+class IRegisterable(IContained):
+    """Mark a component as registerable.
+
+    All registerable components need to implement this interface. 
+    """
+    containers(IRegisterableContainer)
+
+
+class IRegisterableContainerContaining(IContainer):
+    """A container that can only contain `IRegisterable`s and
+    `IRegisterableContainer`s.
+
+    This interface was designed to be always used together with the
+    `IRegisterableContainer`.
+    """
+    contains(IRegisterable, IRegisterableContainer)
+    
+
+class IRegistered(Interface):
+    """An object that can track down its registrations.
+
+    The object need not implement this functionality itself, but must at
+    least support doing so via an adapter.
+    """
+
+    def registrations():
+        """Return a sequence of registration objects for this object."""

Deleted: Zope3/branches/srichter-blow-services/src/zope/app/component/interfaces.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/interfaces.py	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/interfaces.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -1,218 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (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.
-#
-##############################################################################
-"""Interfaces for the Local Component Architecture
-
-$Id$
-"""
-import zope.interface
-import zope.schema
-from zope.component.interfaces import ISiteManager
-from zope.app.container.interfaces import IContainer
-from zope.app.container.constraints import ContainerTypesConstraint
-from zope.app.container.constraints import ItemTypePrecondition
-from zope.app.registration import interfaces as registration
-
-
-class IComponentManager(zope.interface.Interface):
-
-    def queryComponent(type=None, filter=None, all=0):
-        """Return all components that match the given type and filter
-
-        The objects are returned a sequence of mapping objects with keys:
-
-        path -- The component path
-
-        component -- The component
-
-        all -- A flag indicating whether all component managers in
-               this place should be queried, or just the local one.
-        """
-
-class IBindingAware(Interface):
-
-    def bound(name):
-        """Inform a service component that it is providing a service
-
-        Called when an immediately-containing service manager binds
-        this object to perform the named service.
-        """
-
-    def unbound(name):
-        """Inform a service component that it is no longer providing a service
-
-        Called when an immediately-containing service manager unbinds
-        this object from performing the named service.
-        """
-
-class IPossibleSite(zope.interface.Interface):
-    """An object that could be a site
-    """
-
-    def setSiteManager(sm):
-        """Sets the service manager for this object.
-        """
-
-    def getSiteManager():
-        """Returns the service manager contained in this object.
-
-        If there isn't a service manager, raise a component lookup.
-        """
-
-class ISite(IPossibleSite):
-    """Marker interface to indicate that we have a site
-    """
-
-class ILocalSiteManager(ISiteManager, IComponentManager,
-                        registration.IRegistry):
-    """Service Managers act as containers for Services.
-
-    If a Service Manager is asked for a service, it checks for those it
-    contains before using a context-based lookup to find another service
-    manager to delegate to.  If no other service manager is found they defer
-    to the ComponentArchitecture ServiceManager which contains file based
-    services.
-    """
-
-    def queryRegistrations(name, default=None):
-        """Return an IRegistrationRegistry for the registration name.
-
-        queryRegistrationsFor(cfg, default) is equivalent to
-        queryRegistrations(cfg.name, default)
-        """
-
-    def createRegistrationsFor(registration):
-        """Create and return an IRegistrationRegistry for the registration
-        name.
-
-        createRegistrationsFor(cfg, default) is equivalent to
-        createRegistrations(cfg.name, default)
-        """
-
-    def listRegistrationNames():
-        """Return a list of all registered registration names.
-        """
-
-    def queryActiveComponent(name, default=None):
-        """Finds the registration registry for a given name, checks if it has
-        an active registration, and if so, returns its component.  Otherwise
-        returns default.
-        """
-
-    def queryLocalService(service_type, default=None):
-        """Return a local service, if there is one
-
-        A local service is one configured in the local service manager.
-        """
-
-    def addSubsite(subsite):
-        """Add a subsite of the site
-
-        Local sites are connected in a tree. Each site knows about
-        its containing sites and its subsites.
-        """
-
-    next = Attribute('The site that this site is a subsite of.')
-
-
-class ISiteManagementFolder(registration.IRegisterableContainer,
-                            IContainer):
-    """Component and component registration containers."""
-
-    __parent__ = zope.schema.Field(
-        constraint = ContainerTypesConstraint(
-            ISiteManager,
-            registration.IRegisterableContainer,
-            ),
-        )
-
-class ISiteManagementFolders(IContainer, IComponentManager):
-    """A collection of ISiteManagementFolder objects.
-
-    An ISiteManagementFolders object supports simple containment as
-    well as package query and lookup.
-    
-    """
-
-class ILocalUtility(registration.IRegisterable):
-    """Local utility marker.
-
-    A marker interface that indicates that a component can be used as
-    a local utility.
-
-    Utilities should usually also declare they implement
-    IAttributeAnnotatable, so that the standard adapter to
-    IRegistered can be used; otherwise, they must provide
-    another way to be adaptable to IRegistered.
-    """
-
-
-class IAdapterRegistration(registration.IRegistration):
-
-    required = zope.schema.Choice(
-        title = _(u"For interface"),
-        description = _(u"The interface of the objects being adapted"),
-        vocabulary="Interfaces",
-        readonly = True)
-
-    provided = zope.schema.Choice(
-        title = _(u"Provided interface"),
-        description = _(u"The interface provided"),
-        vocabulary="Interfaces",
-        readonly = True,
-        required = True)
-
-    name = zope.schema.TextLine(
-        title=_(u"Name"),
-        readonly=True,
-        required=False,
-        )
-
-    factoryName = zope.schema.BytesLine(
-        title=_(u"The dotted name of a factory for creating the adapter"),
-        readonly = True,
-        required = True,
-        )
-
-    permission = zope.schema.Choice(
-        title=_(u"The permission required for use"),
-        vocabulary="Permission Ids",
-        readonly=False,
-        required=False,
-        )
-        
-    factory = zope.interface.Attribute(
-        _("Factory to be called to construct the component")
-        )
-
-class IUtilityRegistration(registration.IComponentRegistration):
-    """Utility registration object.
-
-    This is keyed off name (which may be empty) and interface. It inherits the
-    `component` property.
-    """
-
-    name = zope.schema.TextLine(
-        title=_("Register As"),
-        description=_("The name that is registered"),
-        readonly=True,
-        required=True,
-        )
-
-    interface = zope.schema.Choice(
-        title=_("Provided interface"),
-        description=_("The interface provided by the utility"),
-        vocabulary="Utility Component Interfaces",
-        readonly=True,
-        required=True,
-        )

Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/metaconfigure.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/metaconfigure.py	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/metaconfigure.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -16,12 +16,11 @@
 $Id$
 """
 __docformat__ = 'restructuredtext'
-from persistent.interfaces import IPersistent
 
 from zope.component.interfaces import IDefaultViewName, IFactory
 from zope.component.service import UndefinedService
 from zope.configuration.exceptions import ConfigurationError
-from zope.interface import Interface, classImplements
+from zope.interface import Interface
 from zope.interface.interfaces import IInterface
 
 from zope.security.checker import InterfaceChecker, CheckerPublic
@@ -29,11 +28,7 @@
 from zope.security.proxy import Proxy, ProxyFactory
 
 from zope.app import zapi
-from zope.app.annotation.interfaces import IAttributeAnnotatable
-from zope.app.component.contentdirective import ContentDirective
 from zope.app.component.interface import queryInterface
-from zope.app.component.interfaces import ILocalUtility
-from zope.app.location.interfaces import ILocation
 from zope.app.security.adapter import TrustedAdapterFactory
 
 
@@ -398,59 +393,3 @@
                (type,), IInterface, 'defaultLayer',
                lambda request: layer, _context.info)
         )
-
-
-class LocalUtilityDirective(ContentDirective):
-    r"""localUtility directive handler.
-
-    Examples:
-
-      >>> from zope.interface import implements
-      >>> class LU1(object):
-      ...     pass
-
-      >>> class LU2(LU1):
-      ...     implements(ILocation)
-
-      >>> class LU3(LU1):
-      ...     __parent__ = None
-
-      >>> class LU4(LU2):
-      ...     implements(IPersistent)
-
-      >>> dir = LocalUtilityDirective(None, LU4)
-      >>> IAttributeAnnotatable.implementedBy(LU4)
-      True
-      >>> ILocalUtility.implementedBy(LU4)
-      True
-
-      >>> LocalUtilityDirective(None, LU3)
-      Traceback (most recent call last):
-      ...
-      ConfigurationError: Class `LU3` does not implement `IPersistent`.
-
-      >>> LocalUtilityDirective(None, LU2)
-      Traceback (most recent call last):
-      ...
-      ConfigurationError: Class `LU2` does not implement `IPersistent`.
-
-      >>> LocalUtilityDirective(None, LU1)
-      Traceback (most recent call last):
-      ...
-      ConfigurationError: Class `LU1` does not implement `ILocation`.
-    """
-
-    def __init__(self, _context, class_):
-        if not ILocation.implementedBy(class_) and \
-               not hasattr(class_, '__parent__'):
-            raise ConfigurationError, \
-                  'Class `%s` does not implement `ILocation`.' %class_.__name__
-
-        if not IPersistent.implementedBy(class_):
-            raise ConfigurationError, \
-                 'Class `%s` does not implement `IPersistent`.' %class_.__name__
-
-        classImplements(class_, IAttributeAnnotatable)
-        classImplements(class_, ILocalUtility)
-
-        super(LocalUtilityDirective, self).__init__(_context, class_)

Copied: Zope3/branches/srichter-blow-services/src/zope/app/component/registration.py (from rev 28687, Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/registration/registration.py)
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/bbb/registration/registration.py	2004-12-22 17:17:53 UTC (rev 28687)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/registration.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -0,0 +1,227 @@
+##############################################################################
+#
+# Copyright (c) 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Component registration support
+
+$Id$
+"""
+from persistent import Persistent
+
+import zope.event
+from zope.interface import implements
+from zope.security.checker import CheckerPublic
+from zope.security.proxy import removeSecurityProxy
+
+from zope.app import zapi
+from zope.app.container.btree import BTreeContainer
+from zope.app.container.contained import Contained
+from zope.app.dependable.interfaces import IDependable, DependencyError
+from zope.app.event import objectevent
+from zope.app.location import inside
+from zope.app.component.interfaces import registration as interfaces
+
+
+class RegistrationEvent(objectevent.ObjectEvent):
+    """An event that is created when a registration-related activity occured."""
+    implements(interfaces.IRegistrationEvent)
+
+class RegistrationActivatedEvent(RegistrationEvent):
+    """An event that is created when a registration is activated."""
+    implements(interfaces.IRegistrationActivatedEvent)
+
+class RegistrationDeactivatedEvent(RegistrationEvent):
+    """An event that is created when a registration is deactivated."""
+    implements(interfaces.IRegistrationDeactivatedEvent)
+
+
+class RegistrationStatusProperty(object):
+    """A descriptor used to implement `IRegistration`'s `status` property."""
+    def __get__(self, inst, klass):
+        registration = inst
+        if registration is None:
+            return self
+
+        registry = registration.getRegistry()
+        if registry and registry.registered(registration):
+            return interfaces.ActiveStatus
+        
+        return interfaces.InactiveStatus
+
+    def __set__(self, inst, value):
+        registration = inst
+        registry = registration.getRegistry()
+        if registry is None:
+            raise ValueError, 'No registry found.'
+
+        if value == interfaces.ActiveStatus:
+            if not registry.registered(registration):
+                registry.register(registration)
+        elif value == interfaces.InactiveStatus:
+            if registry.registered(registration):
+                registry.unregister(registration)
+        else:
+            raise ValueError, value
+
+
+class SimpleRegistration(Persistent, Contained):
+    """Registration objects that just contain registration data"""
+    implements(interfaces.IRegistration)
+
+    # See interfaces.IRegistration
+    status = RegistrationStatusProperty()
+
+    def getRegistry(self):
+        """See interfaces.IRegistration"""
+        raise NotImplementedError, \
+              'This method must be implemented by each specific regstration.' 
+
+
+class ComponentRegistration(SimpleRegistration):
+    """Component registration.
+
+    Subclasses should define a getInterface() method returning the interface
+    of the component.
+    """
+    implements(interfaces.IComponentRegistration)
+
+    def __init__(self, component, permission=None):
+        self.component = component
+        if permission == 'zope.Public':
+            permission = CheckerPublic
+        self.permission = permission
+
+    def _getComponent(self):
+        if self.permission and self.getInterface():
+            checker = InterfaceChecker(self.getInterface(), self.permission)
+            return Proxy(self._component, checker)
+        return self._component
+
+    def _setComponent(self, component):
+        # We always want to set the plain component. Untrusted code will
+        # get back a proxied component anyways.
+        self._component = removeSecurityProxy(component)
+
+    component = property(_getComponent, _setComponent)
+
+    def getInterface(self):
+        return None
+
+
+def SimpleRegistrationRemoveSubscriber(registration, event):
+    """Receive notification of remove event."""
+    sm = zapi.getSiteManager(registration)
+    removed = event.object
+    if (sm == removed) or inside(sm, removed):
+        # we don't really care if the registration is active, since the site
+        # is going away.
+        return
+
+    objectstatus = registration.status
+
+    if objectstatus == interfaces.ActiveStatus:
+        try:
+            objectpath = zapi.getPath(registration)
+        except: # XXX
+            objectpath = str(registration)
+        raise DependencyError("Can't delete active registration (%s)"
+                              % objectpath)
+
+
+def ComponentRegistrationRemoveSubscriber(component_registration, event):
+    """Receive notification of remove event."""
+    component = component_registration.component
+    dependents = IDependable(component)
+    objectpath = zapi.getPath(component_registration)
+    dependents.removeDependent(objectpath)
+
+
+def ComponentRegistrationAddSubscriber(component_registration, event):
+    """Receive notification of add event."""
+    component = component_registration.component
+    dependents = IDependable(component)
+    objectpath = zapi.getPath(component_registration)
+    dependents.addDependent(objectpath)
+
+
+def RegisterableMoveSubscriber(registerable, event):
+    """A registerable cannot be moved as long as it has registrations in the
+    registration manager."""
+    if event.oldParent is not None and event.newParent is not None:
+        if event.oldParent is not event.newParent:
+            raise DependencyError(
+                "Can't move a registered component from its container.")
+
+
+class Registered(object):
+    """An adapter from IRegisterable to IRegistered.
+
+    This class is the only place that knows how 'Registered'
+    data is represented.
+    """
+    implements(interfaces.IRegistered)
+    __used_for__ = interfaces.IRegisterable
+
+    def __init__(self, registerable):
+        self.registerable = registerable
+
+    def registrations(self):
+        rm = zapi.getParent(self.registerable).registrationManager
+        return [reg for reg in rm
+                if (IComponentRegistration.providedBy(reg) and
+                    reg.component is self.registerable)]
+
+
+class RegistrationManager(BTreeContainer):
+    """Registration manager
+
+    Manages registrations within a package.
+    """
+    implements(interfaces.IRegistrationManager)
+
+    def addRegistration(self, reg):
+        "See IWriteContainer"
+        key = self._chooseName('', reg)
+        self[key] = reg
+        return key
+
+    def _chooseName(self, name, reg):
+        """Choose a name for the registration."""
+        if not name:
+            name = reg.__class__.__name__
+
+        i = 1
+        chosenName = name
+        while chosenName in self:
+            i += 1
+            chosenName = name + str(i)
+
+        return chosenName
+
+
+class RegisterableContainer(object):
+    """Mix-in to implement `IRegisterableContainer`"""
+    implements(interfaces.IRegisterableContainer,
+               interfaces.IRegisterableContainerContaining)
+
+    def __init__(self):
+        super(RegisterableContainer, self).__init__()
+        self.__createRegistrationManager()
+
+    def __createRegistrationManager(self):
+        "Create a registration manager and store it as `registrationManager`"
+        # See interfaces.IRegisterableContainer
+        self.registrationManager = RegistrationManager()
+        self.registrationManager.__parent__ = self
+        self.registrationManager.__name__ = 'RegistrationManager'
+        zope.event.notify(
+            objectevent.ObjectCreatedEvent(self.registrationManager))

Added: Zope3/branches/srichter-blow-services/src/zope/app/component/registration.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/registration.txt	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/registration.txt	2004-12-23 18:26:32 UTC (rev 28692)
@@ -0,0 +1,268 @@
+==========================
+The Registration Framework
+==========================
+
+The registration framework's task is to manage registrations and ensure that
+the correct registrations are inserted into the correct registries. Each
+registration knows to which registry it belongs. If a registration is set
+active, then the registration is added to the regstry; when inactive, it is
+removed from the registry. Please see `statusproperty.txt` for a demonstration
+on how the setting of the registration's status affects the registry.
+
+The true power of the registration framework, however, comes from the ability
+to provide registrations for registerable components. In the context of Zope
+3's component architecture, registerable components are adapters and
+utilities. Since the registration framework can be used for any kind of
+component registration, I am going to refer to registerable components
+(including adapters and interface) as components. 
+
+The first task is to create a simple component registry. It will implement all
+required `IRegistry` methods and a `getComponents()` method, which will return
+a list of all registered (active) components.
+
+  >>> import zope.interface
+  >>> from zope.app.component import interfaces
+  >>> class ComponentRegistry(object):
+  ...     zope.interface.implements(interfaces.registration.IRegistry)
+  ...
+  ...     def __init__(self):
+  ...         self._registrations = []
+  ...
+  ...     def registrations(self):
+  ...         """See zope.component.interfaces.IRegistry"""
+  ...         return self._registrations
+  ...
+  ...     def register(self, registration):
+  ...         """See interfaces.registration.IRegistry"""
+  ...         self._registrations.append(registration)
+  ...
+  ...     def unregister(self, registration):
+  ...         """See interfaces.registration.IRegistry"""
+  ...         del self._registrations[self._registrations.index(registration)]
+  ...
+  ...     def registered(self, registration):
+  ...         """See interfaces.registration.IRegistry"""
+  ...         return registration in self._registrations
+  ...
+  ...     def getComponents(self):
+  ...         return [reg.component for reg in self.registrations()]  
+
+  >>> registry = ComponentRegistry()
+
+Effectively, a registry manages a set of active registrations. A simple
+UML diagram would be:
+
+                          ---------------------------    
+    --------------- *   1 |  IRegistration          |
+    |  IRegistry  |-------| - - - - - - - - - - - - |
+    ---------------       |  status = ActiveStatus  |
+                          ---------------------------
+
+Next we need to create a registration object that can register components with
+our new registry. The framework already provides a base-class for
+component-based registrations, so that we only need to implement the
+`getRegistry()` method:
+
+  >>> from zope.app.component.registration import ComponentRegistration
+  >>> class Registration(ComponentRegistration):
+  ...
+  ...     def getRegistry(self):
+  ...         global registry
+  ...         return registry
+  ... 
+  ...     def __repr__(self):
+  ...         return "<Registration for '%s'>" %self.component
+
+In the implementation above, all `Registration` instances are simply going to
+use the global `registry` object. Now that we have a registry and a suitable
+registration class, let's test what we have so far. To do that we have to
+create a component that we would like to register:
+
+  >>> from zope.app.container.contained import Contained
+  >>> class Component(Contained):
+  ...     zope.interface.implements(interfaces.registration.IRegisterable)
+  ...     def __init__(self, title=u''):
+  ...         self.title = title
+  ...     def __repr__(self):
+  ...        return "<Component: '%s'>" %self.title
+
+Note that `Contained` is used as a base class, since `IRegisterable` requires
+it to be. We will later see why this is the case. 
+
+Before we are registering any component, the registry is empty:
+
+  >>> registry.getComponents()
+  []
+
+Now we create a component and a registration:
+
+  >>> foo = Component('Foo')
+  >>> regFoo = Registration(foo)
+  >>> regFoo.component
+  <Component: 'Foo'>
+  >>> regFoo.status
+  u'Inactive'
+
+Finally, we activate the registration:
+
+ 
+  >>> regFoo.status = interfaces.registration.ActiveStatus
+  >>> regFoo.status
+  u'Active'
+  >>> registry.getComponents()
+  [<Component: 'Foo'>]
+
+Of course, we can add a second registered component:
+
+  >>> bar = Component('Bar')
+  >>> regBar = Registration(bar)
+  >>> regBar.component
+  <Component: 'Bar'>
+  >>> regBar.status
+  u'Inactive'
+  >>> regBar.status = interfaces.registration.ActiveStatus
+  >>> regBar.status
+  u'Active'
+  >>> registry.getComponents()
+  [<Component: 'Foo'>, <Component: 'Bar'>]
+
+Of course, when deactivating a registration, it will be gone from the registry
+as well:
+
+  >>> regFoo.status = interfaces.registration.InactiveStatus
+  >>> regFoo.status
+  u'Inactive'
+  >>> registry.getComponents()
+  [<Component: 'Bar'>]
+
+This is everything that there is about registrations and their interaction
+with a registry. However, the point of registrations and registerable
+components is that they should be persistent (otherwise we could use
+ZCML). Thus we need a way of managing local components and their
+registrations.
+
+
+Management of Local Components and Registrations
+------------------------------------------------
+
+The starting point here is the `IRegisterableContainer`, which can contain
+`IRegiserable` and other `IRegisterableContainer` components.
+
+  >>> from zope.app.container.btree import BTreeContainer
+  >>> from zope.app.component.registration import RegisterableContainer
+
+  >>> class RegisterableManager(RegisterableContainer, BTreeContainer):
+  ...     pass
+  >>> registerables = RegisterableManager()
+
+The `RegisterableContainer` class is merely a mixin and leaves it up to the
+developer to implement the `IContainer` interface. In our case, we simply used
+the default btree container implementation to provide the container
+interface. However, the `RegisterableContainer` class does implement the
+`IRegisterableContainer` interface, which means it ensures the existance of
+the `registrationManager` attribute, which always contains an
+`IRegistrationManager` instance:
+
+  >>> registerables.registrationManager is not None
+  True
+  >>> interfaces.registration.IRegistrationManager.providedBy(
+  ...     registerables.registrationManager)
+  True
+
+The registration manager is a simple container that can only contain
+components providing `IRegistration` and implements a method called
+`addRegistration(registration)` that lets you add a registration to the
+manager without specifying a name. The name will be automatically chosen for
+you and is returned. So let's add our two existing components and their
+registrations:
+
+  >>> regManager = registerables.registrationManager
+
+  >>> registerables['foo'] = foo
+  >>> regManager.addRegistration(regFoo)
+  'Registration'
+
+  >>> registerables['bar'] = bar
+  >>> regManager.addRegistration(regBar)
+  'Registration2'
+
+  >>> items = list(registerables.items())
+  >>> items.sort()
+  >>> items
+  [(u'bar', <Component: 'Bar'>), (u'foo', <Component: 'Foo'>)]
+  >>> regs = list(regManager.items())
+  >>> regs.sort()
+  >>> regs #doctest: +NORMALIZE_WHITESPACE
+  [(u'Registration', <Registration for '<Component: 'Foo'>'>), 
+   (u'Registration2', <Registration for '<Component: 'Bar'>'>)]
+
+Of course, adding a registration to the registration manager does not mean the
+registration is added to the registry, since it still may not be active:
+
+  >>> registry.getComponents()
+  [<Component: 'Bar'>]
+
+Also, there are no restrictions on how many registrations you can create for a
+single component. For example, we can register the `foo` one more time:
+
+  >>> regFoo2 = Registration(foo)
+  >>> regManager.addRegistration(regFoo2)
+  'Registration3'
+  >>> regs = list(regManager.items())
+  >>> regs.sort()
+  >>> regs #doctest: +NORMALIZE_WHITESPACE
+  [(u'Registration', <Registration for '<Component: 'Foo'>'>), 
+   (u'Registration2', <Registration for '<Component: 'Bar'>'>),
+   (u'Registration3', <Registration for '<Component: 'Foo'>'>)]
+
+This also means that our registry can provide a component multiple times:
+
+  >>> regFoo.status = interfaces.registration.ActiveStatus
+  >>> regFoo2.status = interfaces.registration.ActiveStatus
+  >>> registry.getComponents()
+  [<Component: 'Bar'>, <Component: 'Foo'>, <Component: 'Foo'>]
+
+Here is a UML diagram of the registerable container and registration manager
+and their relationships to the other registration-related components we
+discussed.  
+
+    ----------------------------
+    |  IRegisterableContainer  |
+    | - - - - - - - - - - - - -|
+    |                       1  |    1 --------------------------
+    |  registrationManager ----+------|  IRegistrationManager  |
+    |                          |      --------------------------
+    ---------------------------+                  | *
+             | *        | *  | 1                  |
+             |          |    |                    | 1
+             | 1        +----+           -------------------
+    -------------------                  |  IRegistration  |
+    |  IRegisterable  |                  -------------------
+    -------------------                           | *
+                                                  |
+                             --------------- 1    |
+                             |  IRegistry  |------+ if status == Active
+                             ---------------
+
+
+The Component Registration
+--------------------------
+
+provided interface
+permission
+Registered
+
+
+Registration Events
+-------------------
+
+RegistrationActivatedEvent
+RegistrationDeactivatedEvent
+
+
+Registrations and Dependencies
+------------------------------
+
+ComponentRegistrationRemoveSubscriber
+ComponentRegistrationAddSubscriber
+RegisterableMoveSubscriber
\ No newline at end of file

Modified: Zope3/branches/srichter-blow-services/src/zope/app/component/site.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/site.py	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/site.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -26,39 +26,45 @@
 $Id$
 """
 import sys
-from transaction import get_transaction
 from zodbcode.module import PersistentModuleRegistry
 
 import zope.event
 import zope.interface
 from zope.component.exceptions import ComponentLookupError
 
-import zope.app.registration.interfaces
 from zope.app import zapi
 from zope.app.component.hooks import setSite
+from zope.app.component.interfaces.registration import IRegistry
+from zope.app.component.interfaces.registration import IRegisterableContainer
+from zope.app.component.registration import ComponentRegistration
+from zope.app.component.registration import RegistrationStack
 from zope.app.container.btree import BTreeContainer
 from zope.app.container.constraints import ItemTypePrecondition
 from zope.app.container.contained import Contained
 from zope.app.container.interfaces import IContainer
 from zope.app.event import objectevent
 from zope.app.location import inside
-from zope.app.registration.interfaces import IRegistry
-from zope.app.registration.registration import ComponentRegistration
-from zope.app.registration.registration import RegistrationStack
-from zope.app.site.folder import SiteManagementFolder
 from zope.app.traversing.interfaces import IContainmentRoot
 
 from zope.app.site.interfaces import IPossibleSite, ISite, ISiteManager
 
-class IRegisterableContainerContainer(zope.interface.Interface):
 
-    def __setitem__(name, folder):
-        """Add a site-management folder
-        """
-    __setitem__.precondition = ItemTypePrecondition(
-       zope.app.registration.interfaces.IRegisterableContainer)
+class SiteManagementFolder(RegisterableContainer, BTreeContainer):
+    implements(ISiteManagementFolder)
 
+class SMFolderFactory(object):
+    implements(IDirectoryFactory)
 
+    def __init__(self, context):
+        self.context = context
+
+    def __call__(self, name):
+        return SiteManagementFolder()
+
+class SiteManagementFolders(BTreeContainer):
+    pass 
+
+
 class LocalSiteManager(BTreeContainer, PersistentModuleRegistry):
 
     zope.interface.implements(ILocalSiteManager,
@@ -184,6 +190,7 @@
             return None
         return findModule(name)
 
+
     def __import(self, module_name):
         mod = self.findModule(module_name)
         if mod is None:
@@ -194,13 +201,46 @@
         return mod
 
 
+    def findModule(self, name):
+        # Used by the persistent modules import hook
+
+        # Look for a .py file first:
+        manager = self.get(name+'.py')
+        if manager is not None:
+            # found an item with that name, make sure it's a module(manager):
+            if IModuleManager.providedBy(manager):
+                return manager.getModule()
+
+        # Look for the module in this folder:
+        manager = self.get(name)
+        if manager is not None:
+            # found an item with that name, make sure it's a module(manager):
+            if IModuleManager.providedBy(manager):
+                return manager.getModule()
+
+
+        # See if out container is a RegisterableContainer:
+        c = self.__parent__
+        if interfaces.IRegisterableContainer.providedBy(c):
+            return c.findModule(name)
+
+        # Use sys.modules in lieu of module service:
+        module = sys.modules.get(name)
+        if module is not None:
+            return module
+
+        raise ImportError(name)
+
+
+    def resolve(self, name):
+        l = name.rfind('.')
+        mod = self.findModule(name[:l])
+        return getattr(mod, name[l+1:])
+
+
 class AdapterRegistration(
     zope.app.registration.registration.SimpleRegistration):
 
-    zope.interface.implements(IAdapterRegistration)
-
-    serviceType = zapi.servicenames.Adapters
-
     with = () # Don't support multi-adapters yet
 
     # TODO: These should be positional arguments, except that required
@@ -221,6 +261,9 @@
         return factory
     factory = property(factory)
 
+    def getRegistry(self):
+        sm = self.getSiteManager()
+        return sm.adapters
 
 
 class UtilityRegistration(ComponentRegistration):
@@ -231,8 +274,6 @@
     """
     zope.interface.implements(IUtilityRegistration)
 
-    serviceType = zapi.servicenames.Utilities
-
     ############################################################
     # To make adapter code happy. Are we going too far?
     #
@@ -248,22 +289,11 @@
         self.name = name
         self.interface = interface
 
-    def usageSummary(self):
-        # Override IRegistration.usageSummary()
-        s = self.getInterface().getName()
-        if self.name:
-            s += " registered as '%s'" % self.name
-        s += ", implemented by %s" %self.component.__class__.__name__
-        s += " '%s'"%zapi.name(self.component)
-        return s
+    def getRegistry(self):
+        sm = self.getSiteManager()
+        return sm.utilities
 
-    def getInterface(self):
-        # ComponentRegistration calls this when you specify a
-        # permission; it needs the interface to create a security
-        # proxy for the interface with the given permission.
-        return self.interface
 
-
 def threadSiteSubscriber(event):
     """A subscriber to BeforeTraverseEvent
 

Added: Zope3/branches/srichter-blow-services/src/zope/app/component/statusproperty.txt
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/statusproperty.txt	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/statusproperty.txt	2004-12-23 18:26:32 UTC (rev 28692)
@@ -0,0 +1,83 @@
+============================
+Registration Status Property
+============================
+
+The registratio status property is a descriptor used to implement the
+`IRegistration`' interface's `status` property.
+
+The property accepts two possible values: `ActiveStatus` and
+`InactiveStatus`. When the registration is active, then the registration is
+also activated in the registry.
+
+  >>> from zope.app.component.interfaces.registration import ActiveStatus
+  >>> from zope.app.component.interfaces.registration import InactiveStatus
+
+When setting the `status` property to `ActiveStatus`, then the registration
+should be added to the nearest matching registry. Here, the registration's
+`getRegistry()` method is used to determine the registry. On the same token,
+if the value is set to `InactiveStatus` the registration should be removed
+from the registry.
+
+To demonstrate this functionality, we first have to create a stub registry
+
+  >>> class Registry(object):
+  ...     registrations = []
+  ...     def register(self, registration):
+  ...         self.registrations.append(registration)
+  ...
+  ...     def unregister(self, registration):
+  ...         del self.registrations[self.registrations.index(registration)]
+  ...
+  ...     def registered(self, registration):
+  ...         return registration in self.registrations
+  
+  >>> registry = Registry()
+
+and a simple registration object
+
+  >>> from zope.app.component.registration import RegistrationStatusProperty
+  >>> class Registration(object):
+  ...     status = RegistrationStatusProperty()
+  ...
+  ...     def __init__(self, registry):
+  ...         self.registry = registry
+  ...
+  ...     def getRegistry(self):
+  ...         return self.registry
+
+Note that here only the `getRegistry()` is part of the registration API.
+
+Now that we have a registry and a registration class, let's create a
+registration:
+
+  >>> reg = Registration(registry)
+
+At the beginning the registration is inactive:
+
+  >>> reg.status
+  u'Inactive'
+  >>> reg.status is InactiveStatus
+  True
+  >>> reg in registry.registrations
+  False
+
+Once we activate the registration, it appears in the registry:
+
+  >>> reg.status = ActiveStatus
+  >>> reg.status
+  u'Active'
+  >>> reg.status is ActiveStatus
+  True
+  >>> reg in registry.registrations
+  True
+
+Now, once we deactivate the registration, it is not available in the registry
+anymore:
+
+  >>> reg.status = InactiveStatus
+  >>> reg.status
+  u'Inactive'
+  >>> reg.status is InactiveStatus
+  True
+  >>> reg in registry.registrations
+  False

Deleted: Zope3/branches/srichter-blow-services/src/zope/app/component/tests/service.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/tests/service.py	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/tests/service.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -1,38 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (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.
-#
-##############################################################################
-"""Service stub for testing
-
-$Id$
-"""
-from zope.interface import Interface, implements
-
-class IFooService(Interface):
-
-    def foo(): pass
-    def foobar(): pass
-
-class FooService(object):
-
-    implements(IFooService)
-
-    def foo(self): return "foo here"
-    def foobar(self): return "foobarred"
-
-    def bar(self): return "you shouldn't get this"
-
-fooService = FooService()
-
-class Foo2(FooService): pass
-
-foo2 = Foo2()

Added: Zope3/branches/srichter-blow-services/src/zope/app/component/tests/test_registration.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/component/tests/test_registration.py	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/component/tests/test_registration.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -0,0 +1,31 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Registration Tests
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+import unittest
+
+from zope.testing import doctest
+
+
+def test_suite():
+    return unittest.TestSuite((
+        doctest.DocFileSuite('../statusproperty.txt'),
+        doctest.DocFileSuite('../registration.txt'),
+        ))
+
+if __name__ == "__main__":
+    unittest.main(defaultTest='test_suite')

Modified: Zope3/branches/srichter-blow-services/src/zope/app/publication/zopepublication.py
===================================================================
--- Zope3/branches/srichter-blow-services/src/zope/app/publication/zopepublication.py	2004-12-22 23:26:23 UTC (rev 28691)
+++ Zope3/branches/srichter-blow-services/src/zope/app/publication/zopepublication.py	2004-12-23 18:26:32 UTC (rev 28692)
@@ -49,7 +49,7 @@
 from zope.app.security.principalregistry import principalRegistry as prin_reg
 from zope.app.security.interfaces import IUnauthenticatedPrincipal
 from zope.app.security.interfaces import IAuthenticationUtility
-from zope.app.site.interfaces import ISite
+from zope.app.component.interfaces import ISite
 from zope.app.traversing.interfaces import IPhysicallyLocatable
 
 class Cleanup(object):



More information about the Zope3-Checkins mailing list