You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iceberg.apache.org by fo...@apache.org on 2025/04/18 10:17:46 UTC
(iceberg-python) branch main updated: Add cast from string to float and double (#1933)
This is an automated email from the ASF dual-hosted git repository.
fokko pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-python.git
The following commit(s) were added to refs/heads/main by this push:
new 02eecb6c Add cast from string to float and double (#1933)
02eecb6c is described below
commit 02eecb6cc9b9bf14b64c13f651ec7cd8631440c0
Author: Akashdeep Gupta <gu...@users.noreply.github.com>
AuthorDate: Fri Apr 18 15:47:41 2025 +0530
Add cast from string to float and double (#1933)
Closes #1919
# Rationale for this change
This is an additional good to have feature where users can convert valid
Float and Double strings to Iceberg FloatType and Double Literal.
# Are these changes tested?
Yes. I have also added tests for the same.
# Are there any user-facing changes?
Yes. Users can cast valid float and double strings to `FloatType` and
`DecimalType`
---
pyiceberg/expressions/literals.py | 20 ++++++++++++++++++++
tests/expressions/test_literals.py | 18 +++++++++++++++++-
2 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/pyiceberg/expressions/literals.py b/pyiceberg/expressions/literals.py
index b29d0d9e..e52ed5e0 100644
--- a/pyiceberg/expressions/literals.py
+++ b/pyiceberg/expressions/literals.py
@@ -603,6 +603,26 @@ class StringLiteral(Literal[str]):
else:
raise ValueError(f"Could not convert {self.value} into a {type_var}")
+ @to.register(FloatType)
+ def _(self, type_var: FloatType) -> Literal[float]:
+ try:
+ number = float(self.value)
+ if FloatType.max < number:
+ return FloatAboveMax()
+ elif FloatType.min > number:
+ return FloatBelowMin()
+ return FloatLiteral(number)
+ except ValueError as e:
+ raise ValueError(f"Could not convert {self.value} into a {type_var}") from e
+
+ @to.register(DoubleType)
+ def _(self, type_var: DoubleType) -> Literal[float]:
+ try:
+ number = float(self.value)
+ return DoubleLiteral(number)
+ except ValueError as e:
+ raise ValueError(f"Could not convert {self.value} into a {type_var}") from e
+
def __repr__(self) -> str:
"""Return the string representation of the StringLiteral class."""
return f"literal({repr(self.value)})"
diff --git a/tests/expressions/test_literals.py b/tests/expressions/test_literals.py
index 6144e327..4d8f5557 100644
--- a/tests/expressions/test_literals.py
+++ b/tests/expressions/test_literals.py
@@ -393,6 +393,22 @@ def test_string_to_boolean_literal() -> None:
assert literal("FALSE").to(BooleanType()) == literal(False)
+def test_string_to_float_literal() -> None:
+ assert literal("3.141").to(FloatType()) == literal(3.141).to(FloatType())
+
+
+def test_string_to_float_outside_bound() -> None:
+ big_lit_str = literal(str(FloatType.max + 1.0e37))
+ assert big_lit_str.to(FloatType()) == FloatAboveMax()
+
+ small_lit_str = literal(str(FloatType.min - 1.0e37))
+ assert small_lit_str.to(FloatType()) == FloatBelowMin()
+
+
+def test_string_to_double_literal() -> None:
+ assert literal("3.141").to(DoubleType()) == literal(3.141)
+
+
@pytest.mark.parametrize(
"val",
["unknown", "off", "on", "0", "1", "y", "yes", "n", "no", "t", "f"],
@@ -744,7 +760,7 @@ def test_invalid_decimal_conversions() -> None:
def test_invalid_string_conversions() -> None:
assert_invalid_conversions(
literal("abc"),
- [FloatType(), DoubleType(), FixedType(1), BinaryType()],
+ [FixedType(1), BinaryType()],
)