diff --git a/test_functools.py b/test_functools.py index 30d419d..02e148f 100644 --- a/test_functools.py +++ b/test_functools.py @@ -19,14 +19,17 @@ def capture(*args, **kw): """capture all positional and keyword arguments""" return args, kw -class TestPartial(unittest.TestCase): +class TestPartialBase(unittest.TestCase): thetype = functools.partial - def test_basic_examples(self): + def test_basic_example(self): p = self.thetype(capture, 1, 2, a=10, b=20) + expected = self._expected_combine_positional((1, 2), (3, 4)) self.assertEqual(p(3, 4, b=30, c=40), - ((1, 2, 3, 4), dict(a=10, b=30, c=40))) + (expected, dict(a=10, b=30, c=40))) + + def test_map_example(self): p = self.thetype(map, lambda x: x*10) self.assertEqual(p([1,2,3,4]), [10, 20, 30, 40]) @@ -71,7 +74,6 @@ class TestPartial(unittest.TestCase): self.assertEqual(p(1,2), ((1,2), {})) p = self.thetype(capture, 1, 2) self.assertEqual(p(), ((1,2), {})) - self.assertEqual(p(3,4), ((1,2,3,4), {})) def test_kw_combinations(self): # exercise special code paths for no keyword args in @@ -89,7 +91,7 @@ class TestPartial(unittest.TestCase): # make sure positional arguments are captured correctly for args in [(), (0,), (0,1), (0,1,2), (0,1,2,3)]: p = self.thetype(capture, *args) - expected = args + ('x',) + expected = self._expected_combine_positional(args, ('x',)) got, empty = p('x') self.failUnless(expected == got and empty == {}) @@ -105,18 +107,11 @@ class TestPartial(unittest.TestCase): # make sure there are no side effects that affect subsequent calls p = self.thetype(capture, 0, a=1) args1, kw1 = p(1, b=2) - self.failUnless(args1 == (0,1) and kw1 == {'a':1,'b':2}) + e_args1 = self._expected_combine_positional((0,), (1,)) + self.failUnless(args1 == e_args1 and kw1 == {'a':1,'b':2}) args2, kw2 = p() self.failUnless(args2 == (0,) and kw2 == {'a':1}) - def test_error_propagation(self): - def f(x, y): - x / y - self.assertRaises(ZeroDivisionError, self.thetype(f, 1, 0)) - self.assertRaises(ZeroDivisionError, self.thetype(f, 1), 0) - self.assertRaises(ZeroDivisionError, self.thetype(f), 1, 0) - self.assertRaises(ZeroDivisionError, self.thetype(f, y=0), 1) - def test_attributes(self): p = self.thetype(hex) try: @@ -133,6 +128,20 @@ class TestPartial(unittest.TestCase): f = None self.assertRaises(ReferenceError, getattr, p, 'func') +class TestPartial(TestPartialBase): + + @staticmethod + def _expected_combine_positional(args1, args2): + return args1 + args2 + + def test_error_propagation(self): + def f(x, y): + x / y + self.assertRaises(ZeroDivisionError, self.thetype(f, 1, 0)) + self.assertRaises(ZeroDivisionError, self.thetype(f, 1), 0) + self.assertRaises(ZeroDivisionError, self.thetype(f), 1, 0) + self.assertRaises(ZeroDivisionError, self.thetype(f, y=0), 1) + def test_with_bound_and_unbound_methods(self): data = map(str, range(10)) join = self.thetype(str.join, '') @@ -147,6 +156,34 @@ class TestPartialSubclass(TestPartial): thetype = PartialSubclass +class TestPartialRight(TestPartialBase): + + thetype = functools.partial_right + + @staticmethod + def _expected_combine_positional(args1, args2): + return args2 + args1 + + def test_map_example(self): + p = self.thetype(map, [1,2,3,4]) + self.assertEqual(p(lambda x: x*10), [10, 20, 30, 40]) + + def test_str_split_example(self): + p = self.thetype(str.split, ',') + self.assertEqual(p('a,b,c'), ['a', 'b', 'c']) + + def test_int_example(self): + p = self.thetype(int, 16) + self.assertEqual(p('100'), 256) + + def test_error_propagation(self): + def f(x, y): + x / y + self.assertRaises(ZeroDivisionError, self.thetype(f, 1, 0)) + self.assertRaises(ZeroDivisionError, self.thetype(f, 0), 1) + self.assertRaises(ZeroDivisionError, self.thetype(f), 1, 0) + self.assertRaises(ZeroDivisionError, self.thetype(f, y=0), 1) + class TestPythonPartial(TestPartial): @@ -314,6 +351,7 @@ def test_main(verbose=None): import sys test_classes = ( TestPartial, + TestPartialRight, TestPartialSubclass, TestPythonPartial, TestUpdateWrapper,