]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-77465: Increase test coverage for the numbers module (GH-111738)
authorAN Long <aisk@users.noreply.github.com>
Thu, 25 Jan 2024 14:35:05 +0000 (22:35 +0800)
committerGitHub <noreply@github.com>
Thu, 25 Jan 2024 14:35:05 +0000 (16:35 +0200)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Lib/test/test_abstract_numbers.py

index 2e06f0d16fdd05bc9e68821b9e0f18afacaa9677..72232b670cdb89e4ff0e8de709db690e4ca5c3c1 100644 (file)
@@ -1,14 +1,34 @@
 """Unit tests for numbers.py."""
 
+import abc
 import math
 import operator
 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):
     def test_int(self):
         self.assertTrue(issubclass(int, Integral))
+        self.assertTrue(issubclass(int, Rational))
+        self.assertTrue(issubclass(int, Real))
         self.assertTrue(issubclass(int, Complex))
+        self.assertTrue(issubclass(int, Number))
 
         self.assertEqual(7, int(7).real)
         self.assertEqual(0, int(7).imag)
@@ -18,8 +38,11 @@ class TestNumbers(unittest.TestCase):
         self.assertEqual(1, int(7).denominator)
 
     def test_float(self):
+        self.assertFalse(issubclass(float, Integral))
         self.assertFalse(issubclass(float, Rational))
         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(0, float(7.3).imag)
@@ -27,8 +50,11 @@ class TestNumbers(unittest.TestCase):
         self.assertEqual(-7.3, float(-7.3).conjugate())
 
     def test_complex(self):
+        self.assertFalse(issubclass(complex, Integral))
+        self.assertFalse(issubclass(complex, Rational))
         self.assertFalse(issubclass(complex, Real))
         self.assertTrue(issubclass(complex, Complex))
+        self.assertTrue(issubclass(complex, Number))
 
         c1, c2 = complex(3, 2), complex(4,1)
         # 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)
 
 
+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__":
     unittest.main()