diff options
Diffstat (limited to 'Lib/test/test_binop.py')
| -rw-r--r-- | Lib/test/test_binop.py | 135 |
1 files changed, 92 insertions, 43 deletions
diff --git a/Lib/test/test_binop.py b/Lib/test/test_binop.py index b1ef626..8417916 100644 --- a/Lib/test/test_binop.py +++ b/Lib/test/test_binop.py @@ -1,7 +1,8 @@ """Tests for binary operators on subtypes of built-in types.""" import unittest -from test import test_support +from test import support +from operator import eq, ne, lt, gt, le, ge def gcd(a, b): """Greatest common divisor using Euclid's algorithm.""" @@ -10,12 +11,12 @@ def gcd(a, b): return b def isint(x): - """Test whether an object is an instance of int or long.""" - return isinstance(x, int) or isinstance(x, long) + """Test whether an object is an instance of int.""" + return isinstance(x, int) def isnum(x): """Test whether an object is an instance of a built-in numeric type.""" - for T in int, long, float, complex: + for T in int, float, complex: if isinstance(x, T): return 1 return 0 @@ -26,24 +27,24 @@ def isRat(x): class Rat(object): - """Rational number implemented as a normalized pair of longs.""" + """Rational number implemented as a normalized pair of ints.""" __slots__ = ['_Rat__num', '_Rat__den'] - def __init__(self, num=0L, den=1L): + def __init__(self, num=0, den=1): """Constructor: Rat([num[, den]]). - The arguments must be ints or longs, and default to (0, 1).""" + The arguments must be ints, and default to (0, 1).""" if not isint(num): - raise TypeError, "Rat numerator must be int or long (%r)" % num + raise TypeError("Rat numerator must be int (%r)" % num) if not isint(den): - raise TypeError, "Rat denominator must be int or long (%r)" % den + raise TypeError("Rat denominator must be int (%r)" % den) # But the zero is always on if den == 0: - raise ZeroDivisionError, "zero denominator" + raise ZeroDivisionError("zero denominator") g = gcd(den, num) - self.__num = long(num//g) - self.__den = long(den//g) + self.__num = int(num//g) + self.__den = int(den//g) def _get_num(self): """Accessor function for read-only 'num' attribute of Rat.""" @@ -73,15 +74,9 @@ class Rat(object): try: return int(self.__num) except OverflowError: - raise OverflowError, ("%s too large to convert to int" % + raise OverflowError("%s too large to convert to int" % repr(self)) - raise ValueError, "can't convert %s to int" % repr(self) - - def __long__(self): - """Convert a Rat to an long; self.den must be 1.""" - if self.__den == 1: - return long(self.__num) - raise ValueError, "can't convert %s to long" % repr(self) + raise ValueError("can't convert %s to int" % repr(self)) def __add__(self, other): """Add two Rats, or a Rat and a number.""" @@ -140,8 +135,6 @@ class Rat(object): return float(self) / other return NotImplemented - __div__ = __truediv__ - def __rtruediv__(self, other): """Divide two Rats, or a Rat and a number (reversed args).""" if isRat(other): @@ -152,8 +145,6 @@ class Rat(object): return other / float(self) return NotImplemented - __rdiv__ = __rtruediv__ - def __floordiv__(self, other): """Divide two Rats, returning the floored result.""" if isint(other): @@ -207,9 +198,6 @@ class Rat(object): """Compare two Rats for inequality.""" return not self == other - # Silence Py3k warning - __hash__ = None - class RatTestCase(unittest.TestCase): """Unit tests for Rat class and its support utilities.""" @@ -232,9 +220,6 @@ class RatTestCase(unittest.TestCase): a = Rat(10, 15) self.assertEqual(a.num, 2) self.assertEqual(a.den, 3) - a = Rat(10L, 15L) - self.assertEqual(a.num, 2) - self.assertEqual(a.den, 3) a = Rat(10, -15) self.assertEqual(a.num, -2) self.assertEqual(a.den, 3) @@ -308,24 +293,88 @@ class RatTestCase(unittest.TestCase): self.assertEqual(Rat(10), 10.0) self.assertEqual(10.0, Rat(10)) - def test_future_div(self): - exec future_test + def test_true_div(self): + self.assertEqual(Rat(10, 3) / Rat(5, 7), Rat(14, 3)) + self.assertEqual(Rat(10, 3) / 3, Rat(10, 9)) + self.assertEqual(2 / Rat(5), Rat(2, 5)) + self.assertEqual(3.0 * Rat(1, 2), 1.5) + self.assertEqual(Rat(1, 2) * 3.0, 1.5) + self.assertEqual(eval('1/2'), 0.5) # XXX Ran out of steam; TO DO: divmod, div, future division -future_test = """ -from __future__ import division -self.assertEqual(Rat(10, 3) / Rat(5, 7), Rat(14, 3)) -self.assertEqual(Rat(10, 3) / 3, Rat(10, 9)) -self.assertEqual(2 / Rat(5), Rat(2, 5)) -self.assertEqual(3.0 * Rat(1, 2), 1.5) -self.assertEqual(Rat(1, 2) * 3.0, 1.5) -self.assertEqual(eval('1/2'), 0.5) -""" -def test_main(): - test_support.run_unittest(RatTestCase) +class OperationLogger: + """Base class for classes with operation logging.""" + def __init__(self, logger): + self.logger = logger + def log_operation(self, *args): + self.logger(*args) + +def op_sequence(op, *classes): + """Return the sequence of operations that results from applying + the operation `op` to instances of the given classes.""" + log = [] + instances = [] + for c in classes: + instances.append(c(log.append)) + + try: + op(*instances) + except TypeError: + pass + return log + +class A(OperationLogger): + def __eq__(self, other): + self.log_operation('A.__eq__') + return NotImplemented + def __le__(self, other): + self.log_operation('A.__le__') + return NotImplemented + def __ge__(self, other): + self.log_operation('A.__ge__') + return NotImplemented + +class B(OperationLogger): + def __eq__(self, other): + self.log_operation('B.__eq__') + return NotImplemented + def __le__(self, other): + self.log_operation('B.__le__') + return NotImplemented + def __ge__(self, other): + self.log_operation('B.__ge__') + return NotImplemented +class C(B): + def __eq__(self, other): + self.log_operation('C.__eq__') + return NotImplemented + def __le__(self, other): + self.log_operation('C.__le__') + return NotImplemented + def __ge__(self, other): + self.log_operation('C.__ge__') + return NotImplemented + +class OperationOrderTests(unittest.TestCase): + def test_comparison_orders(self): + self.assertEqual(op_sequence(eq, A, A), ['A.__eq__', 'A.__eq__']) + self.assertEqual(op_sequence(eq, A, B), ['A.__eq__', 'B.__eq__']) + self.assertEqual(op_sequence(eq, B, A), ['B.__eq__', 'A.__eq__']) + # C is a subclass of B, so C.__eq__ is called first + self.assertEqual(op_sequence(eq, B, C), ['C.__eq__', 'B.__eq__']) + self.assertEqual(op_sequence(eq, C, B), ['C.__eq__', 'B.__eq__']) + + self.assertEqual(op_sequence(le, A, A), ['A.__le__', 'A.__ge__']) + self.assertEqual(op_sequence(le, A, B), ['A.__le__', 'B.__ge__']) + self.assertEqual(op_sequence(le, B, A), ['B.__le__', 'A.__ge__']) + self.assertEqual(op_sequence(le, B, C), ['C.__ge__', 'B.__le__']) + self.assertEqual(op_sequence(le, C, B), ['C.__le__', 'B.__ge__']) + +def test_main(): + support.run_unittest(RatTestCase, OperationOrderTests) if __name__ == "__main__": test_main() |
