From 17901af607074436228727243ae6c2356e6b4903 Mon Sep 17 00:00:00 2001 From: Will Ayd Date: Sun, 6 Nov 2022 11:17:17 -0800 Subject: [PATCH 1/3] gh-86018 Inconsistent errors for JSON-encoding NaNs with allow_nan=False Fix issue where json.dumps provided a different error message than json.dump with non-finite values --- Lib/test/test_json/test_float.py | 5 ++-- ...2-11-06-19-59-56.gh-issue-86018.xAt6g2.rst | 1 + Modules/_json.c | 30 +++++++++++-------- 3 files changed, 21 insertions(+), 15 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2022-11-06-19-59-56.gh-issue-86018.xAt6g2.rst diff --git a/Lib/test/test_json/test_float.py b/Lib/test/test_json/test_float.py index d0c7214334d6e5..8abcf317253083 100644 --- a/Lib/test/test_json/test_float.py +++ b/Lib/test/test_json/test_float.py @@ -26,8 +26,9 @@ def test_allow_nan(self): res = self.loads(out) self.assertEqual(len(res), 1) self.assertNotEqual(res[0], res[0]) - self.assertRaises(ValueError, self.dumps, [val], allow_nan=False) - + self.assertRaisesRegex( + ValueError, str(val), self.dumps, [val], allow_nan=False + ) class TestPyFloat(TestFloat, PyTest): pass class TestCFloat(TestFloat, CTest): pass diff --git a/Misc/NEWS.d/next/Library/2022-11-06-19-59-56.gh-issue-86018.xAt6g2.rst b/Misc/NEWS.d/next/Library/2022-11-06-19-59-56.gh-issue-86018.xAt6g2.rst new file mode 100644 index 00000000000000..2b9a7e7803c8cd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-11-06-19-59-56.gh-issue-86018.xAt6g2.rst @@ -0,0 +1 @@ ++ Fix issue where the error messages for :func:`json.dump` and :func:`json.dumps` were inconsistent when serializing non-finite values with ``allow_nan=False`` diff --git a/Modules/_json.c b/Modules/_json.c index fe8695110f017d..960ee6b46c46e5 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1324,21 +1324,25 @@ encoder_encode_float(PyEncoderObject *s, PyObject *obj) /* Return the JSON representation of a PyFloat. */ double i = PyFloat_AS_DOUBLE(obj); if (!Py_IS_FINITE(i)) { - if (!s->allow_nan) { - PyErr_SetString( - PyExc_ValueError, - "Out of range float values are not JSON compliant" - ); - return NULL; - } + char* value; + char *py_value; if (i > 0) { - return PyUnicode_FromString("Infinity"); - } - else if (i < 0) { - return PyUnicode_FromString("-Infinity"); + value = "Infinity"; + py_value = "inf"; + } else if (i < 0) { + value = "-Infinity"; + py_value = "-inf"; + } else { + value = "NaN"; + py_value = "nan"; } - else { - return PyUnicode_FromString("NaN"); + + if (!s->allow_nan) { + char message[55] = "Out of range float values are not JSON compliant: "; + PyErr_SetString(PyExc_ValueError, strcat(message, py_value)); + return NULL; + } else { + return PyUnicode_FromString(value); } } return PyFloat_Type.tp_repr(obj); From 0d2798e9d94f374499054a3b788e73ff26d22736 Mon Sep 17 00:00:00 2001 From: Will Ayd Date: Mon, 7 Nov 2022 10:36:25 -0800 Subject: [PATCH 2/3] suggestions --- .../2022-11-06-19-59-56.gh-issue-86018.xAt6g2.rst | 2 +- Modules/_json.c | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2022-11-06-19-59-56.gh-issue-86018.xAt6g2.rst b/Misc/NEWS.d/next/Library/2022-11-06-19-59-56.gh-issue-86018.xAt6g2.rst index 2b9a7e7803c8cd..dad1fc22f47b2a 100644 --- a/Misc/NEWS.d/next/Library/2022-11-06-19-59-56.gh-issue-86018.xAt6g2.rst +++ b/Misc/NEWS.d/next/Library/2022-11-06-19-59-56.gh-issue-86018.xAt6g2.rst @@ -1 +1 @@ -+ Fix issue where the error messages for :func:`json.dump` and :func:`json.dumps` were inconsistent when serializing non-finite values with ``allow_nan=False`` ++ Fix issue where the error messages for :meth:`json.dump` and :meth:`json.dumps` were inconsistent when serializing non-finite values with ``allow_nan=False`` diff --git a/Modules/_json.c b/Modules/_json.c index 960ee6b46c46e5..61a69b2213b698 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1325,21 +1325,18 @@ encoder_encode_float(PyEncoderObject *s, PyObject *obj) double i = PyFloat_AS_DOUBLE(obj); if (!Py_IS_FINITE(i)) { char* value; - char *py_value; if (i > 0) { value = "Infinity"; - py_value = "inf"; } else if (i < 0) { value = "-Infinity"; - py_value = "-inf"; } else { value = "NaN"; - py_value = "nan"; } if (!s->allow_nan) { - char message[55] = "Out of range float values are not JSON compliant: "; - PyErr_SetString(PyExc_ValueError, strcat(message, py_value)); + PyErr_Format(PyExc_ValueError, + "Out of range float values are not JSON compliant: %S", + obj); return NULL; } else { return PyUnicode_FromString(value); From 4b8516cf143129225aca0d7b90180d86dfd1ac77 Mon Sep 17 00:00:00 2001 From: Will Ayd Date: Mon, 7 Nov 2022 10:38:31 -0800 Subject: [PATCH 3/3] simplified implementation --- Modules/_json.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/Modules/_json.c b/Modules/_json.c index 61a69b2213b698..f496b9401e1baa 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1324,22 +1324,21 @@ encoder_encode_float(PyEncoderObject *s, PyObject *obj) /* Return the JSON representation of a PyFloat. */ double i = PyFloat_AS_DOUBLE(obj); if (!Py_IS_FINITE(i)) { - char* value; - if (i > 0) { - value = "Infinity"; - } else if (i < 0) { - value = "-Infinity"; - } else { - value = "NaN"; - } - if (!s->allow_nan) { - PyErr_Format(PyExc_ValueError, - "Out of range float values are not JSON compliant: %S", - obj); + PyErr_Format( + PyExc_ValueError, + "Out of range float values are not JSON compliant: %S", obj + ); return NULL; - } else { - return PyUnicode_FromString(value); + } + if (i > 0) { + return PyUnicode_FromString("Infinity"); + } + else if (i < 0) { + return PyUnicode_FromString("-Infinity"); + } + else { + return PyUnicode_FromString("NaN"); } } return PyFloat_Type.tp_repr(obj);