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;