
A question came up on python-list regarding the message given when you call float(""). It's somewhat unclear due to the way humans tend to ignore a lack of content:
Firstly, is there a reason for the empty string to not be surrounded with quotes? The source code, AIUI, is this: x = PyOS_string_to_double(s, (char **)&end, NULL); if (end != last) { PyErr_Format(PyExc_ValueError, "could not convert string to float: " "%R", obj); return NULL; } which, by my reading, should always be repr'ing the string. Secondly, the actual feature suggestion/request: Incorporate the original string in the exception's arguments. That way, if there's any confusion, e.args[1] is the safest way to check what string was actually being floated. Feasible? Useful? ChrisA

On 06/06/2017 12:51 PM, Chris Angelico wrote:
The confusing part is that if the string is empty, then the line if (end != last) { does not evaluate to true. So you never enter that part of the if statement. Instead you get here: else if (x == -1.0 && PyErr_Occurred()) { return NULL; } (You can check in a debugger that this happens.) Cheers, Thomas

I think this diff is probably the correct solution. Basically it just checks if there's anything left after spaces are stripped and then throws an error if not: (By the way sorry for not being clearer in my other message. This diff is against the current 3.7 master branch. I didn't look at the original 2.7 because I wanted to check that it wasn't fixed in a future version (which apparently it isn't).) --------------------- $ git diff diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 8c4fe74..c1886cc 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -144,7 +144,13 @@ float_from_string_inner(const char *s, Py_ssize_t len, void *obj) while (s < last - 1 && Py_ISSPACE(last[-1])) { last--; } - + /* If nothing is left after stripping spaces, return error. */ + if (s == last) { + PyErr_Format(PyExc_ValueError, + "could not convert string to float: " + "%R", obj); + return NULL; + } /* We don't care about overflow or underflow. If the platform * supports them, infinities and signed zeroes (on underflow) are * fine. */ --------------------- I just compiled and tested it and it seems to do what we want:
Cheers, Thomas

On 06/06/2017 12:51 PM, Chris Angelico wrote:
The confusing part is that if the string is empty, then the line if (end != last) { does not evaluate to true. So you never enter that part of the if statement. Instead you get here: else if (x == -1.0 && PyErr_Occurred()) { return NULL; } (You can check in a debugger that this happens.) Cheers, Thomas

I think this diff is probably the correct solution. Basically it just checks if there's anything left after spaces are stripped and then throws an error if not: (By the way sorry for not being clearer in my other message. This diff is against the current 3.7 master branch. I didn't look at the original 2.7 because I wanted to check that it wasn't fixed in a future version (which apparently it isn't).) --------------------- $ git diff diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 8c4fe74..c1886cc 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -144,7 +144,13 @@ float_from_string_inner(const char *s, Py_ssize_t len, void *obj) while (s < last - 1 && Py_ISSPACE(last[-1])) { last--; } - + /* If nothing is left after stripping spaces, return error. */ + if (s == last) { + PyErr_Format(PyExc_ValueError, + "could not convert string to float: " + "%R", obj); + return NULL; + } /* We don't care about overflow or underflow. If the platform * supports them, infinities and signed zeroes (on underflow) are * fine. */ --------------------- I just compiled and tested it and it seems to do what we want:
Cheers, Thomas
participants (2)
-
Chris Angelico
-
Thomas Nyberg