summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-02-07 22:42:51 (GMT)
committerGitHub <noreply@github.com>2020-02-07 22:42:51 (GMT)
commitdc7a50d73a3d16918529669ff7b8783c08cff090 (patch)
tree03dd057164d756447338063473d5559a1fc9c957 /Lib
parent60ac6ed5579f6666130fc264d3b748ee9575e3aa (diff)
downloadcpython-dc7a50d73a3d16918529669ff7b8783c08cff090.zip
cpython-dc7a50d73a3d16918529669ff7b8783c08cff090.tar.gz
cpython-dc7a50d73a3d16918529669ff7b8783c08cff090.tar.bz2
bpo-39350: Fix fractions for int subclasses (GH-18375)
Fix regression in fractions.Fraction if the numerator and/or the denominator is an int subclass. The math.gcd() function is now used to normalize the numerator and denominator. math.gcd() always return a int type. Previously, the GCD type depended on numerator and denominator.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/fractions.py10
-rw-r--r--Lib/test/test_fractions.py22
2 files changed, 25 insertions, 7 deletions
diff --git a/Lib/fractions.py b/Lib/fractions.py
index f5a8544..de3e23b 100644
--- a/Lib/fractions.py
+++ b/Lib/fractions.py
@@ -155,13 +155,9 @@ class Fraction(numbers.Rational):
if denominator == 0:
raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
if _normalize:
- if type(numerator) is int is type(denominator):
- # *very* normal case
- g = math.gcd(numerator, denominator)
- if denominator < 0:
- g = -g
- else:
- g = _gcd(numerator, denominator)
+ g = math.gcd(numerator, denominator)
+ if denominator < 0:
+ g = -g
numerator //= g
denominator //= g
self._numerator = numerator
diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py
index 4649a34..c748533 100644
--- a/Lib/test/test_fractions.py
+++ b/Lib/test/test_fractions.py
@@ -703,6 +703,28 @@ class FractionTest(unittest.TestCase):
r = F(13, 7)
self.assertRaises(AttributeError, setattr, r, 'a', 10)
+ def test_int_subclass(self):
+ class myint(int):
+ def __mul__(self, other):
+ return type(self)(int(self) * int(other))
+ def __floordiv__(self, other):
+ return type(self)(int(self) // int(other))
+ def __mod__(self, other):
+ x = type(self)(int(self) % int(other))
+ return x
+ @property
+ def numerator(self):
+ return type(self)(int(self))
+ @property
+ def denominator(self):
+ return type(self)(1)
+
+ f = fractions.Fraction(myint(1 * 3), myint(2 * 3))
+ self.assertEqual(f.numerator, 1)
+ self.assertEqual(f.denominator, 2)
+ self.assertEqual(type(f.numerator), myint)
+ self.assertEqual(type(f.denominator), myint)
+
if __name__ == '__main__':
unittest.main()