moomindani commented on code in PR #3630:
URL: https://github.com/apache/iceberg-python/pull/3630#discussion_r3827827424


##########
pyiceberg/partitioning.py:
##########
@@ -115,13 +117,34 @@ def map_source_ids_onto_source_id(cls, data: Any) -> Any:
                     if len(source_ids) == 0:
                         raise ValueError("Empty source-ids is not allowed")
                     if len(source_ids) > 1:
-                        raise ValueError("Multi argument transforms are not 
yet supported")
+                        if data.get("transform") is None:

Review Comment:
   Good catch on both counts.
   
   You're right that the block is skipped when both keys are present — the 
guard was `"source-id" not in data and "source-ids" in data`. The consequence 
is worse than just losing the normalization: a multi-argument field written 
with both keys keeps its real transform instead of being replaced with 
`UnknownTransform`, so we would evaluate e.g. `bucket[4]` against only the 
first source column rather than treating it as unknown.
   
   The spec only ever writes one of the two keys ("For partition fields with a 
transform with a single argument, only `source-id` is written. In case of a 
multi-argument transform, only `source-ids` is written." — same wording for 
sort fields), so both-present is non-conformant input. I went with the lenient 
read: `source-ids` is authoritative whenever it is present, and a `source-id` 
next to it is ignored. That also means an empty `source-ids` is now rejected 
even when a `source-id` is present. There is no Java implementation of 
`source-ids` to align with — the string does not appear anywhere in 
apache/iceberg's Java tree — so the spec text is the only reference here.
   
   The nesting is gone as well: the validator is now a flat sequence of guards 
with early returns. New tests cover the both-present case for multi-argument, 
single-element and empty `source-ids`, on partition fields and sort fields.
   



##########
pyiceberg/partitioning.py:
##########
@@ -77,6 +78,7 @@ class PartitionField(IcebergBaseModel):
     """
 
     source_id: int = Field(alias="source-id")
+    source_ids: list[int] | None = Field(alias="source-ids", default=None, 
repr=False)

Review Comment:
   Done, and this was the right call — the same three pieces (before-validator, 
model serializer, `__str__`) were duplicated between `PartitionField` and 
`SortField`.
   
   Added `TransformSourceMixin` in `pyiceberg/transforms.py`, which both 
classes now inherit. It owns the `source-id`/`source-ids` fields, the 
validator, the serializer, and two accessors:
   
   - `transform_arguments -> list[int]` — the source column ids the transform 
is applied to (`source_ids` when multi-argument, otherwise `[source_id]`)
   - `is_multi_argument -> bool` — derived from the above, so the arity check 
has a single definition
   
   `__str__` in both classes is now a single line over `transform_arguments`, 
and the only code that touches the raw `"source-id"` / `"source-ids"` keys is 
the mixin. Both files shrank by 46 lines.
   
   It lives in `transforms.py` because `UnknownTransform` is already there and 
both call sites import from it, so this needed no new module and no new 
dependency edge. Happy to move it, or rename the accessors, if you would rather 
have it elsewhere.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to