mirror of https://github.com/tiangolo/fastapi.git
🐛 Fix `TypeError` when encoding a decimal with a `NaN` or `Infinity` value (#12935)
Signed-off-by: Kent Huang <kent@infuseai.io>
This commit is contained in:
parent
ee490906d8
commit
20f40b29c0
|
|
@ -34,14 +34,14 @@ def isoformat(o: Union[datetime.date, datetime.time]) -> str:
|
|||
return o.isoformat()
|
||||
|
||||
|
||||
# Taken from Pydantic v1 as is
|
||||
# Adapted from Pydantic v1
|
||||
# TODO: pv2 should this return strings instead?
|
||||
def decimal_encoder(dec_value: Decimal) -> Union[int, float]:
|
||||
"""
|
||||
Encodes a Decimal as int of there's no exponent, otherwise float
|
||||
Encodes a Decimal as int if there's no exponent, otherwise float
|
||||
|
||||
This is useful when we use ConstrainedDecimal to represent Numeric(x,0)
|
||||
where a integer (but not int typed) is used. Encoding this as a float
|
||||
where an integer (but not int typed) is used. Encoding this as a float
|
||||
results in failed round-tripping between encode and parse.
|
||||
Our Id type is a prime example of this.
|
||||
|
||||
|
|
@ -50,8 +50,12 @@ def decimal_encoder(dec_value: Decimal) -> Union[int, float]:
|
|||
|
||||
>>> decimal_encoder(Decimal("1"))
|
||||
1
|
||||
|
||||
>>> decimal_encoder(Decimal("NaN"))
|
||||
nan
|
||||
"""
|
||||
if dec_value.as_tuple().exponent >= 0: # type: ignore[operator]
|
||||
exponent = dec_value.as_tuple().exponent
|
||||
if isinstance(exponent, int) and exponent >= 0:
|
||||
return int(dec_value)
|
||||
else:
|
||||
return float(dec_value)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ from dataclasses import dataclass
|
|||
from datetime import datetime, timezone
|
||||
from decimal import Decimal
|
||||
from enum import Enum
|
||||
from math import isinf, isnan
|
||||
from pathlib import PurePath, PurePosixPath, PureWindowsPath
|
||||
from typing import Optional
|
||||
|
||||
|
|
@ -306,6 +307,20 @@ def test_decimal_encoder_int():
|
|||
assert jsonable_encoder(data) == {"value": 2}
|
||||
|
||||
|
||||
@needs_pydanticv2
|
||||
def test_decimal_encoder_nan():
|
||||
data = {"value": Decimal("NaN")}
|
||||
assert isnan(jsonable_encoder(data)["value"])
|
||||
|
||||
|
||||
@needs_pydanticv2
|
||||
def test_decimal_encoder_infinity():
|
||||
data = {"value": Decimal("Infinity")}
|
||||
assert isinf(jsonable_encoder(data)["value"])
|
||||
data = {"value": Decimal("-Infinity")}
|
||||
assert isinf(jsonable_encoder(data)["value"])
|
||||
|
||||
|
||||
def test_encode_deque_encodes_child_models():
|
||||
class Model(BaseModel):
|
||||
test: str
|
||||
|
|
|
|||
Loading…
Reference in New Issue