[Zope3-checkins] CVS: Zope3/src/zope/interface/tests - foodforthought.txt:1.1 test_adapter.py:1.4

Jim Fulton jim at zope.com
Mon Mar 15 15:41:56 EST 2004


Update of /cvs-repository/Zope3/src/zope/interface/tests
In directory cvs.zope.org:/tmp/cvs-serv3209/src/zope/interface/tests

Modified Files:
	test_adapter.py 
Added Files:
	foodforthought.txt 
Log Message:
Defined (and changed) the adapter registration and lookup apis:

- Simpler methods

- Multi-adapter registration and lookup the default, so always
  register multiple (including one or zero) required specifications.

- Subscriptions no longer specify names (yagni)

- Removed factory semantics from the api

Changed the implementation to allow fast lookup of all names for
a given adapter.  (Still need to provide an access api.)


=== Added File Zope3/src/zope/interface/tests/foodforthought.txt ===
================================
Food-based subscription examples
================================


This file gives more subscription examples using a cooking-based examples

    >>> from zope.interface.adapter import AdapterRegistry
    >>> registry = AdapterRegistry()

    >>> import zope.interface
    >>> class IAnimal(zope.interface.Interface):
    ...     pass
    >>> class IPoultry(IAnimal):
    ...     pass
    >>> class IChicken(IPoultry):
    ...     pass
    >>> class ISeafood(IAnimal):
    ...     pass

Adapting to some other interface for which there is no
subscription adapter returns an empty sequence:

    >>> class IRecipe(zope.interface.Interface):
    ...     pass
    >>> class ISausages(IRecipe):
    ...     pass
    >>> class INoodles(IRecipe):
    ...     pass
    >>> class IKFC(IRecipe):
    ...     pass

>>> list(registry.subscriptions([IPoultry], IRecipe))
[]

unless we define a subscription::

>>> registry.subscribe([IAnimal], ISausages, 'sausages')
>>> list(registry.subscriptions([IPoultry], ISausages))
['sausages']

And define another subscription adapter:

>>> registry.subscribe([IPoultry], INoodles, 'noodles')
>>> meals = list(registry.subscriptions([IPoultry], IRecipe))
>>> meals.sort()
>>> meals
['noodles', 'sausages']

>>> registry.subscribe([IChicken], IKFC, 'kfc')
>>> meals = list(registry.subscriptions([IChicken], IRecipe))
>>> meals.sort()
>>> meals
['kfc', 'noodles', 'sausages']

And the answer for poultry hasn't changed:

>>> meals = list(registry.subscriptions([IPoultry], IRecipe))
>>> meals.sort()
>>> meals
['noodles', 'sausages']


=== Zope3/src/zope/interface/tests/test_adapter.py 1.3 => 1.4 ===
--- Zope3/src/zope/interface/tests/test_adapter.py:1.3	Mon Mar  8 12:26:57 2004
+++ Zope3/src/zope/interface/tests/test_adapter.py	Mon Mar 15 15:41:55 2004
@@ -15,8 +15,8 @@
 
 $Id$
 """
-import unittest
-from zope.testing.doctestunit import DocTestSuite
+import unittest, doctest
+import zope.interface
 from zope.interface.adapter import AdapterRegistry
 import zope.interface
 
@@ -25,9 +25,6 @@
 class IF1(IF0):
     pass
 
-class F1:
-    zope.interface.implements(IF1)
-
 class IB0(zope.interface.Interface):
     pass
 class IB1(IB0):
@@ -38,169 +35,112 @@
 class IR1(IR0):
     pass
 
-class R1:
-    zope.interface.implements(IR1)
-
-class Adapter:
-    def __init__(self, *args):
-        self.args = args
-
-class A1(Adapter):
-    pass
-
-class A2(Adapter):
-    pass
-
 def test_multi_adapter_w_default():
     """
-    >>> c = F1()
-    >>> r = R1()
-
     >>> registry = AdapterRegistry()
     
-    >>> registry.provideAdapter(None, IB1, [A1], name='bob', with=[IR0])
+    >>> registry.register([None, IR0], IB1, 'bob', 'A1')
 
-    >>> a = registry.queryMultiAdapter((c, r), IB0, 'bob')
-    >>> a.__class__ is A1
-    True
-    >>> a.args == (c, r)
-    True
+    >>> registry.lookup((IF1, IR1), IB0, 'bob')
+    'A1'
     
-    >>> registry.queryMultiAdapter((c, r), IB0, 'bruce')
+    >>> registry.lookup((IF1, IR1), IB0, 'bruce')
 
-    >>> registry.provideAdapter(None, IB1, [A2], name='bob', with=[IR1])
-    >>> a = registry.queryMultiAdapter((c, r), IB0, 'bob')
-    >>> a.__class__ is A2
-    True
-    >>> a.args == (c, r)
-    True
-    
+    >>> registry.register([None, IR1], IB1, 'bob', 'A2')
+    >>> registry.lookup((IF1, IR1), IB0, 'bob')
+    'A2'
     """
 
 def test_multi_adapter_w_inherited_and_multiple_registrations():
     """
-    >>> c = F1()
-    >>> r = R1()
-
     >>> registry = AdapterRegistry()
 
     >>> class IX(zope.interface.Interface):
     ...    pass
 
-    >>> class AX(Adapter):
-    ...     pass
-    
-    >>> registry.provideAdapter(IF0, IB1, [A1], name='bob', with=[IR0])
-    >>> registry.provideAdapter(IF1, IB1, [AX], name='bob', with=[IX])
+    >>> registry.register([IF0, IR0], IB1, 'bob', 'A1')
+    >>> registry.register([IF1, IX], IB1, 'bob', 'AX')
 
-    >>> a = registry.queryMultiAdapter((c, r), IB0, 'bob')
-    >>> a.__class__ is A1
-    True
-    >>> a.args == (c, r)
-    True
+    >>> registry.lookup((IF1, IR1), IB0, 'bob')
+    'A1'
     """
 
 def test_named_adapter_with_default():
     """Query a named simple adapter
 
-    >>> import zope.interface
-
-    >>> c = F1()
-
     >>> registry = AdapterRegistry()
 
     If we ask for a named adapter, we won't get a result unless there
     is a named adapter, even if the object implements the interface:
 
-    >>> registry.queryNamedAdapter(c, IF0, 'bob')
+    >>> registry.lookup([IF1], IF0, 'bob')
 
-    >>> registry.provideAdapter(None, IB1, [A1], name='bob')
-    >>> a = registry.queryNamedAdapter(c, IB0, 'bob')
-    >>> a.__class__ is A1
-    True
-    >>> a.args == (c, )
-    True
-
-    >>> registry.queryNamedAdapter(c, IB0, 'bruce')
-
-    >>> registry.provideAdapter(None, IB0, [A2], name='bob')
-    >>> a = registry.queryNamedAdapter(c, IB0, 'bob')
-    >>> a.__class__ is A2
-    True
-    >>> a.args == (c, )
-    True
+    >>> registry.register([None], IB1, 'bob', 'A1')
+    >>> registry.lookup([IF1], IB0, 'bob')
+    'A1'
 
+    >>> registry.lookup([IF1], IB0, 'bruce')
 
+    >>> registry.register([None], IB0, 'bob', 'A2')
+    >>> registry.lookup([IF1], IB0, 'bob')
+    'A2'
     """
 
 def test_multi_adapter_gets_closest_provided():
     """
-    >>> c = F1()
-    >>> r = R1()
-
     >>> registry = AdapterRegistry()
-    >>> registry.provideAdapter(IF1, IB0, [A1], name='bob', with=[IR0])
-    >>> registry.provideAdapter(IF1, IB1, [A2], name='bob', with=[IR0])
-    >>> a = registry.queryMultiAdapter((c, r), IB0, 'bob')
-    >>> a.__class__ is A1
-    True
+    >>> registry.register([IF1, IR0], IB0, 'bob', 'A1')
+    >>> registry.register((IF1, IR0), IB1, 'bob', 'A2')
+    >>> registry.lookup((IF1, IR1), IB0, 'bob')
+    'A1'
 
     >>> registry = AdapterRegistry()
-    >>> registry.provideAdapter(IF1, IB1, [A2], name='bob', with=[IR0])
-    >>> registry.provideAdapter(IF1, IB0, [A1], name='bob', with=[IR0])
-    >>> a = registry.queryMultiAdapter((c, r), IB0, 'bob')
-    >>> a.__class__ is A1
-    True
+    >>> registry.register([IF1, IR0], IB1, 'bob', 'A2')
+    >>> registry.register([IF1, IR0], IB0, 'bob', 'A1')
+    >>> registry.lookup([IF1, IR0], IB0, 'bob')
+    'A1'
 
     >>> registry = AdapterRegistry()
-    >>> registry.provideAdapter(IF1, IB0, [A1], name='bob', with=[IR0])
-    >>> registry.provideAdapter(IF1, IB1, [A2], name='bob', with=[IR1])
-    >>> a = registry.queryMultiAdapter((c, r), IB0, 'bob')
-    >>> a.__class__ is A2
-    True
+    >>> registry.register([IF1, IR0], IB0, 'bob', 'A1')
+    >>> registry.register([IF1, IR1], IB1, 'bob', 'A2')
+    >>> registry.lookup([IF1, IR1], IB0, 'bob')
+    'A2'
 
     >>> registry = AdapterRegistry()
-    >>> registry.provideAdapter(IF1, IB1, [A2], name='bob', with=[IR1])
-    >>> registry.provideAdapter(IF1, IB0, [A1], name='bob', with=[IR0])
-    >>> a = registry.queryMultiAdapter((c, r), IB0, 'bob')
-    >>> a.__class__ is A2
-    True
-
+    >>> registry.register([IF1, IR1], IB1, 'bob', 2)
+    >>> registry.register([IF1, IR0], IB0, 'bob', 1)
+    >>> registry.lookup([IF1, IR1], IB0, 'bob')
+    2
     """
 
 def test_multi_adapter_check_non_default_dont_hide_default():
     """
-    >>> c = F1()
-    >>> r = R1()
-
     >>> registry = AdapterRegistry()
 
     >>> class IX(zope.interface.Interface):
     ...     pass
 
     
-    >>> registry.provideAdapter(None, IB0, [A1], name='bob', with=[IR0])
-    >>> registry.provideAdapter(IF1,  IB0, [A2], name='bob', with=[IX])
-    >>> a = registry.queryMultiAdapter((c, r), IB0, 'bob')
-    >>> a.__class__.__name__
-    'A1'
-
+    >>> registry.register([None, IR0], IB0, 'bob', 1)
+    >>> registry.register([IF1,   IX], IB0, 'bob', 2)
+    >>> registry.lookup([IF1, IR1], IB0, 'bob')
+    1
     """
 
 
 def test_getRegisteredMatching_with_with():
     """
     >>> registry = AdapterRegistry()
-    >>> registry.provideAdapter(None, IB0, '_0')
-    >>> registry.provideAdapter(IF0, IB0, '00')
-    >>> registry.provideAdapter(IF1, IB0, '10')
-    >>> registry.provideAdapter(IF1, IB1, '11')
-    >>> registry.provideAdapter(IF0, IB0, '000', with=(IR0,))
-    >>> registry.provideAdapter(IF1, IB0, '100', with=(IR0,))
-    >>> registry.provideAdapter(IF1, IB1, '110', with=(IR0,))
-    >>> registry.provideAdapter(IF0, IB0, '001', with=(IR1,))
-    >>> registry.provideAdapter(IF1, IB0, '101', with=(IR1,))
-    >>> registry.provideAdapter(IF1, IB1, '111', with=(IR1,))
+    >>> registry.register([None], IB0, '', '_0')
+    >>> registry.register([IF0], IB0, '', '00')
+    >>> registry.register([IF1], IB0, '', '10')
+    >>> registry.register([IF1], IB1, '', '11')
+    >>> registry.register((IF0, IR0), IB0, '', '000')
+    >>> registry.register((IF1, IR0), IB0, '', '100')
+    >>> registry.register((IF1, IR0), IB1, '', '110')
+    >>> registry.register((IF0, IR1), IB0, '', '001')
+    >>> registry.register((IF1, IR1), IB0, '', '101')
+    >>> registry.register((IF1, IR1), IB1, '', '111')
 
     >>> from pprint import PrettyPrinter
     >>> pprint = PrettyPrinter(width=60).pprint
@@ -258,11 +198,34 @@
 
 
 
+def DocFileSuite(*paths):
+    # It's not entirely obvious how to connection this single string
+    # with unittest.  For now, re-use the _utest() function that comes
+    # standard with doctest in Python 2.3.  One problem is that the
+    # error indicator doesn't point to the line of the doctest file
+    # that failed.
+    import os, doctest, new
+    t = doctest.Tester(globs={})
+    suite = unittest.TestSuite()
+    dir = os.path.split(__file__)[0]
+    for path in paths:
+        path = os.path.join(dir, path)
+        source = open(path).read()
+        def runit(path=path, source=source):
+            doctest._utest(t, path, source, path, 0)
+        runit = new.function(runit.func_code, runit.func_globals, path,
+                             runit.func_defaults, runit.func_closure)
+        f = unittest.FunctionTestCase(runit,
+                                      description="doctest from %s" % path)
+        suite.addTest(f)
+    return suite
+
 
 def test_suite():
     return unittest.TestSuite((
-        DocTestSuite('zope.interface.adapter'),
-        DocTestSuite(),
+        DocFileSuite('../adapter.txt', 'foodforthought.txt'),
+        doctest.DocTestSuite('zope.interface.adapter'),
+        doctest.DocTestSuite(),
         ))
 
 if __name__ == '__main__': unittest.main()




More information about the Zope3-Checkins mailing list