From 1771a0189bcec1face72e6d1ffb88023fd486279 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 22 Aug 2021 13:18:53 +0100 Subject: [PATCH 1/5] bpo-24234: implement complex.__complex__ --- Lib/test/test_complex.py | 12 +++++++++++ .../2021-08-22-12-28-50.bpo-24234.n3oTdx.rst | 3 +++ Objects/clinic/complexobject.c.h | 20 +++++++++++++++++- Objects/complexobject.c | 21 +++++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py index abd7e39cc5ae73..1cd025ed53a5d0 100644 --- a/Lib/test/test_complex.py +++ b/Lib/test/test_complex.py @@ -499,6 +499,18 @@ def __complex__(self): self.assertEqual(complex(complex1(1j)), 2j) self.assertRaises(TypeError, complex, complex2(1j)) + def test___complex__(self): + z = 3 + 4j + self.assertEqual(z.__complex__(), z) + self.assertEqual(type(z.__complex__()), complex) + + class complex_subclass(complex): + pass + + z = complex_subclass(3 + 4j) + self.assertEqual(z.__complex__(), 3 + 4j) + self.assertEqual(type(z.__complex__()), complex) + @support.requires_IEEE_754 def test_constructor_special_numbers(self): class complex2(complex): diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst b/Misc/NEWS.d/next/Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst new file mode 100644 index 00000000000000..f79e6a6a6f0639 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst @@ -0,0 +1,3 @@ +Implement the ``__complex__`` special method on the :class:`complex` type, +so a complex number `z` passes an ``isinstance(z, typing.SupportsComplex)`` +check. diff --git a/Objects/clinic/complexobject.c.h b/Objects/clinic/complexobject.c.h index 557fbf9752faf7..e7d8065e874ef3 100644 --- a/Objects/clinic/complexobject.c.h +++ b/Objects/clinic/complexobject.c.h @@ -69,6 +69,24 @@ complex___format__(PyComplexObject *self, PyObject *arg) return return_value; } +PyDoc_STRVAR(complex___complex____doc__, +"__complex__($self, /)\n" +"--\n" +"\n" +"Convert this value to exact type complex."); + +#define COMPLEX___COMPLEX___METHODDEF \ + {"__complex__", (PyCFunction)complex___complex__, METH_NOARGS, complex___complex____doc__}, + +static PyObject * +complex___complex___impl(PyComplexObject *self); + +static PyObject * +complex___complex__(PyComplexObject *self, PyObject *Py_UNUSED(ignored)) +{ + return complex___complex___impl(self); +} + PyDoc_STRVAR(complex_new__doc__, "complex(real=0, imag=0)\n" "--\n" @@ -113,4 +131,4 @@ complex_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=056cac3226d94967 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6d85094ace15677e input=a9049054013a1b77]*/ diff --git a/Objects/complexobject.c b/Objects/complexobject.c index 3e479497cfcc31..cfe6c737578a03 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -693,8 +693,29 @@ complex___format___impl(PyComplexObject *self, PyObject *format_spec) return _PyUnicodeWriter_Finish(&writer); } +/*[clinic input] +complex.__complex__ + +Convert this value to exact type complex. +[clinic start generated code]*/ + +static PyObject * +complex___complex___impl(PyComplexObject *self) +/*[clinic end generated code: output=e6b35ba3d275dc9c input=3589ada9d27db854]*/ +{ + if (PyComplex_CheckExact(self)) { + Py_INCREF(self); + return (PyObject *)self; + } + else { + return PyComplex_FromCComplex(self->cval); + } +} + + static PyMethodDef complex_methods[] = { COMPLEX_CONJUGATE_METHODDEF + COMPLEX___COMPLEX___METHODDEF COMPLEX___GETNEWARGS___METHODDEF COMPLEX___FORMAT___METHODDEF {NULL, NULL} /* sentinel */ From 3f5f29ba1aba39c344aca8aef83e1464911281f7 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 22 Aug 2021 14:01:27 +0100 Subject: [PATCH 2/5] Bump expected number of builtins docstrings in test_doctest --- Lib/test/test_doctest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py index 8f761d7a52c23e..571dc78bf5076e 100644 --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -668,7 +668,7 @@ def non_Python_modules(): r""" >>> import builtins >>> tests = doctest.DocTestFinder().find(builtins) - >>> 816 < len(tests) < 836 # approximate number of objects with docstrings + >>> 820 < len(tests) < 840 # approximate number of objects with docstrings True >>> real_tests = [t for t in tests if len(t.examples) > 0] >>> len(real_tests) # objects that actually have doctests From 19632aca7e141858caea3372e012118f0b4d3c65 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 22 Aug 2021 14:57:48 +0100 Subject: [PATCH 3/5] Fix reST markup --- .../Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst b/Misc/NEWS.d/next/Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst index f79e6a6a6f0639..46963081ab309c 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst @@ -1,3 +1,3 @@ Implement the ``__complex__`` special method on the :class:`complex` type, -so a complex number `z` passes an ``isinstance(z, typing.SupportsComplex)`` +so a complex number ``z`` passes an ``isinstance(z, typing.SupportsComplex)`` check. From 87ce0892560b540fb360b9c2afda5a5354f855d0 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 22 Aug 2021 15:44:48 +0100 Subject: [PATCH 4/5] Fix reST markup in news entry Co-authored-by: Dong-hee Na --- .../Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst b/Misc/NEWS.d/next/Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst index 46963081ab309c..52397e90fbdfa1 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2021-08-22-12-28-50.bpo-24234.n3oTdx.rst @@ -1,3 +1,3 @@ -Implement the ``__complex__`` special method on the :class:`complex` type, +Implement the :meth:`__complex__` special method on the :class:`complex` type, so a complex number ``z`` passes an ``isinstance(z, typing.SupportsComplex)`` check. From 21955d11d6aa140ec07f48b788eb205f756dba7b Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 22 Aug 2021 15:47:59 +0100 Subject: [PATCH 5/5] Update test_supports_complex in test_typing --- Lib/test/test_typing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 3bd5894f425741..84521ee7dd95f5 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -1533,11 +1533,11 @@ def test_supports_float(self): def test_supports_complex(self): - # Note: complex itself doesn't have __complex__. class C: def __complex__(self): return 0j + self.assertIsSubclass(complex, typing.SupportsComplex) self.assertIsSubclass(C, typing.SupportsComplex) self.assertNotIsSubclass(str, typing.SupportsComplex)