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 dab25362 Update `__repr__` for `initial-default` and `write-default`
(#2287)
dab25362 is described below
commit dab25362831c9a2d6563b041b38f9698dc320d33
Author: Alex Stephen <[email protected]>
AuthorDate: Thu Aug 7 14:01:57 2025 -0700
Update `__repr__` for `initial-default` and `write-default` (#2287)
<!--
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 #1853
This adds a new repr function that ensures that `initial-default` and
`write-default` will not appear if they are None. Unfortunately, this
functionality isn't baked into Pydantic.
# Rationale for this change
__repr__ changes may be breaking.
# Are these changes tested?
Tests included.
# Are there any user-facing changes?
<!-- In the case of user-facing changes, please add the changelog label.
-->
---
pyiceberg/types.py | 19 +++++++++++++++++--
tests/test_types.py | 15 +++++++++++++++
2 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/pyiceberg/types.py b/pyiceberg/types.py
index 58225979..6872663f 100644
--- a/pyiceberg/types.py
+++ b/pyiceberg/types.py
@@ -340,8 +340,8 @@ class NestedField(IcebergType):
field_type: SerializeAsAny[IcebergType] = Field(alias="type")
required: bool = Field(default=False)
doc: Optional[str] = Field(default=None, repr=False)
- initial_default: Optional[DefaultValue] = Field(alias="initial-default",
default=None, repr=False) # type: ignore
- write_default: Optional[DefaultValue] = Field(alias="write-default",
default=None, repr=False) # type: ignore
+ initial_default: Optional[DefaultValue] = Field(alias="initial-default",
default=None, repr=True) # type: ignore
+ write_default: Optional[DefaultValue] = Field(alias="write-default",
default=None, repr=True) # type: ignore
@field_validator("field_type", mode="before")
def convert_field_type(cls, v: Any) -> IcebergType:
@@ -401,6 +401,21 @@ class NestedField(IcebergType):
req = "required" if self.required else "optional"
return f"{self.field_id}: {self.name}: {req} {self.field_type}{doc}"
+ def __repr__(self) -> str:
+ """Return the string representation of the NestedField class."""
+ parts = [
+ f"field_id={self.field_id}",
+ f"name={self.name!r}",
+ f"field_type={self.field_type!r}",
+ f"required={self.required}",
+ ]
+ if self.initial_default is not None:
+ parts.append(f"initial_default={self.initial_default!r}")
+ if self.write_default is not None:
+ parts.append(f"write_default={self.write_default!r}")
+
+ return f"NestedField({', '.join(parts)})"
+
def __getnewargs__(self) -> Tuple[int, str, IcebergType, bool,
Optional[str]]:
"""Pickle the NestedField class."""
return (self.field_id, self.name, self.field_type, self.required,
self.doc)
diff --git a/tests/test_types.py b/tests/test_types.py
index 2527f0e8..18eb909d 100644
--- a/tests/test_types.py
+++ b/tests/test_types.py
@@ -525,6 +525,21 @@ def test_repr_decimal() -> None:
assert repr(DecimalType(19, 25)) == "DecimalType(precision=19, scale=25)"
+def test_repr_nested_field_default_nones_should_not_appear() -> None:
+ assert (
+ repr(NestedField(1, "required_field", StringType(), required=False,
initial_default=None, write_default=None))
+ == "NestedField(field_id=1, name='required_field',
field_type=StringType(), required=False)"
+ )
+ assert (
+ repr(NestedField(1, "required_field", StringType(), required=False,
initial_default="hello", write_default=None))
+ == "NestedField(field_id=1, name='required_field',
field_type=StringType(), required=False, initial_default='hello')"
+ )
+ assert (
+ repr(NestedField(1, "required_field", StringType(), required=False,
initial_default="hello", write_default="bye"))
+ == "NestedField(field_id=1, name='required_field',
field_type=StringType(), required=False, initial_default='hello',
write_default='bye')"
+ )
+
+
def test_serialization_nestedfield() -> None:
expected =
'{"id":1,"name":"required_field","type":"string","required":true,"doc":"this is
a doc"}'
actual = NestedField(1, "required_field", StringType(), True, "this is a
doc").model_dump_json()