Skip to content

Commit f3ba689

Browse files
committed
support big ints in literals and enums
1 parent 727deee commit f3ba689

File tree

4 files changed

+34
-7
lines changed

4 files changed

+34
-7
lines changed

src/input/return_enums.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,7 @@ impl<'a> EitherInt<'a> {
549549
Ok(Self::BigInt(big_int))
550550
}
551551
}
552+
552553
pub fn into_i64(self, py: Python<'a>) -> ValResult<i64> {
553554
match self {
554555
EitherInt::I64(i) => Ok(i),

src/validators/literal.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use core::fmt::Debug;
44
use std::cmp::Ordering;
55

66
use pyo3::prelude::*;
7-
use pyo3::types::{PyDict, PyList};
7+
use pyo3::types::{PyDict, PyInt, PyList};
88
use pyo3::{intern, PyTraverseError, PyVisit};
99

1010
use ahash::AHashMap;
@@ -58,11 +58,13 @@ impl<T: Debug> LiteralLookup<T> {
5858
expected_bool.false_id = Some(id);
5959
}
6060
}
61-
if let Ok(either_int) = k.exact_int() {
62-
let int = either_int
63-
.into_i64(py)
64-
.map_err(|_| py_schema_error_type!("error extracting int {:?}", k))?;
65-
expected_int.insert(int, id);
61+
if k.is_exact_instance_of::<PyInt>() {
62+
if let Ok(int_64) = k.extract::<i64>() {
63+
expected_int.insert(int_64, id);
64+
} else {
65+
// cover the case of an int that's > i64::MAX etc.
66+
expected_py_dict.set_item(k, id)?;
67+
}
6668
} else if let Ok(either_str) = k.exact_str() {
6769
let str = either_str
6870
.as_cow()

tests/validators/test_enums.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import re
22
import sys
3-
from enum import Enum, IntFlag
3+
from enum import Enum, IntEnum, IntFlag
44

55
import pytest
66

@@ -331,3 +331,16 @@ class MyFlags(IntFlag):
331331

332332
with pytest.raises(ValidationError):
333333
v.validate_python(None)
334+
335+
336+
def test_big_int():
337+
class ColorEnum(IntEnum):
338+
GREEN = 1 << 63
339+
BLUE = 1 << 64
340+
341+
v = SchemaValidator(
342+
core_schema.with_default_schema(schema=core_schema.enum_schema(ColorEnum, list(ColorEnum.__members__.values())))
343+
)
344+
345+
assert v.validate_python(ColorEnum.GREEN) is ColorEnum.GREEN
346+
assert v.validate_python(1 << 63) is ColorEnum.GREEN

tests/validators/test_literal.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,3 +378,14 @@ class Foo(str, Enum):
378378
with pytest.raises(ValidationError) as exc_info:
379379
v.validate_python('bar_val')
380380
assert exc_info.value.errors(include_url=False) == err
381+
382+
383+
def test_big_int():
384+
big_int = 2**64 + 1
385+
massive_int = 2**128 + 1
386+
v = SchemaValidator(core_schema.literal_schema([big_int, massive_int]))
387+
assert v.validate_python(big_int) == big_int
388+
assert v.validate_python(massive_int) == massive_int
389+
m = r'Input should be 18446744073709551617 or 340282366920938463463374607431768211457 \[type=literal_error'
390+
with pytest.raises(ValidationError, match=m):
391+
v.validate_python(37)

0 commit comments

Comments
 (0)