Skip to content

bpo-47079: return a correct type from the Integral.denominator #32022

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Lib/numbers.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,6 @@ def numerator(self):
@property
def denominator(self):
"""Integers have a denominator of 1."""
return 1
return type(self)(1)

Integral.register(int)
63 changes: 63 additions & 0 deletions Lib/test/test_abstract_numbers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,61 @@
import unittest
from numbers import Complex, Real, Rational, Integral


class DummyIntegral(Integral):
"""Dummy Integral class to test default implementations of methods."""

def __init__(self, val=0):
self._val = int(val)

def __int__(self):
return self._val

def __pow__(self, exponent, modulus=None):
return NotImplemented
__rpow__ = __pow__

def __lshift__(self, other):
return NotImplemented
__rlshift__ = __lshift__
__rshift__ = __lshift__
__rrshift__ = __lshift__
__and__ = __lshift__
__rand__ = __lshift__
__xor__ = __lshift__
__rxor__ = __lshift__
__or__ = __lshift__
__ror__ = __lshift__
__add__ = __lshift__
__radd__ = __lshift__
__mul__ = __lshift__
__rmul__ = __lshift__
__mod__ = __lshift__
__rmod__ = __lshift__
__floordiv__ = __lshift__
__rfloordiv__ = __lshift__
__truediv__ = __lshift__
__rtruediv__ = __lshift__
__lt__ = __lshift__
__le__ = __lshift__

def __eq__(self, other):
return all(isinstance(_, DummyIntegral)
for _ in [self, other]) and self._val == other._val

def __invert__(self):
return NotImplemented
__abs__ = __invert__
__neg__ = __invert__
__trunc__ = __invert__
__ceil__ = __invert__
__floor__ = __invert__
__round__ = __invert__

def __pos__(self):
return self


class TestNumbers(unittest.TestCase):
def test_int(self):
self.assertTrue(issubclass(int, Integral))
Expand All @@ -17,6 +72,14 @@ def test_int(self):
self.assertEqual(7, int(7).numerator)
self.assertEqual(1, int(7).denominator)

def test_DummyIntegral(self):
seven = DummyIntegral(7)
one = DummyIntegral(1)
self.assertEqual(float(seven), 7.0)
self.assertEqual(float(one), 1.0)
self.assertEqual(seven.numerator, seven)
self.assertEqual(seven.denominator, one)

def test_float(self):
self.assertFalse(issubclass(float, Rational))
self.assertTrue(issubclass(float, Real))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Correct the implementation of :attr:`Integral.denominator`.