Serhiy Storchaka <storch...@gmail.com> added the comment:
Here is a patch with tests.
> Nope. Values just larger than DBL_MAX won't raise OverflowError here.
Isn't that a little bit. But values that rounded to DBL_MAX can raise
OverflowError. In any case it's too difficult to achieve strict behavior
in this corner case.
> Possibly. But there's also the fact that 3.2 already returns inf here; we'd
> need a pretty good reason to break that.
In the end, we may add the environment variable
PYTHONDONTRAISEEXCEPTIONIFFLOATOVERFLOWS to control this behaviour.
> Like I said, I'm not sure which the right way to go here is.
Take a look at the tests and may be you'll see the system.
----------
Added file: http://bugs.python.org/file25455/getargs_float_overflow_2.patch
_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue14722>
_______________________________________
diff -r 01824bf55376 Lib/test/test_getargs2.py
--- a/Lib/test/test_getargs2.py Fri May 04 11:06:09 2012 -0400
+++ b/Lib/test/test_getargs2.py Fri May 04 22:07:37 2012 +0300
@@ -1,4 +1,5 @@
import unittest
+import math
from test import support
from _testcapi import getargs_keywords, getargs_keyword_only
@@ -22,6 +23,9 @@
> K * unsigned long long none
> L long long LLONG_MIN..LLONG_MAX
+> f float -FLT_MAX..FLT_MAX
+> d double -DBL_MAX..DBL_MAX
+
> Notes:
>
> * New format codes.
@@ -39,17 +43,25 @@
from _testcapi import UCHAR_MAX, USHRT_MAX, UINT_MAX, ULONG_MAX, INT_MAX, \
INT_MIN, LONG_MIN, LONG_MAX, PY_SSIZE_T_MIN, PY_SSIZE_T_MAX, \
- SHRT_MIN, SHRT_MAX
+ SHRT_MIN, SHRT_MAX, \
+ FLT_MAX, FLT_EPSILON, DBL_MAX, DBL_EPSILON
# fake, they are not defined in Python's header files
LLONG_MAX = 2**63-1
LLONG_MIN = -2**63
ULLONG_MAX = 2**64-1
+INF = float('inf')
+NAN = float('nan')
+
class Int:
def __int__(self):
return 99
+class Float:
+ def __float__(self):
+ return 34.125
+
class Unsigned_TestCase(unittest.TestCase):
def test_b(self):
from _testcapi import getargs_b
@@ -215,6 +227,50 @@
self.assertEqual(VERY_LARGE & ULLONG_MAX, getargs_K(VERY_LARGE))
+class Float_TestCase(unittest.TestCase):
+ def test_f(self):
+ from _testcapi import getargs_f
+ # f returns 'float', and does range checking (-FLT_MAX ... FLT_MAX)
+ self.assertRaises(TypeError, getargs_f, "Hello")
+ self.assertEqual(34.125, getargs_f(Float()))
+
+ self.assertRaises(OverflowError, getargs_f, -int(FLT_MAX) -
int(FLT_MAX*FLT_EPSILON))
+ self.assertEqual(FLT_MAX, getargs_f(FLT_MAX))
+ self.assertEqual(-FLT_MAX, getargs_f(-FLT_MAX))
+ self.assertRaises(OverflowError, getargs_f, int(FLT_MAX) +
int(FLT_MAX*FLT_EPSILON))
+ if -FLT_MAX != -FLT_MAX - FLT_MAX*FLT_EPSILON:
+ self.assertRaises(OverflowError, getargs_f, -FLT_MAX -
FLT_MAX*FLT_EPSILON)
+ if FLT_MAX != FLT_MAX + FLT_MAX*FLT_EPSILON:
+ self.assertRaises(OverflowError, getargs_f, FLT_MAX +
FLT_MAX*FLT_EPSILON)
+
+ self.assertEqual(0, getargs_f(0))
+ self.assertEqual(34.125, getargs_f(34.125))
+ self.assertRaises(OverflowError, getargs_f, 10**1000)
+
+ self.assertEqual(INF, getargs_f(INF))
+ self.assertEqual(-INF, getargs_f(-INF))
+ self.assertTrue(math.isnan(getargs_f(NAN)))
+
+ def test_d(self):
+ from _testcapi import getargs_d
+ # d returns 'double', and does range checking (-DBL_MAX ... DBL_MAX)
+ self.assertRaises(TypeError, getargs_d, "Hello")
+ self.assertEqual(34.125, getargs_d(Float()))
+
+ self.assertRaises(OverflowError, getargs_d, -int(DBL_MAX) -
int(DBL_MAX*DBL_EPSILON))
+ self.assertEqual(DBL_MAX, getargs_d(DBL_MAX))
+ self.assertEqual(-DBL_MAX, getargs_d(-DBL_MAX))
+ self.assertRaises(OverflowError, getargs_d, int(DBL_MAX) +
int(DBL_MAX*DBL_EPSILON))
+
+ self.assertEqual(0, getargs_d(0))
+ self.assertEqual(34.125, getargs_d(34.125))
+ self.assertRaises(OverflowError, getargs_d, 10**1000)
+
+ self.assertEqual(INF, getargs_d(INF))
+ self.assertEqual(-INF, getargs_d(-INF))
+ self.assertTrue(math.isnan(getargs_d(NAN)))
+
+
class Tuple_TestCase(unittest.TestCase):
def test_tuple(self):
from _testcapi import getargs_tuple
@@ -510,6 +566,7 @@
tests = [
Signed_TestCase,
Unsigned_TestCase,
+ Float_TestCase,
Tuple_TestCase,
Keywords_TestCase,
KeywordOnly_TestCase,
diff -r 01824bf55376 Modules/_testcapimodule.c
--- a/Modules/_testcapimodule.c Fri May 04 11:06:09 2012 -0400
+++ b/Modules/_testcapimodule.c Fri May 04 22:07:37 2012 +0300
@@ -992,6 +992,24 @@
}
static PyObject *
+getargs_f(PyObject *self, PyObject *args)
+{
+ float value;
+ if (!PyArg_ParseTuple(args, "f", &value))
+ return NULL;
+ return PyFloat_FromDouble(value);
+}
+
+static PyObject *
+getargs_d(PyObject *self, PyObject *args)
+{
+ double value;
+ if (!PyArg_ParseTuple(args, "d", &value))
+ return NULL;
+ return PyFloat_FromDouble(value);
+}
+
+static PyObject *
getargs_c(PyObject *self, PyObject *args)
{
char c;
@@ -2447,6 +2465,8 @@
(PyCFunction)test_long_long_and_overflow, METH_NOARGS},
{"test_L_code", (PyCFunction)test_L_code, METH_NOARGS},
#endif
+ {"getargs_f", getargs_f, METH_VARARGS},
+ {"getargs_d", getargs_d, METH_VARARGS},
{"getargs_c", getargs_c, METH_VARARGS},
{"getargs_s", getargs_s, METH_VARARGS},
{"getargs_s_star", getargs_s_star, METH_VARARGS},
@@ -2698,8 +2718,10 @@
PyModule_AddObject(m, "ULONG_MAX", PyLong_FromUnsignedLong(ULONG_MAX));
PyModule_AddObject(m, "FLT_MAX", PyFloat_FromDouble(FLT_MAX));
PyModule_AddObject(m, "FLT_MIN", PyFloat_FromDouble(FLT_MIN));
+ PyModule_AddObject(m, "FLT_EPSILON", PyFloat_FromDouble(FLT_EPSILON));
PyModule_AddObject(m, "DBL_MAX", PyFloat_FromDouble(DBL_MAX));
PyModule_AddObject(m, "DBL_MIN", PyFloat_FromDouble(DBL_MIN));
+ PyModule_AddObject(m, "DBL_EPSILON", PyFloat_FromDouble(DBL_EPSILON));
PyModule_AddObject(m, "LLONG_MAX", PyLong_FromLongLong(PY_LLONG_MAX));
PyModule_AddObject(m, "LLONG_MIN", PyLong_FromLongLong(PY_LLONG_MIN));
PyModule_AddObject(m, "ULLONG_MAX",
PyLong_FromUnsignedLongLong(PY_ULLONG_MAX));
diff -r 01824bf55376 Python/getargs.c
--- a/Python/getargs.c Fri May 04 11:06:09 2012 -0400
+++ b/Python/getargs.c Fri May 04 22:07:37 2012 +0300
@@ -4,6 +4,7 @@
#include "Python.h"
#include <ctype.h>
+#include <float.h>
#ifdef __cplusplus
@@ -757,8 +758,19 @@
double dval = PyFloat_AsDouble(arg);
if (PyErr_Occurred())
RETURN_ERR_OCCURRED;
- else
- *p = (float) dval;
+ if (Py_IS_FINITE(dval)) {
+ if (dval < -FLT_MAX) {
+ PyErr_SetString(PyExc_OverflowError,
+ "float is less than minimum");
+ RETURN_ERR_OCCURRED;
+ }
+ else if (dval > FLT_MAX) {
+ PyErr_SetString(PyExc_OverflowError,
+ "float is greater than maximum");
+ RETURN_ERR_OCCURRED;
+ }
+ }
+ *p = (float) dval;
break;
}
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com