[Zope3-checkins] SVN: Zope3/branches/jim-adapter/src/zope/component/ Added registration events.

Jim Fulton jim at zope.com
Sun Apr 2 13:00:12 EDT 2006


Log message for revision 66323:
  Added registration events.
  
  Registrations now include a registry attribute, indicating where they
  came from.
  
  All registries now have names and a repr that includes the name.
  
  Moved ObjectEvent/IObjectEvent to zope.component.interfaces.
  
  Eventually, we'll move the object dispatching code here.
  

Changed:
  U   Zope3/branches/jim-adapter/src/zope/component/interfaces.py
  U   Zope3/branches/jim-adapter/src/zope/component/registry.py
  U   Zope3/branches/jim-adapter/src/zope/component/registry.txt
  U   Zope3/branches/jim-adapter/src/zope/component/tests.py

-=-
Modified: Zope3/branches/jim-adapter/src/zope/component/interfaces.py
===================================================================
--- Zope3/branches/jim-adapter/src/zope/component/interfaces.py	2006-04-02 17:00:10 UTC (rev 66322)
+++ Zope3/branches/jim-adapter/src/zope/component/interfaces.py	2006-04-02 17:00:12 UTC (rev 66323)
@@ -17,9 +17,8 @@
 """
 
 import zope.deferredimport
-from zope.interface import Interface, Attribute
+from zope import interface
 
-
 # BBB: Backward-compatibility; 12/05/2004
 from bbb.interfaces import *
 
@@ -32,7 +31,27 @@
 class Misused(Exception):
     """A component is being used (registered) for the wrong interface."""
 
-class IComponentArchitecture(Interface):
+
+class IObjectEvent(interface.Interface):
+    """An event related to an object.
+
+    The object that generated this event is not necessarily the object
+    refered to by location.
+    """
+
+    object = interface.Attribute("The subject of the event.")
+
+
+class ObjectEvent(object):
+    interface.implements(IObjectEvent)
+
+    def __init__(self, object):
+        self.object = object
+
+    def __repr__(self):
+        return "%s event:\n%r" % (self.__class__.__name__, self.object)
+
+class IComponentArchitecture(interface.Interface):
     """The Component Architecture is defined by two key components: Adapters
     and Utiltities. Both are managed by site managers. All other components
     build on top of them.
@@ -51,9 +70,10 @@
 
         If `context` is `None`, return the global site manager.
 
-        If the `context` is not `None`, it is expected that an adapter from
-        the `context` to `IComponentLookup` can be found. If no adapter is found,
-        a `ComponentLookupError` is raised.
+        If the `context` is not `None`, it is expected that an adapter
+        from the `context` to `IComponentLookup` can be found. If no
+        adapter is found, a `ComponentLookupError` is raised.
+        
         """
 
     # Utility API
@@ -90,7 +110,9 @@
 
     # Adapter API
 
-    def getAdapter(object, interface=Interface, name=u'', context=None):
+    def getAdapter(object,
+                   interface=interface.Interface, name=u'',
+                   context=None):
         """Get a named adapter to an interface for an object
 
         Returns an adapter that can adapt object to interface.  If a matching
@@ -125,7 +147,9 @@
         returned.
         """
 
-    def getMultiAdapter(objects, interface=Interface, name='', context=None):
+    def getMultiAdapter(objects,
+                        interface=interface.Interface, name='',
+                        context=None):
         """Look for a multi-adapter to an interface for an objects
 
         Returns a multi-adapter that can adapt objects to interface.  If a
@@ -142,7 +166,7 @@
         named adapter methods with an empty string for a name.
         """
 
-    def queryAdapter(object, interface=Interface, name=u'', default=None,
+    def queryAdapter(object, interface=interface.Interface, name=u'', default=None,
                      context=None):
         """Look for a named adapter to an interface for an object
 
@@ -178,7 +202,9 @@
         returned.
         """
 
-    def queryMultiAdapter(objects, interface=Interface, name=u'', default=None,
+    def queryMultiAdapter(objects,
+                          interface=interface.Interface, name=u'',
+                          default=None,
                           context=None):
         """Look for a multi-adapter to an interface for objects
 
@@ -271,18 +297,18 @@
         create objects which implement the given interface.
         """
 
-class IComponentLookup(Interface):
+class IComponentLookup(interface.Interface):
     """Component Manager for a Site
 
     This object manages the components registered at a particular site. The
     definition of a site is intentionally vague.
     """
 
-    adapters = Attribute("Adapter Registry to manage all registered "
-                         "adapters.")
+    adapters = interface.Attribute(
+        "Adapter Registry to manage all registered adapters.")
 
-    utilities = Attribute("Adapter Registry to manage all registered "
-                          "utilities.")
+    utilities = interface.Attribute(
+        "Adapter Registry to manage all registered utilities.")
 
     def queryAdapter(object, interface, name=u'', default=None):
         """Look for a named adapter to an interface for an object
@@ -357,7 +383,7 @@
     ISiteManager = "zope.component.interfaces:IComponentLookup",
     )
         
-class IComponentRegistrationConvenience(Interface):
+class IComponentRegistrationConvenience(interface.Interface):
     """API for registering components.
 
     CAUTION: This API should only be used from test or
@@ -439,7 +465,7 @@
         activity. 
         """
 
-class IRegistry(Interface):
+class IRegistry(interface.Interface):
     """Object that supports component registry
     """
 
@@ -447,12 +473,12 @@
         """Return an iterable of component registrations
         """
 
-class IFactory(Interface):
+class IFactory(interface.Interface):
     """A factory is responsible for creating other components."""
 
-    title = Attribute("The factory title.")
+    title = interface.Attribute("The factory title.")
 
-    description = Attribute("A brief description of the factory.")
+    description = interface.Attribute("A brief description of the factory.")
 
     def __call__(*args, **kw):
         """Return an instance of the objects we're a factory for."""
@@ -466,8 +492,86 @@
         instance cannot be created, an empty Implements instance is returned.
         """
 
+class IRegistration(interface.Interface):
+    """A registration-information object 
+    """
 
-class IComponentRegistry(Interface):
+    registry = interface.Attribute("The registry having the registration")
+
+    name = interface.Attribute("The registration name")
+
+    info = interface.Attribute("""Information about the registration
+
+    This is information deemed useful to people browsing the
+    configuration of a system. It could, for example, include
+    commentary or information about the source of the configuration.
+    """)
+
+class IUtilityRegistration(IRegistration):
+    """Information about the registration of a utility
+    """
+
+    component = interface.Attribute("The object registered")
+    provided = interface.Attribute("The interface provided by the component")
+
+class IAdapterRegistration(IRegistration):
+    """Information about the registration of an adapter
+    """
+
+    factory = interface.Attribute("The factory used to create adapters")
+
+    required = interface.Attribute("""The adapted interfaces
+
+    This is a sequence of interfaces adapters by the registered
+    factory.  The factory will be caled with a sequence of objects, as
+    positional arguments, that provide these interfaces. 
+    """)
+
+    provided = interface.Attribute("""The interface provided by the adapters.
+
+    This interface is implemented by the factory
+    """)
+
+class ISubscriptionAdapterRegistration(IAdapterRegistration):
+    """Information about the registration of a subscription adapter
+    """
+
+class IHandlerRegistration(IRegistration):
+
+    handler = interface.Attribute("An object called used to handle an event")
+
+    required = interface.Attribute("""The handled interfaces
+
+    This is a sequence of interfaces handled by the registered
+    handler.  The handler will be caled with a sequence of objects, as
+    positional arguments, that provide these interfaces. 
+    """)
+
+class IRegistrationEvent(IObjectEvent):
+    """An event that involves a registration"""
+
+class RegistrationEvent(ObjectEvent):
+    """There has been a change in a registration
+    """
+    interface.implements(IRegistrationEvent)
+
+class IRegistered(IRegistrationEvent):
+    """A component or factory was registered 
+    """
+    
+class Registered(RegistrationEvent):
+    interface.implements(IRegistered)
+
+class IUnregistered(IRegistrationEvent):
+    """A component or factory was registered 
+    """
+
+class Unregistered(RegistrationEvent):
+    """A component or factory was registered 
+    """
+    interface.implements(IUnregistered)
+
+class IComponentRegistry(interface.Interface):
     """Register components
     """
 
@@ -489,6 +593,8 @@
         info
            An object that can be converted to a string to provide
            information about the registration.
+
+        A Registered event is generated with an IUtilityRegistration.
         """
 
     def unregisterUtility(component=None, provided=None, name=u''):
@@ -514,25 +620,15 @@
 
         name
            The utility name.
+
+        An UnRegistered event is generated with an IUtilityRegistration.
         """
 
     def registeredUtilities():
-        """Return an iterable of utility-information objects
+        """Return an iterable of IUtilityRegistrations.
 
-        The information objects will have attributes:
-
-        provided
-           The provided interface
-
-        name
-           The name
-
-        component
-           The registered component
-
-        info
-           An object that can be converted to a string to provide
-           information about the registration.
+        These registrations describe the current utility registrations
+        in the object.
         """
 
     def registerAdapter(factory, required=None, provided=None, name=u'',
@@ -568,6 +664,8 @@
         info
            An object that can be converted to a string to provide
            information about the registration.
+           
+        A Registered event is generated with an IAdapterRegistration.
         """
 
     def unregisterAdapter(factory=None, required=None,
@@ -609,27 +707,15 @@
 
         name
             The adapter name.
+
+        An Unregistered event is generated with an IAdapterRegistration.
         """
 
     def registeredAdapters():
-        """Return an iterable of adapter-information objects
+        """Return an iterable of IAdapterRegistrations.
 
-        The adapter information objects will have attributes:
-
-        required
-           An iterable of required interfaces
-
-        provided
-           The provided interface
-
-        name
-           The name
-
-        factory
-           The registered factory
-
-        info
-           Provide some info about this particular adapter registration.
+        These registrations describe the current adapter registrations
+        in the object.
         """
 
     def registerSubscriptionAdapter(factory, required=None, provides=None,
@@ -668,6 +754,9 @@
         info
            An object that can be converted to a string to provide
            information about the registration.
+
+        A Registered event is generated with an
+        ISubscriptionAdapterRegistration.
         """
 
     def unregisterSubscriptionAdapter(factory=None, required=None, 
@@ -712,28 +801,16 @@
 
             Note that this parameter is ignored and is reserved
             for future use when named subscribers are implemented.
+
+        An Unregistered event is generated with an
+        ISubscriptionAdapterRegistration.
         """
 
     def registeredSubscriptionAdapters():
-        """Return an iterable of subscriber-information objects
+        """Return an iterable of ISubscriptionAdapterRegistrations.
 
-        The subscriber information objects will have attributes:
-
-        required
-           An iterable of required interfaces
-
-        provided
-           The provided interface
-
-        name
-           The name
-
-        factory
-           The registered factory
-
-        info
-           An object that can be converted to a string to provide
-           information about the registration.
+        These registrations describe the current subscription adapter
+        registrations in the object.
         """
 
     def registerHandler(handler, adapts=None, name=u'', info=''):
@@ -768,6 +845,9 @@
         info
            An object that can be converted to a string to provide
            information about the registration.
+
+
+        A Registered event is generated with an IHandlerRegistration.
         """
 
     def unregisterHandler(handler=None, adapts=None, name=u''):
@@ -801,27 +881,18 @@
 
             Note that this parameter is ignored and is reserved
             for future use when named handlers are implemented.
+
+        An Unregistered event is generated with an IHandlerRegistration.
         """
 
     def registeredHandlers():
-        """Return an iterable of handler-information objects
+        """Return an iterable of IHandlerRegistrations.
 
-        The subscriber information objects will have attributes:
+        These registrations describe the current handler registrations
+        in the object.
+        """
 
-        required
-           An iterable of required interfaces
 
-        name
-           The name
-
-        handler
-           The registered handler
-
-        info
-           An object that can be converted to a string to provide
-           information about the registration.
-        """
-
 class IComponents(IComponentLookup, IComponentRegistry):
     """Component registration and access
     """

Modified: Zope3/branches/jim-adapter/src/zope/component/registry.py
===================================================================
--- Zope3/branches/jim-adapter/src/zope/component/registry.py	2006-04-02 17:00:10 UTC (rev 66322)
+++ Zope3/branches/jim-adapter/src/zope/component/registry.py	2006-04-02 17:00:12 UTC (rev 66323)
@@ -21,16 +21,22 @@
 from zope import interface
 from zope.component import interfaces
 import zope.interface.interfaces
+import zope.event
 
 class Components(object):
 
     interface.implements(interfaces.IComponents)
 
-    def __init__(self, bases=()):
+    def __init__(self, name='', bases=()):
+        assert isinstance(name, basestring)
+        self.__name__ = name
         self._init_registries()
         self._init_registrations()
         self.__bases__ = tuple(bases)
 
+    def __repr__(self):
+        return "<%s %s>" % (self.__class__.__name__, self.__name__) 
+
     def _init_registries(self):
         self.adapters = zope.interface.adapter.AdapterRegistry()
         self.utilities = zope.interface.adapter.AdapterRegistry()
@@ -75,6 +81,10 @@
         if not subscribed:
             self.utilities.subscribe((), provided, component)
 
+        zope.event.notify(interfaces.Registered(
+            UtilityRegistration(self, provided, name, component, info)
+            ))
+
     def unregisterUtility(self, component=None, provided=None, name=u''):
         if provided is None:
             if component is None:
@@ -99,13 +109,17 @@
 
         if not subscribed:
             self.utilities.unsubscribe((), provided, component)
+
+        zope.event.notify(interfaces.Unregistered(
+            UtilityRegistration(self, provided, name, component, old[1])
+            ))
         
         return True
 
     def registeredUtilities(self):
         for ((provided, name), (component, info)
              ) in self._utility_registrations.iteritems():
-            yield UtilityRegistration(provided, name, component, info)
+            yield UtilityRegistration(self, provided, name, component, info)
 
     def queryUtility(self, provided, name=u'', default=None):
         return self.utilities.lookup((), provided, name, default)
@@ -133,7 +147,13 @@
         self._adapter_registrations[(required, provided, name)
                                     ] = factory, info
         self.adapters.register(required, provided, name, factory)
+        
+        zope.event.notify(interfaces.Registered(
+            AdapterRegistration(self, required, provided, name,
+                                factory, info)
+            ))
 
+
     def unregisterAdapter(self, factory=None,
                           required=None, provided=None, name=u'',
                           ):
@@ -153,12 +173,18 @@
         
         del self._adapter_registrations[(required, provided, name)]
         self.adapters.unregister(required, provided, name)
+        
+        zope.event.notify(interfaces.Unregistered(
+            AdapterRegistration(self, required, provided, name,
+                                *old)
+            ))
+
         return True
         
     def registeredAdapters(self):
         for ((required, provided, name), (component, info)
              ) in self._adapter_registrations.iteritems():
-            yield AdapterRegistration(required, provided, name,
+            yield AdapterRegistration(self, required, provided, name,
                                       component, info)
 
     def queryAdapter(self, object, interface, name=u'', default=None):
@@ -200,10 +226,15 @@
             (required, provided, name, factory, info)
             )
         self.adapters.subscribe(required, provided, factory)
+        
+        zope.event.notify(interfaces.Registered(
+            SubscriptionRegistration(self, required, provided, name,
+                                     factory, info)
+            ))
 
     def registeredSubscriptionAdapters(self):
         for data in self._subscription_registrations:
-            yield SubscriptionRegistration(*data)
+            yield SubscriptionRegistration(self, *data)
 
     def unregisterSubscriptionAdapter(self, factory=None,
                           required=None, provided=None, name=u'',
@@ -239,14 +270,17 @@
 
         self._subscription_registrations = new
         self.adapters.unsubscribe(required, provided)
+        
+        zope.event.notify(interfaces.Unregistered(
+            SubscriptionRegistration(self, required, provided, name,
+                                     factory, '')
+            ))
+
         return True
 
     def subscribers(self, objects, provided):
         return self.adapters.subscribers(objects, provided)
 
-
-
-
     def registerHandler(self,
                         factory, required=None,
                         name=u'', info=u''):
@@ -257,10 +291,14 @@
             (required, name, factory, info)
             )
         self.adapters.subscribe(required, None, factory)
+        
+        zope.event.notify(interfaces.Registered(
+            HandlerRegistration(self, required, name, factory, info)
+            ))
 
     def registeredHandlers(self):
         for data in self._handler_registrations:
-            yield HandlerRegistration(*data)
+            yield HandlerRegistration(self, *data)
 
     def unregisterHandler(self, factory=None, required=None, name=u''):
         if name:
@@ -289,6 +327,11 @@
         
         self._handler_registrations = new
         self.adapters.unsubscribe(required, None)
+        
+        zope.event.notify(interfaces.Unregistered(
+            HandlerRegistration(self, required, name, factory, '')
+            ))
+
         return True
 
     def handle(self, *objects):
@@ -343,15 +386,16 @@
         
 class UtilityRegistration(object):
 
-    def __init__(self, provided, name, component, doc):
-        (self.provided, self.name, self.component, self.info
-         ) = provided, name, component, doc
+    def __init__(self, registry, provided, name, component, doc):
+        (self.registry, self.provided, self.name, self.component, self.info
+         ) = registry, provided, name, component, doc
 
     def __repr__(self):
-        return '%s(%r, %r, %r, %r)' % (
+        return '%s(%r, %s, %r, %s, %r)' % (
             self.__class__.__name__,
+            self.registry,
             getattr(self.provided, '__name__', None), self.name,
-            getattr(self.component, '__name__', self.component), self.info,
+            getattr(self.component, '__name__', `self.component`), self.info,
             )
 
     def __cmp__(self, other):
@@ -359,29 +403,38 @@
         
 class AdapterRegistration(object):
 
-    def __init__(self, required, provided, name, component, doc):
-        (self.required, self.provided, self.name, self.factory, self.info
-         ) = required, provided, name, component, doc
+    def __init__(self, registry, required, provided, name, component, doc):
+        (self.registry, self.required, self.provided, self.name,
+         self.factory, self.info
+         ) = registry, required, provided, name, component, doc
 
     def __repr__(self):
-        return '%s(%r, %r, %r, %r, %r)' % (
+        return '%s(%r, %s, %s, %r, %s, %r)' % (
             self.__class__.__name__,
-            tuple([r.__name__ for r in self.required]), 
+            self.registry,
+            '[' + ", ".join([r.__name__ for r in self.required]) + ']', 
             getattr(self.provided, '__name__', None), self.name,
-            getattr(self.factory, '__name__', self.factory), self.info,
+            getattr(self.factory, '__name__', `self.factory`), self.info,
             )
 
     def __cmp__(self, other):
         return cmp(self.__repr__(), other.__repr__())
 
+    @property
+    @zope.deprecation.deprecate(
+        "The component attribute on adapter registrations will be unsupported "
+        "in Zope 3.5. Use the factory attribute instead.")
+    def component(self):
+        return self.factory
+
 class SubscriptionRegistration(AdapterRegistration):
     pass
 
-class HandlerRegistration(object):
+class HandlerRegistration(AdapterRegistration):
 
-    def __init__(self, required, name, handler, doc):
-        (self.required, self.name, self.handler, self.info
-         ) = required, name, handler, doc
+    def __init__(self, registry, required, name, handler, doc):
+        (self.registry, self.required, self.name, self.handler, self.info
+         ) = registry, required, name, handler, doc
 
     @property
     def factory(self):
@@ -390,10 +443,11 @@
     provided = None
 
     def __repr__(self):
-        return '%s(%r, %r, %r, %r)' % (
+        return '%s(%r, %s, %r, %s, %r)' % (
             self.__class__.__name__,
-            tuple([r.__name__ for r in self.required]), 
+            self.registry,
+            '[' + ", ".join([r.__name__ for r in self.required]) + ']', 
             self.name,
-            getattr(self.factory, '__name__', self.factory), self.info,
+            getattr(self.factory, '__name__', `self.factory`), self.info,
             )
     

Modified: Zope3/branches/jim-adapter/src/zope/component/registry.txt
===================================================================
--- Zope3/branches/jim-adapter/src/zope/component/registry.txt	2006-04-02 17:00:10 UTC (rev 66322)
+++ Zope3/branches/jim-adapter/src/zope/component/registry.txt	2006-04-02 17:00:12 UTC (rev 66323)
@@ -18,7 +18,15 @@
 
     >>> from zope.component.registry import Components
     >>> from zope.component import tests
-    >>> components = Components()
+    >>> components = Components('comps')
+
+As components atr registered, events are generated.  Let's register
+an event subscriber, so we can see the events generated:
+
+    >>> import zope.event
+    >>> def logevent(event):
+    ...     print event
+    >>> zope.event.subscribers.append(logevent)
     
 Utilities
 ---------
@@ -26,6 +34,8 @@
 You can register Utilities using registerUtility:
 
     >>> components.registerUtility(tests.U1(1))
+    Registered event:
+    UtilityRegistration(<Components comps>, I1, u'', 1, u'')
 
 Here we didn't specify an interface or name.  An unnamed utility was
 registered for interface I1, since that is only interface implemented
@@ -55,10 +65,14 @@
 We can provide an interface if desired:
 
     >>> components.registerUtility(tests.U12(2), tests.I2)
+    Registered event:
+    UtilityRegistration(<Components comps>, I2, u'', 2, u'')
 
 and we can specify a name:
 
     >>> components.registerUtility(tests.U12(3), tests.I2, u'three')
+    Registered event:
+    UtilityRegistration(<Components comps>, I2, u'three', 3, u'')
 
     >>> components.getUtility(tests.I2)
     U12(2)
@@ -98,6 +112,8 @@
 Duplicate registrations replace existing ones:
 
     >>> components.registerUtility(tests.U1(4), info=u'use 4 now')
+    Registered event:
+    UtilityRegistration(<Components comps>, I1, u'', 4, u'use 4 now')
     >>> components.getUtility(tests.I1)
     U1(4)
 
@@ -118,6 +134,8 @@
 You can also unregister utilities:
 
     >>> components.unregisterUtility(provided=tests.I1)
+    Unregistered event:
+    UtilityRegistration(<Components comps>, I1, u'', 4, u'use 4 now')
     True
 
 A boolean is returned indicating whether anything changed:
@@ -136,11 +154,15 @@
 
     >>> u5 = tests.U1(5)
     >>> components.registerUtility(u5)
+    Registered event:
+    UtilityRegistration(<Components comps>, I1, u'', 5, u'')
     >>> components.unregisterUtility(tests.U1(6))
     False
     >>> components.queryUtility(tests.I1)
     U1(5)
     >>> components.unregisterUtility(u5)
+    Unregistered event:
+    UtilityRegistration(<Components comps>, I1, u'', 5, u'')
     True
     >>> components.queryUtility(tests.I1)
 
@@ -150,6 +172,8 @@
 You can register adapters with registerAdapter:
 
     >>> components.registerAdapter(tests.A12_1)
+    Registered event:
+    AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
 
 Here, we didn't specify required interfaces, a provided interface, or
 a name.  The required interfaces were determined from the factory
@@ -172,6 +196,8 @@
 Unless the provided interface is specified:
 
     >>> components.registerAdapter(tests.A1_12, provided=tests.IA2)
+    Registered event:
+    AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
 
 If a factory doesn't declare an implemented interface, an exception will be
 raised:
@@ -186,6 +212,8 @@
 Unless the provided interface is specified:
 
     >>> components.registerAdapter(tests.A12_, provided=tests.IA2)
+    Registered event:
+    AdapterRegistration(<Components comps>, [I1, I2], IA2, u'', A12_, u'')
 
 If the required interface needs to be specified in the
 registration if the factory doesn't have a __component_adapts__
@@ -201,12 +229,18 @@
 Unless the required specifications specified:
 
     >>> components.registerAdapter(tests.A_2, required=[tests.I3])
+    Registered event:
+    AdapterRegistration(<Components comps>, [I3], IA2, u'', A_2, u'')
 
 Classes can be specified in place of specifications, in which case the
 implementedBy specification for the class is used:
 
     >>> components.registerAdapter(tests.A_3, required=[tests.U],
     ...                            info="Really class specific")
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Registered event:
+    AdapterRegistration(<Components comps>, [zope.component.tests.U], IA3, u'',
+                        A_3, 'Really class specific')
 
 We can see the adapters that have been registered using the
 registeredAdapters method:
@@ -278,7 +312,10 @@
 be provided:
 
     >>> components.unregisterAdapter(tests.A12_1)
+    Unregistered event:
+    AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
     True
+
     >>> for regsitration in sorted(components.registeredAdapters()):
     ...     print regsitration.required
     ...     print regsitration.provided, regsitration.name
@@ -313,6 +350,8 @@
 Unless the provided interface is specified:
 
     >>> components.unregisterAdapter(tests.A1_12, provided=tests.IA2)
+    Unregistered event:
+    AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
     True
 
 If a factory doesn't declare an implemented interface, an exception will be
@@ -328,6 +367,8 @@
 Unless the provided interface is specified:
 
     >>> components.unregisterAdapter(tests.A12_, provided=tests.IA2)
+    Unregistered event:
+    AdapterRegistration(<Components comps>, [I1, I2], IA2, u'', A12_, u'')
     True
 
 The required interface needs to be specified if the factory doesn't
@@ -341,6 +382,8 @@
     attribute and no required specifications were specified 
 
     >>> components.unregisterAdapter(tests.A_2, required=[tests.I3])
+    Unregistered event:
+    AdapterRegistration(<Components comps>, [I3], IA2, u'', A_2, u'')
     True
 
     >>> for regsitration in sorted(components.registeredAdapters()):
@@ -365,6 +408,10 @@
 specified required and provided interfaces:
 
     >>> components.unregisterAdapter(required=[tests.U], provided=tests.IA3)
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Unregistered event:
+    AdapterRegistration(<Components comps>, [zope.component.tests.U], 
+                        IA3, u'', A_3, 'Really class specific')
     True
 
     >>> for regsitration in sorted(components.registeredAdapters()):
@@ -374,6 +421,8 @@
 
     >>> components.registerAdapter(tests.A1_12, provided=tests.IA2, 
     ...                            name=u'test')
+    Registered event:
+    AdapterRegistration(<Components comps>, [I1], IA2, u'test', A1_12, u'')
 
     >>> components.queryMultiAdapter((tests.U1(9), ), tests.IA2)
     >>> components.queryMultiAdapter((tests.U1(9), ), tests.IA2, name=u'test')
@@ -390,8 +439,13 @@
 
     >>> components.registerAdapter(tests.A1_23, provided=tests.IA2, 
     ...                            name=u'test 2')
+    Registered event:
+    AdapterRegistration(<Components comps>, [I1], IA2, u'test 2', A1_23, u'')
 
     >>> components.registerAdapter(tests.A1_12, provided=tests.IA2)
+    Registered event:
+    AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
+
     >>> for name, adapter in sorted(components.getAdapters((tests.U1(9), ), 
     ...                                                    tests.IA2)):
     ...     print name, adapter
@@ -408,9 +462,16 @@
     >>> components.registerAdapter(tests.noop, 
     ...                            required=[tests.IA1], provided=tests.IA2, 
     ...                            name=u'test noop')
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Registered event:
+    AdapterRegistration(<Components comps>, [IA1], IA2, u'test noop', 
+                        noop, u'')
     >>> components.queryAdapter(tests.U1(9), tests.IA2, name=u'test noop')
 
     >>> components.registerAdapter(tests.A1_12, provided=tests.IA2)
+    Registered event:
+    AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
+
     >>> for name, adapter in sorted(components.getAdapters((tests.U1(9), ), 
     ...                                                    tests.IA2)):
     ...     print name, adapter
@@ -420,9 +481,13 @@
 
 
     >>> components.unregisterAdapter(tests.A1_12, provided=tests.IA2, 
-    ...                            name=u'test')
+    ...                              name=u'test')
+    Unregistered event:
+    AdapterRegistration(<Components comps>, [I1], IA2, u'test', A1_12, u'')
     True
     >>> components.unregisterAdapter(tests.A1_12, provided=tests.IA2)
+    Unregistered event:
+    AdapterRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
     True
     >>> for regsitration in sorted(components.registeredAdapters()):
     ...     print regsitration.required
@@ -446,14 +511,24 @@
 
 Subscribers are registered by calling registerSubscriptionAdapter:
 
-     >>> components.registerSubscriptionAdapter(tests.A1_2)
+    >>> components.registerSubscriptionAdapter(tests.A1_2)
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Registered event:
+    SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
 
-     >>> components.registerSubscriptionAdapter(
-     ...     tests.A1_12, provided=tests.IA2)
+    >>> components.registerSubscriptionAdapter(
+    ...     tests.A1_12, provided=tests.IA2)
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Registered event:
+    SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_12, u'')
 
-     >>> components.registerSubscriptionAdapter(
-     ...     tests.A, [tests.I1], tests.IA2,
-     ...     info='a sample comment')
+    >>> components.registerSubscriptionAdapter(
+    ...     tests.A, [tests.I1], tests.IA2,
+    ...     info='a sample comment')
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Registered event:
+    SubscriptionRegistration(<Components comps>, [I1], IA2, u'', 
+                             A, 'a sample comment')
 
 The same rules, with regard to when required and provided interfaces
 have to be specified apply as with adapters:
@@ -485,6 +560,10 @@
 
     >>> components.registerSubscriptionAdapter(
     ...     tests.A, [tests.I1], tests.IA2, u'', 'a sample comment')
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Registered event:
+    SubscriptionRegistration(<Components comps>, [I1], IA2, u'', 
+                             A, 'a sample comment')
 
     >>> components.registerSubscriptionAdapter(
     ...     tests.A, [tests.I1], tests.IA2, u'oops', 'a sample comment')
@@ -506,8 +585,10 @@
 
 As with normal adapters, if a factory returns None, the result is skipped:
 
-     >>> components.registerSubscriptionAdapter(
-     ...     tests.noop, [tests.I1], tests.IA2)
+    >>> components.registerSubscriptionAdapter(
+    ...     tests.noop, [tests.I1], tests.IA2)
+    Registered event:
+    SubscriptionRegistration(<Components comps>, [I1], IA2, u'', noop, u'')
 
     >>> for s in components.subscribers((tests.U1(1), ), tests.IA2):
     ...    print s
@@ -542,6 +623,9 @@
 We can also unregister subscriptions in much the same way we can for adapters:
 
     >>> components.unregisterSubscriptionAdapter(tests.A1_2)
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Unregistered event:
+    SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, '')
     True
 
     >>> for registration in sorted(
@@ -564,6 +648,8 @@
 
     >>> components.unregisterSubscriptionAdapter(
     ...     tests.A, [tests.I1], tests.IA2)
+    Unregistered event:
+    SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A, '')
     True
 
     >>> for registration in sorted(
@@ -594,6 +680,8 @@
 
     >>> components.unregisterSubscriptionAdapter(
     ...     required=[tests.I1], provided=tests.IA2)
+    Unregistered event:
+    SubscriptionRegistration(<Components comps>, [I1], IA2, u'', None, '')
     True
 
     >>> for registration in sorted(
@@ -624,7 +712,8 @@
     TypeError: The adapter factory doesn't implement a single interface
     and no provided interface was specified.
 
-If you unregister something that's not registered, nothing will be changed and False will be returned:
+If you unregister something that's not registered, nothing will be
+changed and False will be returned:
 
 
     >>> components.unregisterSubscriptionAdapter(
@@ -644,6 +733,10 @@
     ...     print 'handle1', x
 
     >>> components.registerHandler(handle1, info="First handler")
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Registered event:
+    HandlerRegistration(<Components comps>, [I1], u'', 
+                        handle1, 'First handler')
     >>> components.handle(tests.U1(1))
     handle1 U1(1)
 
@@ -652,6 +745,8 @@
     ...     print 'handle12', x, y
 
     >>> components.registerHandler(handle12)
+    Registered event:
+    HandlerRegistration(<Components comps>, [I1, I2], u'', handle12, u'')
     >>> components.handle(tests.U1(1), tests.U12(2))
     handle12 U1(1) U12(2)
 
@@ -670,11 +765,17 @@
 
     >>> components.registerHandler(handle, required=[tests.I1], 
     ...                            info="a comment")
+    Registered event:
+    HandlerRegistration(<Components comps>, [I1], u'', handle, 'a comment')
 
 Handlers can also be registered for classes:
 
     >>> components.registerHandler(handle, required=[tests.U], 
     ...                            info="handle a class")
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Registered event:
+    HandlerRegistration(<Components comps>, [zope.component.tests.U], u'', 
+                        handle, 'handle a class')
 
 
     >>> components.handle(tests.U1(1))
@@ -701,6 +802,10 @@
 and we can unregister handlers:
 
     >>> components.unregisterHandler(required=[tests.U])
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Unregistered event:
+    HandlerRegistration(<Components comps>, [zope.component.tests.U], u'', 
+                        None, '')
     True
 
     >>> for registration in components.registeredHandlers():
@@ -716,6 +821,8 @@
     <function handle at 0xb78f5ca4> a comment
 
     >>> components.unregisterHandler(handle12)
+    Unregistered event:
+    HandlerRegistration(<Components comps>, [I1, I2], u'', handle12, '')
     True
 
     >>> for registration in components.registeredHandlers():
@@ -747,50 +854,72 @@
 Component-management objects can extend other component-management
 objects. 
 
-    >>> c1 = Components()
+    >>> c1 = Components('1')
     >>> c1.__bases__
     ()
 
-    >>> c2 = Components((c1, ))
+    >>> c2 = Components('2', (c1, ))
     >>> c2.__bases__ == (c1, )
     True
 
     >>> c1.registerUtility(tests.U1(1))
+    Registered event:
+    UtilityRegistration(<Components 1>, I1, u'', 1, u'')
+
     >>> c1.queryUtility(tests.I1)
     U1(1)
     >>> c2.queryUtility(tests.I1)
     U1(1)
     >>> c1.registerUtility(tests.U1(2))
+    Registered event:
+    UtilityRegistration(<Components 1>, I1, u'', 2, u'')
+
     >>> c2.queryUtility(tests.I1)
     U1(2)
 
 We can use multiple inheritence:
 
-    >>> c3 = Components((c1, ))
-    >>> c4 = Components((c2, c3))
+    >>> c3 = Components('3', (c1, ))
+    >>> c4 = Components('4', (c2, c3))
     >>> c4.queryUtility(tests.I1)
     U1(2)
 
     >>> c1.registerUtility(tests.U12(1), tests.I2)
+    Registered event:
+    UtilityRegistration(<Components 1>, I2, u'', 1, u'')
+
     >>> c4.queryUtility(tests.I2)
     U12(1)
 
     >>> c3.registerUtility(tests.U12(3), tests.I2)
+    Registered event:
+    UtilityRegistration(<Components 3>, I2, u'', 3, u'')
     >>> c4.queryUtility(tests.I2)
     U12(3)
 
     >>> c1.registerHandler(handle1, info="First handler")
+    Registered event:
+    HandlerRegistration(<Components 1>, [I1], u'', handle1, 'First handler')
+
     >>> c2.registerHandler(handle, required=[tests.U])
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Registered event:
+    HandlerRegistration(<Components 2>, [zope.component.tests.U], u'', 
+                        handle, u'')
     
     >>> @component.adapter(tests.I1)
     ... def handle3(x):
     ...     print 'handle3', x
     >>> c3.registerHandler(handle3)
+    Registered event:
+    HandlerRegistration(<Components 3>, [I1], u'', handle3, u'')
     
     >>> @component.adapter(tests.I1)
     ... def handle4(x):
     ...     print 'handle4', x
     >>> c4.registerHandler(handle4)
+    Registered event:
+    HandlerRegistration(<Components 4>, [I1], u'', handle4, u'')
 
     >>> c4.handle(tests.U1(1))
     handle1 U1(1)

Modified: Zope3/branches/jim-adapter/src/zope/component/tests.py
===================================================================
--- Zope3/branches/jim-adapter/src/zope/component/tests.py	2006-04-02 17:00:10 UTC (rev 66322)
+++ Zope3/branches/jim-adapter/src/zope/component/tests.py	2006-04-02 17:00:12 UTC (rev 66323)
@@ -710,19 +710,19 @@
     >>> from zope.component.persistentregistry import PersistentComponents
 
     >>> _ = t1.begin()
-    >>> r1[1] = PersistentComponents()
+    >>> r1[1] = PersistentComponents('1')
     >>> t1.commit()
 
     >>> _ = t2.begin()
-    >>> r2[2] = PersistentComponents((r2[1], ))
+    >>> r2[2] = PersistentComponents('2', (r2[1], ))
     >>> t2.commit()
 
     >>> _ = t1.begin()
-    >>> r1[3] = PersistentComponents((r1[1], ))
+    >>> r1[3] = PersistentComponents('3', (r1[1], ))
     >>> t1.commit()
 
     >>> _ = t2.begin()
-    >>> r2[4] = PersistentComponents((r2[2], r2[3]))
+    >>> r2[4] = PersistentComponents('4', (r2[2], r2[3]))
     >>> t2.commit()
 
     >>> _ = t1.begin()
@@ -789,6 +789,10 @@
     >>> db.close()
     """
 
+def tearDownRegistryTests(tests):
+    import zope.event
+    zope.event.subscribers.pop()
+
 def test_suite():
     checker = renormalizing.RENormalizing([
         (re.compile('at 0x[0-9a-f]+'), 'at <SOME ADDRESS>'),
@@ -803,7 +807,8 @@
                              setUp=setUp, tearDown=tearDown),
         doctest.DocFileSuite('factory.txt',
                              setUp=setUp, tearDown=tearDown),
-        doctest.DocFileSuite('registry.txt', checker=checker),
+        doctest.DocFileSuite('registry.txt', checker=checker,
+                             tearDown=tearDownRegistryTests),
         ))
 
 if __name__ == "__main__":



More information about the Zope3-Checkins mailing list