Skip to content

Commit 19517d0

Browse files
committed
add tests
1 parent 6a4cef0 commit 19517d0

File tree

3 files changed

+51
-3
lines changed

3 files changed

+51
-3
lines changed

pysrc/orjson/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"JSONEncodeError",
1212
"loads",
1313
"OPT_APPEND_NEWLINE",
14+
"OPT_DISALLOW_NAN",
1415
"OPT_INDENT_2",
1516
"OPT_NAIVE_UTC",
1617
"OPT_NON_STR_KEYS",

src/serialize/per_type/dict.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,10 +382,17 @@ fn non_str_uuid(key: *mut pyo3_ffi::PyObject) -> Result<CompactString, Serialize
382382

383383
#[cold]
384384
#[inline(never)]
385-
fn non_str_float(key: *mut pyo3_ffi::PyObject) -> Result<CompactString, SerializeError> {
385+
fn non_str_float(
386+
key: *mut pyo3_ffi::PyObject,
387+
opts: crate::opt::Opt,
388+
) -> Result<CompactString, SerializeError> {
386389
let val = ffi!(PyFloat_AS_DOUBLE(key));
387390
if !val.is_finite() {
388-
Ok(CompactString::const_new("null"))
391+
if unlikely!(opt_enabled!(opts, crate::opt::DISALLOW_NAN)) {
392+
Err(SerializeError::FloatNotFinite)
393+
} else {
394+
Ok(CompactString::const_new("null"))
395+
}
389396
} else {
390397
Ok(CompactString::from(ryu::Buffer::new().format_finite(val)))
391398
}
@@ -432,7 +439,7 @@ impl DictNonStrKey {
432439
}
433440
}
434441
ObType::Int => non_str_int(key),
435-
ObType::Float => non_str_float(key),
442+
ObType::Float => non_str_float(key, opts),
436443
ObType::Datetime => non_str_datetime(key, opts),
437444
ObType::Date => non_str_date(key),
438445
ObType::Time => non_str_time(key, opts),

test/test_type.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,46 @@ def test_infinity_loads(self):
373373
assert str(orjson.loads("[-Infinity]")[0]) == "-inf"
374374
assert str(orjson.loads("[-infinity]")[0]) == "-inf"
375375

376+
def test_disallow_nan_raises(self):
377+
"""
378+
OPT_DISALLOW_NAN raises on NaN and Infinity
379+
"""
380+
for val in (float("nan"), float("inf"), float("-inf")):
381+
with pytest.raises(orjson.JSONEncodeError):
382+
orjson.dumps(val, option=orjson.OPT_DISALLOW_NAN)
383+
384+
def test_disallow_nan_finite_ok(self):
385+
"""
386+
OPT_DISALLOW_NAN allows finite floats
387+
"""
388+
assert orjson.dumps(3.14, option=orjson.OPT_DISALLOW_NAN) == b"3.14"
389+
assert orjson.dumps(0.0, option=orjson.OPT_DISALLOW_NAN) == b"0.0"
390+
assert orjson.dumps(-1.5, option=orjson.OPT_DISALLOW_NAN) == b"-1.5"
391+
392+
def test_disallow_nan_in_list(self):
393+
"""
394+
OPT_DISALLOW_NAN raises on NaN inside a list
395+
"""
396+
with pytest.raises(orjson.JSONEncodeError):
397+
orjson.dumps([1.0, float("nan"), 3.0], option=orjson.OPT_DISALLOW_NAN)
398+
399+
def test_disallow_nan_in_dict(self):
400+
"""
401+
OPT_DISALLOW_NAN raises on Infinity inside a dict value
402+
"""
403+
with pytest.raises(orjson.JSONEncodeError):
404+
orjson.dumps({"x": float("inf")}, option=orjson.OPT_DISALLOW_NAN)
405+
406+
def test_disallow_nan_dict_key(self):
407+
"""
408+
OPT_DISALLOW_NAN raises on NaN as a dict key with OPT_NON_STR_KEYS
409+
"""
410+
with pytest.raises(orjson.JSONEncodeError):
411+
orjson.dumps(
412+
{float("nan"): 1},
413+
option=orjson.OPT_DISALLOW_NAN | orjson.OPT_NON_STR_KEYS,
414+
)
415+
376416
def test_int_53(self):
377417
"""
378418
int 53-bit

0 commit comments

Comments
 (0)