[Zope3-checkins] SVN: Zope3/branches/ZopeX3-3.0/src/zope/interface/
Merge patch by Gustavo Niemeyer to return the best match for
a multi-adapter, which got checked in only on trunk
Sidnei da Silva
sidnei at awkly.org
Wed Oct 20 22:31:02 EDT 2004
Log message for revision 28224:
Merge patch by Gustavo Niemeyer to return the best match for a multi-adapter, which got checked in only on trunk
Changed:
U Zope3/branches/ZopeX3-3.0/src/zope/interface/adapter.py
U Zope3/branches/ZopeX3-3.0/src/zope/interface/tests/test_adapter.py
-=-
Modified: Zope3/branches/ZopeX3-3.0/src/zope/interface/adapter.py
===================================================================
--- Zope3/branches/ZopeX3-3.0/src/zope/interface/adapter.py 2004-10-21 01:20:02 UTC (rev 28223)
+++ Zope3/branches/ZopeX3-3.0/src/zope/interface/adapter.py 2004-10-21 02:31:02 UTC (rev 28224)
@@ -352,12 +352,30 @@
if not bywith:
continue
+ # Selecting multi-adapters is not just a matter of matching the
+ # required interfaces of the adapter to the ones passed. Several
+ # adapters might match, but we only want the best one. We use a
+ # ranking algorithm to determine the best match.
+
+ # `best` carries the rank and value of the best found adapter.
+ best = None
for rwith, value in bywith:
+ # the `rank` describes how well the found adapter matches.
+ rank = []
for rspec, spec in zip(rwith, with):
if not spec.isOrExtends(rspec):
break # This one is no good
+ # Determine the rank of this particular specification.
+ rank.append(list(spec.__sro__).index(rspec))
else:
- return value
+ # If the new rank is better than the best previously
+ # recorded one, make the new adapter the best one found.
+ rank = tuple(rank)
+ if best is None or rank < best[0]:
+ best = rank, value
+ # If any match was found, return the best one.
+ if best:
+ return best[1]
return default
Modified: Zope3/branches/ZopeX3-3.0/src/zope/interface/tests/test_adapter.py
===================================================================
--- Zope3/branches/ZopeX3-3.0/src/zope/interface/tests/test_adapter.py 2004-10-21 01:20:02 UTC (rev 28223)
+++ Zope3/branches/ZopeX3-3.0/src/zope/interface/tests/test_adapter.py 2004-10-21 02:31:02 UTC (rev 28224)
@@ -35,6 +35,51 @@
class IR1(IR0):
pass
+
+def test_orderwith():
+ """
+ >>> Interface = zope.interface.Interface
+ >>> bywith = {(Interface, Interface): 'A0',
+ ... (IF0, Interface): 'A1',
+ ... (Interface, IB0): 'A2',
+ ... (IF0, IB0): 'A3',
+ ... (IF1, IB0): 'A4',
+ ... (IF0, IB1): 'A5',
+ ... (IF1, IB1): 'A6',
+ ... }
+
+ >>> [value for spec, value in zope.interface.adapter.orderwith(bywith)]
+ ['A6', 'A4', 'A5', 'A3', 'A1', 'A2', 'A0']
+ """
+
+
+def test_multi_adapter_get_best_match():
+ """
+ >>> registry = AdapterRegistry()
+
+ >>> class IB2(IB0):
+ ... pass
+ >>> class IB3(IB2, IB1):
+ ... pass
+ >>> class IB4(IB1, IB2):
+ ... pass
+
+ >>> registry.register([None, IB1], IR0, '', 'A1')
+ >>> registry.register([None, IB0], IR0, '', 'A0')
+ >>> registry.register([None, IB2], IR0, '', 'A2')
+
+ >>> registry.lookup((IF1, IB1), IR0, '')
+ 'A1'
+ >>> registry.lookup((IF1, IB2), IR0, '')
+ 'A2'
+ >>> registry.lookup((IF1, IB0), IR0, '')
+ 'A0'
+ >>> registry.lookup((IF1, IB3), IR0, '')
+ 'A2'
+ >>> registry.lookup((IF1, IB4), IR0, '')
+ 'A1'
+ """
+
def test_multi_adapter_w_default():
"""
>>> registry = AdapterRegistry()
@@ -141,4 +186,5 @@
doctest.DocTestSuite(),
))
-if __name__ == '__main__': unittest.main()
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
More information about the Zope3-Checkins
mailing list