[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