This is an automated email from the ASF dual-hosted git repository.
kevinjqliu 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 2ad32801 Make Reference JSON serializable (#2564)
2ad32801 is described below
commit 2ad32801893d05617e9d377603ce5c720f670bd1
Author: Fokko Driesprong <[email protected]>
AuthorDate: Sun Oct 5 21:08:30 2025 +0200
Make Reference JSON serializable (#2564)
<!--
Thanks for opening a pull request!
-->
<!-- In the case this PR will resolve an issue, please replace
${GITHUB_ISSUE_ID} below with the actual Github issue id. -->
<!-- Closes #${GITHUB_ISSUE_ID} -->
# Rationale for this change
## Are these changes tested?
## Are there any user-facing changes?
<!-- In the case of user-facing changes, please add the changelog label.
-->
---
pyiceberg/expressions/__init__.py | 20 +++++++++++++-------
tests/expressions/test_expressions.py | 2 ++
2 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/pyiceberg/expressions/__init__.py
b/pyiceberg/expressions/__init__.py
index cbebbd01..c3b5ae74 100644
--- a/pyiceberg/expressions/__init__.py
+++ b/pyiceberg/expressions/__init__.py
@@ -32,6 +32,8 @@ from typing import (
Union,
)
+from pydantic import Field
+
from pyiceberg.expressions.literals import (
AboveMax,
BelowMin,
@@ -202,7 +204,7 @@ class UnboundTerm(Term[Any], Unbound[BoundTerm[L]], ABC):
def bind(self, schema: Schema, case_sensitive: bool = True) ->
BoundTerm[L]: ...
-class Reference(UnboundTerm[Any]):
+class Reference(UnboundTerm[Any], IcebergRootModel[str]):
"""A reference not yet bound to a field in a schema.
Args:
@@ -212,18 +214,18 @@ class Reference(UnboundTerm[Any]):
An unbound reference is sometimes referred to as a "named" reference.
"""
- name: str
+ root: str = Field()
def __init__(self, name: str) -> None:
- self.name = name
+ super().__init__(name)
def __repr__(self) -> str:
"""Return the string representation of the Reference class."""
- return f"Reference(name={repr(self.name)})"
+ return f"Reference(name={repr(self.root)})"
- def __eq__(self, other: Any) -> bool:
- """Return the equality of two instances of the Reference class."""
- return self.name == other.name if isinstance(other, Reference) else
False
+ def __str__(self) -> str:
+ """Return the string representation of the Reference class."""
+ return f"Reference(name={repr(self.root)})"
def bind(self, schema: Schema, case_sensitive: bool = True) ->
BoundReference[L]:
"""Bind the reference to an Iceberg schema.
@@ -242,6 +244,10 @@ class Reference(UnboundTerm[Any]):
accessor = schema.accessor_for_field(field.field_id)
return self.as_bound(field=field, accessor=accessor) # type: ignore
+ @property
+ def name(self) -> str:
+ return self.root
+
@property
def as_bound(self) -> Type[BoundReference[L]]:
return BoundReference[L]
diff --git a/tests/expressions/test_expressions.py
b/tests/expressions/test_expressions.py
index ac5411ff..bcbf25a1 100644
--- a/tests/expressions/test_expressions.py
+++ b/tests/expressions/test_expressions.py
@@ -691,6 +691,8 @@ def test_reference() -> None:
assert repr(ref) == "Reference(name='abc')"
assert ref == eval(repr(ref))
assert ref == pickle.loads(pickle.dumps(ref))
+ assert ref.model_dump_json() == '"abc"'
+ assert Reference.model_validate_json('"abc"') == ref
def test_and() -> None: