From 40e252a8243402c0ca5bed0991d038c141907d33 Mon Sep 17 00:00:00 2001 From: Ken Robbins Date: Fri, 29 Sep 2017 20:59:26 -0700 Subject: [PATCH] Allow None to be passed into loads for object_hook and dumps for default. --- CHANGES.rst | 7 +++++++ rapidjson.cpp | 16 ++++++++++++---- tests/test_params.py | 30 ++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 27f993b..e47bc83 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,13 @@ Changes ------- +Unreleased +~~~~~~~~~~ + +* Fix bug where loads's ``object_hook`` and dumps's ``default`` arguments could + not be passed ``None`` explicitly. + + 0.2.4 (2017-09-17) ~~~~~~~~~~~~~~~~~~ diff --git a/rapidjson.cpp b/rapidjson.cpp index 64a8f59..61d7665 100644 --- a/rapidjson.cpp +++ b/rapidjson.cpp @@ -1008,8 +1008,12 @@ loads(PyObject* self, PyObject* args, PyObject* kwargs) return NULL; if (objectHook && !PyCallable_Check(objectHook)) { - PyErr_SetString(PyExc_TypeError, "object_hook is not callable"); - return NULL; + if (objectHook == Py_None) + objectHook = NULL; + else { + PyErr_SetString(PyExc_TypeError, "object_hook is not callable"); + return NULL; + } } Py_ssize_t jsonStrLen; @@ -2130,8 +2134,12 @@ dumps(PyObject* self, PyObject* args, PyObject* kwargs) return NULL; if (defaultFn && !PyCallable_Check(defaultFn)) { - PyErr_SetString(PyExc_TypeError, "default must be a callable"); - return NULL; + if (defaultFn == Py_None) + defaultFn = NULL; + else { + PyErr_SetString(PyExc_TypeError, "default must be a callable"); + return NULL; + } } if (indent && indent != Py_None) { diff --git a/tests/test_params.py b/tests/test_params.py index 1cfbb8e..03e977f 100644 --- a/tests/test_params.py +++ b/tests/test_params.py @@ -557,3 +557,33 @@ def test_invalid_dumps_params(posargs, kwargs, dumps): pass else: assert False, "Expected either a TypeError or a ValueError" + + +@pytest.mark.unit +def test_explicit_defaults_loads(): + assert rj.loads( + s='"foo"', + object_hook=None, + number_mode=None, + datetime_mode=None, + uuid_mode=None, + parse_mode=None, + allow_nan=True, + ) == "foo" + + +@pytest.mark.unit +def test_explicit_defaults_dumps(): + assert rj.dumps( + obj='foo', + skipkeys=False, + ensure_ascii=True, + indent=None, + default=None, + sort_keys=False, + max_recursion_depth=2048, + number_mode=None, + datetime_mode=None, + uuid_mode=None, + allow_nan=True, + ) == '"foo"'