[Checkins] SVN: zope3org/trunk/src/zorg/usage/ Added the sources for the usage package

Uwe Oestermeier uwe_oestermeier at iwm-kmrc.de
Fri Apr 7 06:55:04 EDT 2006


Log message for revision 66632:
  Added the sources for the usage package

Changed:
  A   zope3org/trunk/src/zorg/usage/README.txt
  A   zope3org/trunk/src/zorg/usage/__init__.py
  A   zope3org/trunk/src/zorg/usage/testadapter.py
  A   zope3org/trunk/src/zorg/usage/tests.py

-=-
Added: zope3org/trunk/src/zorg/usage/README.txt
===================================================================
--- zope3org/trunk/src/zorg/usage/README.txt	2006-04-07 10:54:19 UTC (rev 66631)
+++ zope3org/trunk/src/zorg/usage/README.txt	2006-04-07 10:55:03 UTC (rev 66632)
@@ -0,0 +1,92 @@
+USAGE
+=====
+
+If you want to use a zope component in different contexts you typically have
+to perform numerous steps. A typical use of an adapter in tests and real world
+contexts requires the following steps:
+
+    1. define an interface,
+    2. write the class resp. implementation,
+    3. declare that the class implements the interface, 
+    4. declare what the class adapts,
+    5. write a test registration for doctests and unittests,
+    6. configure the adapter in zcml for a usage outside tests.
+    
+The 'usage' package automates steps 5 and 6 to a large degree. If you declare
+the usage of components directly in the classes you can register all
+described components of a module with a single call.
+
+Using an adapter
+----------------
+
+The usual pattern goes like this. You write a component with a basic
+behavior:
+
+>>> import zope.interface
+>>> import zope.component
+>>> class IAdaptMe(zope.interface.Interface) :
+...     def cry() : pass
+
+>>> class AdaptMe(object) :
+...     zope.interface.implements(IAdaptMe)
+...     def cry(self) : print "Please, please adapt me."
+
+>>> adaptMe = AdaptMe()
+>>> adaptMe.cry()
+Please, please adapt me.
+
+You want an adapter that modifies or replaces the behavior :
+
+>>> class IAdapter(zope.interface.Interface) :
+...     def lull() : pass
+
+>>> class Adapter(object) :
+...     zope.interface.implements(IAdapter)
+...     zope.component.adapts(IAdaptMe)
+...
+...     def __init__(self, context) :
+...         self.context = context
+...     def lull(self) :
+...         self.context.cry()
+...         print "Don't worry"
+
+Let's test whether the implementation works:
+
+>>> Adapter(adaptMe).lull()
+Please, please adapt me.
+Don't worry
+
+We can use the implementation with a single call:
+
+>>> import zorg.usage
+>>> zorg.usage.AdapterUsage(Adapter).register()
+
+>>> adapter = IAdapter(adaptMe)
+>>> adapter.lull()
+Please, please adapt me.
+Don't worry
+
+That after all is not very different from calling zope.component.provideAdapter.
+The interesting part comes now. We can declare the usage in the class itself
+and register all usages of a module with a single call. With n adapters in
+a single module you safe the typing of n test registrations and n zcml
+adapter statements.
+
+The ensureRegistrations function collects all usage descriptions in a single
+module and registers them:
+
+>>> zorg.usage.ensureRegistrations("zorg.usage.testadapter")
+
+>>> from zorg.usage.testadapter import First, Second, ICount, IIncrement
+>>> incr = IIncrement(First())
+>>> incr.incr()
+2
+
+
+
+#>>> from zope.app import zapi
+#>>> counter = zapi.getMultiAdapter((First(), Second()), ICount, name="test")
+#>>> counter.count()
+1
+2
+

Added: zope3org/trunk/src/zorg/usage/__init__.py
===================================================================
--- zope3org/trunk/src/zorg/usage/__init__.py	2006-04-07 10:54:19 UTC (rev 66631)
+++ zope3org/trunk/src/zorg/usage/__init__.py	2006-04-07 10:55:03 UTC (rev 66632)
@@ -0,0 +1,116 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.
+#
+##############################################################################
+"""
+
+$Id: __init__.py 41271 2006-01-11 17:02:07Z oestermeier $
+"""
+__docformat__ = 'restructuredtext'
+
+import sys, unittest, doctest
+
+import zope.interface
+import zope.component
+
+from zope.interface.advice import addClassAdvisor
+from zope.dottedname.resolve import resolve
+
+class ClassUsage(object) :
+    """ Describes the usage of a class. """
+    
+    def __init__(self, klass) :
+        self.klass = klass
+    
+class AdapterUsage(ClassUsage) :
+    """ Describes the usage of a class as an adapter factory. """
+    
+    def __init__(self, klass, adapts=None, provides=None, name='') :
+        self.klass = klass
+        self.adapts = adapts
+        self.provides = provides
+        self.name = name
+        
+    def register(self) :
+        """ Registers the adapter. """
+        zope.component.provideAdapter(self.klass, 
+                                            adapts=self.adapts,
+                                            provides=self.provides,
+                                            name=self.name)
+        
+class GlobalUtilityUsage(ClassUsage) :
+    """ Describes the usage of a class as a factory for a global utility. """
+
+    def register(self) :
+        """ Registers the global utility. """
+
+
+def _adapter(cls):
+    
+    adapts, provides, name = cls.__dict__['__adapter_usage_data__']
+    del cls.__adapter_usage_data__
+    
+    if provides is None :
+        provides = list(cls.__implemented__.interfaces())[0]
+    else :
+        classImplements(cls, iface)
+        
+    if adapts is None :
+        adapts = zope.component.adaptedBy(cls)
+    else :
+        zope.component.adapter(adapts)(cls)
+      
+    if not hasattr(cls, '__zorg_usages__') :
+        cls.__zorg_usages__ = []
+        
+    usage = AdapterUsage(cls, adapts=adapts, provides=provides, name=name)
+    cls.__zorg_usages__.append(usage)
+    return cls
+
+def adapter(adapts=None, provides=None, name='') :
+    """
+    Declares the usage of a class as an adapter factory.
+    
+    >>> class IAdapted(zope.interface.Interface) :
+    ...     pass
+    >>> class IAdapter(zope.interface.Interface) :
+    ...     pass
+    
+    class Adapter(object) :
+    ...     zope.interface.implements(IAdapter)
+    ...     zope.component.adapts(IAdapted)
+    ...     adapter()
+        
+        
+    
+    """
+    frame = sys._getframe(1)
+    locals = frame.f_locals
+    
+    # Try to make sure we were called from a class def. In 2.2.0 we can't
+    # check for __module__ since it doesn't seem to be added to the locals
+    # until later on.
+    if (locals is frame.f_globals) or ('__module__' not in locals):
+        raise TypeError("provides can be used only from a class definition.")
+
+    locals['__adapter_usage_data__'] =  adapts, provides, name
+    addClassAdvisor(_adapter)
+    
+def globalUtility() :
+    pass # to be written
+    
+def ensureRegistrations(dotted_name) :
+    module = resolve(dotted_name)
+    for key in dir(module) :
+        obj = getattr(module, key)
+        for usage in getattr(obj, "__zorg_usages__", ()) :
+            usage.register()
\ No newline at end of file

Added: zope3org/trunk/src/zorg/usage/testadapter.py
===================================================================
--- zope3org/trunk/src/zorg/usage/testadapter.py	2006-04-07 10:54:19 UTC (rev 66631)
+++ zope3org/trunk/src/zorg/usage/testadapter.py	2006-04-07 10:55:03 UTC (rev 66632)
@@ -0,0 +1,98 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.
+#
+##############################################################################
+"""
+
+$Id: testadapter.py 41271 2006-01-11 17:02:07Z oestermeier $
+"""
+__docformat__ = 'restructuredtext'
+
+import zope.interface
+import zope.component
+import zorg.usage
+
+# Define some test interfaces
+
+class INumber(zope.interface.Interface) :
+
+    def number() :
+        pass
+    
+class IFirst(INumber) :
+    pass
+    
+class ISecond(INumber) :
+    pass
+    
+class IIncrement(zope.interface.Interface) :
+    
+    def incr() :
+        pass
+        
+class ICount(zope.interface.Interface) :
+
+    def count() : 
+        pass
+
+# Define some trivial base classes
+
+class First(object) :
+
+    zope.interface.implements(IFirst)
+    
+    def number(self) :
+        return 1
+
+class Second(object) :
+
+    zope.interface.implements(ISecond)
+    
+    def number(self) :
+        return 2
+
+# Define some adapter
+
+class Increment(object) :
+    """ A simple sample adapter. """
+    
+    zope.interface.implements(IIncrement)
+    zope.component.adapts(INumber)
+    
+    zorg.usage.adapter()
+    
+    def __init__(self, context) :
+        self.context = context
+        
+    def incr(self) :
+        return self.context.number() + 1
+
+
+class Count(object) :
+    """ A multiadapter. """
+
+    zope.interface.implements(ICount)
+    zope.component.adapts(IFirst, ISecond)
+    
+    zorg.usage.adapter()
+
+    def __init__(self, first, second) :
+        self.first = first
+        self.second = second
+
+    def count(self) :
+        print self.first.number()
+        print self.second.number()
+       
+class Named(object) :
+    """ A named adapter. """
+    

Added: zope3org/trunk/src/zorg/usage/tests.py
===================================================================
--- zope3org/trunk/src/zorg/usage/tests.py	2006-04-07 10:54:19 UTC (rev 66631)
+++ zope3org/trunk/src/zorg/usage/tests.py	2006-04-07 10:55:03 UTC (rev 66632)
@@ -0,0 +1,43 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.
+#
+##############################################################################
+"""
+
+$Id: tests.py 41271 2006-01-11 17:02:07Z oestermeier $
+"""
+__docformat__ = 'restructuredtext'
+
+import unittest
+from zope.testing import doctest, doctestunit
+
+import zope.app.zapi
+import zope.component.testing
+         
+       
+def test_suite():
+
+    return unittest.TestSuite((
+        #doctest.DocTestSuite(setUp=setUp, tearDown=tearDown)),
+        
+        doctest.DocFileSuite("README.txt", 
+                    setUp=zope.component.testing.setUp, 
+                    tearDown=zope.component.testing.tearDown,
+                    globs={'zapi': zope.app.zapi,
+                           'pprint': doctestunit.pprint,
+                           'TestRequest': zope.publisher.browser.TestRequest                                
+                          },
+                    optionflags=doctest.NORMALIZE_WHITESPACE+doctest.ELLIPSIS),        
+        ))
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')    
\ No newline at end of file



More information about the Checkins mailing list