diff -r 909099686e6e Lib/test/test_float.py --- a/Lib/test/test_float.py Tue May 10 12:01:56 2016 +0300 +++ b/Lib/test/test_float.py Tue May 10 22:07:12 2016 +0300 @@ -161,11 +161,12 @@ class GeneralFloatCases(unittest.TestCas def __float__(self): return float(str(self)) + 1 - self.assertAlmostEqual(float(Foo1()), 42.) - self.assertAlmostEqual(float(Foo2()), 42.) - self.assertAlmostEqual(float(Foo3(21)), 42.) + self.assertEqual(float(Foo1()), 42.) + self.assertEqual(float(Foo2()), 42.) + with self.assertWarns(DeprecationWarning): + self.assertEqual(float(Foo3(21)), 42.) self.assertRaises(TypeError, float, Foo4(42)) - self.assertAlmostEqual(float(FooStr('8')), 9.) + self.assertEqual(float(FooStr('8')), 9.) class Foo5: def __float__(self): @@ -176,10 +177,14 @@ class GeneralFloatCases(unittest.TestCas class F: def __float__(self): return OtherFloatSubclass(42.) - self.assertAlmostEqual(float(F()), 42.) - self.assertIs(type(float(F())), OtherFloatSubclass) - self.assertAlmostEqual(FloatSubclass(F()), 42.) - self.assertIs(type(FloatSubclass(F())), FloatSubclass) + 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) def test_is_integer(self): self.assertFalse((1.1).is_integer()) diff -r 909099686e6e Objects/abstract.c --- a/Objects/abstract.c Tue May 10 12:01:56 2016 +0300 +++ b/Objects/abstract.c Tue May 10 22:07:12 2016 +0300 @@ -1353,15 +1353,29 @@ PyNumber_Float(PyObject *o) return null_error(); m = o->ob_type->tp_as_number; if (m && m->nb_float) { /* This should include subclasses of float */ - PyObject *res = m->nb_float(o); - if (res && !PyFloat_Check(res)) { + PyObject *res = m->nb_float(o), *res2; + if (!res || PyFloat_CheckExact(res)) { + return res; + } + if (!PyFloat_Check(res)) { PyErr_Format(PyExc_TypeError, "__float__ returned non-float (type %.200s)", res->ob_type->tp_name); Py_DECREF(res); return NULL; } - return res; + /* Issue #26983: warn if 'res' not of exact type float. */ + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "__float__ returned non-float (type %.200s). " + "The ability to return an instance of a strict subclass of float " + "is deprecated, and may be removed in a future version of Python.", + res->ob_type->tp_name)) { + Py_DECREF(res); + return NULL; + } + res2 = PyFloat_FromDouble(((PyFloatObject *)res)->ob_fval); + Py_DECREF(res); + return res2; } if (PyFloat_Check(o)) { /* A float subclass with nb_float == NULL */ PyFloatObject *po = (PyFloatObject *)o;