Skip to content

Commit 9ed59ed

Browse files
committed
port the add OPT_DISALLOW_NAN PR too.
1 parent 4d4766e commit 9ed59ed

File tree

15 files changed

+82
-14
lines changed

15 files changed

+82
-14
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
# Changelog
22

33

4+
## 3.11.7-post3
5+
6+
### Added
7+
8+
- `OPT_DISALLOW_NAN` option flag for `dumps()`. When set, raises `JSONEncodeError` if a float value is NaN, Infinity, or -Infinity. Default behavior (allowing NaN/Infinity) is unchanged.
9+
410
## 3.11.7-post2
511

612
### Added

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "orjson"
3-
version = "3.11.7-post2"
3+
version = "3.11.7-post3"
44
authors = ["ijl <ijl@mailbox.org>"]
55
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
66
repository = "https://github.com/ijl/orjson"

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "orjson"
3-
version = "3.11.7-post2"
3+
version = "3.11.7-post3"
44
repository = "https://github.com/ijl/orjson"
55
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
66
requires-python = ">=3.10"

pysrc/orjson/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"JSONEncodeError",
1313
"loads",
1414
"OPT_APPEND_NEWLINE",
15+
"OPT_DISALLOW_NAN",
1516
"OPT_INDENT_2",
1617
"OPT_NAIVE_UTC",
1718
"OPT_NON_STR_KEYS",

pysrc/orjson/__init__.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class Fragment(tuple):
2121
contents: bytes | str
2222

2323
OPT_APPEND_NEWLINE: int
24+
OPT_DISALLOW_NAN: int
2425
OPT_INDENT_2: int
2526
OPT_NAIVE_UTC: int
2627
OPT_NON_STR_KEYS: int

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ pub(crate) unsafe extern "C" fn orjson_init_exec(mptr: *mut PyObject) -> c_int {
149149
add!(mptr, c"Fragment", typeref::FRAGMENT_TYPE.cast::<PyObject>());
150150

151151
opt!(mptr, c"OPT_APPEND_NEWLINE", opt::APPEND_NEWLINE);
152+
opt!(mptr, c"OPT_DISALLOW_NAN", opt::DISALLOW_NAN);
152153
opt!(mptr, c"OPT_INDENT_2", opt::INDENT_2);
153154
opt!(mptr, c"OPT_NAIVE_UTC", opt::NAIVE_UTC);
154155
opt!(mptr, c"OPT_NON_STR_KEYS", opt::NON_STR_KEYS);

src/opt.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub(crate) const PASSTHROUGH_SUBCLASS: Opt = 1 << 8;
1515
pub(crate) const PASSTHROUGH_DATETIME: Opt = 1 << 9;
1616
pub(crate) const APPEND_NEWLINE: Opt = 1 << 10;
1717
pub(crate) const PASSTHROUGH_DATACLASS: Opt = 1 << 11;
18+
pub(crate) const DISALLOW_NAN: Opt = 1 << 12;
1819

1920
// deprecated
2021
pub(crate) const SERIALIZE_DATACLASS: Opt = 0;
@@ -27,6 +28,7 @@ pub(crate) const NOT_PASSTHROUGH: Opt =
2728

2829
#[allow(clippy::cast_possible_wrap)]
2930
pub(crate) const MAX_OPT: i32 = (APPEND_NEWLINE
31+
| DISALLOW_NAN
3032
| INDENT_2
3133
| NAIVE_UTC
3234
| NON_STR_KEYS

src/serialize/error.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use core::ptr::NonNull;
77
pub(crate) enum SerializeError {
88
DatetimeLibraryUnsupported,
99
DefaultRecursionLimit,
10+
FloatNotFinite,
1011
Integer53Bits,
1112
Integer64Bits,
1213
InvalidStr,
@@ -36,6 +37,9 @@ impl core::fmt::Display for SerializeError {
3637
SerializeError::DefaultRecursionLimit => {
3738
write!(f, "default serializer exceeds recursion limit")
3839
}
40+
SerializeError::FloatNotFinite => {
41+
write!(f, "Cannot serialize Infinity or NaN")
42+
}
3943
SerializeError::Integer53Bits => write!(f, "Integer exceeds 53-bit range"),
4044
SerializeError::Integer64Bits => write!(f, "Integer exceeds 64-bit range"),
4145
SerializeError::InvalidStr => write!(f, "{}", crate::util::INVALID_STR),

src/serialize/per_type/dict.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ macro_rules! impl_serialize_entry {
125125
$map.serialize_key($key).unwrap();
126126
$map.serialize_value(&FloatSerializer::new(unsafe {
127127
PyFloatRef::from_ptr_unchecked($value)
128-
}))?;
128+
}, $self.state.opts()))?;
129129
}
130130
ObType::Bool => {
131131
$map.serialize_key($key).unwrap();
@@ -434,10 +434,17 @@ fn non_str_uuid(key: PyUuidRef) -> Result<String, SerializeError> {
434434
#[allow(clippy::unnecessary_wraps)]
435435
#[cold]
436436
#[inline(never)]
437-
fn non_str_float(key: *mut crate::ffi::PyObject) -> Result<String, SerializeError> {
437+
fn non_str_float(
438+
key: *mut crate::ffi::PyObject,
439+
opts: crate::opt::Opt,
440+
) -> Result<String, SerializeError> {
438441
let val = ffi!(PyFloat_AS_DOUBLE(key));
439442
if !val.is_finite() {
440-
Ok(String::from("null"))
443+
if opt_enabled!(opts, crate::opt::DISALLOW_NAN) {
444+
Err(SerializeError::FloatNotFinite)
445+
} else {
446+
Ok(String::from("null"))
447+
}
441448
} else {
442449
Ok(String::from(zmij::Buffer::new().format_finite(val)))
443450
}
@@ -487,7 +494,7 @@ impl DictNonStrKey {
487494
}
488495
}
489496
ObType::Int => non_str_int(key),
490-
ObType::Float => non_str_float(key),
497+
ObType::Float => non_str_float(key, opts),
491498
ObType::Datetime => non_str_datetime(key, opts),
492499
ObType::Date => non_str_date(key),
493500
ObType::Time => non_str_time(key, opts),

0 commit comments

Comments
 (0)