blob: 0845f7921c39ec7f7c0f090e0f471668b75388f6 [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
Christian Heimes969fe572008-01-25 11:23:10 +000012from copy import copy, deepcopy
Neal Norwitz6ff93fe2008-01-26 21:52:30 +000013from pickle import dumps, loads
Christian Heimes68f5fbe2008-02-14 08:27:37 +000014F = fractions.Fraction
Victor Stinner4691a2f2020-01-16 11:02:51 +010015
Christian Heimesaf98da12008-01-27 15:18:18 +000016
Mark Dickinson85424c92009-07-18 14:41:42 +000017class 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):
Serhiy Storchaka48e47aa2015-05-13 00:19:51 +030053 g = math.gcd(num, den)
Mark Dickinson85424c92009-07-18 14:41:42 +000054 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"
Christian Heimesaf98da12008-01-27 15:18:18 +000080
Ezio Melotti682d3742012-02-29 14:05:53 +020081class DummyFraction(fractions.Fraction):
82 """Dummy Fraction subclass for copy and deepcopy testing."""
83
Guido van Rossum7736b5b2008-01-15 21:44:53 +000084
85def _components(r):
86 return (r.numerator, r.denominator)
87
Christian Heimesaf98da12008-01-27 15:18:18 +000088
Christian Heimes3feef612008-02-11 06:19:17 +000089class FractionTest(unittest.TestCase):
Guido van Rossum7736b5b2008-01-15 21:44:53 +000090
91 def assertTypedEquals(self, expected, actual):
92 """Asserts that both the types and values are the same."""
Ezio Melottib3aedd42010-11-20 19:04:17 +000093 self.assertEqual(type(expected), type(actual))
94 self.assertEqual(expected, actual)
Guido van Rossum7736b5b2008-01-15 21:44:53 +000095
Stefan Behnel3a374e02019-01-02 13:22:06 +010096 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
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000101 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:
Ezio Melottib3aedd42010-11-20 19:04:17 +0000107 self.assertEqual(message, str(e))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000108 else:
109 self.fail("%s not raised" % exc_type.__name__)
110
111 def testInit(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000112 self.assertEqual((0, 1), _components(F()))
113 self.assertEqual((7, 1), _components(F(7)))
114 self.assertEqual((7, 3), _components(F(F(7, 3))))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000115
Ezio Melottib3aedd42010-11-20 19:04:17 +0000116 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)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000122
Ezio Melottib3aedd42010-11-20 19:04:17 +0000123 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))))
Mark Dickinsond4d95f82009-04-24 14:06:19 +0000126
Christian Heimes3feef612008-02-11 06:19:17 +0000127 self.assertRaisesMessage(ZeroDivisionError, "Fraction(12, 0)",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000128 F, 12, 0)
Georg Brandl86b2fb92008-07-16 03:43:04 +0000129 self.assertRaises(TypeError, F, 1.5 + 3j)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000130
Georg Brandl86b2fb92008-07-16 03:43:04 +0000131 self.assertRaises(TypeError, F, "3/2", 3)
Mark Dickinsond4d95f82009-04-24 14:06:19 +0000132 self.assertRaises(TypeError, F, 3, 0j)
133 self.assertRaises(TypeError, F, 3, 1j)
Mark Dickinson7caf9082016-08-23 16:16:52 +0100134 self.assertRaises(TypeError, F, 1, 2, 3)
Mark Dickinsond4d95f82009-04-24 14:06:19 +0000135
Mark Dickinson98127c32010-04-03 11:18:52 +0000136 @requires_IEEE_754
137 def testInitFromFloat(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000138 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)))
Mark Dickinson73726aa2012-11-15 20:58:40 +0000142 # 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'))
Mark Dickinson98127c32010-04-03 11:18:52 +0000146
147 def testInitFromDecimal(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000148 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'))))
Mark Dickinson73726aa2012-11-15 20:58:40 +0000154 # 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'))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000159
160 def testFromString(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000161 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")))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000175
176 self.assertRaisesMessage(
Christian Heimes3feef612008-02-11 06:19:17 +0000177 ZeroDivisionError, "Fraction(3, 0)",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000178 F, "3/0")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000179 self.assertRaisesMessage(
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000180 ValueError, "Invalid literal for Fraction: '3/'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000181 F, "3/")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000182 self.assertRaisesMessage(
Mark Dickinsoncf63f2f2009-04-22 17:50:21 +0000183 ValueError, "Invalid literal for Fraction: '/2'",
184 F, "/2")
185 self.assertRaisesMessage(
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000186 ValueError, "Invalid literal for Fraction: '3 /2'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000187 F, "3 /2")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000188 self.assertRaisesMessage(
189 # Denominators don't need a sign.
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000190 ValueError, "Invalid literal for Fraction: '3/+2'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000191 F, "3/+2")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000192 self.assertRaisesMessage(
193 # Imitate float's parsing.
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000194 ValueError, "Invalid literal for Fraction: '+ 3/2'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000195 F, "+ 3/2")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000196 self.assertRaisesMessage(
Christian Heimesaf98da12008-01-27 15:18:18 +0000197 # Avoid treating '.' as a regex special character.
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000198 ValueError, "Invalid literal for Fraction: '3a2'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000199 F, "3a2")
Christian Heimesaf98da12008-01-27 15:18:18 +0000200 self.assertRaisesMessage(
Christian Heimesaf98da12008-01-27 15:18:18 +0000201 # Don't accept combinations of decimals and rationals.
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000202 ValueError, "Invalid literal for Fraction: '3/7.2'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000203 F, "3/7.2")
Christian Heimesaf98da12008-01-27 15:18:18 +0000204 self.assertRaisesMessage(
205 # Don't accept combinations of decimals and rationals.
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000206 ValueError, "Invalid literal for Fraction: '3.2/7'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000207 F, "3.2/7")
Christian Heimes292d3512008-02-03 16:51:08 +0000208 self.assertRaisesMessage(
209 # Allow 3. and .3, but not .
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000210 ValueError, "Invalid literal for Fraction: '.'",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000211 F, ".")
Christian Heimes587c2bf2008-01-19 16:21:02 +0000212
213 def testImmutable(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000214 r = F(7, 3)
Christian Heimes587c2bf2008-01-19 16:21:02 +0000215 r.__init__(2, 15)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000216 self.assertEqual((7, 3), _components(r))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000217
Christian Heimes400adb02008-02-01 08:12:03 +0000218 self.assertRaises(AttributeError, setattr, r, 'numerator', 12)
219 self.assertRaises(AttributeError, setattr, r, 'denominator', 6)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000220 self.assertEqual((7, 3), _components(r))
Christian Heimes400adb02008-02-01 08:12:03 +0000221
222 # But if you _really_ need to:
223 r._numerator = 4
224 r._denominator = 2
Ezio Melottib3aedd42010-11-20 19:04:17 +0000225 self.assertEqual((4, 2), _components(r))
Christian Heimes400adb02008-02-01 08:12:03 +0000226 # Which breaks some important operations:
Ezio Melottib3aedd42010-11-20 19:04:17 +0000227 self.assertNotEqual(F(4, 2), r)
Christian Heimes400adb02008-02-01 08:12:03 +0000228
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000229 def testFromFloat(self):
Georg Brandl2ee470f2008-07-16 12:55:28 +0000230 self.assertRaises(TypeError, F.from_float, 3+4j)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000231 self.assertEqual((10, 1), _components(F.from_float(10)))
Georg Brandl3a9b0622009-01-03 22:07:57 +0000232 bigint = 1234567890123456789
Ezio Melottib3aedd42010-11-20 19:04:17 +0000233 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)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000243
244 inf = 1e1000
245 nan = inf - inf
Mark Dickinson73726aa2012-11-15 20:58:40 +0000246 # bug 16469: error types should be consistent with float -> int
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000247 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200248 OverflowError, "cannot convert Infinity to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000249 F.from_float, inf)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000250 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200251 OverflowError, "cannot convert Infinity to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000252 F.from_float, -inf)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000253 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200254 ValueError, "cannot convert NaN to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000255 F.from_float, nan)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000256
Christian Heimes587c2bf2008-01-19 16:21:02 +0000257 def testFromDecimal(self):
Georg Brandl2ee470f2008-07-16 12:55:28 +0000258 self.assertRaises(TypeError, F.from_decimal, 3+4j)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000259 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)))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000266
Mark Dickinson73726aa2012-11-15 20:58:40 +0000267 # bug 16469: error types should be consistent with decimal -> int
Christian Heimes587c2bf2008-01-19 16:21:02 +0000268 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200269 OverflowError, "cannot convert Infinity to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000270 F.from_decimal, Decimal("inf"))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000271 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200272 OverflowError, "cannot convert Infinity to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000273 F.from_decimal, Decimal("-inf"))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000274 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200275 ValueError, "cannot convert NaN to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000276 F.from_decimal, Decimal("nan"))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000277 self.assertRaisesMessage(
Serhiy Storchaka0d250bc2015-12-29 22:34:23 +0200278 ValueError, "cannot convert NaN to integer ratio",
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000279 F.from_decimal, Decimal("snan"))
Christian Heimes587c2bf2008-01-19 16:21:02 +0000280
Raymond Hettingerf03b4c82019-08-11 14:40:59 -0700281 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
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000287 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))
Ezio Melotti682d3742012-02-29 14:05:53 +0200296 for i in (0, -1):
297 self.assertRaisesMessage(
298 ValueError, "max_denominator should be at least 1",
299 F(1).limit_denominator, i)
Christian Heimesbbffeb62008-01-24 09:42:52 +0000300
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000301 def testConversions(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000302 self.assertTypedEquals(-1, math.trunc(F(-11, 10)))
Ezio Melotti682d3742012-02-29 14:05:53 +0200303 self.assertTypedEquals(1, math.trunc(F(11, 10)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000304 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)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000312
Ezio Melottib3aedd42010-11-20 19:04:17 +0000313 self.assertEqual(False, bool(F(0, 1)))
314 self.assertEqual(True, bool(F(3, 2)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000315 self.assertTypedEquals(0.1, float(F(1, 10)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000316
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'))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000320 self.assertAlmostEqual(2.0/3,
321 float(F(int('2'*400+'7'), int('3'*400+'1'))))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000322
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000323 self.assertTypedEquals(0.1+0j, complex(F(1,10)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000324
Sebastian Berg427c84f2020-02-06 06:54:05 -0800325 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
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000361 def testRound(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000362 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000367
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000368 def testArithmetic(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000369 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))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000373 self.assertTypedEquals(2, F(9, 10) // F(2, 5))
374 self.assertTypedEquals(10**23, F(10**23, 1) // F(1))
Stefan Behnel3a374e02019-01-02 13:22:06 +0100375 self.assertEqual(F(5, 6), F(7, 3) % F(3, 2))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000376 self.assertEqual(F(2, 3), F(-7, 3) % F(3, 2))
Stefan Behnel3a374e02019-01-02 13:22:06 +0100377 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)))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000379 self.assertEqual(F(8, 27), F(2, 3) ** F(3))
380 self.assertEqual(F(27, 8), F(2, 3) ** F(-3))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000381 self.assertTypedEquals(2.0, F(4) ** F(1, 2))
Ezio Melotti682d3742012-02-29 14:05:53 +0200382 self.assertEqual(F(1, 1), +F(1, 1))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000383 z = pow(F(-1), F(1, 2))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000384 self.assertAlmostEqual(z.real, 0)
385 self.assertEqual(z.imag, 1)
Mark Dickinson84479652016-08-22 10:50:53 +0100386 # 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)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000399
Stefan Behnel3a374e02019-01-02 13:22:06 +0100400 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
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000434 def testMixedArithmetic(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000435 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000441
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000442 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000448
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000449 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000455
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000456 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000462
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000463 self.assertTypedEquals(0, F(1, 10) // 1)
Elias Zamaria393f1ff2018-08-26 23:59:28 -0700464 self.assertTypedEquals(0.0, F(1, 10) // 1.0)
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000465 self.assertTypedEquals(10, 1 // F(1, 10))
466 self.assertTypedEquals(10**23, 10**22 // F(1, 10))
Elias Zamaria393f1ff2018-08-26 23:59:28 -0700467 self.assertTypedEquals(1.0 // 0.1, 1.0 // F(1, 10))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000468
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000469 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))
Elias Zamaria393f1ff2018-08-26 23:59:28 -0700472 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'))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000477
Stefan Behnel3a374e02019-01-02 13:22:06 +0100478 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')))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000486
487 # ** has more interesting conversion rules.
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000488 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))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000494 self.assertAlmostEqual(0, z.real)
495 self.assertEqual(1, z.imag)
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000496 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))
Mark Dickinson3c286e22014-04-05 09:29:00 +0100500 self.assertRaises(ZeroDivisionError, operator.pow,
501 F(0, 1), -2)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000502
503 def testMixingWithDecimal(self):
Mark Dickinson08ade6f2010-06-11 10:44:52 +0000504 # Decimal refuses mixed arithmetic (but not mixed comparisons)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100505 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000509
510 def testComparisons(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000511 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000520
Mark Dickinson85424c92009-07-18 14:41:42 +0000521 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
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000565 def testMixedLess(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000566 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)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000570
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000571 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000575
Mark Dickinson85424c92009-07-18 14:41:42 +0000576 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
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000583 def testMixedLessEqual(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000584 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)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000592
Mark Dickinson85424c92009-07-18 14:41:42 +0000593 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
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000600 def testBigFloatComparisons(self):
601 # Because 10**23 can't be represented exactly as a float:
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000602 self.assertFalse(F(10**23) == float(10**23))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000603 # The first test demonstrates why these are important.
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000604 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000609
610 def testBigComplexComparisons(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000611 self.assertFalse(F(10**23) == complex(10**23))
Mark Dickinson327f02c2010-03-27 11:11:13 +0000612 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)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000627
628 def testMixedEqual(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000629 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)
Mark Dickinson85424c92009-07-18 14:41:42 +0000637 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))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000641
642 def testStringification(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000643 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)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000650
651 def testHash(self):
Ezio Melotti682d3742012-02-29 14:05:53 +0200652 hmod = sys.hash_info.modulus
653 hinf = sys.hash_info.inf
Ezio Melottib3aedd42010-11-20 19:04:17 +0000654 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)))
Ezio Melotti682d3742012-02-29 14:05:53 +0200657 self.assertEqual(hinf, hash(F(1, hmod)))
Mark Dickinsonfec66202010-11-13 10:27:38 +0000658 # Check that __hash__ produces the same value as hash(), for
659 # consistency with int and Decimal. (See issue #10356.)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000660 self.assertEqual(hash(F(-1)), F(-1).__hash__())
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000661
662 def testApproximatePi(self):
663 # Algorithm borrowed from
664 # http://docs.python.org/lib/decimal-recipes.html
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000665 three = F(3)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000666 lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000667 while abs(s - lasts) > F(1, 10**9):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000668 lasts = s
669 n, na = n+na, na+8
670 d, da = d+da, da+32
671 t = (t * n) / d
672 s += t
Ezio Melottib3aedd42010-11-20 19:04:17 +0000673 self.assertAlmostEqual(math.pi, s)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000674
675 def testApproximateCos1(self):
676 # Algorithm borrowed from
677 # http://docs.python.org/lib/decimal-recipes.html
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000678 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):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000681 lasts = s
682 i += 2
683 fact *= i * (i-1)
684 num *= x * x
685 sign *= -1
686 s += num / fact * sign
Ezio Melottib3aedd42010-11-20 19:04:17 +0000687 self.assertAlmostEqual(math.cos(1), s)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000688
Christian Heimes969fe572008-01-25 11:23:10 +0000689 def test_copy_deepcopy_pickle(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000690 r = F(13, 7)
Ezio Melotti682d3742012-02-29 14:05:53 +0200691 dr = DummyFraction(13, 7)
Christian Heimes969fe572008-01-25 11:23:10 +0000692 self.assertEqual(r, loads(dumps(r)))
693 self.assertEqual(id(r), id(copy(r)))
694 self.assertEqual(id(r), id(deepcopy(r)))
Ezio Melotti682d3742012-02-29 14:05:53 +0200695 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))
Christian Heimes969fe572008-01-25 11:23:10 +0000699
Mark Dickinsonc28ad272009-02-12 17:58:36 +0000700 def test_slots(self):
701 # Issue 4998
702 r = F(13, 7)
703 self.assertRaises(AttributeError, setattr, r, 'a', 10)
704
Victor Stinnerdc7a50d2020-02-07 23:42:51 +0100705 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
Victor Stinner4691a2f2020-01-16 11:02:51 +0100727
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000728if __name__ == '__main__':
Zachary Ware38c707e2015-04-13 15:00:43 -0500729 unittest.main()