This is an automated email from the ASF dual-hosted git repository.

claudevdm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to refs/heads/master by this push:
     new 0140552d6d5 [#30019] Fix type checking failures around unions with 
nested complex types (#39413)
0140552d6d5 is described below

commit 0140552d6d5fe028c6256f29ad7f10c1e8365274
Author: Jack McCluskey <[email protected]>
AuthorDate: Thu Jul 23 11:50:20 2026 -0400

    [#30019] Fix type checking failures around unions with nested complex types 
(#39413)
---
 sdks/python/apache_beam/typehints/typehints.py      | 13 +++++++------
 sdks/python/apache_beam/typehints/typehints_test.py | 18 ++++++++++++++++++
 2 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/sdks/python/apache_beam/typehints/typehints.py 
b/sdks/python/apache_beam/typehints/typehints.py
index ffef40de667..041a719ff83 100644
--- a/sdks/python/apache_beam/typehints/typehints.py
+++ b/sdks/python/apache_beam/typehints/typehints.py
@@ -1569,7 +1569,7 @@ def regex_consistency(sub, base) -> bool:
 
 
 def get_yielded_type(type_hint):
-  """Obtains the type of elements yielded by an iterable.s
+  """Obtains the type of elements yielded by an iterable.
 
   Note that "iterable" here means: can be iterated over in a for loop, 
excluding
   strings and dicts.
@@ -1583,10 +1583,16 @@ def get_yielded_type(type_hint):
   Raises:
     ValueError if not iterable.
   """
+  type_hint = normalize(type_hint, none_as_type=True)
   if isinstance(type_hint, typing.TypeVar):
     return typing.Any
   if isinstance(type_hint, AnyTypeConstraint):
     return type_hint
+  if isinstance(type_hint, UnionConstraint):
+    yielded_types = set()
+    for typ in type_hint.inner_types():
+      yielded_types.add(get_yielded_type(typ))
+    return Union[yielded_types]
   if is_consistent_with(type_hint, Iterator[Any]):
     return type_hint.yielded_type
   if is_consistent_with(type_hint, Tuple[Any, ...]):
@@ -1595,11 +1601,6 @@ def get_yielded_type(type_hint):
     else:  # TupleSequenceConstraint
       return type_hint.inner_type
   if is_consistent_with(type_hint, Iterable[Any]):
-    if isinstance(type_hint, UnionConstraint):
-      yielded_types = set()
-      for typ in type_hint.inner_types():
-        yielded_types.add(get_yielded_type(typ))
-      return Union[yielded_types]
     return type_hint.inner_type
   raise ValueError('%s is not iterable' % type_hint)
 
diff --git a/sdks/python/apache_beam/typehints/typehints_test.py 
b/sdks/python/apache_beam/typehints/typehints_test.py
index b097a01fed4..d33c6789d84 100644
--- a/sdks/python/apache_beam/typehints/typehints_test.py
+++ b/sdks/python/apache_beam/typehints/typehints_test.py
@@ -1703,6 +1703,22 @@ class TestGetYieldedType(unittest.TestCase):
         typehints.Union[int, str],
         typehints.get_yielded_type(
             typehints.Union[typehints.List[int], typehints.List[str]]))
+    self.assertEqual(
+        typehints.Union[int, str],
+        typehints.get_yielded_type(
+            typehints.Union[typehints.Iterator[int], typehints.Iterator[str]]))
+    self.assertEqual(
+        typehints.Union[int, str],
+        typehints.get_yielded_type(
+            typehints.Union[typehints.Tuple[int, int],
+                            typehints.Tuple[str, str]]))
+    self.assertEqual(
+        typehints.Union[int, str],
+        typehints.get_yielded_type(typing.Iterable[int] | 
typing.Iterable[str]))
+    self.assertEqual(
+        typehints.Union[int, str],
+        typehints.get_yielded_type(
+            typing.Union[typing.Iterator[int], typing.Iterator[str]]))
 
   def test_not_iterable(self):
     with self.assertRaisesRegex(ValueError, r'not iterable'):
@@ -1711,6 +1727,8 @@ class TestGetYieldedType(unittest.TestCase):
   def test_union_not_iterable(self):
     with self.assertRaisesRegex(ValueError, r'not iterable'):
       typehints.get_yielded_type(typehints.Union[int, typehints.List[int]])
+    with self.assertRaisesRegex(ValueError, r'not iterable'):
+      typehints.get_yielded_type(int | typing.List[str])
 
 
 class TestCoerceToKvType(TypeHintTestCase):

Reply via email to