gh-77465: Increase test coverage for the numbers module (GH-111738)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
AN Long 2024-01-25 22:35:05 +08:00 committed by GitHub
parent 0315941441
commit e721adf4bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 157 additions and 1 deletions

View File

@ -1,14 +1,34 @@
"""Unit tests for numbers.py.""" """Unit tests for numbers.py."""
import abc
import math import math
import operator import operator
import unittest import unittest
from numbers import Complex, Real, Rational, Integral from numbers import Complex, Real, Rational, Integral, Number
def concretize(cls):
def not_implemented(*args, **kwargs):
raise NotImplementedError()
for name in dir(cls):
try:
value = getattr(cls, name)
if value.__isabstractmethod__:
setattr(cls, name, not_implemented)
except AttributeError:
pass
abc.update_abstractmethods(cls)
return cls
class TestNumbers(unittest.TestCase): class TestNumbers(unittest.TestCase):
def test_int(self): def test_int(self):
self.assertTrue(issubclass(int, Integral)) self.assertTrue(issubclass(int, Integral))
self.assertTrue(issubclass(int, Rational))
self.assertTrue(issubclass(int, Real))
self.assertTrue(issubclass(int, Complex)) self.assertTrue(issubclass(int, Complex))
self.assertTrue(issubclass(int, Number))
self.assertEqual(7, int(7).real) self.assertEqual(7, int(7).real)
self.assertEqual(0, int(7).imag) self.assertEqual(0, int(7).imag)
@ -18,8 +38,11 @@ class TestNumbers(unittest.TestCase):
self.assertEqual(1, int(7).denominator) self.assertEqual(1, int(7).denominator)
def test_float(self): def test_float(self):
self.assertFalse(issubclass(float, Integral))
self.assertFalse(issubclass(float, Rational)) self.assertFalse(issubclass(float, Rational))
self.assertTrue(issubclass(float, Real)) self.assertTrue(issubclass(float, Real))
self.assertTrue(issubclass(float, Complex))
self.assertTrue(issubclass(float, Number))
self.assertEqual(7.3, float(7.3).real) self.assertEqual(7.3, float(7.3).real)
self.assertEqual(0, float(7.3).imag) self.assertEqual(0, float(7.3).imag)
@ -27,8 +50,11 @@ class TestNumbers(unittest.TestCase):
self.assertEqual(-7.3, float(-7.3).conjugate()) self.assertEqual(-7.3, float(-7.3).conjugate())
def test_complex(self): def test_complex(self):
self.assertFalse(issubclass(complex, Integral))
self.assertFalse(issubclass(complex, Rational))
self.assertFalse(issubclass(complex, Real)) self.assertFalse(issubclass(complex, Real))
self.assertTrue(issubclass(complex, Complex)) self.assertTrue(issubclass(complex, Complex))
self.assertTrue(issubclass(complex, Number))
c1, c2 = complex(3, 2), complex(4,1) c1, c2 = complex(3, 2), complex(4,1)
# XXX: This is not ideal, but see the comment in math_trunc(). # XXX: This is not ideal, but see the comment in math_trunc().
@ -40,5 +66,135 @@ class TestNumbers(unittest.TestCase):
self.assertRaises(TypeError, int, c1) self.assertRaises(TypeError, int, c1)
class TestNumbersDefaultMethods(unittest.TestCase):
def test_complex(self):
@concretize
class MyComplex(Complex):
def __init__(self, real, imag):
self.r = real
self.i = imag
@property
def real(self):
return self.r
@property
def imag(self):
return self.i
def __add__(self, other):
if isinstance(other, Complex):
return MyComplex(self.imag + other.imag,
self.real + other.real)
raise NotImplementedError
def __neg__(self):
return MyComplex(-self.real, -self.imag)
def __eq__(self, other):
if isinstance(other, Complex):
return self.imag == other.imag and self.real == other.real
if isinstance(other, Number):
return self.imag == 0 and self.real == other.real
# test __bool__
self.assertTrue(bool(MyComplex(1, 1)))
self.assertTrue(bool(MyComplex(0, 1)))
self.assertTrue(bool(MyComplex(1, 0)))
self.assertFalse(bool(MyComplex(0, 0)))
# test __sub__
self.assertEqual(MyComplex(2, 3) - complex(1, 2), MyComplex(1, 1))
# test __rsub__
self.assertEqual(complex(2, 3) - MyComplex(1, 2), MyComplex(1, 1))
def test_real(self):
@concretize
class MyReal(Real):
def __init__(self, n):
self.n = n
def __pos__(self):
return self.n
def __float__(self):
return float(self.n)
def __floordiv__(self, other):
return self.n // other
def __rfloordiv__(self, other):
return other // self.n
def __mod__(self, other):
return self.n % other
def __rmod__(self, other):
return other % self.n
# test __divmod__
self.assertEqual(divmod(MyReal(3), 2), (1, 1))
# test __rdivmod__
self.assertEqual(divmod(3, MyReal(2)), (1, 1))
# test __complex__
self.assertEqual(complex(MyReal(1)), 1+0j)
# test real
self.assertEqual(MyReal(3).real, 3)
# test imag
self.assertEqual(MyReal(3).imag, 0)
# test conjugate
self.assertEqual(MyReal(123).conjugate(), 123)
def test_rational(self):
@concretize
class MyRational(Rational):
def __init__(self, numerator, denominator):
self.n = numerator
self.d = denominator
@property
def numerator(self):
return self.n
@property
def denominator(self):
return self.d
# test__float__
self.assertEqual(float(MyRational(5, 2)), 2.5)
def test_integral(self):
@concretize
class MyIntegral(Integral):
def __init__(self, n):
self.n = n
def __pos__(self):
return self.n
def __int__(self):
return self.n
# test __index__
self.assertEqual(operator.index(MyIntegral(123)), 123)
# test __float__
self.assertEqual(float(MyIntegral(123)), 123.0)
# test numerator
self.assertEqual(MyIntegral(123).numerator, 123)
# test denominator
self.assertEqual(MyIntegral(123).denominator, 1)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()