blob: b92552531d6bb214129af35fc4506cc2f469b5b4 [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))
Sergey B Kirpichev690aca72021-03-22 05:30:55 +0300372 self.assertEqual(F(5, 6), F(2, 3) * F(5, 4))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000373 self.assertEqual(F(1, 4), F(1, 10) / F(2, 5))
Sergey B Kirpichev690aca72021-03-22 05:30:55 +0300374 self.assertEqual(F(-15, 8), F(3, 4) / F(-2, 5))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000375 self.assertTypedEquals(2, F(9, 10) // F(2, 5))
376 self.assertTypedEquals(10**23, F(10**23, 1) // F(1))
Stefan Behnel3a374e02019-01-02 13:22:06 +0100377 self.assertEqual(F(5, 6), F(7, 3) % F(3, 2))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000378 self.assertEqual(F(2, 3), F(-7, 3) % F(3, 2))
Stefan Behnel3a374e02019-01-02 13:22:06 +0100379 self.assertEqual((F(1), F(5, 6)), divmod(F(7, 3), F(3, 2)))
380 self.assertEqual((F(-2), F(2, 3)), divmod(F(-7, 3), F(3, 2)))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000381 self.assertEqual(F(8, 27), F(2, 3) ** F(3))
382 self.assertEqual(F(27, 8), F(2, 3) ** F(-3))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000383 self.assertTypedEquals(2.0, F(4) ** F(1, 2))
Ezio Melotti682d3742012-02-29 14:05:53 +0200384 self.assertEqual(F(1, 1), +F(1, 1))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000385 z = pow(F(-1), F(1, 2))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000386 self.assertAlmostEqual(z.real, 0)
387 self.assertEqual(z.imag, 1)
Mark Dickinson84479652016-08-22 10:50:53 +0100388 # Regression test for #27539.
389 p = F(-1, 2) ** 0
390 self.assertEqual(p, F(1, 1))
391 self.assertEqual(p.numerator, 1)
392 self.assertEqual(p.denominator, 1)
393 p = F(-1, 2) ** -1
394 self.assertEqual(p, F(-2, 1))
395 self.assertEqual(p.numerator, -2)
396 self.assertEqual(p.denominator, 1)
397 p = F(-1, 2) ** -2
398 self.assertEqual(p, F(4, 1))
399 self.assertEqual(p.numerator, 4)
400 self.assertEqual(p.denominator, 1)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000401
Stefan Behnel3a374e02019-01-02 13:22:06 +0100402 def testLargeArithmetic(self):
403 self.assertTypedEquals(
404 F(10101010100808080808080808101010101010000000000000000,
405 1010101010101010101010101011111111101010101010101010101010101),
406 F(10**35+1, 10**27+1) % F(10**27+1, 10**35-1)
407 )
408 self.assertTypedEquals(
409 F(7, 1901475900342344102245054808064),
410 F(-2**100, 3) % F(5, 2**100)
411 )
412 self.assertTypedTupleEquals(
413 (9999999999999999,
414 F(10101010100808080808080808101010101010000000000000000,
415 1010101010101010101010101011111111101010101010101010101010101)),
416 divmod(F(10**35+1, 10**27+1), F(10**27+1, 10**35-1))
417 )
418 self.assertTypedEquals(
419 -2 ** 200 // 15,
420 F(-2**100, 3) // F(5, 2**100)
421 )
422 self.assertTypedEquals(
423 1,
424 F(5, 2**100) // F(3, 2**100)
425 )
426 self.assertTypedEquals(
427 (1, F(2, 2**100)),
428 divmod(F(5, 2**100), F(3, 2**100))
429 )
430 self.assertTypedTupleEquals(
431 (-2 ** 200 // 15,
432 F(7, 1901475900342344102245054808064)),
433 divmod(F(-2**100, 3), F(5, 2**100))
434 )
435
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000436 def testMixedArithmetic(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000437 self.assertTypedEquals(F(11, 10), F(1, 10) + 1)
438 self.assertTypedEquals(1.1, F(1, 10) + 1.0)
439 self.assertTypedEquals(1.1 + 0j, F(1, 10) + (1.0 + 0j))
440 self.assertTypedEquals(F(11, 10), 1 + F(1, 10))
441 self.assertTypedEquals(1.1, 1.0 + F(1, 10))
442 self.assertTypedEquals(1.1 + 0j, (1.0 + 0j) + F(1, 10))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000443
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000444 self.assertTypedEquals(F(-9, 10), F(1, 10) - 1)
445 self.assertTypedEquals(-0.9, F(1, 10) - 1.0)
446 self.assertTypedEquals(-0.9 + 0j, F(1, 10) - (1.0 + 0j))
447 self.assertTypedEquals(F(9, 10), 1 - F(1, 10))
448 self.assertTypedEquals(0.9, 1.0 - F(1, 10))
449 self.assertTypedEquals(0.9 + 0j, (1.0 + 0j) - F(1, 10))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000450
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000451 self.assertTypedEquals(F(1, 10), F(1, 10) * 1)
452 self.assertTypedEquals(0.1, F(1, 10) * 1.0)
453 self.assertTypedEquals(0.1 + 0j, F(1, 10) * (1.0 + 0j))
454 self.assertTypedEquals(F(1, 10), 1 * F(1, 10))
455 self.assertTypedEquals(0.1, 1.0 * F(1, 10))
456 self.assertTypedEquals(0.1 + 0j, (1.0 + 0j) * F(1, 10))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000457
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000458 self.assertTypedEquals(F(1, 10), F(1, 10) / 1)
459 self.assertTypedEquals(0.1, F(1, 10) / 1.0)
460 self.assertTypedEquals(0.1 + 0j, F(1, 10) / (1.0 + 0j))
461 self.assertTypedEquals(F(10, 1), 1 / F(1, 10))
462 self.assertTypedEquals(10.0, 1.0 / F(1, 10))
463 self.assertTypedEquals(10.0 + 0j, (1.0 + 0j) / F(1, 10))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000464
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000465 self.assertTypedEquals(0, F(1, 10) // 1)
Elias Zamaria393f1ff2018-08-26 23:59:28 -0700466 self.assertTypedEquals(0.0, F(1, 10) // 1.0)
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000467 self.assertTypedEquals(10, 1 // F(1, 10))
468 self.assertTypedEquals(10**23, 10**22 // F(1, 10))
Elias Zamaria393f1ff2018-08-26 23:59:28 -0700469 self.assertTypedEquals(1.0 // 0.1, 1.0 // F(1, 10))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000470
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000471 self.assertTypedEquals(F(1, 10), F(1, 10) % 1)
472 self.assertTypedEquals(0.1, F(1, 10) % 1.0)
473 self.assertTypedEquals(F(0, 1), 1 % F(1, 10))
Elias Zamaria393f1ff2018-08-26 23:59:28 -0700474 self.assertTypedEquals(1.0 % 0.1, 1.0 % F(1, 10))
475 self.assertTypedEquals(0.1, F(1, 10) % float('inf'))
476 self.assertTypedEquals(float('-inf'), F(1, 10) % float('-inf'))
477 self.assertTypedEquals(float('inf'), F(-1, 10) % float('inf'))
478 self.assertTypedEquals(-0.1, F(-1, 10) % float('-inf'))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000479
Stefan Behnel3a374e02019-01-02 13:22:06 +0100480 self.assertTypedTupleEquals((0, F(1, 10)), divmod(F(1, 10), 1))
481 self.assertTypedTupleEquals(divmod(0.1, 1.0), divmod(F(1, 10), 1.0))
482 self.assertTypedTupleEquals((10, F(0)), divmod(1, F(1, 10)))
483 self.assertTypedTupleEquals(divmod(1.0, 0.1), divmod(1.0, F(1, 10)))
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')))
487 self.assertTypedTupleEquals(divmod(-0.1, float('-inf')), divmod(F(-1, 10), float('-inf')))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000488
489 # ** has more interesting conversion rules.
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000490 self.assertTypedEquals(F(100, 1), F(1, 10) ** -2)
491 self.assertTypedEquals(F(100, 1), F(10, 1) ** 2)
492 self.assertTypedEquals(0.1, F(1, 10) ** 1.0)
493 self.assertTypedEquals(0.1 + 0j, F(1, 10) ** (1.0 + 0j))
494 self.assertTypedEquals(4 , 2 ** F(2, 1))
495 z = pow(-1, F(1, 2))
Ezio Melottib3aedd42010-11-20 19:04:17 +0000496 self.assertAlmostEqual(0, z.real)
497 self.assertEqual(1, z.imag)
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000498 self.assertTypedEquals(F(1, 4) , 2 ** F(-2, 1))
499 self.assertTypedEquals(2.0 , 4 ** F(1, 2))
500 self.assertTypedEquals(0.25, 2.0 ** F(-2, 1))
501 self.assertTypedEquals(1.0 + 0j, (1.0 + 0j) ** F(1, 10))
Mark Dickinson3c286e22014-04-05 09:29:00 +0100502 self.assertRaises(ZeroDivisionError, operator.pow,
503 F(0, 1), -2)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000504
505 def testMixingWithDecimal(self):
Mark Dickinson08ade6f2010-06-11 10:44:52 +0000506 # Decimal refuses mixed arithmetic (but not mixed comparisons)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100507 self.assertRaises(TypeError, operator.add,
508 F(3,11), Decimal('3.1415926'))
509 self.assertRaises(TypeError, operator.add,
510 Decimal('3.1415926'), F(3,11))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000511
512 def testComparisons(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000513 self.assertTrue(F(1, 2) < F(2, 3))
514 self.assertFalse(F(1, 2) < F(1, 2))
515 self.assertTrue(F(1, 2) <= F(2, 3))
516 self.assertTrue(F(1, 2) <= F(1, 2))
517 self.assertFalse(F(2, 3) <= F(1, 2))
518 self.assertTrue(F(1, 2) == F(1, 2))
519 self.assertFalse(F(1, 2) == F(1, 3))
520 self.assertFalse(F(1, 2) != F(1, 2))
521 self.assertTrue(F(1, 2) != F(1, 3))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000522
Mark Dickinson85424c92009-07-18 14:41:42 +0000523 def testComparisonsDummyRational(self):
524 self.assertTrue(F(1, 2) == DummyRational(1, 2))
525 self.assertTrue(DummyRational(1, 2) == F(1, 2))
526 self.assertFalse(F(1, 2) == DummyRational(3, 4))
527 self.assertFalse(DummyRational(3, 4) == F(1, 2))
528
529 self.assertTrue(F(1, 2) < DummyRational(3, 4))
530 self.assertFalse(F(1, 2) < DummyRational(1, 2))
531 self.assertFalse(F(1, 2) < DummyRational(1, 7))
532 self.assertFalse(F(1, 2) > DummyRational(3, 4))
533 self.assertFalse(F(1, 2) > DummyRational(1, 2))
534 self.assertTrue(F(1, 2) > DummyRational(1, 7))
535 self.assertTrue(F(1, 2) <= DummyRational(3, 4))
536 self.assertTrue(F(1, 2) <= DummyRational(1, 2))
537 self.assertFalse(F(1, 2) <= DummyRational(1, 7))
538 self.assertFalse(F(1, 2) >= DummyRational(3, 4))
539 self.assertTrue(F(1, 2) >= DummyRational(1, 2))
540 self.assertTrue(F(1, 2) >= DummyRational(1, 7))
541
542 self.assertTrue(DummyRational(1, 2) < F(3, 4))
543 self.assertFalse(DummyRational(1, 2) < F(1, 2))
544 self.assertFalse(DummyRational(1, 2) < F(1, 7))
545 self.assertFalse(DummyRational(1, 2) > F(3, 4))
546 self.assertFalse(DummyRational(1, 2) > F(1, 2))
547 self.assertTrue(DummyRational(1, 2) > F(1, 7))
548 self.assertTrue(DummyRational(1, 2) <= F(3, 4))
549 self.assertTrue(DummyRational(1, 2) <= F(1, 2))
550 self.assertFalse(DummyRational(1, 2) <= F(1, 7))
551 self.assertFalse(DummyRational(1, 2) >= F(3, 4))
552 self.assertTrue(DummyRational(1, 2) >= F(1, 2))
553 self.assertTrue(DummyRational(1, 2) >= F(1, 7))
554
555 def testComparisonsDummyFloat(self):
556 x = DummyFloat(1./3.)
557 y = F(1, 3)
558 self.assertTrue(x != y)
559 self.assertTrue(x < y or x > y)
560 self.assertFalse(x == y)
561 self.assertFalse(x <= y and x >= y)
562 self.assertTrue(y != x)
563 self.assertTrue(y < x or y > x)
564 self.assertFalse(y == x)
565 self.assertFalse(y <= x and y >= x)
566
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000567 def testMixedLess(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000568 self.assertTrue(2 < F(5, 2))
569 self.assertFalse(2 < F(4, 2))
570 self.assertTrue(F(5, 2) < 3)
571 self.assertFalse(F(4, 2) < 2)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000572
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000573 self.assertTrue(F(1, 2) < 0.6)
574 self.assertFalse(F(1, 2) < 0.4)
575 self.assertTrue(0.4 < F(1, 2))
576 self.assertFalse(0.5 < F(1, 2))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000577
Mark Dickinson85424c92009-07-18 14:41:42 +0000578 self.assertFalse(float('inf') < F(1, 2))
579 self.assertTrue(float('-inf') < F(0, 10))
580 self.assertFalse(float('nan') < F(-3, 7))
581 self.assertTrue(F(1, 2) < float('inf'))
582 self.assertFalse(F(17, 12) < float('-inf'))
583 self.assertFalse(F(144, -89) < float('nan'))
584
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000585 def testMixedLessEqual(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000586 self.assertTrue(0.5 <= F(1, 2))
587 self.assertFalse(0.6 <= F(1, 2))
588 self.assertTrue(F(1, 2) <= 0.5)
589 self.assertFalse(F(1, 2) <= 0.4)
590 self.assertTrue(2 <= F(4, 2))
591 self.assertFalse(2 <= F(3, 2))
592 self.assertTrue(F(4, 2) <= 2)
593 self.assertFalse(F(5, 2) <= 2)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000594
Mark Dickinson85424c92009-07-18 14:41:42 +0000595 self.assertFalse(float('inf') <= F(1, 2))
596 self.assertTrue(float('-inf') <= F(0, 10))
597 self.assertFalse(float('nan') <= F(-3, 7))
598 self.assertTrue(F(1, 2) <= float('inf'))
599 self.assertFalse(F(17, 12) <= float('-inf'))
600 self.assertFalse(F(144, -89) <= float('nan'))
601
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000602 def testBigFloatComparisons(self):
603 # Because 10**23 can't be represented exactly as a float:
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000604 self.assertFalse(F(10**23) == float(10**23))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000605 # The first test demonstrates why these are important.
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000606 self.assertFalse(1e23 < float(F(math.trunc(1e23) + 1)))
607 self.assertTrue(1e23 < F(math.trunc(1e23) + 1))
608 self.assertFalse(1e23 <= F(math.trunc(1e23) - 1))
609 self.assertTrue(1e23 > F(math.trunc(1e23) - 1))
610 self.assertFalse(1e23 >= F(math.trunc(1e23) + 1))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000611
612 def testBigComplexComparisons(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000613 self.assertFalse(F(10**23) == complex(10**23))
Mark Dickinson327f02c2010-03-27 11:11:13 +0000614 self.assertRaises(TypeError, operator.gt, F(10**23), complex(10**23))
615 self.assertRaises(TypeError, operator.le, F(10**23), complex(10**23))
616
617 x = F(3, 8)
618 z = complex(0.375, 0.0)
619 w = complex(0.375, 0.2)
620 self.assertTrue(x == z)
621 self.assertFalse(x != z)
622 self.assertFalse(x == w)
623 self.assertTrue(x != w)
624 for op in operator.lt, operator.le, operator.gt, operator.ge:
625 self.assertRaises(TypeError, op, x, z)
626 self.assertRaises(TypeError, op, z, x)
627 self.assertRaises(TypeError, op, x, w)
628 self.assertRaises(TypeError, op, w, x)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000629
630 def testMixedEqual(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000631 self.assertTrue(0.5 == F(1, 2))
632 self.assertFalse(0.6 == F(1, 2))
633 self.assertTrue(F(1, 2) == 0.5)
634 self.assertFalse(F(1, 2) == 0.4)
635 self.assertTrue(2 == F(4, 2))
636 self.assertFalse(2 == F(3, 2))
637 self.assertTrue(F(4, 2) == 2)
638 self.assertFalse(F(5, 2) == 2)
Mark Dickinson85424c92009-07-18 14:41:42 +0000639 self.assertFalse(F(5, 2) == float('nan'))
640 self.assertFalse(float('nan') == F(3, 7))
641 self.assertFalse(F(5, 2) == float('inf'))
642 self.assertFalse(float('-inf') == F(2, 5))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000643
644 def testStringification(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +0000645 self.assertEqual("Fraction(7, 3)", repr(F(7, 3)))
646 self.assertEqual("Fraction(6283185307, 2000000000)",
647 repr(F('3.1415926535')))
648 self.assertEqual("Fraction(-1, 100000000000000000000)",
649 repr(F(1, -10**20)))
650 self.assertEqual("7/3", str(F(7, 3)))
651 self.assertEqual("7", str(F(7, 1)))
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000652
653 def testHash(self):
Ezio Melotti682d3742012-02-29 14:05:53 +0200654 hmod = sys.hash_info.modulus
655 hinf = sys.hash_info.inf
Ezio Melottib3aedd42010-11-20 19:04:17 +0000656 self.assertEqual(hash(2.5), hash(F(5, 2)))
657 self.assertEqual(hash(10**50), hash(F(10**50)))
658 self.assertNotEqual(hash(float(10**23)), hash(F(10**23)))
Ezio Melotti682d3742012-02-29 14:05:53 +0200659 self.assertEqual(hinf, hash(F(1, hmod)))
Mark Dickinsonfec66202010-11-13 10:27:38 +0000660 # Check that __hash__ produces the same value as hash(), for
661 # consistency with int and Decimal. (See issue #10356.)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000662 self.assertEqual(hash(F(-1)), F(-1).__hash__())
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000663
664 def testApproximatePi(self):
665 # Algorithm borrowed from
666 # http://docs.python.org/lib/decimal-recipes.html
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000667 three = F(3)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000668 lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000669 while abs(s - lasts) > F(1, 10**9):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000670 lasts = s
671 n, na = n+na, na+8
672 d, da = d+da, da+32
673 t = (t * n) / d
674 s += t
Ezio Melottib3aedd42010-11-20 19:04:17 +0000675 self.assertAlmostEqual(math.pi, s)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000676
677 def testApproximateCos1(self):
678 # Algorithm borrowed from
679 # http://docs.python.org/lib/decimal-recipes.html
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000680 x = F(1)
681 i, lasts, s, fact, num, sign = 0, 0, F(1), 1, 1, 1
682 while abs(s - lasts) > F(1, 10**9):
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000683 lasts = s
684 i += 2
685 fact *= i * (i-1)
686 num *= x * x
687 sign *= -1
688 s += num / fact * sign
Ezio Melottib3aedd42010-11-20 19:04:17 +0000689 self.assertAlmostEqual(math.cos(1), s)
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000690
Christian Heimes969fe572008-01-25 11:23:10 +0000691 def test_copy_deepcopy_pickle(self):
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000692 r = F(13, 7)
Ezio Melotti682d3742012-02-29 14:05:53 +0200693 dr = DummyFraction(13, 7)
Christian Heimes969fe572008-01-25 11:23:10 +0000694 self.assertEqual(r, loads(dumps(r)))
695 self.assertEqual(id(r), id(copy(r)))
696 self.assertEqual(id(r), id(deepcopy(r)))
Ezio Melotti682d3742012-02-29 14:05:53 +0200697 self.assertNotEqual(id(dr), id(copy(dr)))
698 self.assertNotEqual(id(dr), id(deepcopy(dr)))
699 self.assertTypedEquals(dr, copy(dr))
700 self.assertTypedEquals(dr, deepcopy(dr))
Christian Heimes969fe572008-01-25 11:23:10 +0000701
Mark Dickinsonc28ad272009-02-12 17:58:36 +0000702 def test_slots(self):
703 # Issue 4998
704 r = F(13, 7)
705 self.assertRaises(AttributeError, setattr, r, 'a', 10)
706
Victor Stinnerdc7a50d2020-02-07 23:42:51 +0100707 def test_int_subclass(self):
708 class myint(int):
709 def __mul__(self, other):
710 return type(self)(int(self) * int(other))
711 def __floordiv__(self, other):
712 return type(self)(int(self) // int(other))
713 def __mod__(self, other):
714 x = type(self)(int(self) % int(other))
715 return x
716 @property
717 def numerator(self):
718 return type(self)(int(self))
719 @property
720 def denominator(self):
721 return type(self)(1)
722
723 f = fractions.Fraction(myint(1 * 3), myint(2 * 3))
724 self.assertEqual(f.numerator, 1)
725 self.assertEqual(f.denominator, 2)
726 self.assertEqual(type(f.numerator), myint)
727 self.assertEqual(type(f.denominator), myint)
728
Victor Stinner4691a2f2020-01-16 11:02:51 +0100729
Guido van Rossum7736b5b2008-01-15 21:44:53 +0000730if __name__ == '__main__':
Zachary Ware38c707e2015-04-13 15:00:43 -0500731 unittest.main()