summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorSergey B Kirpichev <skirpichev@gmail.com>2022-09-04 12:15:59 (GMT)
committerGitHub <noreply@github.com>2022-09-04 12:15:59 (GMT)
commit8464b754c4168586b99e2135ccd2567e025625a9 (patch)
treed4a79892904a7d853a10ed6b6e8dae5f5f428e54 /Lib
parent9b9394df5fa808f9a125e3e472e7df4c24aea5a1 (diff)
downloadcpython-8464b754c4168586b99e2135ccd2567e025625a9.zip
cpython-8464b754c4168586b99e2135ccd2567e025625a9.tar.gz
cpython-8464b754c4168586b99e2135ccd2567e025625a9.tar.bz2
gh-68163: Correct conversion of Rational instances to float (GH-25619)
* gh-68163: Correct conversion of Rational instances to float Also document that numerator/denominator properties are instances of Integral. Co-authored-by: Mark Dickinson <dickinsm@gmail.com>
Diffstat (limited to 'Lib')
-rw-r--r--Lib/numbers.py2
-rw-r--r--Lib/test/test_numeric_tower.py28
2 files changed, 29 insertions, 1 deletions
diff --git a/Lib/numbers.py b/Lib/numbers.py
index 8e37d79..a2913e3 100644
--- a/Lib/numbers.py
+++ b/Lib/numbers.py
@@ -313,7 +313,7 @@ class Rational(Real):
so that ratios of huge integers convert without overflowing.
"""
- return self.numerator / self.denominator
+ return int(self.numerator) / int(self.denominator)
class Integral(Rational):
diff --git a/Lib/test/test_numeric_tower.py b/Lib/test/test_numeric_tower.py
index c54dedb..9cd85e1 100644
--- a/Lib/test/test_numeric_tower.py
+++ b/Lib/test/test_numeric_tower.py
@@ -14,6 +14,27 @@ from fractions import Fraction as F
_PyHASH_MODULUS = sys.hash_info.modulus
_PyHASH_INF = sys.hash_info.inf
+
+class DummyIntegral(int):
+ """Dummy Integral class to test conversion of the Rational to float."""
+
+ def __mul__(self, other):
+ return DummyIntegral(super().__mul__(other))
+ __rmul__ = __mul__
+
+ def __truediv__(self, other):
+ return NotImplemented
+ __rtruediv__ = __truediv__
+
+ @property
+ def numerator(self):
+ return DummyIntegral(self)
+
+ @property
+ def denominator(self):
+ return DummyIntegral(1)
+
+
class HashTest(unittest.TestCase):
def check_equal_hash(self, x, y):
# check both that x and y are equal and that their hashes are equal
@@ -121,6 +142,13 @@ class HashTest(unittest.TestCase):
self.assertEqual(hash(F(7*_PyHASH_MODULUS, 1)), 0)
self.assertEqual(hash(F(-_PyHASH_MODULUS, 1)), 0)
+ # The numbers ABC doesn't enforce that the "true" division
+ # of integers produces a float. This tests that the
+ # Rational.__float__() method has required type conversions.
+ x = F(DummyIntegral(1), DummyIntegral(2), _normalize=False)
+ self.assertRaises(TypeError, lambda: x.numerator/x.denominator)
+ self.assertEqual(float(x), 0.5)
+
def test_hash_normalization(self):
# Test for a bug encountered while changing long_hash.
#