1"""Tests for Lib/fractions.py."""
2
3from decimal import Decimal
4from test.support import requires_IEEE_754
5import math
6import numbers
7import operator
8import fractions
9import functools
10import sys
11import unittest
12from copy import copy, deepcopy
13from pickle import dumps, loads
14F = fractions.Fraction
15
16
17class DummyFloat(object):
18    """Dummy float class for testing comparisons with Fractions"""
19
20    def __init__(self, value):
21        if not isinstance(value, float):
22            raise TypeError("DummyFloat can only be initialized from float")
23        self.value = value
24
25    def _richcmp(self, other, op):
26        if isinstance(other, numbers.Rational):
27            return op(F.from_float(self.value), other)
28        elif isinstance(other, DummyFloat):
29            return op(self.value, other.value)
30        else:
31            return NotImplemented
32
33    def __eq__(self, other): return self._richcmp(other, operator.eq)
34    def __le__(self, other): return self._richcmp(other, operator.le)
35    def __lt__(self, other): return self._richcmp(other, operator.lt)
36    def __ge__(self, other): return self._richcmp(other, operator.ge)
37    def __gt__(self, other): return self._richcmp(other, operator.gt)
38
39    # shouldn't be calling __float__ at all when doing comparisons
40    def __float__(self):
41        assert False, "__float__ should not be invoked for comparisons"
42
43    # same goes for subtraction
44    def __sub__(self, other):
45        assert False, "__sub__ should not be invoked for comparisons"
46    __rsub__ = __sub__
47
48
49class DummyRational(object):
50    """Test comparison of Fraction with a naive rational implementation."""
51
52    def __init__(self, num, den):
53        g = math.gcd(num, den)
54        self.num = num // g
55        self.den = den // g
56
57    def __eq__(self, other):
58        if isinstance(other, fractions.Fraction):
59            return (self.num == other._numerator and
60                    self.den == other._denominator)
61        else:
62            return NotImplemented
63
64    def __lt__(self, other):
65        return(self.num * other._denominator < self.den * other._numerator)
66
67    def __gt__(self, other):
68        return(self.num * other._denominator > self.den * other._numerator)
69
70    def __le__(self, other):
71        return(self.num * other._denominator <= self.den * other._numerator)
72
73    def __ge__(self, other):
74        return(self.num * other._denominator >= self.den * other._numerator)
75
76    # this class is for testing comparisons; conversion to float
77    # should never be used for a comparison, since it loses accuracy
78    def __float__(self):
79        assert False, "__float__ should not be invoked"
80
81class DummyFraction(fractions.Fraction):
82    """Dummy Fraction subclass for copy and deepcopy testing."""
83
84
85def _components(r):
86    return (r.numerator, r.denominator)
87
88
89class FractionTest(unittest.TestCase):
90
91    def assertTypedEquals(self, expected, actual):
92        """Asserts that both the types and values are the same."""
93        self.assertEqual(type(expected), type(actual))
94        self.assertEqual(expected, actual)
95
96    def assertTypedTupleEquals(self, expected, actual):
97        """Asserts that both the types and values in the tuples are the same."""
98        self.assertTupleEqual(expected, actual)
99        self.assertListEqual(list(map(type, expected)), list(map(type, actual)))
100
101    def assertRaisesMessage(self, exc_type, message,
102                            callable, *args, **kwargs):
103        """Asserts that callable(*args, **kwargs) raises exc_type(message)."""
104        try:
105            callable(*args, **kwargs)
106        except exc_type as e:
107            self.assertEqual(message, str(e))
108        else:
109            self.fail("%s not raised" % exc_type.__name__)
110
111    def testInit(self):
112        self.assertEqual((0, 1), _components(F()))
113        self.assertEqual((7, 1), _components(F(7)))
114        self.assertEqual((7, 3), _components(F(F(7, 3))))
115
116        self.assertEqual((-1, 1), _components(F(-1, 1)))
117        self.assertEqual((-1, 1), _components(F(1, -1)))
118        self.assertEqual((1, 1), _components(F(-2, -2)))
119        self.assertEqual((1, 2), _components(F(5, 10)))
120        self.assertEqual((7, 15), _components(F(7, 15)))
121        self.assertEqual((10**23, 1), _components(F(10**23)))
122
123        self.assertEqual((3, 77), _components(F(F(3, 7), 11)))
124        self.assertEqual((-9, 5), _components(F(2, F(-10, 9))))
125        self.assertEqual((2486, 2485), _components(F(F(22, 7), F(355, 113))))
126
127        self.assertRaisesMessage(ZeroDivisionError, "Fraction(12, 0)",
128                                 F, 12, 0)
129        self.assertRaises(TypeError, F, 1.5 + 3j)
130
131        self.assertRaises(TypeError, F, "3/2", 3)
132        self.assertRaises(TypeError, F, 3, 0j)
133        self.assertRaises(TypeError, F, 3, 1j)
134        self.assertRaises(TypeError, F, 1, 2, 3)
135
136    @requires_IEEE_754
137    def testInitFromFloat(self):
138        self.assertEqual((5, 2), _components(F(2.5)))
139        self.assertEqual((0, 1), _components(F(-0.0)))
140        self.assertEqual((3602879701896397, 36028797018963968),
141                         _components(F(0.1)))
142        # bug 16469: error types should be consistent with float -> int
143        self.assertRaises(ValueError, F, float('nan'))
144        self.assertRaises(OverflowError, F, float('inf'))
145        self.assertRaises(OverflowError, F, float('-inf'))
146
147    def testInitFromDecimal(self):
148        self.assertEqual((11, 10),
149                         _components(F(Decimal('1.1'))))
150        self.assertEqual((7, 200),
151                         _components(F(Decimal('3.5e-2'))))
152        self.assertEqual((0, 1),
153                         _components(F(Decimal('.000e20'))))
154        # bug 16469: error types should be consistent with decimal -> int
155        self.assertRaises(ValueError, F, Decimal('nan'))
156        self.assertRaises(ValueError, F, Decimal('snan'))
157        self.assertRaises(OverflowError, F, Decimal('inf'))
158        self.assertRaises(OverflowError, F, Decimal('-inf'))
159
160    def testFromString(self):
161        self.assertEqual((5, 1), _components(F("5")))
162        self.assertEqual((3, 2), _components(F("3/2")))
163        self.assertEqual((3, 2), _components(F(" \n  +3/2")))
164        self.assertEqual((-3, 2), _components(F("-3/2  ")))
165        self.assertEqual((13, 2), _components(F("    013/02 \n  ")))
166        self.assertEqual((16, 5), _components(F(" 3.2 ")))
167        self.assertEqual((-16, 5), _components(F(" -3.2 ")))
168        self.assertEqual((-3, 1), _components(F(" -3. ")))
169        self.assertEqual((3, 5), _components(F(" .6 ")))
170        self.assertEqual((1, 3125), _components(F("32.e-5")))
171        self.assertEqual((1000000, 1), _components(F("1E+06")))
172        self.assertEqual((-12300, 1), _components(F("-1.23e4")))
173        self.assertEqual((0, 1), _components(F(" .0e+0\t")))
174        self.assertEqual((0, 1), _components(F("-0.000e0")))
175
176        self.assertRaisesMessage(
177            ZeroDivisionError, "Fraction(3, 0)",
178            F, "3/0")
179        self.assertRaisesMessage(
180            ValueError, "Invalid literal for Fraction: '3/'",
181            F, "3/")
182        self.assertRaisesMessage(
183            ValueError, "Invalid literal for Fraction: '/2'",
184            F, "/2")
185        self.assertRaisesMessage(
186            ValueError, "Invalid literal for Fraction: '3 /2'",
187            F, "3 /2")
188        self.assertRaisesMessage(
189            # Denominators don't need a sign.
190            ValueError, "Invalid literal for Fraction: '3/+2'",
191            F, "3/+2")
192        self.assertRaisesMessage(
193            # Imitate float's parsing.
194            ValueError, "Invalid literal for Fraction: '+ 3/2'",
195            F, "+ 3/2")
196        self.assertRaisesMessage(
197            # Avoid treating '.' as a regex special character.
198            ValueError, "Invalid literal for Fraction: '3a2'",
199            F, "3a2")
200        self.assertRaisesMessage(
201            # Don't accept combinations of decimals and rationals.
202            ValueError, "Invalid literal for Fraction: '3/7.2'",
203            F, "3/7.2")
204        self.assertRaisesMessage(
205            # Don't accept combinations of decimals and rationals.
206            ValueError, "Invalid literal for Fraction: '3.2/7'",
207            F, "3.2/7")
208        self.assertRaisesMessage(
209            # Allow 3. and .3, but not .
210            ValueError, "Invalid literal for Fraction: '.'",
211            F, ".")
212
213    def testImmutable(self):
214        r = F(7, 3)
215        r.__init__(2, 15)
216        self.assertEqual((7, 3), _components(r))
217
218        self.assertRaises(AttributeError, setattr, r, 'numerator', 12)
219        self.assertRaises(AttributeError, setattr, r, 'denominator', 6)
220        self.assertEqual((7, 3), _components(r))
221
222        # But if you _really_ need to:
223        r._numerator = 4
224        r._denominator = 2
225        self.assertEqual((4, 2), _components(r))
226        # Which breaks some important operations:
227        self.assertNotEqual(F(4, 2), r)
228
229    def testFromFloat(self):
230        self.assertRaises(TypeError, F.from_float, 3+4j)
231        self.assertEqual((10, 1), _components(F.from_float(10)))
232        bigint = 1234567890123456789
233        self.assertEqual((bigint, 1), _components(F.from_float(bigint)))
234        self.assertEqual((0, 1), _components(F.from_float(-0.0)))
235        self.assertEqual((10, 1), _components(F.from_float(10.0)))
236        self.assertEqual((-5, 2), _components(F.from_float(-2.5)))
237        self.assertEqual((99999999999999991611392, 1),
238                         _components(F.from_float(1e23)))
239        self.assertEqual(float(10**23), float(F.from_float(1e23)))
240        self.assertEqual((3602879701896397, 1125899906842624),
241                         _components(F.from_float(3.2)))
242        self.assertEqual(3.2, float(F.from_float(3.2)))
243
244        inf = 1e1000
245        nan = inf - inf
246        # bug 16469: error types should be consistent with float -> int
247        self.assertRaisesMessage(
248            OverflowError, "cannot convert Infinity to integer ratio",
249            F.from_float, inf)
250        self.assertRaisesMessage(
251            OverflowError, "cannot convert Infinity to integer ratio",
252            F.from_float, -inf)
253        self.assertRaisesMessage(
254            ValueError, "cannot convert NaN to integer ratio",
255            F.from_float, nan)
256
257    def testFromDecimal(self):
258        self.assertRaises(TypeError, F.from_decimal, 3+4j)
259        self.assertEqual(F(10, 1), F.from_decimal(10))
260        self.assertEqual(F(0), F.from_decimal(Decimal("-0")))
261        self.assertEqual(F(5, 10), F.from_decimal(Decimal("0.5")))
262        self.assertEqual(F(5, 1000), F.from_decimal(Decimal("5e-3")))
263        self.assertEqual(F(5000), F.from_decimal(Decimal("5e3")))
264        self.assertEqual(1 - F(1, 10**30),
265                         F.from_decimal(Decimal("0." + "9" * 30)))
266
267        # bug 16469: error types should be consistent with decimal -> int
268        self.assertRaisesMessage(
269            OverflowError, "cannot convert Infinity to integer ratio",
270            F.from_decimal, Decimal("inf"))
271        self.assertRaisesMessage(
272            OverflowError, "cannot convert Infinity to integer ratio",
273            F.from_decimal, Decimal("-inf"))
274        self.assertRaisesMessage(
275            ValueError, "cannot convert NaN to integer ratio",
276            F.from_decimal, Decimal("nan"))
277        self.assertRaisesMessage(
278            ValueError, "cannot convert NaN to integer ratio",
279            F.from_decimal, Decimal("snan"))
280
281    def test_as_integer_ratio(self):
282        self.assertEqual(F(4, 6).as_integer_ratio(), (2, 3))
283        self.assertEqual(F(-4, 6).as_integer_ratio(), (-2, 3))
284        self.assertEqual(F(4, -6).as_integer_ratio(), (-2, 3))
285        self.assertEqual(F(0, 6).as_integer_ratio(), (0, 1))
286
287    def testLimitDenominator(self):
288        rpi = F('3.1415926535897932')
289        self.assertEqual(rpi.limit_denominator(10000), F(355, 113))
290        self.assertEqual(-rpi.limit_denominator(10000), F(-355, 113))
291        self.assertEqual(rpi.limit_denominator(113), F(355, 113))
292        self.assertEqual(rpi.limit_denominator(112), F(333, 106))
293        self.assertEqual(F(201, 200).limit_denominator(100), F(1))
294        self.assertEqual(F(201, 200).limit_denominator(101), F(102, 101))
295        self.assertEqual(F(0).limit_denominator(10000), F(0))
296        for i in (0, -1):
297            self.assertRaisesMessage(
298                ValueError, "max_denominator should be at least 1",
299                F(1).limit_denominator, i)
300
301    def testConversions(self):
302        self.assertTypedEquals(-1, math.trunc(F(-11, 10)))
303        self.assertTypedEquals(1, math.trunc(F(11, 10)))
304        self.assertTypedEquals(-2, math.floor(F(-11, 10)))
305        self.assertTypedEquals(-1, math.ceil(F(-11, 10)))
306        self.assertTypedEquals(-1, math.ceil(F(-10, 10)))
307        self.assertTypedEquals(-1, int(F(-11, 10)))
308        self.assertTypedEquals(0, round(F(-1, 10)))
309        self.assertTypedEquals(0, round(F(-5, 10)))
310        self.assertTypedEquals(-2, round(F(-15, 10)))
311        self.assertTypedEquals(-1, round(F(-7, 10)))
312
313        self.assertEqual(False, bool(F(0, 1)))
314        self.assertEqual(True, bool(F(3, 2)))
315        self.assertTypedEquals(0.1, float(F(1, 10)))
316
317        # Check that __float__ isn't implemented by converting the
318        # numerator and denominator to float before dividing.
319        self.assertRaises(OverflowError, float, int('2'*400+'7'))
320        self.assertAlmostEqual(2.0/3,
321                               float(F(int('2'*400+'7'), int('3'*400+'1'))))
322
323        self.assertTypedEquals(0.1+0j, complex(F(1,10)))
324
325    def testBoolGuarateesBoolReturn(self):
326        # Ensure that __bool__ is used on numerator which guarantees a bool
327        # return.  See also bpo-39274.
328        @functools.total_ordering
329        class CustomValue:
330            denominator = 1
331
332            def __init__(self, value):
333                self.value = value
334
335            def __bool__(self):
336                return bool(self.value)
337
338            @property
339            def numerator(self):
340                # required to preserve `self` during instantiation
341                return self
342
343            def __eq__(self, other):
344                raise AssertionError("Avoid comparisons in Fraction.__bool__")
345
346            __lt__ = __eq__
347
348        # We did not implement all abstract methods, so register:
349        numbers.Rational.register(CustomValue)
350
351        numerator = CustomValue(1)
352        r = F(numerator)
353        # ensure the numerator was not lost during instantiation:
354        self.assertIs(r.numerator, numerator)
355        self.assertIs(bool(r), True)
356
357        numerator = CustomValue(0)
358        r = F(numerator)
359        self.assertIs(bool(r), False)
360
361    def testRound(self):
362        self.assertTypedEquals(F(-200), round(F(-150), -2))
363        self.assertTypedEquals(F(-200), round(F(-250), -2))
364        self.assertTypedEquals(F(30), round(F(26), -1))
365        self.assertTypedEquals(F(-2, 10), round(F(-15, 100), 1))
366        self.assertTypedEquals(F(-2, 10), round(F(-25, 100), 1))
367
368    def testArithmetic(self):
369        self.assertEqual(F(1, 2), F(1, 10) + F(2, 5))
370        self.assertEqual(F(-3, 10), F(1, 10) - F(2, 5))
371        self.assertEqual(F(1, 25), F(1, 10) * F(2, 5))
372        self.assertEqual(F(1, 4), F(1, 10) / F(2, 5))
373        self.assertTypedEquals(2, F(9, 10) // F(2, 5))
374        self.assertTypedEquals(10**23, F(10**23, 1) // F(1))
375        self.assertEqual(F(5, 6), F(7, 3) % F(3, 2))
376        self.assertEqual(F(2, 3), F(-7, 3) % F(3, 2))
377        self.assertEqual((F(1), F(5, 6)), divmod(F(7, 3), F(3, 2)))
378        self.assertEqual((F(-2), F(2, 3)), divmod(F(-7, 3), F(3, 2)))
379        self.assertEqual(F(8, 27), F(2, 3) ** F(3))
380        self.assertEqual(F(27, 8), F(2, 3) ** F(-3))
381        self.assertTypedEquals(2.0, F(4) ** F(1, 2))
382        self.assertEqual(F(1, 1), +F(1, 1))
383        z = pow(F(-1), F(1, 2))
384        self.assertAlmostEqual(z.real, 0)
385        self.assertEqual(z.imag, 1)
386        # Regression test for #27539.
387        p = F(-1, 2) ** 0
388        self.assertEqual(p, F(1, 1))
389        self.assertEqual(p.numerator, 1)
390        self.assertEqual(p.denominator, 1)
391        p = F(-1, 2) ** -1
392        self.assertEqual(p, F(-2, 1))
393        self.assertEqual(p.numerator, -2)
394        self.assertEqual(p.denominator, 1)
395        p = F(-1, 2) ** -2
396        self.assertEqual(p, F(4, 1))
397        self.assertEqual(p.numerator, 4)
398        self.assertEqual(p.denominator, 1)
399
400    def testLargeArithmetic(self):
401        self.assertTypedEquals(
402            F(10101010100808080808080808101010101010000000000000000,
403              1010101010101010101010101011111111101010101010101010101010101),
404            F(10**35+1, 10**27+1) % F(10**27+1, 10**35-1)
405        )
406        self.assertTypedEquals(
407            F(7, 1901475900342344102245054808064),
408            F(-2**100, 3) % F(5, 2**100)
409        )
410        self.assertTypedTupleEquals(
411            (9999999999999999,
412             F(10101010100808080808080808101010101010000000000000000,
413               1010101010101010101010101011111111101010101010101010101010101)),
414            divmod(F(10**35+1, 10**27+1), F(10**27+1, 10**35-1))
415        )
416        self.assertTypedEquals(
417            -2 ** 200 // 15,
418            F(-2**100, 3) // F(5, 2**100)
419        )
420        self.assertTypedEquals(
421            1,
422            F(5, 2**100) // F(3, 2**100)
423        )
424        self.assertTypedEquals(
425            (1, F(2, 2**100)),
426            divmod(F(5, 2**100), F(3, 2**100))
427        )
428        self.assertTypedTupleEquals(
429            (-2 ** 200 // 15,
430             F(7, 1901475900342344102245054808064)),
431            divmod(F(-2**100, 3), F(5, 2**100))
432        )
433
434    def testMixedArithmetic(self):
435        self.assertTypedEquals(F(11, 10), F(1, 10) + 1)
436        self.assertTypedEquals(1.1, F(1, 10) + 1.0)
437        self.assertTypedEquals(1.1 + 0j, F(1, 10) + (1.0 + 0j))
438        self.assertTypedEquals(F(11, 10), 1 + F(1, 10))
439        self.assertTypedEquals(1.1, 1.0 + F(1, 10))
440        self.assertTypedEquals(1.1 + 0j, (1.0 + 0j) + F(1, 10))
441
442        self.assertTypedEquals(F(-9, 10), F(1, 10) - 1)
443        self.assertTypedEquals(-0.9, F(1, 10) - 1.0)
444        self.assertTypedEquals(-0.9 + 0j, F(1, 10) - (1.0 + 0j))
445        self.assertTypedEquals(F(9, 10), 1 - F(1, 10))
446        self.assertTypedEquals(0.9, 1.0 - F(1, 10))
447        self.assertTypedEquals(0.9 + 0j, (1.0 + 0j) - F(1, 10))
448
449        self.assertTypedEquals(F(1, 10), F(1, 10) * 1)
450        self.assertTypedEquals(0.1, F(1, 10) * 1.0)
451        self.assertTypedEquals(0.1 + 0j, F(1, 10) * (1.0 + 0j))
452        self.assertTypedEquals(F(1, 10), 1 * F(1, 10))
453        self.assertTypedEquals(0.1, 1.0 * F(1, 10))
454        self.assertTypedEquals(0.1 + 0j, (1.0 + 0j) * F(1, 10))
455
456        self.assertTypedEquals(F(1, 10), F(1, 10) / 1)
457        self.assertTypedEquals(0.1, F(1, 10) / 1.0)
458        self.assertTypedEquals(0.1 + 0j, F(1, 10) / (1.0 + 0j))
459        self.assertTypedEquals(F(10, 1), 1 / F(1, 10))
460        self.assertTypedEquals(10.0, 1.0 / F(1, 10))
461        self.assertTypedEquals(10.0 + 0j, (1.0 + 0j) / F(1, 10))
462
463        self.assertTypedEquals(0, F(1, 10) // 1)
464        self.assertTypedEquals(0.0, F(1, 10) // 1.0)
465        self.assertTypedEquals(10, 1 // F(1, 10))
466        self.assertTypedEquals(10**23, 10**22 // F(1, 10))
467        self.assertTypedEquals(1.0 // 0.1, 1.0 // F(1, 10))
468
469        self.assertTypedEquals(F(1, 10), F(1, 10) % 1)
470        self.assertTypedEquals(0.1, F(1, 10) % 1.0)
471        self.assertTypedEquals(F(0, 1), 1 % F(1, 10))
472        self.assertTypedEquals(1.0 % 0.1, 1.0 % F(1, 10))
473        self.assertTypedEquals(0.1, F(1, 10) % float('inf'))
474        self.assertTypedEquals(float('-inf'), F(1, 10) % float('-inf'))
475        self.assertTypedEquals(float('inf'), F(-1, 10) % float('inf'))
476        self.assertTypedEquals(-0.1, F(-1, 10) % float('-inf'))
477
478        self.assertTypedTupleEquals((0, F(1, 10)), divmod(F(1, 10), 1))
479        self.assertTypedTupleEquals(divmod(0.1, 1.0), divmod(F(1, 10), 1.0))
480        self.assertTypedTupleEquals((10, F(0)), divmod(1, F(1, 10)))
481        self.assertTypedTupleEquals(divmod(1.0, 0.1), divmod(1.0, F(1, 10)))
482        self.assertTypedTupleEquals(divmod(0.1, float('inf')), divmod(F(1, 10), float('inf')))
483        self.assertTypedTupleEquals(divmod(0.1, float('-inf')), divmod(F(1, 10), float('-inf')))
484        self.assertTypedTupleEquals(divmod(-0.1, float('inf')), divmod(F(-1, 10), float('inf')))
485        self.assertTypedTupleEquals(divmod(-0.1, float('-inf')), divmod(F(-1, 10), float('-inf')))
486
487        # ** has more interesting conversion rules.
488        self.assertTypedEquals(F(100, 1), F(1, 10) ** -2)
489        self.assertTypedEquals(F(100, 1), F(10, 1) ** 2)
490        self.assertTypedEquals(0.1, F(1, 10) ** 1.0)
491        self.assertTypedEquals(0.1 + 0j, F(1, 10) ** (1.0 + 0j))
492        self.assertTypedEquals(4 , 2 ** F(2, 1))
493        z = pow(-1, F(1, 2))
494        self.assertAlmostEqual(0, z.real)
495        self.assertEqual(1, z.imag)
496        self.assertTypedEquals(F(1, 4) , 2 ** F(-2, 1))
497        self.assertTypedEquals(2.0 , 4 ** F(1, 2))
498        self.assertTypedEquals(0.25, 2.0 ** F(-2, 1))
499        self.assertTypedEquals(1.0 + 0j, (1.0 + 0j) ** F(1, 10))
500        self.assertRaises(ZeroDivisionError, operator.pow,
501                          F(0, 1), -2)
502
503    def testMixingWithDecimal(self):
504        # Decimal refuses mixed arithmetic (but not mixed comparisons)
505        self.assertRaises(TypeError, operator.add,
506                          F(3,11), Decimal('3.1415926'))
507        self.assertRaises(TypeError, operator.add,
508                          Decimal('3.1415926'), F(3,11))
509
510    def testComparisons(self):
511        self.assertTrue(F(1, 2) < F(2, 3))
512        self.assertFalse(F(1, 2) < F(1, 2))
513        self.assertTrue(F(1, 2) <= F(2, 3))
514        self.assertTrue(F(1, 2) <= F(1, 2))
515        self.assertFalse(F(2, 3) <= F(1, 2))
516        self.assertTrue(F(1, 2) == F(1, 2))
517        self.assertFalse(F(1, 2) == F(1, 3))
518        self.assertFalse(F(1, 2) != F(1, 2))
519        self.assertTrue(F(1, 2) != F(1, 3))
520
521    def testComparisonsDummyRational(self):
522        self.assertTrue(F(1, 2) == DummyRational(1, 2))
523        self.assertTrue(DummyRational(1, 2) == F(1, 2))
524        self.assertFalse(F(1, 2) == DummyRational(3, 4))
525        self.assertFalse(DummyRational(3, 4) == F(1, 2))
526
527        self.assertTrue(F(1, 2) < DummyRational(3, 4))
528        self.assertFalse(F(1, 2) < DummyRational(1, 2))
529        self.assertFalse(F(1, 2) < DummyRational(1, 7))
530        self.assertFalse(F(1, 2) > DummyRational(3, 4))
531        self.assertFalse(F(1, 2) > DummyRational(1, 2))
532        self.assertTrue(F(1, 2) > DummyRational(1, 7))
533        self.assertTrue(F(1, 2) <= DummyRational(3, 4))
534        self.assertTrue(F(1, 2) <= DummyRational(1, 2))
535        self.assertFalse(F(1, 2) <= DummyRational(1, 7))
536        self.assertFalse(F(1, 2) >= DummyRational(3, 4))
537        self.assertTrue(F(1, 2) >= DummyRational(1, 2))
538        self.assertTrue(F(1, 2) >= DummyRational(1, 7))
539
540        self.assertTrue(DummyRational(1, 2) < F(3, 4))
541        self.assertFalse(DummyRational(1, 2) < F(1, 2))
542        self.assertFalse(DummyRational(1, 2) < F(1, 7))
543        self.assertFalse(DummyRational(1, 2) > F(3, 4))
544        self.assertFalse(DummyRational(1, 2) > F(1, 2))
545        self.assertTrue(DummyRational(1, 2) > F(1, 7))
546        self.assertTrue(DummyRational(1, 2) <= F(3, 4))
547        self.assertTrue(DummyRational(1, 2) <= F(1, 2))
548        self.assertFalse(DummyRational(1, 2) <= F(1, 7))
549        self.assertFalse(DummyRational(1, 2) >= F(3, 4))
550        self.assertTrue(DummyRational(1, 2) >= F(1, 2))
551        self.assertTrue(DummyRational(1, 2) >= F(1, 7))
552
553    def testComparisonsDummyFloat(self):
554        x = DummyFloat(1./3.)
555        y = F(1, 3)
556        self.assertTrue(x != y)
557        self.assertTrue(x < y or x > y)
558        self.assertFalse(x == y)
559        self.assertFalse(x <= y and x >= y)
560        self.assertTrue(y != x)
561        self.assertTrue(y < x or y > x)
562        self.assertFalse(y == x)
563        self.assertFalse(y <= x and y >= x)
564
565    def testMixedLess(self):
566        self.assertTrue(2 < F(5, 2))
567        self.assertFalse(2 < F(4, 2))
568        self.assertTrue(F(5, 2) < 3)
569        self.assertFalse(F(4, 2) < 2)
570
571        self.assertTrue(F(1, 2) < 0.6)
572        self.assertFalse(F(1, 2) < 0.4)
573        self.assertTrue(0.4 < F(1, 2))
574        self.assertFalse(0.5 < F(1, 2))
575
576        self.assertFalse(float('inf') < F(1, 2))
577        self.assertTrue(float('-inf') < F(0, 10))
578        self.assertFalse(float('nan') < F(-3, 7))
579        self.assertTrue(F(1, 2) < float('inf'))
580        self.assertFalse(F(17, 12) < float('-inf'))
581        self.assertFalse(F(144, -89) < float('nan'))
582
583    def testMixedLessEqual(self):
584        self.assertTrue(0.5 <= F(1, 2))
585        self.assertFalse(0.6 <= F(1, 2))
586        self.assertTrue(F(1, 2) <= 0.5)
587        self.assertFalse(F(1, 2) <= 0.4)
588        self.assertTrue(2 <= F(4, 2))
589        self.assertFalse(2 <= F(3, 2))
590        self.assertTrue(F(4, 2) <= 2)
591        self.assertFalse(F(5, 2) <= 2)
592
593        self.assertFalse(float('inf') <= F(1, 2))
594        self.assertTrue(float('-inf') <= F(0, 10))
595        self.assertFalse(float('nan') <= F(-3, 7))
596        self.assertTrue(F(1, 2) <= float('inf'))
597        self.assertFalse(F(17, 12) <= float('-inf'))
598        self.assertFalse(F(144, -89) <= float('nan'))
599
600    def testBigFloatComparisons(self):
601        # Because 10**23 can't be represented exactly as a float:
602        self.assertFalse(F(10**23) == float(10**23))
603        # The first test demonstrates why these are important.
604        self.assertFalse(1e23 < float(F(math.trunc(1e23) + 1)))
605        self.assertTrue(1e23 < F(math.trunc(1e23) + 1))
606        self.assertFalse(1e23 <= F(math.trunc(1e23) - 1))
607        self.assertTrue(1e23 > F(math.trunc(1e23) - 1))
608        self.assertFalse(1e23 >= F(math.trunc(1e23) + 1))
609
610    def testBigComplexComparisons(self):
611        self.assertFalse(F(10**23) == complex(10**23))
612        self.assertRaises(TypeError, operator.gt, F(10**23), complex(10**23))
613        self.assertRaises(TypeError, operator.le, F(10**23), complex(10**23))
614
615        x = F(3, 8)
616        z = complex(0.375, 0.0)
617        w = complex(0.375, 0.2)
618        self.assertTrue(x == z)
619        self.assertFalse(x != z)
620        self.assertFalse(x == w)
621        self.assertTrue(x != w)
622        for op in operator.lt, operator.le, operator.gt, operator.ge:
623            self.assertRaises(TypeError, op, x, z)
624            self.assertRaises(TypeError, op, z, x)
625            self.assertRaises(TypeError, op, x, w)
626            self.assertRaises(TypeError, op, w, x)
627
628    def testMixedEqual(self):
629        self.assertTrue(0.5 == F(1, 2))
630        self.assertFalse(0.6 == F(1, 2))
631        self.assertTrue(F(1, 2) == 0.5)
632        self.assertFalse(F(1, 2) == 0.4)
633        self.assertTrue(2 == F(4, 2))
634        self.assertFalse(2 == F(3, 2))
635        self.assertTrue(F(4, 2) == 2)
636        self.assertFalse(F(5, 2) == 2)
637        self.assertFalse(F(5, 2) == float('nan'))
638        self.assertFalse(float('nan') == F(3, 7))
639        self.assertFalse(F(5, 2) == float('inf'))
640        self.assertFalse(float('-inf') == F(2, 5))
641
642    def testStringification(self):
643        self.assertEqual("Fraction(7, 3)", repr(F(7, 3)))
644        self.assertEqual("Fraction(6283185307, 2000000000)",
645                         repr(F('3.1415926535')))
646        self.assertEqual("Fraction(-1, 100000000000000000000)",
647                         repr(F(1, -10**20)))
648        self.assertEqual("7/3", str(F(7, 3)))
649        self.assertEqual("7", str(F(7, 1)))
650
651    def testHash(self):
652        hmod = sys.hash_info.modulus
653        hinf = sys.hash_info.inf
654        self.assertEqual(hash(2.5), hash(F(5, 2)))
655        self.assertEqual(hash(10**50), hash(F(10**50)))
656        self.assertNotEqual(hash(float(10**23)), hash(F(10**23)))
657        self.assertEqual(hinf, hash(F(1, hmod)))
658        # Check that __hash__ produces the same value as hash(), for
659        # consistency with int and Decimal.  (See issue #10356.)
660        self.assertEqual(hash(F(-1)), F(-1).__hash__())
661
662    def testApproximatePi(self):
663        # Algorithm borrowed from
664        # http://docs.python.org/lib/decimal-recipes.html
665        three = F(3)
666        lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
667        while abs(s - lasts) > F(1, 10**9):
668            lasts = s
669            n, na = n+na, na+8
670            d, da = d+da, da+32
671            t = (t * n) / d
672            s += t
673        self.assertAlmostEqual(math.pi, s)
674
675    def testApproximateCos1(self):
676        # Algorithm borrowed from
677        # http://docs.python.org/lib/decimal-recipes.html
678        x = F(1)
679        i, lasts, s, fact, num, sign = 0, 0, F(1), 1, 1, 1
680        while abs(s - lasts) > F(1, 10**9):
681            lasts = s
682            i += 2
683            fact *= i * (i-1)
684            num *= x * x
685            sign *= -1
686            s += num / fact * sign
687        self.assertAlmostEqual(math.cos(1), s)
688
689    def test_copy_deepcopy_pickle(self):
690        r = F(13, 7)
691        dr = DummyFraction(13, 7)
692        self.assertEqual(r, loads(dumps(r)))
693        self.assertEqual(id(r), id(copy(r)))
694        self.assertEqual(id(r), id(deepcopy(r)))
695        self.assertNotEqual(id(dr), id(copy(dr)))
696        self.assertNotEqual(id(dr), id(deepcopy(dr)))
697        self.assertTypedEquals(dr, copy(dr))
698        self.assertTypedEquals(dr, deepcopy(dr))
699
700    def test_slots(self):
701        # Issue 4998
702        r = F(13, 7)
703        self.assertRaises(AttributeError, setattr, r, 'a', 10)
704
705    def test_int_subclass(self):
706        class myint(int):
707            def __mul__(self, other):
708                return type(self)(int(self) * int(other))
709            def __floordiv__(self, other):
710                return type(self)(int(self) // int(other))
711            def __mod__(self, other):
712                x = type(self)(int(self) % int(other))
713                return x
714            @property
715            def numerator(self):
716                return type(self)(int(self))
717            @property
718            def denominator(self):
719                return type(self)(1)
720
721        f = fractions.Fraction(myint(1 * 3), myint(2 * 3))
722        self.assertEqual(f.numerator, 1)
723        self.assertEqual(f.denominator, 2)
724        self.assertEqual(type(f.numerator), myint)
725        self.assertEqual(type(f.denominator), myint)
726
727
728if __name__ == '__main__':
729    unittest.main()
730