Skip to content

Commit d0384c7

Browse files
authored
Support BigInt serialization for int subclasses (#1417)
1 parent f4a0675 commit d0384c7

File tree

2 files changed

+44
-4
lines changed

2 files changed

+44
-4
lines changed

src/serializers/infer.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::borrow::Cow;
22

3+
use num_bigint::BigInt;
34
use pyo3::exceptions::PyTypeError;
45
use pyo3::intern;
56
use pyo3::prelude::*;
@@ -116,10 +117,15 @@ pub(crate) fn infer_to_python_known(
116117
// `bool` and `None` can't be subclasses, `ObType::Int`, `ObType::Float`, `ObType::Str` refer to exact types
117118
ObType::None | ObType::Bool | ObType::Int | ObType::Str => value.into_py(py),
118119
// have to do this to make sure subclasses of for example str are upcast to `str`
119-
ObType::IntSubclass => match extract_i64(value) {
120-
Some(v) => v.into_py(py),
121-
None => return py_err!(PyTypeError; "expected int, got {}", safe_repr(value)),
122-
},
120+
ObType::IntSubclass => {
121+
if let Some(v) = extract_i64(value) {
122+
v.into_py(py)
123+
} else if let Ok(b) = value.extract::<BigInt>() {
124+
b.into_py(py)
125+
} else {
126+
return py_err!(PyTypeError; "Expected int, got {}", safe_repr(value));
127+
}
128+
}
123129
ObType::Float | ObType::FloatSubclass => {
124130
let v = value.extract::<f64>()?;
125131
if (v.is_nan() || v.is_infinite()) && extra.config.inf_nan_mode == InfNanMode::Null {

tests/serializers/test_any.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,40 @@ def test_ser_json_inf_nan_with_list_of_any() -> None:
654654
assert s.to_json([nan]) == b'[null]'
655655

656656

657+
def test_ser_json_int_subclass_value_larger_than_i64():
658+
class IntSubclass(int):
659+
pass
660+
661+
schema = core_schema.model_schema(
662+
MyModel,
663+
core_schema.model_fields_schema(
664+
dict(
665+
stuff=core_schema.model_field(
666+
core_schema.dict_schema(
667+
keys_schema=core_schema.str_schema(),
668+
values_schema=core_schema.any_schema(),
669+
)
670+
)
671+
)
672+
),
673+
)
674+
s = SchemaSerializer(schema)
675+
676+
assert (
677+
s.to_json(
678+
MyModel(stuff={'value': IntSubclass(9_223_372_036_854_775_809)}),
679+
)
680+
== b'{"stuff":{"value":9223372036854775809}}'
681+
)
682+
683+
assert str(
684+
s.to_python(
685+
MyModel(stuff={'value': IntSubclass(9_223_372_036_854_775_809)}),
686+
mode='json',
687+
)
688+
) == str({'stuff': {'value': 9223372036854775809}})
689+
690+
657691
def test_simple_any_ser_schema_repr():
658692
assert (
659693
plain_repr(SchemaSerializer(core_schema.simple_ser_schema('any')))

0 commit comments

Comments
 (0)