diff options
| author | Tres Seaver <tseaver@palladion.com> | 2014-12-08 13:11:38 -0500 |
|---|---|---|
| committer | Tres Seaver <tseaver@palladion.com> | 2014-12-08 13:14:30 -0500 |
| commit | 859cdddeb89613c2ab8474e1723e641b10d1a5d8 (patch) | |
| tree | 1cfee006ee21ee2965d6ee9485fd998d69f3ce6f /src | |
| parent | 50496ac60e204eb721050227738d6816da7c7a37 (diff) | |
| download | zope-interface-859cdddeb89613c2ab8474e1723e641b10d1a5d8.tar.gz | |
100% branch coverage for 'zope.interface.ro'.
Diffstat (limited to 'src')
| -rw-r--r-- | src/zope/interface/ro.py | 29 | ||||
| -rw-r--r-- | src/zope/interface/tests/test_ro.py | 115 |
2 files changed, 127 insertions, 17 deletions
diff --git a/src/zope/interface/ro.py b/src/zope/interface/ro.py index ab47a4c..84f10dc 100644 --- a/src/zope/interface/ro.py +++ b/src/zope/interface/ro.py @@ -15,13 +15,7 @@ """ __docformat__ = 'restructuredtext' - -def ro(object): - """Compute a "resolution order" for an object - """ - return mergeOrderings([_flatten(object)]) - -def mergeOrderings(orderings, seen=None): +def _mergeOrderings(orderings): """Merge multiple orderings so that within-ordering order is preserved Orderings are constrained in such a way that if an object appears @@ -30,7 +24,7 @@ def mergeOrderings(orderings, seen=None): For example: - >>> mergeOrderings([ + >>> _mergeOrderings([ ... ['x', 'y', 'z'], ... ['q', 'z'], ... [1, 3, 5], @@ -40,19 +34,14 @@ def mergeOrderings(orderings, seen=None): """ - if seen is None: - seen = {} + seen = {} result = [] - orderings.reverse() - for ordering in orderings: - ordering = list(ordering) - ordering.reverse() - for o in ordering: + for ordering in reversed(orderings): + for o in reversed(ordering): if o not in seen: seen[o] = 1 - result.append(o) + result.insert(0, o) - result.reverse() return result def _flatten(ob): @@ -67,3 +56,9 @@ def _flatten(ob): # by definition. result[i:i] = ob.__bases__ return result + + +def ro(object): + """Compute a "resolution order" for an object + """ + return _mergeOrderings([_flatten(object)]) diff --git a/src/zope/interface/tests/test_ro.py b/src/zope/interface/tests/test_ro.py new file mode 100644 index 0000000..0756c6d --- /dev/null +++ b/src/zope/interface/tests/test_ro.py @@ -0,0 +1,115 @@ +############################################################################## +# +# Copyright (c) 2014 Zope Foundation 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. +# +############################################################################## +"""Resolution ordering utility tests""" +import unittest + + +class Test__mergeOrderings(unittest.TestCase): + + def _callFUT(self, orderings): + from zope.interface.ro import _mergeOrderings + return _mergeOrderings(orderings) + + def test_empty(self): + self.assertEqual(self._callFUT([]), []) + + def test_single(self): + self.assertEqual(self._callFUT(['a', 'b', 'c']), ['a', 'b', 'c']) + + def test_w_duplicates(self): + self.assertEqual(self._callFUT([['a'], ['b', 'a']]), ['b', 'a']) + + def test_suffix_across_multiple_duplicats(self): + O1 = ['x', 'y', 'z'] + O2 = ['q', 'z'] + O3 = [1, 3, 5] + O4 = ['z'] + self.assertEqual(self._callFUT([O1, O2, O3, O4]), + ['x', 'y', 'q', 1, 3, 5, 'z']) + + +class Test__flatten(unittest.TestCase): + + def _callFUT(self, ob): + from zope.interface.ro import _flatten + return _flatten(ob) + + def test_w_empty_bases(self): + class Foo(object): + pass + foo = Foo() + foo.__bases__ = () + self.assertEqual(self._callFUT(foo), [foo]) + + def test_w_single_base(self): + class Foo(object): + pass + self.assertEqual(self._callFUT(Foo), [Foo, object]) + + def test_w_bases(self): + class Foo(object): + pass + class Bar(Foo): + pass + self.assertEqual(self._callFUT(Bar), [Bar, Foo, object]) + + def test_w_diamond(self): + class Foo(object): + pass + class Bar(Foo): + pass + class Baz(Foo): + pass + class Qux(Bar, Baz): + pass + self.assertEqual(self._callFUT(Qux), + [Qux, Bar, Foo, object, Baz, Foo, object]) + + +class Test_ro(unittest.TestCase): + + def _callFUT(self, ob): + from zope.interface.ro import ro + return ro(ob) + + def test_w_empty_bases(self): + class Foo(object): + pass + foo = Foo() + foo.__bases__ = () + self.assertEqual(self._callFUT(foo), [foo]) + + def test_w_single_base(self): + class Foo(object): + pass + self.assertEqual(self._callFUT(Foo), [Foo, object]) + + def test_w_bases(self): + class Foo(object): + pass + class Bar(Foo): + pass + self.assertEqual(self._callFUT(Bar), [Bar, Foo, object]) + + def test_w_diamond(self): + class Foo(object): + pass + class Bar(Foo): + pass + class Baz(Foo): + pass + class Qux(Bar, Baz): + pass + self.assertEqual(self._callFUT(Qux), + [Qux, Bar, Baz, Foo, object]) |
