Abacn opened a new issue, #40079:
URL: https://github.com/apache/beam/issues/40079

   ### What happened?
   
   When Beam derives a schema (RowTypeConstraint / RowCoder) for user types 
(such as dataclasses, NamedTuples, or dynamic keys generated by transforms like 
beam.GroupBy), fields of type tuple (or Tuple[...], tuple[T, ...]) exhibit 
inconsistent and breaking behavior depending on whether type hints are inferred:
   
   * **Untyped / `Any`:** Falls back to `FastPrimitivesCoder` and preserves 
`tuple` identity.
   * **Typed as `tuple`:** Converted to `ArrayType` in Schema and deserialized 
by `IterableCoder` as a `list`.
   * **Impact:** Breaks downstream code expecting hashable/immutable objects 
(e.g., `TypeError: cannot use 'list' as a dict key`).
   * **Related bug (heterogeneous tuples):** `schemas.py` assumes all 
`Sequence` types are homogeneous by taking only `arg_types[0]`. For `tuple[str, 
int]`, it treats the entire tuple as `str` and crashes during encoding with 
`AttributeError: 'int' object has no attribute 'encode'`.
   
   #### Minimal Reproducer
   
   ```python
   import apache_beam as beam
   from apache_beam.testing.test_pipeline import TestPipeline
   
   # Case 1: tuple deserializes as unhashable list
   with TestPipeline() as p:
     _ = (
         p
         | beam.Create([('a', 'b')])
         | beam.Map(lambda x: beam.Row(spec=x))
         | beam.Reshuffle()  # forces RowCoder serialization
         | beam.Map(lambda row: {row.spec: 1})  # TypeError: unhashable type: 
'list'
         | beam.Map(print)
     )
   
   # Case 1b: pipeline succeeded with tuple preserved if typehint get lost
   
   def no_hint(x):
     return x if isinstance(x, tuple) else str(x)
   
   with TestPipeline() as p:
     _ = (
         p
         | beam.Create([('a', 'b')])
         | beam.Map(no_hint)
         | beam.Map(lambda x: beam.Row(spec=x))
         | beam.Reshuffle()
         | beam.Map(lambda row: {row.spec: 1})
         | beam.Map(print)
     )
   
   # Case 2: Heterogeneous tuple crashes on encode
   with TestPipeline() as p:
     _ = (
         p
         | beam.Create([('count', 42)])
         | beam.Map(lambda x: beam.Row(spec=x))
         | beam.Reshuffle() # AttributeError: 'int' object has no attribute 
'encode'
         | beam.Map(print)
     )
   
   # Case 2b: success if typehint get lost
   with TestPipeline() as p:
     _ = (
         p
         | beam.Create([('count', 42)])
         | beam.Map(no_hint)
         | beam.Map(lambda x: beam.Row(spec=x))
         | beam.Reshuffle()
         | beam.Map(print)
     )
   ```
   
   #### Root Cause
   1. **`apache_beam/typehints/schemas.py:377`**: Maps all `Sequence` types 
(including `tuple`) to `ArrayType`, taking only `arg_types[0]`.
   2. **`apache_beam/coders/row_coder.py:165` & `coder_impl.py:1466`**: Uses 
`IterableCoder`, which constructs a Python `list` upon decoding `ArrayType`.
   
   #### Suggested Fix
   * Reconstruct `tuple` (or use `TupleSequenceCoderImpl`) in `RowCoder` when 
the original type constraint is a `TupleConstraint`.
   * Do not treat fixed-length / heterogeneous `Tuple[T1, T2]` as homogeneous 
`ArrayType(element_type=T1)`.
   * 
   
   ### Issue Priority
   
   Priority: 2 (default / most bugs should be filed as P2)
   
   ### Issue Components
   
   - [x] Component: Python SDK
   - [ ] Component: Java SDK
   - [ ] Component: Go SDK
   - [ ] Component: Typescript SDK
   - [ ] Component: IO connector
   - [ ] Component: Beam YAML
   - [ ] Component: Beam examples
   - [ ] Component: Beam playground
   - [ ] Component: Beam katas
   - [ ] Component: Website
   - [ ] Component: Infrastructure
   - [ ] Component: Spark Runner
   - [ ] Component: Flink Runner
   - [ ] Component: Prism Runner
   - [ ] Component: Twister2 Runner
   - [ ] Component: Hazelcast Jet Runner
   - [ ] Component: Google Cloud Dataflow Runner


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

Reply via email to