[Checkins] SVN: Zope3/branches/jim-adapter/src/zope/component/ Added a dispatcher that dispatches to registered components.

Jim Fulton jim at zope.com
Tue Apr 18 19:56:38 EDT 2006


Log message for revision 67111:
  Added a dispatcher that dispatches to registered components.
  
  Also refactoried the registration objects and interfaces to make the
  different registration types more distinct.
  

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

-=-
Modified: Zope3/branches/jim-adapter/src/zope/component/interfaces.py
===================================================================
--- Zope3/branches/jim-adapter/src/zope/component/interfaces.py	2006-04-18 23:56:35 UTC (rev 67110)
+++ Zope3/branches/jim-adapter/src/zope/component/interfaces.py	2006-04-18 23:56:37 UTC (rev 67111)
@@ -166,8 +166,8 @@
         named adapter methods with an empty string for a name.
         """
 
-    def queryAdapter(object, interface=interface.Interface, name=u'', default=None,
-                     context=None):
+    def queryAdapter(object, interface=interface.Interface, name=u'',
+                     default=None, context=None):
         """Look for a named adapter to an interface for an object
 
         Returns an adapter that can adapt object to interface.  If a matching
@@ -514,7 +514,7 @@
     component = interface.Attribute("The object registered")
     provided = interface.Attribute("The interface provided by the component")
 
-class IAdapterRegistration(IRegistration):
+class _IBaseAdapterRegistration(IRegistration):
     """Information about the registration of an adapter
     """
 
@@ -532,7 +532,11 @@
     This interface is implemented by the factory
     """)
 
-class ISubscriptionAdapterRegistration(IAdapterRegistration):
+class IAdapterRegistration(_IBaseAdapterRegistration):
+    """Information about the registration of an adapter
+    """
+
+class ISubscriptionAdapterRegistration(_IBaseAdapterRegistration):
     """Information about the registration of a subscription adapter
     """
 

Modified: Zope3/branches/jim-adapter/src/zope/component/registry.py
===================================================================
--- Zope3/branches/jim-adapter/src/zope/component/registry.py	2006-04-18 23:56:35 UTC (rev 67110)
+++ Zope3/branches/jim-adapter/src/zope/component/registry.py	2006-04-18 23:56:37 UTC (rev 67111)
@@ -17,8 +17,9 @@
 """
 
 import types
+import zope.deprecation
 import zope.interface.adapter
-from zope import interface
+from zope import component, interface
 from zope.component import interfaces
 import zope.interface.interfaces
 import zope.event
@@ -68,6 +69,10 @@
         if provided is None:
             provided = _getUtilityProvided(component)
 
+        if (self._utility_registrations.get((provided, name))
+            == (component, info)):
+            # already registered
+            return
 
         subscribed = [
             1
@@ -386,6 +391,8 @@
         
 class UtilityRegistration(object):
 
+    interface.implements(interfaces.IUtilityRegistration)
+
     def __init__(self, registry, provided, name, component, doc):
         (self.registry, self.provided, self.name, self.component, self.info
          ) = registry, provided, name, component, doc
@@ -403,6 +410,8 @@
         
 class AdapterRegistration(object):
 
+    interface.implements(interfaces.IAdapterRegistration)
+
     def __init__(self, registry, required, provided, name, component, doc):
         (self.registry, self.required, self.provided, self.name,
          self.factory, self.info
@@ -428,10 +437,13 @@
         return self.factory
 
 class SubscriptionRegistration(AdapterRegistration):
-    pass
 
+    interface.implementsOnly(interfaces.ISubscriptionAdapterRegistration)
+
 class HandlerRegistration(AdapterRegistration):
 
+    interface.implementsOnly(interfaces.IHandlerRegistration)
+
     def __init__(self, registry, required, name, handler, doc):
         (self.registry, self.required, self.name, self.handler, self.info
          ) = registry, required, name, handler, doc
@@ -450,4 +462,26 @@
             self.name,
             getattr(self.factory, '__name__', `self.factory`), self.info,
             )
+
+
+ at component.adapter(interfaces.IUtilityRegistration,
+                   interfaces.IRegistrationEvent)
+def dispatchUtilityRegistrationEvent(registration, event):
+    component.handle(registration.component, event)
+
+ at component.adapter(interfaces.IAdapterRegistration,
+                   interfaces.IRegistrationEvent)
+def dispatchAdapterRegistrationEvent(registration, event):
+    component.handle(registration.factory, event)
+
+ at component.adapter(interfaces.ISubscriptionAdapterRegistration,
+                   interfaces.IRegistrationEvent)
+def dispatchSubscriptionAdapterRegistrationEvent(registration, event):
+    component.handle(registration.factory, event)
+
+ at component.adapter(interfaces.IHandlerRegistration,
+                   interfaces.IRegistrationEvent)
+def dispatchHandlerRegistrationEvent(registration, event):
+    component.handle(registration.handler, event)
+
     

Modified: Zope3/branches/jim-adapter/src/zope/component/registry.txt
===================================================================
--- Zope3/branches/jim-adapter/src/zope/component/registry.txt	2006-04-18 23:56:35 UTC (rev 67110)
+++ Zope3/branches/jim-adapter/src/zope/component/registry.txt	2006-04-18 23:56:37 UTC (rev 67111)
@@ -16,9 +16,9 @@
 implementation of zope.component.interfaces.IComponents that provides
 these features.
 
-    >>> from zope.component.registry import Components
+    >>> from zope.component import registry
     >>> from zope.component import tests
-    >>> components = Components('comps')
+    >>> components = registry.Components('comps')
 
 As components atr registered, events are generated.  Let's register
 an event subscriber, so we can see the events generated:
@@ -854,11 +854,11 @@
 Component-management objects can extend other component-management
 objects. 
 
-    >>> c1 = Components('1')
+    >>> c1 = registry.Components('1')
     >>> c1.__bases__
     ()
 
-    >>> c2 = Components('2', (c1, ))
+    >>> c2 = registry.Components('2', (c1, ))
     >>> c2.__bases__ == (c1, )
     True
 
@@ -879,8 +879,8 @@
 
 We can use multiple inheritence:
 
-    >>> c3 = Components('3', (c1, ))
-    >>> c4 = Components('4', (c2, c3))
+    >>> c3 = registry.Components('3', (c1, ))
+    >>> c4 = registry.Components('4', (c2, c3))
     >>> c4.queryUtility(tests.I1)
     U1(2)
 
@@ -926,3 +926,130 @@
     handle3 U1(1)
     handle (U1(1),)
     handle4 U1(1)
+
+Redispatch of registration events
+---------------------------------
+
+Some handlers are available that, if registered, redispatch
+registration events to the objects being registered.  They depend on
+being dispatched to by the object-event dispatcher:
+
+    >>> from zope import component
+    >>> import zope.component.event
+    >>> zope.component.provideHandler(zope.component.event.objectEventNotify)
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Registered event:
+    HandlerRegistration(<BaseGlobalComponents base>, 
+                        [IObjectEvent], u'', objectEventNotify, u'')
+
+To see this, we'll first register a multi-handler to show is when
+handlers are called on 2 objects:
+
+    >>> @zope.component.adapter(None, None)
+    ... def double_handler(o1, o2):
+    ...     print 'Double dispatch:'
+    ...     print ' ', o1
+    ...     print ' ', o2
+    >>> zope.component.provideHandler(double_handler)
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Double dispatch:
+      HandlerRegistration(<BaseGlobalComponents base>, 
+                          [Interface, Interface], u'', double_handler, u'')
+      Registered event:
+      HandlerRegistration(<BaseGlobalComponents base>, 
+      [Interface, Interface], u'', double_handler, u'')
+    Registered event:
+    HandlerRegistration(<BaseGlobalComponents base>, 
+                        [Interface, Interface], u'', double_handler, u'')
+
+In the example above, the double_handler reported it's own registration. :)
+
+Now we'll register our handlers:
+
+    >>> zope.component.provideHandler(
+    ...     registry.dispatchUtilityRegistrationEvent)
+    ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+    Double dispatch:
+    ...
+
+    >>> zope.component.provideHandler(
+    ...     registry.dispatchAdapterRegistrationEvent)
+    ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+    Double dispatch:
+    ...
+
+    >>> zope.component.provideHandler(
+    ...     registry.dispatchSubscriptionAdapterRegistrationEvent)
+    ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
+    Double dispatch:
+    ...
+
+    >>> zope.component.provideHandler(
+    ...     registry.dispatchHandlerRegistrationEvent)
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Double dispatch:
+      HandlerRegistration(<BaseGlobalComponents base>, 
+                          [IHandlerRegistration, IRegistrationEvent], u'', 
+                          dispatchHandlerRegistrationEvent, u'')
+      Registered event:
+      HandlerRegistration(<BaseGlobalComponents base>, 
+                          [IHandlerRegistration, IRegistrationEvent], u'', 
+                          dispatchHandlerRegistrationEvent, u'')
+    Double dispatch:
+      <function dispatchHandlerRegistrationEvent at 0xb799f72c>
+      Registered event:
+      HandlerRegistration(<BaseGlobalComponents base>,
+                          [IHandlerRegistration, IRegistrationEvent], u'',
+                          dispatchHandlerRegistrationEvent, u'')
+    Registered event:
+    HandlerRegistration(<BaseGlobalComponents base>,
+                        [IHandlerRegistration, IRegistrationEvent], u'',
+                        dispatchHandlerRegistrationEvent, u'')
+
+In the last example above, we can see that the registration of
+dispatchHandlerRegistrationEvent was handled by
+dispatchHandlerRegistrationEvent and redispatched.  This can be seen
+in the second double-dispatch output, where the first argument is the
+object being registered, which is dispatchHandlerRegistrationEvent.
+
+If we change some other registrations, we can the double dispatch
+taking place:
+
+    >>> components.registerUtility(u5)
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Double dispatch:
+      UtilityRegistration(<Components comps>, I1, u'', 5, u'')
+      Registered event:
+      UtilityRegistration(<Components comps>, I1, u'', 5, u'')
+    Double dispatch:
+      U1(5)
+      Registered event:
+      UtilityRegistration(<Components comps>, I1, u'', 5, u'')
+    Registered event:
+    UtilityRegistration(<Components comps>, I1, u'', 5, u'')
+
+    >>> components.registerAdapter(tests.A12_1)
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Double dispatch:
+      AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
+      Registered event:
+      AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
+    Double dispatch:
+      zope.component.tests.A12_1
+      Registered event:
+      AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
+    Registered event:
+    AdapterRegistration(<Components comps>, [I1, I2], IA1, u'', A12_1, u'')
+
+    >>> components.registerSubscriptionAdapter(tests.A1_2)
+    ... # doctest: +NORMALIZE_WHITESPACE
+    Double dispatch:
+      SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
+      Registered event:
+      SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
+    Double dispatch:
+      zope.component.tests.A1_2
+      Registered event:
+      SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')
+    Registered event:
+    SubscriptionRegistration(<Components comps>, [I1], IA2, u'', A1_2, u'')



More information about the Checkins mailing list