qzyu999 commented on issue #3812:
URL: 
https://github.com/apache/iceberg-python/issues/3812#issuecomment-5347604756

   ## Notes on `inspect.py` and `transforms.py`
   
   Adding some analysis on the two "TBD" items to guide discussion.
   
   ### `table/inspect.py`
   
   Every method in `InspectTable` follows the same pattern: iterate over 
metadata objects, build a list of Python dicts, define a `pa.schema(...)`, and 
call `pa.Table.from_pylist(data, schema=schema)`.
   
   Absorption would mean moving the schema definitions and `from_pylist` calls 
into helper functions in `io/pyarrow.py`:
   
   ```python
   # io/pyarrow.py
   def _build_snapshots_table(snapshots: list[dict[str, Any]]) -> pa.Table:
       schema = pa.schema([
           pa.field("committed_at", pa.timestamp(unit="ms"), nullable=False),
           pa.field("snapshot_id", pa.int64(), nullable=False),
           ...
       ])
       return pa.Table.from_pylist(snapshots, schema=schema)
   ```
   
   Then `inspect.py` would only gather dicts and delegate:
   
   ```python
   # table/inspect.py
   from pyiceberg.io.pyarrow import _build_snapshots_table
   
   def snapshots(self) -> "pa.Table":
       rows = [{"committed_at": ..., ...} for s in self.tbl.metadata.snapshots]
       return _build_snapshots_table(rows)
   ```
   
   **My read:** This is technically doable but adds ~10 trivial wrapper 
functions whose only job is `pa.Table.from_pylist(data, schema=X)`. There's no 
compute here that benefits from engine substitution. A DataFusion engine would 
not build metadata inspection tables any differently. This is output 
formatting, not a substitution target 
   
   Leaning toward **leave**, but open to feedback.
   
   ### `transforms.py`
   
   Each transform subclass defines a `pyarrow_transform()` method returning a 
`Callable[[pa.Array], pa.Array]`. The shared `_pyiceberg_transform_wrapper` 
dispatches on `pa.Array` vs `pa.ChunkedArray`.
   
   Absorption would mean moving the implementations out of the classes and into 
a dispatch function in `io/pyarrow.py`:
   
   ```python
   # io/pyarrow.py
   def _get_pyarrow_transform(transform: Transform, source: IcebergType) -> 
Callable[[pa.Array], pa.Array]:
       if isinstance(transform, BucketTransform):
           return _pyiceberg_transform_wrapper(core.bucket, 
transform._num_buckets)
       elif isinstance(transform, YearTransform):
           return _pyiceberg_transform_wrapper(core.year, 
expected_type=pa.int32())
       ...
   ```
   
   **My read:** This fights the existing OO design. The `pyarrow_transform()` 
methods are polymorphic for a reason: each transform subclass owns its own 
implementation. Pulling them into a central `isinstance` dispatch:
   - Mirrors the class hierarchy in a fragile way (adding a new transform 
requires editing two places)
   - Doesn't improve substitutability. If DataFusion came in, you'd add a 
parallel `datafusion_transform()` method or a generic `transform(engine)` 
dispatch alongside the existing methods, not replace them.
   
   The methods are already scoped by name (`pyarrow_transform`) to signal 
they're the PyArrow-specific path. They *are* the extension point.
   
   Leaning toward **leave**.
   
   ### Summary
   
   | File | Absorption approach | Recommendation |
   |------|-------------------|----------------|
   | `inspect.py` | Move schema defs + `from_pylist` into `io/pyarrow.py` 
helpers | Leave. No compute to substitute, just output formatting |
   | `transforms.py` | Central dispatch function replacing polymorphic methods 
| Leave. Breaks OO design, methods already serve as the named extension point |
   
   Happy to reconsider if there's a use case I'm missing.
   


-- 
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