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 +#include #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; }