[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