[Zope3-checkins] SVN: Zope3/trunk/src/zope/component/ Added provideHandler and handle apis. Also fixed some other

Jim Fulton jim at zope.com
Fri Mar 18 08:53:03 EST 2005


Log message for revision 29558:
  Added provideHandler and handle apis.  Also fixed some other
  documentation in the interface.
  

Changed:
  U   Zope3/trunk/src/zope/component/README.txt
  U   Zope3/trunk/src/zope/component/__init__.py
  U   Zope3/trunk/src/zope/component/interfaces.py

-=-
Modified: Zope3/trunk/src/zope/component/README.txt
===================================================================
--- Zope3/trunk/src/zope/component/README.txt	2005-03-18 13:43:28 UTC (rev 29557)
+++ Zope3/trunk/src/zope/component/README.txt	2005-03-18 13:53:02 UTC (rev 29558)
@@ -297,7 +297,7 @@
     ...         else:
     ...             return ''
 
-We can register these as subscription adapters:
+We can register these as subscription adapters [1]_:
 
     >>> component.provideSubscriptionAdapter(SingleLineSummary)
     >>> component.provideSubscriptionAdapter(AdequateLength)
@@ -322,7 +322,75 @@
     ...  if adapter.validate()]
     ['too short']
 
+Handlers
+********
 
+Handlers are subscription adapter factories that don't produce
+anything.  They do all of their work when called.  Handlers
+are typically used to handle events.
+
+Event subscribers are different from other subscription adapters in
+that the caller of event subscribers doesn't expect to interact with
+them in any direct way.  For example, an event publisher doesn't
+expect to get any return value.  Because subscribers don't need to
+provide an API to their callers, it is more natural to define them
+with functions, rather than classes.  For example, in a
+document-management system, we might want to record creation times for
+documents:
+
+    >>> import datetime
+
+    >>> def documentCreated(event):
+    ...     event.doc.created = datetime.datetime.utcnow()
+
+In this example, we have a function that takes an event and performs
+some processing.  It doesn't actually return anything.  This is a
+special case of a subscription adapter that adapts an event to
+nothing.  All of the work is done when the adapter "factory" is
+called.  We call subscribers that don't actually create anything
+"handlers".  There are special APIs for registering and calling
+them.
+
+To register the subscriber above, we define a document-created event: 
+
+    >>> class IDocumentCreated(interface.Interface):
+    ...     doc = interface.Attribute("The document that was created")
+
+    >>> class DocumentCreated:
+    ...     interface.implements(IDocumentCreated)
+    ...
+    ...     def __init__(self, doc):
+    ...         self.doc = doc
+
+We'll also change our handler definition to:
+
+    >>> def documentCreated(event):
+    ...     event.doc.created = datetime.datetime.utcnow()
+
+    >>> documentCreated = component.adapter(IDocumentCreated)(documentCreated)
+
+(Note that in Python 2.4, this can be written:
+
+     @component.adapter(IDocumentCreated)
+     def documentCreated(event):
+         event.doc.created = datetime.datetime.utcnow()
+)
+
+This marks the handler as an adapter of `IDocumentCreated` events.
+
+Now we'll register the handler  [1]_:
+
+    >>> component.provideHandler(documentCreated)
+
+Now, if we can create an event and use the `handle` function to call
+handlers registered for the event:
+
+    >>> component.handle(DocumentCreated(doc))
+    >>> doc.created.__class__.__name__
+    'datetime'
+
+
+
 .. [1] CAUTION: This API should only be used from test or
        application-setup code. This API shouldn't be used by regular
        library modules, as component registration is a configuration

Modified: Zope3/trunk/src/zope/component/__init__.py
===================================================================
--- Zope3/trunk/src/zope/component/__init__.py	2005-03-18 13:43:28 UTC (rev 29557)
+++ Zope3/trunk/src/zope/component/__init__.py	2005-03-18 13:53:02 UTC (rev 29558)
@@ -180,6 +180,10 @@
         return []
     return sitemanager.subscribers(objects, interface)
 
+def handle(*objects):
+    sitemanager = getSiteManager(None)
+    tuple(sitemanager.subscribers(objects, None))
+
 class _adapts_descr(object):
     def __init__(self, interfaces):
         self.interfaces = interfaces
@@ -211,7 +215,7 @@
     # until later on.
     if (locals is frame.f_globals) or (
         ('__module__' not in locals) and sys.version_info[:3] > (2, 2, 0)):
-        raise TypeError(name+" can be used only from a class definition.")
+        raise TypeError("adapts can be used only from a class definition.")
 
     if '__component_adapts__' in locals:
         raise TypeError("adapts can be used only once in a class definition.")
@@ -346,3 +350,13 @@
             raise TypeError("Missing 'adapts' argument")
             
     getGlobalSiteManager().subscribe(adapts, provides, factory)
+
+def provideHandler(factory, adapts=None):
+
+    if adapts is None:
+        try:
+            adapts = factory.__component_adapts__
+        except AttributeError:
+            raise TypeError("Missing 'adapts' argument")
+            
+    getGlobalSiteManager().subscribe(adapts, None, factory)

Modified: Zope3/trunk/src/zope/component/interfaces.py
===================================================================
--- Zope3/trunk/src/zope/component/interfaces.py	2005-03-18 13:43:28 UTC (rev 29557)
+++ Zope3/trunk/src/zope/component/interfaces.py	2005-03-18 13:53:02 UTC (rev 29558)
@@ -225,6 +225,16 @@
         and this adapter's 'Adapters' service is used.
         """
 
+    def handle(*objects):
+        """Call all of the handlers for the given objects
+
+        Handlers are subscription adapter factories that don't produce
+        anything.  They do all of their work when called.  Handlers
+        are typically used to handle events.
+        
+        """
+
+
     def adapts(*interfaces):
         """Declare that a class adapts the given interfaces.
 
@@ -351,7 +361,7 @@
         provided to provide a less specific interface.)
 
         CAUTION: This API should only be used from test or
-        application-setup code. This api shouldn't be used by regular
+        application-setup code. This API shouldn't be used by regular
         library modules, as component registration is a configuration
         activity. 
         
@@ -372,15 +382,15 @@
         adapts argument can be provided to override the declaration.)
 
         CAUTION: This API should only be used from test or
-        application-setup code. This api shouldn't be used by regular
+        application-setup code. This API shouldn't be used by regular
         library modules, as component registration is a configuration
         activity. 
         """
 
     def provideSubscriptionAdapter(factory, adapts=None, provides=None):
-        """Register an adapter globally
+        """Register a subscription adapter
 
-        An adapter is registered to provide an interface with a name
+        A subscription adapter is registered to provide an interface
         for some number of object types. If a factory implements only
         one interface, then the provides argument can be omitted and
         the provided interface will be used. (In this case, a provides
@@ -392,11 +402,28 @@
         adapts argument can be provided to override the declaration.)
 
         CAUTION: This API should only be used from test or
-        application-setup code. This api shouldn't be used by regular
+        application-setup code. This API shouldn't be used by regular
         library modules, as component registration is a configuration
         activity. 
         """
 
+    def provideHandler(handler, adapts=None):
+        """Register a handler
+
+        Handlers are subscription adapter factories that don't produce
+        anything.  They do all of their work when called.  Handlers
+        are typically used to handle events.
+
+        If the handler has an adapts declaration, then the adapts
+        argument can be omitted and the declaration will be used.  (An
+        adapts argument can be provided to override the declaration.)
+
+        CAUTION: This API should only be used from test or
+        application-setup code. This API shouldn't be used by regular
+        library modules, as component registration is a configuration
+        activity. 
+        """
+
 class IRegistry(Interface):
     """Object that supports component registry
     """



More information about the Zope3-Checkins mailing list