summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTres Seaver <tseaver@palladion.com>2014-12-08 13:11:38 -0500
committerTres Seaver <tseaver@palladion.com>2014-12-08 13:14:30 -0500
commit859cdddeb89613c2ab8474e1723e641b10d1a5d8 (patch)
tree1cfee006ee21ee2965d6ee9485fd998d69f3ce6f /src
parent50496ac60e204eb721050227738d6816da7c7a37 (diff)
downloadzope-interface-859cdddeb89613c2ab8474e1723e641b10d1a5d8.tar.gz
100% branch coverage for 'zope.interface.ro'.
Diffstat (limited to 'src')
-rw-r--r--src/zope/interface/ro.py29
-rw-r--r--src/zope/interface/tests/test_ro.py115
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])