summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_binop.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/test_binop.py')
-rw-r--r--Lib/test/test_binop.py135
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()