blob: c748533c7912981f5e997690de49ac37d7327149 [file] [log] [blame]
Christian Heimes3feef612008-02-11 06:19:17 +00001"""Tests for Lib/fractions.py."""
Guido van Rossum7736b5b2008-01-15 21:44:53 +00002
3from decimal import Decimal
Zachary Ware38c707e2015-04-13 15:00:43 -05004from test.support import requires_IEEE_754
Guido van Rossum7736b5b2008-01-15 21:44:53 +00005import math
Mark Dickinson85424c92009-07-18 14:41:42 +00006import numbers
Guido van Rossum7736b5b2008-01-15 21:44:53 +00007import operator
Christian Heimes3feef612008-02-11 06:19:17 +00008import fractions
Sebastian Berg427c84f2020-02-06 06:54:05 -08009import functools
Ezio Melotti682d3742012-02-29 14:05:53 +020010import sys
Guido van Rossum7736b5b2008-01-15 21:44:53 +000011import unittest
Serhiy Storchaka48e47aa2015-05-13 00:19:51 +030012import warnings
Christian Heimes969fe572008-01-25 11:23:10 +000013from copy import copy, deepcopy
Neal Norwitz6ff93fe2008-01-26 21:52:30 +000014from pickle import dumps, loads
Christian Heimes68f5fbe2008-02-14 08:27:37 +000015F = fractions.Fraction
Victor Stinner4691a2f2020-01-16 11:02:51 +010016
Christian Heimesaf98da12008-01-27 15:18:18 +000017
Mark Dickinson85424c92009-07-18 14:41:42 +000018class DummyFloat(object):
19 """Dummy float class for testing comparisons with Fractions"""
20
21 def __init__(self, value):
22 if not isinstance(value, float):
23 raise TypeError("DummyFloat can only be initialized from float")
24 self.value = value
25
26 def _richcmp(self, other, op):
27 if isinstance(other, numbers.Rational):
28 return op(F.from_float(self.value), other)
29 elif isinstance(other, DummyFloat):
30 return op(self.value, other.value)
31 else:
32 return NotImplemented
33
34 def __eq__(self, other): return self._richcmp(other, operator.eq)
35 def __le__(self, other): return self._richcmp(other, operator.le)
36 def __lt__(self, other): return self._richcmp(other, operator.lt)
37 def __ge__(self, other): return self._richcmp(other, operator.ge)
38 def __gt__(self, other): return self._richcmp(other, operator.gt)
39
40 # shouldn't be calling __float__ at all when doing comparisons
41 def __float__(self):
42 assert False, "__float__ should not be invoked for comparisons"
43
44 # same goes for subtraction
45 def __sub__(self, other):
46 assert False, "__sub__ should not be invoked for comparisons"
47 __rsub__ = __sub__
48
49
50class DummyRational(object):
51 """Test comparison of Fraction with a naive rational implementation."""
52
53 def __init__(self, num, den):
Serhiy Storchaka48e47aa2015-05-13 00:19:51 +030054 g = math.gcd(num, den)
Mark Dickinson85424c92009-07-18 14:41:42 +000055 self.num = num // g
56 self.den = den // g
57
58 def __eq__(self, other):
59 if isinstance(other, fractions.Fraction):
60 return (self.num == other._numerator and
61 self.den == other._denominator)
62 else:
63 return NotImplemented
64
65 def __lt__(self, other):
66 return(self.num * other._denominator < self.den * other._numerator)
67
68 def __gt__(self, other):
69 return(self.num * other._denominator > self.den * other._numerator)
70
71 def __le__(self, other):
72 return(self.num * other._denominator <= self.den * other._numerator)
73
74 def __ge__(self, other):
75 return(self.num * other._denominator >= self.den * other._numerator)
76
77 # this class is for testing comparisons; conversion to float
78 # should never be used for a comparison, since it loses accuracy
79 def __float__(self):
80 assert False, "__float__ should not be invoked"
Christian Heimesaf98da12008-01-27 15:18:18 +000081
Ezio Melotti682d3742012-02-29 14:05:53 +020082class DummyFraction(fractions.Fraction):
83 """Dummy Fraction subclass for copy and deepcopy testing."""
84
Guido van Rossum7736b5b2008-01-15 21:44:53 +000085
86def _components(r):
87 return (r.numerator, r.denominator)
88
Christian Heimesaf98da12008-01-27 15:18:18 +000089
Christian Heimes3feef612008-02-11 06:19:17 +000090class FractionTest(unittest.TestCase):
Guido van Rossum7736b5b2008-01-15 21:44:53 +000091
92 def assertTypedEquals(self, expected, actual):
93 """Asserts that both the types and values are the same."""
Ezio Melottib3aedd42010-11-20 19:04:17 +000094 self.assertEqual(type(expected), type(actual))
95 self.assertEqual(expected, actual)
Guido van Rossum7736b5b2008-01-15 21:44:53 +000096
Stefan Behnel3a374e02019-01-02 13:22:06 +010097 def assertTypedTupleEquals(self, expected, actual):
98 """Asserts that both the types and values in the tuples are the same."""
99 self.assertTupleEqual(expected, actual)
100 self.assertListEqual(list(map(type, expected)), list(map(type, actual)))
101
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000102 def assertRaisesMessage(self, exc_type, message,
103 callable, *args, **kwargs):
104 """Asserts that callable(*args, **kwargs) raises exc_type(message)."""
105 try:
106 callable(*args, **kwargs)
107 except exc_type as e:
Ezio Melottib3aedd42010-11-20 19:04:17 +0000108 self.assertEqual(message, str(e))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000109 else:
110 self.fail("%s not raised" % exc_type.__name__)
111
112 def testInit(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000113 self.assertEqual((0, 1), _components(F()))
114 self.assertEqual((7, 1), _components(F(7)))
115 self.assertEqual((7, 3), _components(F(F(7, 3))))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000116
Ezio Melottib3aedd42010-11-20 19:04:17 +0000117 self.assertEqual((-1, 1), _components(F(-1, 1)))
118 self.assertEqual((-1, 1), _components(F(1, -1)))
119 self.assertEqual((1, 1), _components(F(-2, -2)))
120 self.assertEqual((1, 2), _components(F(5, 10)))
121 self.assertEqual((7, 15), _components(F(7, 15)))
122 self.assertEqual((10**23, 1), _components(F(10**23)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000123
Ezio Melottib3aedd42010-11-20 19:04:17 +0000124 self.assertEqual((3, 77), _components(F(F(3, 7), 11)))
125 self.assertEqual((-9, 5), _components(F(2, F(-10, 9))))
126 self.assertEqual((2486, 2485), _components(F(F(22, 7), F(355, 113))))
Mark Dickinsond4d95f82009-04-24 14:06:19 +0000127
Christian Heimes3feef612008-02-11 06:19:17 +0000128 self.assertRaisesMessage(ZeroDivisionError, "Fraction(12, 0)",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000129 F, 12, 0)
Georg Brandl86b2fb92008-07-16 03:43:04 +0000130 self.assertRaises(TypeError, F, 1.5 + 3j)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000131
Georg Brandl86b2fb92008-07-16 03:43:04 +0000132 self.assertRaises(TypeError, F, "3/2", 3)
Mark Dickinsond4d95f82009-04-24 14:06:19 +0000133 self.assertRaises(TypeError, F, 3, 0j)
134 self.assertRaises(TypeError, F, 3, 1j)
Mark Dickinson7caf9082016-08-23 16:16:52 +0100135 self.assertRaises(TypeError, F, 1, 2, 3)
Mark Dickinsond4d95f82009-04-24 14:06:19 +0000136
Mark Dickinson98127c32010-04-03 11:18:52 +0000137 @requires_IEEE_754
138 def testInitFromFloat(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000139 self.assertEqual((5, 2), _components(F(2.5)))
140 self.assertEqual((0, 1), _components(F(-0.0)))
141 self.assertEqual((3602879701896397, 36028797018963968),
142 _components(F(0.1)))
Mark Dickinson73726aa2012-11-15 20:58:40 +0000143 # bug 16469: error types should be consistent with float -> int
144 self.assertRaises(ValueError, F, float('nan'))
145 self.assertRaises(OverflowError, F, float('inf'))
146 self.assertRaises(OverflowError, F, float('-inf'))
Mark Dickinson98127c32010-04-03 11:18:52 +0000147
148 def testInitFromDecimal(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000149 self.assertEqual((11, 10),
150 _components(F(Decimal('1.1'))))
151 self.assertEqual((7, 200),
152 _components(F(Decimal('3.5e-2'))))
153 self.assertEqual((0, 1),
154 _components(F(Decimal('.000e20'))))
Mark Dickinson73726aa2012-11-15 20:58:40 +0000155 # bug 16469: error types should be consistent with decimal -> int
156 self.assertRaises(ValueError, F, Decimal('nan'))
157 self.assertRaises(ValueError, F, Decimal('snan'))
158 self.assertRaises(OverflowError, F, Decimal('inf'))
159 self.assertRaises(OverflowError, F, Decimal('-inf'))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000160
161 def testFromString(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000162 self.assertEqual((5, 1), _components(F("5")))
163 self.assertEqual((3, 2), _components(F("3/2")))
164 self.assertEqual((3, 2), _components(F(" \n +3/2")))
165 self.assertEqual((-3, 2), _components(F("-3/2 ")))
166 self.assertEqual((13, 2), _components(F(" 013/02 \n ")))
167 self.assertEqual((16, 5), _components(F(" 3.2 ")))
168 self.assertEqual((-16, 5), _components(F(" -3.2 ")))
169 self.assertEqual((-3, 1), _components(F(" -3. ")))
170 self.assertEqual((3, 5), _components(F(" .6 ")))
171 self.assertEqual((1, 3125), _components(F("32.e-5")))
172 self.assertEqual((1000000, 1), _components(F("1E+06")))
173 self.assertEqual((-12300, 1), _components(F("-1.23e4")))
174 self.assertEqual((0, 1), _components(F(" .0e+0\t")))
175 self.assertEqual((0, 1), _components(F("-0.000e0")))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000176
177 self.assertRaisesMessage(
Christian Heimes3feef612008-02-11 06:19:17 +0000178 ZeroDivisionError, "Fraction(3, 0)",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000179 F, "3/0")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000180 self.assertRaisesMessage(
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000181 ValueError, "Invalid literal for Fraction: '3/'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000182 F, "3/")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000183 self.assertRaisesMessage(
Mark Dickinsoncf63f2f2009-04-22 17:50:21 +0000184 ValueError, "Invalid literal for Fraction: '/2'",
185 F, "/2")
186 self.assertRaisesMessage(
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000187 ValueError, "Invalid literal for Fraction: '3 /2'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000188 F, "3 /2")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000189 self.assertRaisesMessage(
190 # Denominators don't need a sign.
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000191 ValueError, "Invalid literal for Fraction: '3/+2'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000192 F, "3/+2")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000193 self.assertRaisesMessage(
194 # Imitate float's parsing.
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000195 ValueError, "Invalid literal for Fraction: '+ 3/2'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000196 F, "+ 3/2")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000197 self.assertRaisesMessage(
Christian Heimesaf98da12008-01-27 15:18:18 +0000198 # Avoid treating '.' as a regex special character.
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000199 ValueError, "Invalid literal for Fraction: '3a2'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000200 F, "3a2")
Christian Heimesaf98da12008-01-27 15:18:18 +0000201 self.assertRaisesMessage(
Christian Heimesaf98da12008-01-27 15:18:18 +0000202 # Don't accept combinations of decimals and rationals.
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000203 ValueError, "Invalid literal for Fraction: '3/7.2'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000204 F, "3/7.2")
Christian Heimesaf98da12008-01-27 15:18:18 +0000205 self.assertRaisesMessage(
206 # Don't accept combinations of decimals and rationals.
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000207 ValueError, "Invalid literal for Fraction: '3.2/7'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000208 F, "3.2/7")
Christian Heimes292d3512008-02-03 16:51:08 +0000209 self.assertRaisesMessage(
210 # Allow 3. and .3, but not .
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000211 ValueError, "Invalid literal for Fraction: '.'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000212 F, ".")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000213
214 def testImmutable(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000215 r = F(7, 3)
Christian Heimes587c2bf2008-01-19 16:21:02 +0000216 r.__init__(2, 15)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000217 self.assertEqual((7, 3), _components(r))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000218
Christian Heimes400adb02008-02-01 08:12:03 +0000219 self.assertRaises(AttributeError, setattr, r, 'numerator', 12)
220 self.assertRaises(AttributeError, setattr, r, 'denominator', 6)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000221 self.assertEqual((7, 3), _components(r))
Christian Heimes400adb02008-02-01 08:12:03 +0000222
223 # But if you _really_ need to:
224 r._numerator = 4
225 r._denominator = 2
Ezio Melottib3aedd42010-11-20 19:04:17 +0000226 self.assertEqual((4, 2), _components(r))
Christian Heimes400adb02008-02-01 08:12:03 +0000227 # Which breaks some important operations:
Ezio Melottib3aedd42010-11-20 19:04:17 +0000228 self.assertNotEqual(F(4, 2), r)
Christian Heimes400adb02008-02-01 08:12:03 +0000229
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000230 def testFromFloat(self):
Georg Brandl2ee470f2008-07-16 12:55:28 +0000231 self.assertRaises(TypeError, F.from_float, 3+4j)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000232 self.assertEqual((10, 1), _components(F.from_float(10)))
Georg Brandl3a9b0622009-01-03 22:07:57 +0000233 bigint = 1234567890123456789
Ezio Melottib3aedd42010-11-20 19:04:17 +0000234 self.assertEqual((bigint, 1), _components(F.from_float(bigint)))
235 self.assertEqual((0, 1), _components(F.from_float(-0.0)))
236 self.assertEqual((10, 1), _components(F.from_float(10.0)))
237 self.assertEqual((-5, 2), _components(F.from_float(-2.5)))
238 self.assertEqual((99999999999999991611392, 1),
239 _components(F.from_float(1e23)))
240 self.assertEqual(float(10**23), float(F.from_float(1e23)))
241 self.assertEqual((3602879701896397, 1125899906842624),
242 _components(F.from_float(3.2)))
243 self.assertEqual(3.2, float(F.from_float(3.2)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000244
245 inf = 1e1000
246 nan = inf - inf
Mark Dickinson73726aa2012-11-15 20:58:40 +0000247 # bug 16469: error types should be consistent with float -> int
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000248 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200249 OverflowError, "cannot convert Infinity to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000250 F.from_float, inf)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000251 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200252 OverflowError, "cannot convert Infinity to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000253 F.from_float, -inf)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000254 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200255 ValueError, "cannot convert NaN to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000256 F.from_float, nan)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000257
Christian Heimes587c2bf2008-01-19 16:21:02 +0000258 def testFromDecimal(self):
Georg Brandl2ee470f2008-07-16 12:55:28 +0000259 self.assertRaises(TypeError, F.from_decimal, 3+4j)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000260 self.assertEqual(F(10, 1), F.from_decimal(10))
261 self.assertEqual(F(0), F.from_decimal(Decimal("-0")))
262 self.assertEqual(F(5, 10), F.from_decimal(Decimal("0.5")))
263 self.assertEqual(F(5, 1000), F.from_decimal(Decimal("5e-3")))
264 self.assertEqual(F(5000), F.from_decimal(Decimal("5e3")))
265 self.assertEqual(1 - F(1, 10**30),
266 F.from_decimal(Decimal("0." + "9" * 30)))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000267
Mark Dickinson73726aa2012-11-15 20:58:40 +0000268 # bug 16469: error types should be consistent with decimal -> int
Christian Heimes587c2bf2008-01-19 16:21:02 +0000269 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200270 OverflowError, "cannot convert Infinity to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000271 F.from_decimal, Decimal("inf"))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000272 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200273 OverflowError, "cannot convert Infinity to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000274 F.from_decimal, Decimal("-inf"))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000275 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200276 ValueError, "cannot convert NaN to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000277 F.from_decimal, Decimal("nan"))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000278 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200279 ValueError, "cannot convert NaN to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000280 F.from_decimal, Decimal("snan"))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000281
Raymond Hettingerf03b4c82019-08-11 14:40:59 -0700282 def test_as_integer_ratio(self):
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(4, -6).as_integer_ratio(), (-2, 3))
286 self.assertEqual(F(0, 6).as_integer_ratio(), (0, 1))
287
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000288 def testLimitDenominator(self):
289 rpi = F('3.1415926535897932')
290 self.assertEqual(rpi.limit_denominator(10000), F(355, 113))
291 self.assertEqual(-rpi.limit_denominator(10000), F(-355, 113))
292 self.assertEqual(rpi.limit_denominator(113), F(355, 113))
293 self.assertEqual(rpi.limit_denominator(112), F(333, 106))
294 self.assertEqual(F(201, 200).limit_denominator(100), F(1))
295 self.assertEqual(F(201, 200).limit_denominator(101), F(102, 101))
296 self.assertEqual(F(0).limit_denominator(10000), F(0))
Ezio Melotti682d3742012-02-29 14:05:53 +0200297 for i in (0, -1):
298 self.assertRaisesMessage(
299 ValueError, "max_denominator should be at least 1",
300 F(1).limit_denominator, i)
Christian Heimesbbffeb62008-01-24 09:42:52 +0000301
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000302 def testConversions(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000303 self.assertTypedEquals(-1, math.trunc(F(-11, 10)))
Ezio Melotti682d3742012-02-29 14:05:53 +0200304 self.assertTypedEquals(1, math.trunc(F(11, 10)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000305 self.assertTypedEquals(-2, math.floor(F(-11, 10)))
306 self.assertTypedEquals(-1, math.ceil(F(-11, 10)))
307 self.assertTypedEquals(-1, math.ceil(F(-10, 10)))
308 self.assertTypedEquals(-1, int(F(-11, 10)))
309 self.assertTypedEquals(0, round(F(-1, 10)))
310 self.assertTypedEquals(0, round(F(-5, 10)))
311 self.assertTypedEquals(-2, round(F(-15, 10)))
312 self.assertTypedEquals(-1, round(F(-7, 10)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000313
Ezio Melottib3aedd42010-11-20 19:04:17 +0000314 self.assertEqual(False, bool(F(0, 1)))
315 self.assertEqual(True, bool(F(3, 2)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000316 self.assertTypedEquals(0.1, float(F(1, 10)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000317
318 # Check that __float__ isn't implemented by converting the
319 # numerator and denominator to float before dividing.
320 self.assertRaises(OverflowError, float, int('2'*400+'7'))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000321 self.assertAlmostEqual(2.0/3,
322 float(F(int('2'*400+'7'), int('3'*400+'1'))))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000323
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000324 self.assertTypedEquals(0.1+0j, complex(F(1,10)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000325
Sebastian Berg427c84f2020-02-06 06:54:05 -0800326 def testBoolGuarateesBoolReturn(self):
327 # Ensure that __bool__ is used on numerator which guarantees a bool
328 # return. See also bpo-39274.
329 @functools.total_ordering
330 class CustomValue:
331 denominator = 1
332
333 def __init__(self, value):
334 self.value = value
335
336 def __bool__(self):
337 return bool(self.value)
338
339 @property
340 def numerator(self):
341 # required to preserve `self` during instantiation
342 return self
343
344 def __eq__(self, other):
345 raise AssertionError("Avoid comparisons in Fraction.__bool__")
346
347 __lt__ = __eq__
348
349 # We did not implement all abstract methods, so register:
350 numbers.Rational.register(CustomValue)
351
352 numerator = CustomValue(1)
353 r = F(numerator)
354 # ensure the numerator was not lost during instantiation:
355 self.assertIs(r.numerator, numerator)
356 self.assertIs(bool(r), True)
357
358 numerator = CustomValue(0)
359 r = F(numerator)
360 self.assertIs(bool(r), False)
361
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000362 def testRound(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000363 self.assertTypedEquals(F(-200), round(F(-150), -2))
364 self.assertTypedEquals(F(-200), round(F(-250), -2))
365 self.assertTypedEquals(F(30), round(F(26), -1))
366 self.assertTypedEquals(F(-2, 10), round(F(-15, 100), 1))
367 self.assertTypedEquals(F(-2, 10), round(F(-25, 100), 1))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000368
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000369 def testArithmetic(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000370 self.assertEqual(F(1, 2), F(1, 10) + F(2, 5))
371 self.assertEqual(F(-3, 10), F(1, 10) - F(2, 5))
372 self.assertEqual(F(1, 25), F(1, 10) * F(2, 5))
373 self.assertEqual(F(1, 4), F(1, 10) / F(2, 5))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000374 self.assertTypedEquals(2, F(9, 10) // F(2, 5))
375 self.assertTypedEquals(10**23, F(10**23, 1) // F(1))
Stefan Behnel3a374e02019-01-02 13:22:06 +0100376 self.assertEqual(F(5, 6), F(7, 3) % F(3, 2))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000377 self.assertEqual(F(2, 3), F(-7, 3) % F(3, 2))
Stefan Behnel3a374e02019-01-02 13:22:06 +0100378 self.assertEqual((F(1), F(5, 6)), divmod(F(7, 3), F(3, 2)))
379 self.assertEqual((F(-2), F(2, 3)), divmod(F(-7, 3), F(3, 2)))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000380 self.assertEqual(F(8, 27), F(2, 3) ** F(3))
381 self.assertEqual(F(27, 8), F(2, 3) ** F(-3))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000382 self.assertTypedEquals(2.0, F(4) ** F(1, 2))
Ezio Melotti682d3742012-02-29 14:05:53 +0200383 self.assertEqual(F(1, 1), +F(1, 1))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000384 z = pow(F(-1), F(1, 2))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000385 self.assertAlmostEqual(z.real, 0)
386 self.assertEqual(z.imag, 1)
Mark Dickinson84479652016-08-22 10:50:53 +0100387 # Regression test for #27539.
388 p = F(-1, 2) ** 0
389 self.assertEqual(p, F(1, 1))
390 self.assertEqual(p.numerator, 1)
391 self.assertEqual(p.denominator, 1)
392 p = F(-1, 2) ** -1
393 self.assertEqual(p, F(-2, 1))
394 self.assertEqual(p.numerator, -2)
395 self.assertEqual(p.denominator, 1)
396 p = F(-1, 2) ** -2
397 self.assertEqual(p, F(4, 1))
398 self.assertEqual(p.numerator, 4)
399 self.assertEqual(p.denominator, 1)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000400
Stefan Behnel3a374e02019-01-02 13:22:06 +0100401 def testLargeArithmetic(self):
402 self.assertTypedEquals(
403 F(10101010100808080808080808101010101010000000000000000,
404 1010101010101010101010101011111111101010101010101010101010101),
405 F(10**35+1, 10**27+1) % F(10**27+1, 10**35-1)
406 )
407 self.assertTypedEquals(
408 F(7, 1901475900342344102245054808064),
409 F(-2**100, 3) % F(5, 2**100)
410 )
411 self.assertTypedTupleEquals(
412 (9999999999999999,
413 F(10101010100808080808080808101010101010000000000000000,
414 1010101010101010101010101011111111101010101010101010101010101)),
415 divmod(F(10**35+1, 10**27+1), F(10**27+1, 10**35-1))
416 )
417 self.assertTypedEquals(
418 -2 ** 200 // 15,
419 F(-2**100, 3) // F(5, 2**100)
420 )
421 self.assertTypedEquals(
422 1,
423 F(5, 2**100) // F(3, 2**100)
424 )
425 self.assertTypedEquals(
426 (1, F(2, 2**100)),
427 divmod(F(5, 2**100), F(3, 2**100))
428 )
429 self.assertTypedTupleEquals(
430 (-2 ** 200 // 15,
431 F(7, 1901475900342344102245054808064)),
432 divmod(F(-2**100, 3), F(5, 2**100))
433 )
434
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000435 def testMixedArithmetic(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000436 self.assertTypedEquals(F(11, 10), F(1, 10) + 1)
437 self.assertTypedEquals(1.1, F(1, 10) + 1.0)
438 self.assertTypedEquals(1.1 + 0j, F(1, 10) + (1.0 + 0j))
439 self.assertTypedEquals(F(11, 10), 1 + F(1, 10))
440 self.assertTypedEquals(1.1, 1.0 + F(1, 10))
441 self.assertTypedEquals(1.1 + 0j, (1.0 + 0j) + F(1, 10))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000442
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000443 self.assertTypedEquals(F(-9, 10), F(1, 10) - 1)
444 self.assertTypedEquals(-0.9, F(1, 10) - 1.0)
445 self.assertTypedEquals(-0.9 + 0j, F(1, 10) - (1.0 + 0j))
446 self.assertTypedEquals(F(9, 10), 1 - F(1, 10))
447 self.assertTypedEquals(0.9, 1.0 - F(1, 10))
448 self.assertTypedEquals(0.9 + 0j, (1.0 + 0j) - F(1, 10))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000449
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000450 self.assertTypedEquals(F(1, 10), F(1, 10) * 1)
451 self.assertTypedEquals(0.1, F(1, 10) * 1.0)
452 self.assertTypedEquals(0.1 + 0j, F(1, 10) * (1.0 + 0j))
453 self.assertTypedEquals(F(1, 10), 1 * F(1, 10))
454 self.assertTypedEquals(0.1, 1.0 * F(1, 10))
455 self.assertTypedEquals(0.1 + 0j, (1.0 + 0j) * F(1, 10))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000456
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000457 self.assertTypedEquals(F(1, 10), F(1, 10) / 1)
458 self.assertTypedEquals(0.1, F(1, 10) / 1.0)
459 self.assertTypedEquals(0.1 + 0j, F(1, 10) / (1.0 + 0j))
460 self.assertTypedEquals(F(10, 1), 1 / F(1, 10))
461 self.assertTypedEquals(10.0, 1.0 / F(1, 10))
462 self.assertTypedEquals(10.0 + 0j, (1.0 + 0j) / F(1, 10))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000463
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000464 self.assertTypedEquals(0, F(1, 10) // 1)
Elias Zamaria393f1ff2018-08-26 23:59:28 -0700465 self.assertTypedEquals(0.0, F(1, 10) // 1.0)
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000466 self.assertTypedEquals(10, 1 // F(1, 10))
467 self.assertTypedEquals(10**23, 10**22 // F(1, 10))
Elias Zamaria393f1ff2018-08-26 23:59:28 -0700468 self.assertTypedEquals(1.0 // 0.1, 1.0 // F(1, 10))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000469
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000470 self.assertTypedEquals(F(1, 10), F(1, 10) % 1)
471 self.assertTypedEquals(0.1, F(1, 10) % 1.0)
472 self.assertTypedEquals(F(0, 1), 1 % F(1, 10))
Elias Zamaria393f1ff2018-08-26 23:59:28 -0700473 self.assertTypedEquals(1.0 % 0.1, 1.0 % F(1, 10))
474 self.assertTypedEquals(0.1, F(1, 10) % float('inf'))
475 self.assertTypedEquals(float('-inf'), F(1, 10) % float('-inf'))
476 self.assertTypedEquals(float('inf'), F(-1, 10) % float('inf'))
477 self.assertTypedEquals(-0.1, F(-1, 10) % float('-inf'))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000478
Stefan Behnel3a374e02019-01-02 13:22:06 +0100479 self.assertTypedTupleEquals((0, F(1, 10)), divmod(F(1, 10), 1))
480 self.assertTypedTupleEquals(divmod(0.1, 1.0), divmod(F(1, 10), 1.0))
481 self.assertTypedTupleEquals((10, F(0)), divmod(1, F(1, 10)))
482 self.assertTypedTupleEquals(divmod(1.0, 0.1), divmod(1.0, F(1, 10)))
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 self.assertTypedTupleEquals(divmod(-0.1, float('-inf')), divmod(F(-1, 10), float('-inf')))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000487
488 # ** has more interesting conversion rules.
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000489 self.assertTypedEquals(F(100, 1), F(1, 10) ** -2)
490 self.assertTypedEquals(F(100, 1), F(10, 1) ** 2)
491 self.assertTypedEquals(0.1, F(1, 10) ** 1.0)
492 self.assertTypedEquals(0.1 + 0j, F(1, 10) ** (1.0 + 0j))
493 self.assertTypedEquals(4 , 2 ** F(2, 1))
494 z = pow(-1, F(1, 2))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000495 self.assertAlmostEqual(0, z.real)
496 self.assertEqual(1, z.imag)
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000497 self.assertTypedEquals(F(1, 4) , 2 ** F(-2, 1))
498 self.assertTypedEquals(2.0 , 4 ** F(1, 2))
499 self.assertTypedEquals(0.25, 2.0 ** F(-2, 1))
500 self.assertTypedEquals(1.0 + 0j, (1.0 + 0j) ** F(1, 10))
Mark Dickinson3c286e22014-04-05 09:29:00 +0100501 self.assertRaises(ZeroDivisionError, operator.pow,
502 F(0, 1), -2)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000503
504 def testMixingWithDecimal(self):
Mark Dickinson08ade6f2010-06-11 10:44:52 +0000505 # Decimal refuses mixed arithmetic (but not mixed comparisons)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100506 self.assertRaises(TypeError, operator.add,
507 F(3,11), Decimal('3.1415926'))
508 self.assertRaises(TypeError, operator.add,
509 Decimal('3.1415926'), F(3,11))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000510
511 def testComparisons(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000512 self.assertTrue(F(1, 2) < F(2, 3))
513 self.assertFalse(F(1, 2) < F(1, 2))
514 self.assertTrue(F(1, 2) <= F(2, 3))
515 self.assertTrue(F(1, 2) <= F(1, 2))
516 self.assertFalse(F(2, 3) <= F(1, 2))
517 self.assertTrue(F(1, 2) == F(1, 2))
518 self.assertFalse(F(1, 2) == F(1, 3))
519 self.assertFalse(F(1, 2) != F(1, 2))
520 self.assertTrue(F(1, 2) != F(1, 3))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000521
Mark Dickinson85424c92009-07-18 14:41:42 +0000522 def testComparisonsDummyRational(self):
523 self.assertTrue(F(1, 2) == DummyRational(1, 2))
524 self.assertTrue(DummyRational(1, 2) == F(1, 2))
525 self.assertFalse(F(1, 2) == DummyRational(3, 4))
526 self.assertFalse(DummyRational(3, 4) == F(1, 2))
527
528 self.assertTrue(F(1, 2) < DummyRational(3, 4))
529 self.assertFalse(F(1, 2) < DummyRational(1, 2))
530 self.assertFalse(F(1, 2) < DummyRational(1, 7))
531 self.assertFalse(F(1, 2) > DummyRational(3, 4))
532 self.assertFalse(F(1, 2) > DummyRational(1, 2))
533 self.assertTrue(F(1, 2) > DummyRational(1, 7))
534 self.assertTrue(F(1, 2) <= DummyRational(3, 4))
535 self.assertTrue(F(1, 2) <= DummyRational(1, 2))
536 self.assertFalse(F(1, 2) <= DummyRational(1, 7))
537 self.assertFalse(F(1, 2) >= DummyRational(3, 4))
538 self.assertTrue(F(1, 2) >= DummyRational(1, 2))
539 self.assertTrue(F(1, 2) >= DummyRational(1, 7))
540
541 self.assertTrue(DummyRational(1, 2) < F(3, 4))
542 self.assertFalse(DummyRational(1, 2) < F(1, 2))
543 self.assertFalse(DummyRational(1, 2) < F(1, 7))
544 self.assertFalse(DummyRational(1, 2) > F(3, 4))
545 self.assertFalse(DummyRational(1, 2) > F(1, 2))
546 self.assertTrue(DummyRational(1, 2) > F(1, 7))
547 self.assertTrue(DummyRational(1, 2) <= F(3, 4))
548 self.assertTrue(DummyRational(1, 2) <= F(1, 2))
549 self.assertFalse(DummyRational(1, 2) <= F(1, 7))
550 self.assertFalse(DummyRational(1, 2) >= F(3, 4))
551 self.assertTrue(DummyRational(1, 2) >= F(1, 2))
552 self.assertTrue(DummyRational(1, 2) >= F(1, 7))
553
554 def testComparisonsDummyFloat(self):
555 x = DummyFloat(1./3.)
556 y = F(1, 3)
557 self.assertTrue(x != y)
558 self.assertTrue(x < y or x > y)
559 self.assertFalse(x == y)
560 self.assertFalse(x <= y and x >= y)
561 self.assertTrue(y != x)
562 self.assertTrue(y < x or y > x)
563 self.assertFalse(y == x)
564 self.assertFalse(y <= x and y >= x)
565
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000566 def testMixedLess(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000567 self.assertTrue(2 < F(5, 2))
568 self.assertFalse(2 < F(4, 2))
569 self.assertTrue(F(5, 2) < 3)
570 self.assertFalse(F(4, 2) < 2)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000571
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000572 self.assertTrue(F(1, 2) < 0.6)
573 self.assertFalse(F(1, 2) < 0.4)
574 self.assertTrue(0.4 < F(1, 2))
575 self.assertFalse(0.5 < F(1, 2))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000576
Mark Dickinson85424c92009-07-18 14:41:42 +0000577 self.assertFalse(float('inf') < F(1, 2))
578 self.assertTrue(float('-inf') < F(0, 10))
579 self.assertFalse(float('nan') < F(-3, 7))
580 self.assertTrue(F(1, 2) < float('inf'))
581 self.assertFalse(F(17, 12) < float('-inf'))
582 self.assertFalse(F(144, -89) < float('nan'))
583
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000584 def testMixedLessEqual(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000585 self.assertTrue(0.5 <= F(1, 2))
586 self.assertFalse(0.6 <= F(1, 2))
587 self.assertTrue(F(1, 2) <= 0.5)
588 self.assertFalse(F(1, 2) <= 0.4)
589 self.assertTrue(2 <= F(4, 2))
590 self.assertFalse(2 <= F(3, 2))
591 self.assertTrue(F(4, 2) <= 2)
592 self.assertFalse(F(5, 2) <= 2)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000593
Mark Dickinson85424c92009-07-18 14:41:42 +0000594 self.assertFalse(float('inf') <= F(1, 2))
595 self.assertTrue(float('-inf') <= F(0, 10))
596 self.assertFalse(float('nan') <= F(-3, 7))
597 self.assertTrue(F(1, 2) <= float('inf'))
598 self.assertFalse(F(17, 12) <= float('-inf'))
599 self.assertFalse(F(144, -89) <= float('nan'))
600
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000601 def testBigFloatComparisons(self):
602 # Because 10**23 can't be represented exactly as a float:
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000603 self.assertFalse(F(10**23) == float(10**23))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000604 # The first test demonstrates why these are important.
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000605 self.assertFalse(1e23 < float(F(math.trunc(1e23) + 1)))
606 self.assertTrue(1e23 < F(math.trunc(1e23) + 1))
607 self.assertFalse(1e23 <= F(math.trunc(1e23) - 1))
608 self.assertTrue(1e23 > F(math.trunc(1e23) - 1))
609 self.assertFalse(1e23 >= F(math.trunc(1e23) + 1))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000610
611 def testBigComplexComparisons(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000612 self.assertFalse(F(10**23) == complex(10**23))
Mark Dickinson327f02c2010-03-27 11:11:13 +0000613 self.assertRaises(TypeError, operator.gt, F(10**23), complex(10**23))
614 self.assertRaises(TypeError, operator.le, F(10**23), complex(10**23))
615
616 x = F(3, 8)
617 z = complex(0.375, 0.0)
618 w = complex(0.375, 0.2)
619 self.assertTrue(x == z)
620 self.assertFalse(x != z)
621 self.assertFalse(x == w)
622 self.assertTrue(x != w)
623 for op in operator.lt, operator.le, operator.gt, operator.ge:
624 self.assertRaises(TypeError, op, x, z)
625 self.assertRaises(TypeError, op, z, x)
626 self.assertRaises(TypeError, op, x, w)
627 self.assertRaises(TypeError, op, w, x)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000628
629 def testMixedEqual(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000630 self.assertTrue(0.5 == F(1, 2))
631 self.assertFalse(0.6 == F(1, 2))
632 self.assertTrue(F(1, 2) == 0.5)
633 self.assertFalse(F(1, 2) == 0.4)
634 self.assertTrue(2 == F(4, 2))
635 self.assertFalse(2 == F(3, 2))
636 self.assertTrue(F(4, 2) == 2)
637 self.assertFalse(F(5, 2) == 2)
Mark Dickinson85424c92009-07-18 14:41:42 +0000638 self.assertFalse(F(5, 2) == float('nan'))
639 self.assertFalse(float('nan') == F(3, 7))
640 self.assertFalse(F(5, 2) == float('inf'))
641 self.assertFalse(float('-inf') == F(2, 5))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000642
643 def testStringification(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000644 self.assertEqual("Fraction(7, 3)", repr(F(7, 3)))
645 self.assertEqual("Fraction(6283185307, 2000000000)",
646 repr(F('3.1415926535')))
647 self.assertEqual("Fraction(-1, 100000000000000000000)",
648 repr(F(1, -10**20)))
649 self.assertEqual("7/3", str(F(7, 3)))
650 self.assertEqual("7", str(F(7, 1)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000651
652 def testHash(self):
Ezio Melotti682d3742012-02-29 14:05:53 +0200653 hmod = sys.hash_info.modulus
654 hinf = sys.hash_info.inf
Ezio Melottib3aedd42010-11-20 19:04:17 +0000655 self.assertEqual(hash(2.5), hash(F(5, 2)))
656 self.assertEqual(hash(10**50), hash(F(10**50)))
657 self.assertNotEqual(hash(float(10**23)), hash(F(10**23)))
Ezio Melotti682d3742012-02-29 14:05:53 +0200658 self.assertEqual(hinf, hash(F(1, hmod)))
Mark Dickinsonfec66202010-11-13 10:27:38 +0000659 # Check that __hash__ produces the same value as hash(), for
660 # consistency with int and Decimal. (See issue #10356.)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000661 self.assertEqual(hash(F(-1)), F(-1).__hash__())
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000662
663 def testApproximatePi(self):
664 # Algorithm borrowed from
665 # http://docs.python.org/lib/decimal-recipes.html
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000666 three = F(3)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000667 lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000668 while abs(s - lasts) > F(1, 10**9):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000669 lasts = s
670 n, na = n+na, na+8
671 d, da = d+da, da+32
672 t = (t * n) / d
673 s += t
Ezio Melottib3aedd42010-11-20 19:04:17 +0000674 self.assertAlmostEqual(math.pi, s)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000675
676 def testApproximateCos1(self):
677 # Algorithm borrowed from
678 # http://docs.python.org/lib/decimal-recipes.html
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000679 x = F(1)
680 i, lasts, s, fact, num, sign = 0, 0, F(1), 1, 1, 1
681 while abs(s - lasts) > F(1, 10**9):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000682 lasts = s
683 i += 2
684 fact *= i * (i-1)
685 num *= x * x
686 sign *= -1
687 s += num / fact * sign
Ezio Melottib3aedd42010-11-20 19:04:17 +0000688 self.assertAlmostEqual(math.cos(1), s)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000689
Christian Heimes969fe572008-01-25 11:23:10 +0000690 def test_copy_deepcopy_pickle(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000691 r = F(13, 7)
Ezio Melotti682d3742012-02-29 14:05:53 +0200692 dr = DummyFraction(13, 7)
Christian Heimes969fe572008-01-25 11:23:10 +0000693 self.assertEqual(r, loads(dumps(r)))
694 self.assertEqual(id(r), id(copy(r)))
695 self.assertEqual(id(r), id(deepcopy(r)))
Ezio Melotti682d3742012-02-29 14:05:53 +0200696 self.assertNotEqual(id(dr), id(copy(dr)))
697 self.assertNotEqual(id(dr), id(deepcopy(dr)))
698 self.assertTypedEquals(dr, copy(dr))
699 self.assertTypedEquals(dr, deepcopy(dr))
Christian Heimes969fe572008-01-25 11:23:10 +0000700
Mark Dickinsonc28ad272009-02-12 17:58:36 +0000701 def test_slots(self):
702 # Issue 4998
703 r = F(13, 7)
704 self.assertRaises(AttributeError, setattr, r, 'a', 10)
705
Victor Stinnerdc7a50d2020-02-07 23:42:51 +0100706 def test_int_subclass(self):
707 class myint(int):
708 def __mul__(self, other):
709 return type(self)(int(self) * int(other))
710 def __floordiv__(self, other):
711 return type(self)(int(self) // int(other))
712 def __mod__(self, other):
713 x = type(self)(int(self) % int(other))
714 return x
715 @property
716 def numerator(self):
717 return type(self)(int(self))
718 @property
719 def denominator(self):
720 return type(self)(1)
721
722 f = fractions.Fraction(myint(1 * 3), myint(2 * 3))
723 self.assertEqual(f.numerator, 1)
724 self.assertEqual(f.denominator, 2)
725 self.assertEqual(type(f.numerator), myint)
726 self.assertEqual(type(f.denominator), myint)
727
Victor Stinner4691a2f2020-01-16 11:02:51 +0100728
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000729if __name__ == '__main__':
Zachary Ware38c707e2015-04-13 15:00:43 -0500730 unittest.main()