From 88cd4e3f67f8a72d99afe0d2e2e87f9f08715a3c Mon Sep 17 00:00:00 2001 From: Ayush Kumar Saha <225407166+AP24110011695@users.noreply.github.com> Date: Thu, 5 Nov 2026 00:32:26 +0530 Subject: [PATCH] fix(expressions): reject non-finite floats on conversion to Decimal float('inf') is a valid float/double literal, but converting it to a Decimal type crashed with a bare decimal.InvalidOperation instead of the ValueError every other impossible conversion in this module raises. NaN is already rejected at literal construction; infinity now gets a clean, consistent domain error. Signed-off-by: Ayush Kumar Saha <225407166+AP24110011695@users.noreply.github.com> --- pyiceberg/expressions/literals.py | 6 +++++- tests/expressions/test_literals.py | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/pyiceberg/expressions/literals.py b/pyiceberg/expressions/literals.py index b91e404627..99f6948b63 100644 --- a/pyiceberg/expressions/literals.py +++ b/pyiceberg/expressions/literals.py @@ -26,7 +26,7 @@ from datetime import date, datetime, time from decimal import ROUND_HALF_UP, Decimal from functools import singledispatchmethod -from math import isnan +from math import isfinite, isnan from typing import Any, Generic from uuid import UUID @@ -414,6 +414,8 @@ def _(self, _: DoubleType) -> Literal[float]: @to.register(DecimalType) def _(self, type_var: DecimalType) -> Literal[Decimal]: + if not isfinite(self.value): + raise ValueError(f"Could not convert {self.value} into a {type_var}, value is not finite") return DecimalLiteral(Decimal(self.value).quantize(Decimal((0, (1,), -type_var.scale)), rounding=ROUND_HALF_UP)) @@ -439,6 +441,8 @@ def _(self, _: FloatType) -> Literal[float]: @to.register(DecimalType) def _(self, type_var: DecimalType) -> Literal[Decimal]: + if not isfinite(self.value): + raise ValueError(f"Could not convert {self.value} into a {type_var}, value is not finite") return DecimalLiteral(Decimal(self.value).quantize(Decimal((0, (1,), -type_var.scale)), rounding=ROUND_HALF_UP)) diff --git a/tests/expressions/test_literals.py b/tests/expressions/test_literals.py index a7f1c2d43d..dcdcd62556 100644 --- a/tests/expressions/test_literals.py +++ b/tests/expressions/test_literals.py @@ -277,6 +277,22 @@ def test_double_to_decimal_conversion(decimal_type: DecimalType, decimal_value: assert lit.to(decimal_type).value.as_tuple() == Decimal(decimal_value).as_tuple() # type: ignore +def test_float_to_decimal_conversion_with_infinity() -> None: + lit = FloatLiteral(float("inf")) + + with pytest.raises(ValueError) as e: + _ = lit.to(DecimalType(9, 2)) + assert "Could not convert inf into a decimal(9, 2), value is not finite" in str(e.value) + + +def test_double_to_decimal_conversion_with_infinity() -> None: + lit = DoubleLiteral(float("inf")) + + with pytest.raises(ValueError) as e: + _ = lit.to(DecimalType(9, 2)) + assert "Could not convert inf into a decimal(9, 2), value is not finite" in str(e.value) + + def test_decimal_to_decimal_conversion() -> None: lit = literal(Decimal("34.11").quantize(Decimal(".01")))