From 21161d73d979012ec3b7247261178b3aa1555486 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sat, 24 Aug 2019 19:45:12 -0700 Subject: [PATCH] [3.8] bpo-37942: Improve argument clinic float converter (GH-15470) (GH-15480) (cherry picked from commit aef9ad82f7f667cd001a7112d3bc636e918626f7) --- Lib/test/clinic.test | 28 ++- .../2019-08-24-12-11-30.bpo-37942.7H8N9a.rst | 1 + Modules/clinic/_ssl.c.h | 14 +- Modules/clinic/_statisticsmodule.c.h | 38 +++- Modules/clinic/audioop.c.h | 62 ++++-- Modules/clinic/cmathmodule.c.h | 50 +++-- Modules/clinic/mathmodule.c.h | 194 +++++++++++++----- Python/clinic/sysmodule.c.h | 14 +- Python/getargs.c | 4 +- Tools/clinic/clinic.py | 24 ++- 10 files changed, 317 insertions(+), 112 deletions(-) create mode 100644 Misc/NEWS.d/next/Tools-Demos/2019-08-24-12-11-30.bpo-37942.7H8N9a.rst diff --git a/Lib/test/clinic.test b/Lib/test/clinic.test index 62c2f00c6b2..ac6f419c0d3 100644 --- a/Lib/test/clinic.test +++ b/Lib/test/clinic.test @@ -1587,9 +1587,15 @@ test_float_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - a = (float) PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + a = (float) (PyFloat_AS_DOUBLE(args[0])); + } + else + { + a = (float) PyFloat_AsDouble(args[0]); + if (a == -1.0 && PyErr_Occurred()) { + goto exit; + } } skip_optional: return_value = test_float_converter_impl(module, a); @@ -1600,7 +1606,7 @@ exit: static PyObject * test_float_converter_impl(PyObject *module, float a) -/*[clinic end generated code: output=8293566b2ec1fc52 input=259c0d98eca35034]*/ +/*[clinic end generated code: output=6b9c7443d2601cea input=259c0d98eca35034]*/ /*[clinic input] @@ -1634,9 +1640,15 @@ test_double_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - a = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + a = PyFloat_AS_DOUBLE(args[0]); + } + else + { + a = PyFloat_AsDouble(args[0]); + if (a == -1.0 && PyErr_Occurred()) { + goto exit; + } } skip_optional: return_value = test_double_converter_impl(module, a); @@ -1647,7 +1659,7 @@ exit: static PyObject * test_double_converter_impl(PyObject *module, double a) -/*[clinic end generated code: output=487081a9b8da67ab input=c6a9945706a41c27]*/ +/*[clinic end generated code: output=5b7b9a0f0791b2cc input=c6a9945706a41c27]*/ /*[clinic input] diff --git a/Misc/NEWS.d/next/Tools-Demos/2019-08-24-12-11-30.bpo-37942.7H8N9a.rst b/Misc/NEWS.d/next/Tools-Demos/2019-08-24-12-11-30.bpo-37942.7H8N9a.rst new file mode 100644 index 00000000000..6f643140955 --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2019-08-24-12-11-30.bpo-37942.7H8N9a.rst @@ -0,0 +1 @@ +Improve ArgumentClinic converter for floats. diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index b1012f7aee2..adef7dbf90c 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -1093,9 +1093,15 @@ _ssl_RAND_add(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } } - entropy = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[1])) { + entropy = PyFloat_AS_DOUBLE(args[1]); + } + else + { + entropy = PyFloat_AsDouble(args[1]); + if (entropy == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = _ssl_RAND_add_impl(module, &view, entropy); @@ -1476,4 +1482,4 @@ exit: #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=a399d0eb393b6fab input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5003112e167cd948 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_statisticsmodule.c.h b/Modules/clinic/_statisticsmodule.c.h index f5a2e4678f3..5ff01efddcd 100644 --- a/Modules/clinic/_statisticsmodule.c.h +++ b/Modules/clinic/_statisticsmodule.c.h @@ -26,17 +26,35 @@ _statistics__normal_dist_inv_cdf(PyObject *module, PyObject *const *args, Py_ssi if (!_PyArg_CheckPositional("_normal_dist_inv_cdf", nargs, 3, 3)) { goto exit; } - p = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + p = PyFloat_AS_DOUBLE(args[0]); } - mu = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + else + { + p = PyFloat_AsDouble(args[0]); + if (p == -1.0 && PyErr_Occurred()) { + goto exit; + } } - sigma = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[1])) { + mu = PyFloat_AS_DOUBLE(args[1]); + } + else + { + mu = PyFloat_AsDouble(args[1]); + if (mu == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[2])) { + sigma = PyFloat_AS_DOUBLE(args[2]); + } + else + { + sigma = PyFloat_AsDouble(args[2]); + if (sigma == -1.0 && PyErr_Occurred()) { + goto exit; + } } _return_value = _statistics__normal_dist_inv_cdf_impl(module, p, mu, sigma); if ((_return_value == -1.0) && PyErr_Occurred()) { @@ -47,4 +65,4 @@ _statistics__normal_dist_inv_cdf(PyObject *module, PyObject *const *args, Py_ssi exit: return return_value; } -/*[clinic end generated code: output=ba6af124acd34732 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c5826928a238326c input=a9049054013a1b77]*/ diff --git a/Modules/clinic/audioop.c.h b/Modules/clinic/audioop.c.h index 4ea7155373b..aa176964b0f 100644 --- a/Modules/clinic/audioop.c.h +++ b/Modules/clinic/audioop.c.h @@ -615,9 +615,15 @@ audioop_mul(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (width == -1 && PyErr_Occurred()) { goto exit; } - factor = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[2])) { + factor = PyFloat_AS_DOUBLE(args[2]); + } + else + { + factor = PyFloat_AsDouble(args[2]); + if (factor == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = audioop_mul_impl(module, &fragment, width, factor); @@ -671,13 +677,25 @@ audioop_tomono(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (width == -1 && PyErr_Occurred()) { goto exit; } - lfactor = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[2])) { + lfactor = PyFloat_AS_DOUBLE(args[2]); } - rfactor = PyFloat_AsDouble(args[3]); - if (PyErr_Occurred()) { - goto exit; + else + { + lfactor = PyFloat_AsDouble(args[2]); + if (lfactor == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[3])) { + rfactor = PyFloat_AS_DOUBLE(args[3]); + } + else + { + rfactor = PyFloat_AsDouble(args[3]); + if (rfactor == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = audioop_tomono_impl(module, &fragment, width, lfactor, rfactor); @@ -731,13 +749,25 @@ audioop_tostereo(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (width == -1 && PyErr_Occurred()) { goto exit; } - lfactor = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[2])) { + lfactor = PyFloat_AS_DOUBLE(args[2]); } - rfactor = PyFloat_AsDouble(args[3]); - if (PyErr_Occurred()) { - goto exit; + else + { + lfactor = PyFloat_AsDouble(args[2]); + if (lfactor == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[3])) { + rfactor = PyFloat_AS_DOUBLE(args[3]); + } + else + { + rfactor = PyFloat_AsDouble(args[3]); + if (rfactor == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = audioop_tostereo_impl(module, &fragment, width, lfactor, rfactor); @@ -1439,4 +1469,4 @@ exit: return return_value; } -/*[clinic end generated code: output=2b173a25726252e9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=af32f4bce9c934fa input=a9049054013a1b77]*/ diff --git a/Modules/clinic/cmathmodule.c.h b/Modules/clinic/cmathmodule.c.h index 83c498c2240..33509872069 100644 --- a/Modules/clinic/cmathmodule.c.h +++ b/Modules/clinic/cmathmodule.c.h @@ -766,13 +766,25 @@ cmath_rect(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("rect", nargs, 2, 2)) { goto exit; } - r = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + r = PyFloat_AS_DOUBLE(args[0]); } - phi = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + else + { + r = PyFloat_AsDouble(args[0]); + if (r == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[1])) { + phi = PyFloat_AS_DOUBLE(args[1]); + } + else + { + phi = PyFloat_AsDouble(args[1]); + if (phi == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = cmath_rect_impl(module, r, phi); @@ -922,17 +934,29 @@ cmath_isclose(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec goto skip_optional_kwonly; } if (args[2]) { - rel_tol = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[2])) { + rel_tol = PyFloat_AS_DOUBLE(args[2]); + } + else + { + rel_tol = PyFloat_AsDouble(args[2]); + if (rel_tol == -1.0 && PyErr_Occurred()) { + goto exit; + } } if (!--noptargs) { goto skip_optional_kwonly; } } - abs_tol = PyFloat_AsDouble(args[3]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[3])) { + abs_tol = PyFloat_AS_DOUBLE(args[3]); + } + else + { + abs_tol = PyFloat_AsDouble(args[3]); + if (abs_tol == -1.0 && PyErr_Occurred()) { + goto exit; + } } skip_optional_kwonly: _return_value = cmath_isclose_impl(module, a, b, rel_tol, abs_tol); @@ -944,4 +968,4 @@ skip_optional_kwonly: exit: return return_value; } -/*[clinic end generated code: output=c7afb866e593fa45 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3ab228947d1709cc input=a9049054013a1b77]*/ diff --git a/Modules/clinic/mathmodule.c.h b/Modules/clinic/mathmodule.c.h index 84561b95578..95d68ee55ae 100644 --- a/Modules/clinic/mathmodule.c.h +++ b/Modules/clinic/mathmodule.c.h @@ -117,9 +117,15 @@ math_frexp(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_frexp_impl(module, x); @@ -151,9 +157,15 @@ math_ldexp(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("ldexp", nargs, 2, 2)) { goto exit; } - x = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + x = PyFloat_AS_DOUBLE(args[0]); + } + else + { + x = PyFloat_AsDouble(args[0]); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } i = args[1]; return_value = math_ldexp_impl(module, x, i); @@ -182,9 +194,15 @@ math_modf(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_modf_impl(module, x); @@ -277,13 +295,25 @@ math_fmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("fmod", nargs, 2, 2)) { goto exit; } - x = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + x = PyFloat_AS_DOUBLE(args[0]); } - y = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + else + { + x = PyFloat_AsDouble(args[0]); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[1])) { + y = PyFloat_AS_DOUBLE(args[1]); + } + else + { + y = PyFloat_AsDouble(args[1]); + if (y == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_fmod_impl(module, x, y); @@ -349,13 +379,25 @@ math_pow(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("pow", nargs, 2, 2)) { goto exit; } - x = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + x = PyFloat_AS_DOUBLE(args[0]); } - y = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + else + { + x = PyFloat_AsDouble(args[0]); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[1])) { + y = PyFloat_AS_DOUBLE(args[1]); + } + else + { + y = PyFloat_AsDouble(args[1]); + if (y == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_pow_impl(module, x, y); @@ -381,9 +423,15 @@ math_degrees(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_degrees_impl(module, x); @@ -409,9 +457,15 @@ math_radians(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_radians_impl(module, x); @@ -437,9 +491,15 @@ math_isfinite(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_isfinite_impl(module, x); @@ -465,9 +525,15 @@ math_isnan(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_isnan_impl(module, x); @@ -493,9 +559,15 @@ math_isinf(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double x; - x = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + x = PyFloat_AS_DOUBLE(arg); + } + else + { + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = math_isinf_impl(module, x); @@ -550,29 +622,53 @@ math_isclose(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - a = PyFloat_AsDouble(args[0]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[0])) { + a = PyFloat_AS_DOUBLE(args[0]); } - b = PyFloat_AsDouble(args[1]); - if (PyErr_Occurred()) { - goto exit; + else + { + a = PyFloat_AsDouble(args[0]); + if (a == -1.0 && PyErr_Occurred()) { + goto exit; + } + } + if (PyFloat_CheckExact(args[1])) { + b = PyFloat_AS_DOUBLE(args[1]); + } + else + { + b = PyFloat_AsDouble(args[1]); + if (b == -1.0 && PyErr_Occurred()) { + goto exit; + } } if (!noptargs) { goto skip_optional_kwonly; } if (args[2]) { - rel_tol = PyFloat_AsDouble(args[2]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[2])) { + rel_tol = PyFloat_AS_DOUBLE(args[2]); + } + else + { + rel_tol = PyFloat_AsDouble(args[2]); + if (rel_tol == -1.0 && PyErr_Occurred()) { + goto exit; + } } if (!--noptargs) { goto skip_optional_kwonly; } } - abs_tol = PyFloat_AsDouble(args[3]); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(args[3])) { + abs_tol = PyFloat_AS_DOUBLE(args[3]); + } + else + { + abs_tol = PyFloat_AsDouble(args[3]); + if (abs_tol == -1.0 && PyErr_Occurred()) { + goto exit; + } } skip_optional_kwonly: _return_value = math_isclose_impl(module, a, b, rel_tol, abs_tol); @@ -712,4 +808,4 @@ math_comb(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=f93cfe13ab2fdb4e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9a2b3dc91eb9aadd input=a9049054013a1b77]*/ diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index 6f248ff18d9..563332eeb5c 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -362,9 +362,15 @@ sys_setswitchinterval(PyObject *module, PyObject *arg) PyObject *return_value = NULL; double interval; - interval = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) { - goto exit; + if (PyFloat_CheckExact(arg)) { + interval = PyFloat_AS_DOUBLE(arg); + } + else + { + interval = PyFloat_AsDouble(arg); + if (interval == -1.0 && PyErr_Occurred()) { + goto exit; + } } return_value = sys_setswitchinterval_impl(module, interval); @@ -1082,4 +1088,4 @@ sys_getandroidapilevel(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=43c4fde7b5783d8d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1a67b37c4486d65f input=a9049054013a1b77]*/ diff --git a/Python/getargs.c b/Python/getargs.c index 59f0fdabb74..051ebc78a0f 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -887,7 +887,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, case 'f': {/* float */ float *p = va_arg(*p_va, float *); double dval = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) + if (dval == -1.0 && PyErr_Occurred()) RETURN_ERR_OCCURRED; else *p = (float) dval; @@ -897,7 +897,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, case 'd': {/* double */ double *p = va_arg(*p_va, double *); double dval = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) + if (dval == -1.0 && PyErr_Occurred()) RETURN_ERR_OCCURRED; else *p = dval; diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 9880b395133..d5863a3effe 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -3106,9 +3106,15 @@ class float_converter(CConverter): def parse_arg(self, argname, argnum): if self.format_unit == 'f': return """ - {paramname} = (float) PyFloat_AsDouble({argname}); - if (PyErr_Occurred()) {{{{ - goto exit; + if (PyFloat_CheckExact({argname})) {{{{ + {paramname} = (float) (PyFloat_AS_DOUBLE({argname})); + }}}} + else + {{{{ + {paramname} = (float) PyFloat_AsDouble({argname}); + if ({paramname} == -1.0 && PyErr_Occurred()) {{{{ + goto exit; + }}}} }}}} """.format(argname=argname, paramname=self.name) return super().parse_arg(argname, argnum) @@ -3122,9 +3128,15 @@ class double_converter(CConverter): def parse_arg(self, argname, argnum): if self.format_unit == 'd': return """ - {paramname} = PyFloat_AsDouble({argname}); - if (PyErr_Occurred()) {{{{ - goto exit; + if (PyFloat_CheckExact({argname})) {{{{ + {paramname} = PyFloat_AS_DOUBLE({argname}); + }}}} + else + {{{{ + {paramname} = PyFloat_AsDouble({argname}); + if ({paramname} == -1.0 && PyErr_Occurred()) {{{{ + goto exit; + }}}} }}}} """.format(argname=argname, paramname=self.name) return super().parse_arg(argname, argnum)