-
-
Notifications
You must be signed in to change notification settings - Fork 31.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gh-101410: customize error messages for 1-arg math functions #129497
base: main
Are you sure you want to change the base?
Changes from all commits
77a643c
d88b55f
b99661e
d57a640
81ae026
11365cb
53b68c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,2 @@ | ||
Support custom messages for domain errors in the :mod:`math` module | ||
(:func:`math.sqrt`, :func:`math.log` and :func:`math.atanh` were modified as | ||
examples). Patch by Charlie Zhao and Sergey B Kirpichev. | ||
Added more detailed messages for domain errors in the :mod:`math` module. | ||
Patch by Charlie Zhao and Sergey B Kirpichev. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1089,17 +1089,20 @@ math_2(PyObject *const *args, Py_ssize_t nargs, | |
}\ | ||
PyDoc_STRVAR(math_##funcname##_doc, docstring); | ||
|
||
FUNC1(acos, acos, 0, | ||
FUNC1D(acos, acos, 0, | ||
"acos($module, x, /)\n--\n\n" | ||
"Return the arc cosine (measured in radians) of x.\n\n" | ||
"The result is between 0 and pi.") | ||
FUNC1(acosh, acosh, 0, | ||
"The result is between 0 and pi.", | ||
"expected a number in range from -1 up to 1, got %s") | ||
FUNC1D(acosh, acosh, 0, | ||
"acosh($module, x, /)\n--\n\n" | ||
"Return the inverse hyperbolic cosine of x.") | ||
FUNC1(asin, asin, 0, | ||
"Return the inverse hyperbolic cosine of x.", | ||
"expected argument value not less than 1, got %s") | ||
FUNC1D(asin, asin, 0, | ||
"asin($module, x, /)\n--\n\n" | ||
"Return the arc sine (measured in radians) of x.\n\n" | ||
"The result is between -pi/2 and pi/2.") | ||
"The result is between -pi/2 and pi/2.", | ||
"expected a number in range from -1 up to 1, got %s") | ||
FUNC1(asinh, asinh, 0, | ||
"asinh($module, x, /)\n--\n\n" | ||
"Return the inverse hyperbolic sine of x.") | ||
|
@@ -1161,9 +1164,10 @@ FUNC2(copysign, copysign, | |
"Return a float with the magnitude (absolute value) of x but the sign of y.\n\n" | ||
"On platforms that support signed zeros, copysign(1.0, -0.0)\n" | ||
"returns -1.0.\n") | ||
FUNC1(cos, cos, 0, | ||
FUNC1D(cos, cos, 0, | ||
"cos($module, x, /)\n--\n\n" | ||
"Return the cosine of x (measured in radians).") | ||
"Return the cosine of x (measured in radians).", | ||
"expected a finite input, got %s") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It works for NaN which is not a finite number. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we should clutter the message with nans stuff. It's expected, that math functions accept nans: garbage in - garbage out. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The point of changing the error messages is to make them more informative, not misleading. If we cannot improve the error message, it is better to leave the old unspecific message. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately, then in this manner we should change all error messages. All will require a specific case for nan. I.e. instead of "expected a number in range from -1 up to 1, got inf" we should get something like "expected a number in range from -1 up to 1, or nan, got inf". I don't think it's a helpful information for readers. We shouldn't clutter the function domain description with details on nan propagation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Finite" is not a colloquial term. It can be understood only in context of floating-point numbers, and there it means not infinity and not NaN. Yes, other messages may need a correction too. Instead of "expected a number in range from -1 up to 1, got inf" it can say "inf is outside of range from -1 up to 1" or something like. The error messages should be correct and unambiguous, otherwise there is no point in changing the old error messages. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
But we are in this context.
Hmm, I'm not sure that 2nd variant much better for nans. Reading this error message I also can't say whether nan is an acceptable input or not. Also, in such versions you will rather describe the complement of the function domain. E.g. instead of "expected a nonnegative input, got -1.0" - something like "-1.0 is not a nonnegative number" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
And in that context
Rather "-1.0 is a negative integer number". If expression for the complement of the function domain is simpler, it should be used instead. In any case, all these messages should be reviewed by native speakers with mathematical or computer science background and teaching experience. cc @rhettinger, @tim-one, @mdickinson There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
With this wording it says something about the input, rather than about the function domain.
I can only appreciate that. As summary, in the proposed patch we have error messages like "expected number in , got %s", which is along the line, suggested by Raymond in the issue description. Problem (well, maybe): this doesn't account the nan as an acceptable input. |
||
FUNC1(cosh, cosh, 1, | ||
"cosh($module, x, /)\n--\n\n" | ||
"Return the hyperbolic cosine of x.") | ||
|
@@ -1228,33 +1232,37 @@ math_floor(PyObject *module, PyObject *number) | |
FUNC1AD(gamma, m_tgamma, | ||
"gamma($module, x, /)\n--\n\n" | ||
"Gamma function at x.", | ||
"expected a float or nonnegative integer, got %s") | ||
FUNC1A(lgamma, m_lgamma, | ||
"expected a noninteger or positive integer, got %s") | ||
FUNC1AD(lgamma, m_lgamma, | ||
"lgamma($module, x, /)\n--\n\n" | ||
"Natural logarithm of absolute value of Gamma function at x.") | ||
FUNC1(log1p, m_log1p, 0, | ||
"Natural logarithm of absolute value of Gamma function at x.", | ||
"expected a noninteger or positive integer, got %s") | ||
FUNC1D(log1p, m_log1p, 0, | ||
"log1p($module, x, /)\n--\n\n" | ||
"Return the natural logarithm of 1+x (base e).\n\n" | ||
"The result is computed in a way which is accurate for x near zero.") | ||
"The result is computed in a way which is accurate for x near zero.", | ||
"expected argument value > -1, got %s") | ||
FUNC2(remainder, m_remainder, | ||
"remainder($module, x, y, /)\n--\n\n" | ||
"Difference between x and the closest integer multiple of y.\n\n" | ||
"Return x - n*y where n*y is the closest integer multiple of y.\n" | ||
"In the case where x is exactly halfway between two multiples of\n" | ||
"y, the nearest even value of n is used. The result is always exact.") | ||
FUNC1(sin, sin, 0, | ||
FUNC1D(sin, sin, 0, | ||
"sin($module, x, /)\n--\n\n" | ||
"Return the sine of x (measured in radians).") | ||
"Return the sine of x (measured in radians).", | ||
"expected a finite input, got %s") | ||
FUNC1(sinh, sinh, 1, | ||
"sinh($module, x, /)\n--\n\n" | ||
"Return the hyperbolic sine of x.") | ||
FUNC1D(sqrt, sqrt, 0, | ||
"sqrt($module, x, /)\n--\n\n" | ||
"Return the square root of x.", | ||
"expected a nonnegative input, got %s") | ||
FUNC1(tan, tan, 0, | ||
FUNC1D(tan, tan, 0, | ||
"tan($module, x, /)\n--\n\n" | ||
"Return the tangent of x (measured in radians).") | ||
"Return the tangent of x (measured in radians).", | ||
"expected a finite input, got %s") | ||
FUNC1(tanh, tanh, 0, | ||
"tanh($module, x, /)\n--\n\n" | ||
"Return the hyperbolic tangent of x.") | ||
|
@@ -2232,8 +2240,10 @@ loghelper(PyObject* arg, double (*func)(double)) | |
|
||
/* Negative or zero inputs give a ValueError. */ | ||
if (!_PyLong_IsPositive((PyLongObject *)arg)) { | ||
PyErr_Format(PyExc_ValueError, | ||
"expected a positive input, got %S", arg); | ||
/* The input can be an arbitrary large integer, so we | ||
don't include it's value in the error message. */ | ||
PyErr_SetString(PyExc_ValueError, | ||
"expected a positive input"); | ||
return NULL; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could say "a number in the interval [-1, 1]" though I'm a bit worried about the notation that may not be understood (for non mathematicians). Otherwise shouldn't we say "in the range from -1 up to 1" ? (I'm not sure here for the English part so @AA-Turner could help us)