From 42a7c4615eb66a7f63d9f047224fa11f1eeda9e1 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Mon, 26 Apr 2021 07:17:18 +0300 Subject: [PATCH 1/7] =?UTF-8?q?bpo-23975:=20Correct=20conversion=20of=20Ra?= =?UTF-8?q?tional=E2=80=99s=20to=20float?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also document that numerator/denominator properties are instances of the Integral. --- Doc/library/numbers.rst | 2 +- Lib/numbers.py | 2 +- .../next/Library/2021-04-26-07-14-21.bpo-23975.h6TJCc.rst | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2021-04-26-07-14-21.bpo-23975.h6TJCc.rst diff --git a/Doc/library/numbers.rst b/Doc/library/numbers.rst index b77845ed0dee92..6024e9ae791308 100644 --- a/Doc/library/numbers.rst +++ b/Doc/library/numbers.rst @@ -60,7 +60,7 @@ The numeric tower Subtypes :class:`Real` and adds :attr:`~Rational.numerator` and :attr:`~Rational.denominator` properties, which - should be in lowest terms. With these, it provides a default for + should be in lowest terms, instances of :class:`Integral`. With these, it provides a default for :func:`float`. .. attribute:: numerator diff --git a/Lib/numbers.py b/Lib/numbers.py index 5b98e642083b36..0985dd85f60a78 100644 --- a/Lib/numbers.py +++ b/Lib/numbers.py @@ -288,7 +288,7 @@ def __float__(self): 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/Misc/NEWS.d/next/Library/2021-04-26-07-14-21.bpo-23975.h6TJCc.rst b/Misc/NEWS.d/next/Library/2021-04-26-07-14-21.bpo-23975.h6TJCc.rst new file mode 100644 index 00000000000000..756f6c9eb9e842 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-04-26-07-14-21.bpo-23975.h6TJCc.rst @@ -0,0 +1 @@ +Correct conversion of :class:`numbers.Rational`'s to :class:`float`. From 40e95845a7f10989877dd76590378b375654269c Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Sun, 20 Mar 2022 12:48:55 +0300 Subject: [PATCH 2/7] Add tests --- Lib/test/test_numeric_tower.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Lib/test/test_numeric_tower.py b/Lib/test/test_numeric_tower.py index c54dedb8b793a0..e5e82286f5bdea 100644 --- a/Lib/test/test_numeric_tower.py +++ b/Lib/test/test_numeric_tower.py @@ -14,6 +14,13 @@ _PyHASH_MODULUS = sys.hash_info.modulus _PyHASH_INF = sys.hash_info.inf + +class DummyIntegral(int): + def __truediv__(self, other): + raise NotImplemented + __rtruediv__ = __truediv__ + + 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 +128,12 @@ def test_fractions(self): 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 produces a float + x = F(*map(DummyIntegral, (1, 2))) + self.assertRaises(TypeError, int(x.numerator)) + self.assertRaises(TypeError, int(x.denominator)) + self.assertEquals(float(x), 0.5) + def test_hash_normalization(self): # Test for a bug encountered while changing long_hash. # From c86c9999b3f133569fe6478652321818dabab808 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Mon, 21 Mar 2022 05:54:54 +0300 Subject: [PATCH 3/7] Correct tests, expand docs --- Lib/test/test_numeric_tower.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_numeric_tower.py b/Lib/test/test_numeric_tower.py index e5e82286f5bdea..10bbb0f82a9e07 100644 --- a/Lib/test/test_numeric_tower.py +++ b/Lib/test/test_numeric_tower.py @@ -16,10 +16,24 @@ 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): - raise NotImplemented + 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): @@ -128,10 +142,11 @@ def test_fractions(self): 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 produces a float - x = F(*map(DummyIntegral, (1, 2))) - self.assertRaises(TypeError, int(x.numerator)) - self.assertRaises(TypeError, int(x.denominator)) + # 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.assertEquals(float(x), 0.5) def test_hash_normalization(self): From 89ba428ed6a7cfa1c3f86d730594ae9ae581f693 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Fri, 22 Jul 2022 06:32:24 +0300 Subject: [PATCH 4/7] assertEquals -> assertEqual --- Lib/test/test_numeric_tower.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_numeric_tower.py b/Lib/test/test_numeric_tower.py index 10bbb0f82a9e07..9cd85e13634c2b 100644 --- a/Lib/test/test_numeric_tower.py +++ b/Lib/test/test_numeric_tower.py @@ -147,7 +147,7 @@ def test_fractions(self): # Rational.__float__() method has required type conversions. x = F(DummyIntegral(1), DummyIntegral(2), _normalize=False) self.assertRaises(TypeError, lambda: x.numerator/x.denominator) - self.assertEquals(float(x), 0.5) + self.assertEqual(float(x), 0.5) def test_hash_normalization(self): # Test for a bug encountered while changing long_hash. From 23ad615da42f5821d023ece03ac645608c4ea067 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 4 Sep 2022 11:39:31 +0100 Subject: [PATCH 5/7] Fix long lines, tweak wording --- Doc/library/numbers.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/numbers.rst b/Doc/library/numbers.rst index c5c8adfc446427..ce27e2e2fc219e 100644 --- a/Doc/library/numbers.rst +++ b/Doc/library/numbers.rst @@ -59,9 +59,9 @@ The numeric tower .. class:: Rational Subtypes :class:`Real` and adds - :attr:`~Rational.numerator` and :attr:`~Rational.denominator` properties, which - should be in lowest terms, instances of :class:`Integral`. With these, it provides a default for - :func:`float`. + :attr:`~Rational.numerator` and :attr:`~Rational.denominator` properties, + which should be in lowest terms, instances of :class:`Integral`. It also + provides a default for :func:`float`. .. attribute:: numerator From e2a2e1aada91ca9cea05712b2b0e6f52a24bfb22 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 4 Sep 2022 12:01:03 +0100 Subject: [PATCH 6/7] Improve readability of doc addition --- Doc/library/numbers.rst | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Doc/library/numbers.rst b/Doc/library/numbers.rst index ce27e2e2fc219e..b3dce151aee289 100644 --- a/Doc/library/numbers.rst +++ b/Doc/library/numbers.rst @@ -58,10 +58,13 @@ The numeric tower .. class:: Rational - Subtypes :class:`Real` and adds - :attr:`~Rational.numerator` and :attr:`~Rational.denominator` properties, - which should be in lowest terms, instances of :class:`Integral`. It also - provides a default for :func:`float`. + Subtypes :class:`Real` and adds :attr:`~Rational.numerator` and + :attr:`~Rational.denominator` properties. It also provides a default for + :func:`float`. + + The :attr:`~Rational.numerator` and :attr:`~Rational.denominator` values + should be instances of :class:`Integral` and should be in lowest terms with + :attr:`~Rational.denominator` positive. .. attribute:: numerator From b7fb6c6ee9033cc1aac369f2f5d9c9f7fefe2903 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 4 Sep 2022 12:33:35 +0100 Subject: [PATCH 7/7] Refresh news entry to use GH issue number --- ...5.h6TJCc.rst => 2022-09-04-12-32-52.gh-issue-68163.h6TJCc.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Misc/NEWS.d/next/Library/{2021-04-26-07-14-21.bpo-23975.h6TJCc.rst => 2022-09-04-12-32-52.gh-issue-68163.h6TJCc.rst} (100%) diff --git a/Misc/NEWS.d/next/Library/2021-04-26-07-14-21.bpo-23975.h6TJCc.rst b/Misc/NEWS.d/next/Library/2022-09-04-12-32-52.gh-issue-68163.h6TJCc.rst similarity index 100% rename from Misc/NEWS.d/next/Library/2021-04-26-07-14-21.bpo-23975.h6TJCc.rst rename to Misc/NEWS.d/next/Library/2022-09-04-12-32-52.gh-issue-68163.h6TJCc.rst