diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index bf186c191b04d1..3a40a57051fd60 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -179,6 +179,17 @@ wave (Contributed by Bénédikt Tran in :gh:`133873`.) +Others +------ + +* Removed support for handling returned + non-:class:`float`/:class:`complex` types from + :meth:`~object.__float__` and :meth:`~object.__complex__`, + respectively. This had previously raised a + :exc:`DeprecationWarning` since Python 3.7. + (Contributed by Sergey B Kirpichev in :gh:`109311`.) + + Porting to Python 3.15 ====================== diff --git a/Lib/test/test_capi/test_complex.py b/Lib/test/test_capi/test_complex.py index c3189a67cc7e2d..2337dd8b752162 100644 --- a/Lib/test/test_capi/test_complex.py +++ b/Lib/test/test_capi/test_complex.py @@ -82,18 +82,13 @@ def test_realasdouble(self): # Test types with __complex__ dunder method self.assertEqual(realasdouble(Complex()), 4.25) self.assertRaises(TypeError, realasdouble, BadComplex()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(realasdouble(BadComplex2()), 4.25) - with warnings.catch_warnings(): - warnings.simplefilter("error", DeprecationWarning) - self.assertRaises(DeprecationWarning, realasdouble, BadComplex2()) + self.assertRaises(TypeError, realasdouble, BadComplex2()) self.assertRaises(RuntimeError, realasdouble, BadComplex3()) # Test types with __float__ dunder method self.assertEqual(realasdouble(Float()), 4.25) self.assertRaises(TypeError, realasdouble, BadFloat()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(realasdouble(BadFloat2()), 4.25) + self.assertRaises(TypeError, realasdouble, BadFloat2()) self.assertRaises(TypeError, realasdouble, object()) @@ -115,18 +110,13 @@ def test_imagasdouble(self): # Test types with __complex__ dunder method self.assertEqual(imagasdouble(Complex()), 0.5) self.assertRaises(TypeError, imagasdouble, BadComplex()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(imagasdouble(BadComplex2()), 0.5) - with warnings.catch_warnings(): - warnings.simplefilter("error", DeprecationWarning) - self.assertRaises(DeprecationWarning, imagasdouble, BadComplex2()) + self.assertRaises(TypeError, imagasdouble, BadComplex2()) self.assertRaises(RuntimeError, imagasdouble, BadComplex3()) # Test types with __float__ dunder method self.assertEqual(imagasdouble(Float()), 0.0) self.assertRaises(TypeError, imagasdouble, BadFloat()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(imagasdouble(BadFloat2()), 0.0) + self.assertRaises(TypeError, imagasdouble, BadFloat2()) self.assertRaises(TypeError, imagasdouble, object()) @@ -150,18 +140,13 @@ def test_asccomplex(self): # Test types with __complex__ dunder method self.assertEqual(asccomplex(Complex()), 4.25+0.5j) self.assertRaises(TypeError, asccomplex, BadComplex()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(asccomplex(BadComplex2()), 4.25+0.5j) - with warnings.catch_warnings(): - warnings.simplefilter("error", DeprecationWarning) - self.assertRaises(DeprecationWarning, asccomplex, BadComplex2()) + self.assertRaises(TypeError, asccomplex, BadComplex2()) self.assertRaises(RuntimeError, asccomplex, BadComplex3()) # Test types with __float__ dunder method self.assertEqual(asccomplex(Float()), 4.25+0.0j) self.assertRaises(TypeError, asccomplex, BadFloat()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(asccomplex(BadFloat2()), 4.25+0.0j) + self.assertRaises(TypeError, asccomplex, BadFloat2()) self.assertRaises(TypeError, asccomplex, object()) diff --git a/Lib/test/test_capi/test_float.py b/Lib/test/test_capi/test_float.py index f7efe0d02549a3..bb93034803e4fb 100644 --- a/Lib/test/test_capi/test_float.py +++ b/Lib/test/test_capi/test_float.py @@ -101,11 +101,7 @@ def __float__(self): self.assertRaises(RuntimeError, asdouble, BadFloat3()) with self.assertWarns(DeprecationWarning): self.assertEqual(asdouble(BadIndex2()), 1.) - with self.assertWarns(DeprecationWarning): - self.assertEqual(asdouble(BadFloat2()), 4.25) - with warnings.catch_warnings(): - warnings.simplefilter("error", DeprecationWarning) - self.assertRaises(DeprecationWarning, asdouble, BadFloat2()) + self.assertRaises(TypeError, asdouble, BadFloat2()) self.assertRaises(TypeError, asdouble, object()) self.assertRaises(TypeError, asdouble, NULL) diff --git a/Lib/test/test_capi/test_getargs.py b/Lib/test/test_capi/test_getargs.py index 67a8da7599511f..9a30f172644023 100644 --- a/Lib/test/test_capi/test_getargs.py +++ b/Lib/test/test_capi/test_getargs.py @@ -451,8 +451,7 @@ def test_f(self): self.assertEqual(getargs_f(FloatSubclass(7.5)), 7.5) self.assertEqual(getargs_f(FloatSubclass2(7.5)), 7.5) self.assertRaises(TypeError, getargs_f, BadFloat()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(getargs_f(BadFloat2()), 4.25) + self.assertRaises(TypeError, getargs_f, BadFloat2()) self.assertEqual(getargs_f(BadFloat3(7.5)), 7.5) self.assertEqual(getargs_f(Index()), 99.0) self.assertRaises(TypeError, getargs_f, Int()) @@ -485,8 +484,7 @@ def test_d(self): self.assertEqual(getargs_d(FloatSubclass(7.5)), 7.5) self.assertEqual(getargs_d(FloatSubclass2(7.5)), 7.5) self.assertRaises(TypeError, getargs_d, BadFloat()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(getargs_d(BadFloat2()), 4.25) + self.assertRaises(TypeError, getargs_d, BadFloat2()) self.assertEqual(getargs_d(BadFloat3(7.5)), 7.5) self.assertEqual(getargs_d(Index()), 99.0) self.assertRaises(TypeError, getargs_d, Int()) @@ -509,8 +507,7 @@ def test_D(self): self.assertEqual(getargs_D(ComplexSubclass(7.5+0.25j)), 7.5+0.25j) self.assertEqual(getargs_D(ComplexSubclass2(7.5+0.25j)), 7.5+0.25j) self.assertRaises(TypeError, getargs_D, BadComplex()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(getargs_D(BadComplex2()), 4.25+0.5j) + self.assertRaises(TypeError, getargs_D, BadComplex2()) self.assertEqual(getargs_D(BadComplex3(7.5+0.25j)), 7.5+0.25j) self.assertEqual(getargs_D(Index()), 99.0+0j) self.assertRaises(TypeError, getargs_D, Int()) diff --git a/Lib/test/test_capi/test_number.py b/Lib/test/test_capi/test_number.py index bdd8868529f632..0c52a5e3d832c5 100644 --- a/Lib/test/test_capi/test_number.py +++ b/Lib/test/test_capi/test_number.py @@ -287,11 +287,7 @@ def test_float(self): self.assertEqual(float_(IndexLike.with_val(-1)), -1.0) self.assertRaises(TypeError, float_, FloatLike.with_val(687)) - with warnings.catch_warnings(): - warnings.simplefilter("error", DeprecationWarning) - self.assertRaises(DeprecationWarning, float_, FloatLike.with_val(subclassof(float)(4.25))) - with self.assertWarns(DeprecationWarning): - self.assertEqual(float_(FloatLike.with_val(subclassof(float)(4.25))), 4.25) + self.assertRaises(TypeError, float_, FloatLike.with_val(subclassof(float)(4.25))) self.assertRaises(RuntimeError, float_, FloatLike.with_exc(RuntimeError)) self.assertRaises(TypeError, float_, IndexLike.with_val(1.25)) diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py index 0c7e7341f13d4e..bde9c7a4a8070d 100644 --- a/Lib/test/test_complex.py +++ b/Lib/test/test_complex.py @@ -626,8 +626,7 @@ def __complex__(self): return None check(complex(complex0(1j)), 0.0, 42.0) - with self.assertWarns(DeprecationWarning): - check(complex(complex1(1j)), 0.0, 2.0) + self.assertRaises(TypeError, complex, complex1(1j)) self.assertRaises(TypeError, complex, complex2(1j)) def test___complex__(self): diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index 237d7b5d35edd7..2bba35f765e2ad 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -229,8 +229,7 @@ def __float__(self): self.assertEqual(float(FloatLike(42.)), 42.) self.assertEqual(float(Foo2()), 42.) - with self.assertWarns(DeprecationWarning): - self.assertEqual(float(Foo3(21)), 42.) + self.assertRaises(TypeError, float, Foo3(21)) self.assertRaises(TypeError, float, Foo4(42)) self.assertEqual(float(FooStr('8')), 9.) @@ -238,14 +237,8 @@ def __float__(self): # Issue #24731 f = FloatLike(OtherFloatSubclass(42.)) - with self.assertWarns(DeprecationWarning): - self.assertEqual(float(f), 42.) - with self.assertWarns(DeprecationWarning): - self.assertIs(type(float(f)), float) - with self.assertWarns(DeprecationWarning): - self.assertEqual(FloatSubclass(f), 42.) - with self.assertWarns(DeprecationWarning): - self.assertIs(type(FloatSubclass(f)), FloatSubclass) + self.assertRaises(TypeError, float, f) + self.assertRaises(TypeError, FloatSubclass, f) self.assertEqual(float(MyIndex(42)), 42.0) self.assertRaises(OverflowError, float, MyIndex(2**2000)) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2023-12-04-04-31-59.gh-issue-109311.G-qgQZ.rst b/Misc/NEWS.d/next/Core_and_Builtins/2023-12-04-04-31-59.gh-issue-109311.G-qgQZ.rst new file mode 100644 index 00000000000000..c2a2f9701d8589 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2023-12-04-04-31-59.gh-issue-109311.G-qgQZ.rst @@ -0,0 +1,2 @@ +Remove support for returning non-:class:`complex` or non-:class:`float` +objects in :meth:`~object.__complex__` and :meth:`~object.__float__`. diff --git a/Objects/abstract.c b/Objects/abstract.c index df96b935eccb44..d676c13dea8deb 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -1607,25 +1607,11 @@ PyNumber_Float(PyObject *o) return res; } - if (!PyFloat_Check(res)) { - PyErr_Format(PyExc_TypeError, - "%.50s.__float__ returned non-float (type %.50s)", - Py_TYPE(o)->tp_name, Py_TYPE(res)->tp_name); - Py_DECREF(res); - return NULL; - } - /* Issue #26983: warn if 'res' not of exact type float. */ - if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, - "%.50s.__float__ returned non-float (type %.50s). " - "The ability to return an instance of a strict subclass of float " - "is deprecated, and may be removed in a future version of Python.", - Py_TYPE(o)->tp_name, Py_TYPE(res)->tp_name)) { - Py_DECREF(res); - return NULL; - } - double val = PyFloat_AS_DOUBLE(res); + PyErr_Format(PyExc_TypeError, + "%T.__float__ returned non-float (type %T)", + o, res); Py_DECREF(res); - return PyFloat_FromDouble(val); + return NULL; } if (m && m->nb_index) { diff --git a/Objects/complexobject.c b/Objects/complexobject.c index c2dd320ae73988..662a7f80aae9d3 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -497,23 +497,11 @@ try_complex_special_method(PyObject *op) if (!res || PyComplex_CheckExact(res)) { return res; } - if (!PyComplex_Check(res)) { - PyErr_Format(PyExc_TypeError, - "__complex__ returned non-complex (type %.200s)", - Py_TYPE(res)->tp_name); - Py_DECREF(res); - return NULL; - } - /* Issue #29894: warn if 'res' not of exact type complex. */ - if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, - "__complex__ returned non-complex (type %.200s). " - "The ability to return an instance of a strict subclass of complex " - "is deprecated, and may be removed in a future version of Python.", - Py_TYPE(res)->tp_name)) { - Py_DECREF(res); - return NULL; - } - return res; + PyErr_Format(PyExc_TypeError, + "%T.__complex__ returned non-complex (type %T)", + op, res); + Py_DECREF(res); + return NULL; } return NULL; } diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 93e1973d6b32fc..a7104b242281de 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -286,21 +286,11 @@ PyFloat_AsDouble(PyObject *op) return -1; } if (!PyFloat_CheckExact(res)) { - if (!PyFloat_Check(res)) { - PyErr_Format(PyExc_TypeError, - "%.50s.__float__ returned non-float (type %.50s)", - Py_TYPE(op)->tp_name, Py_TYPE(res)->tp_name); - Py_DECREF(res); - return -1; - } - if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, - "%.50s.__float__ returned non-float (type %.50s). " - "The ability to return an instance of a strict subclass of float " - "is deprecated, and may be removed in a future version of Python.", - Py_TYPE(op)->tp_name, Py_TYPE(res)->tp_name)) { - Py_DECREF(res); - return -1; - } + PyErr_Format(PyExc_TypeError, + "%T.__float__ returned non-float (type %T)", + op, res); + Py_DECREF(res); + return -1; } val = PyFloat_AS_DOUBLE(res);