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:

Reply via email to