raams95 opened a new pull request, #40680:
URL: https://github.com/apache/beam/pull/40680

   Fixes #20899
   
   Type inference gives a slice of a fixed-size tuple the type of the whole 
tuple. For an element of type `Tuple[str, str, int]`, `row[1:]` is inferred as 
`Tuple[str, str, int]` instead of `Tuple[str, int]`. This breaks pipelines, not 
only the reported `element_type`. Dropping the first field before combining 
fails at construction:
   
   ```python
   rows = [('day1', 'a', 1), ('day2', 'a', 2), ('day1', 'b', 3)]
   with beam.Pipeline() as p:
     _ = (
         p
         | beam.Create(rows).with_output_types(Tuple[str, str, int])
         | 'DropDate' >> beam.Map(lambda row: row[1:])
         | beam.CombinePerKey(sum))
   ```
   
   ```
   TypeCheckError: The transform 'CombinePerKey(sum)' requires PCollections of 
type 'Tuple[TypeVariable[K], Any]' but was applied to a PCollection of type 
'Tuple[<class 'str'>, <class 'str'>, <class 'int'>]' (produced by the transform 
'DropDate').
   ```
   
   When the sliced PCollection is encoded, for example before a `Reshuffle`, 
the coder for the whole tuple is used and the pipeline fails with `TypeError: 
'<' not supported between instances of 'str' and 'int'` for `row[1:]`, or 
`IndexError: tuple index out of range` for `row[:2]`.
   
   With this change, a slice of a fixed-size `Tuple` with constant bounds is 
inferred as the tuple of the selected element types (`Tuple[str, int]` above, 
`Tuple[float, str, int]` for `[::-1]` on `Tuple[int, str, float]`). A slice 
with bounds that aren't constants, such as `row[i:]`, is inferred as 
`Tuple[Union[...], ...]` of the element types, in line with a variable index 
(`row[i]` is inferred as `Union[...]`) and tuple unpacking (`(*a, *b)`). Slices 
of lists, `Tuple[T, ...]` and `str` keep the type of the sliced value, as 
before.
   
   Slices compile to different bytecode depending on the Python version: 
`BUILD_SLICE` followed by a subscript on 3.10 and 3.11 and for slices with a 
step, `BINARY_SLICE` on 3.12 and later, and a constant `slice` object on 3.14. 
`build_slice` now keeps constant bounds as a `Const` slice, and `binary_subscr` 
and `binary_slice` share one helper, so all versions infer the same types.
   
   Tests:
   - `testGetItemSlice` in `trivial_inference_test.py` has new cases for 
fixed-size tuples.
   - `test_inferred_type_of_tuple_slice` in `typed_pipeline_test.py` runs the 
pipeline above.
   
   Both fail before the change and pass after it on Python 3.10, 3.11, 3.12, 
3.13 and 3.14.
   
   Testing:
   - `pytest apache_beam/typehints/trivial_inference_test.py 
apache_beam/typehints/typed_pipeline_test.py` on Python 3.10, 3.11, 3.12, 3.13 
and 3.14
   - `pytest apache_beam/typehints apache_beam/transforms apache_beam/coders 
apache_beam/pipeline_test.py apache_beam/dataframe/transforms_test.py 
apache_beam/yaml/yaml_mapping_test.py apache_beam/yaml/yaml_udf_test.py` on 
Python 3.12
   - `yapf --diff` and `ruff check` on the changed files
   
   ------------------------
   
   Thank you for your contribution! Follow this checklist to help us 
incorporate your contribution quickly and easily:
   
    - [x] Mention the appropriate issue in your description (for example: 
`addresses #123` or `fixes #456`).
    - [x] Update `CHANGES.md` with noteworthy changes.
    - [ ] If this contribution is large, please file an Apache [Individual 
Contributor License Agreement](https://www.apache.org/licenses/icla.pdf). (Not 
needed, small change.)
   
   See the [Contributor Guide](https://beam.apache.org/contribute) for more 
tips on [how to make review process 
smoother](https://github.com/apache/beam/blob/master/CONTRIBUTING.md#make-the-reviewers-job-easier).
   


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