raams95 commented on code in PR #40757:
URL: https://github.com/apache/beam/pull/40757#discussion_r4477551365
##########
sdks/python/apache_beam/typehints/typehints.py:
##########
@@ -1536,6 +1548,9 @@ def is_consistent_with(
# Cannot check unsupported parameterized generic which will cause
issubclass
# to fail with an exception.
return False
+ elif _is_unchecked_protocol(base):
+ # Protocols are matched structurally, which issubclass cannot check.
+ return True
Review Comment:
Moved the check right after the base `TypeConstraint` branch in efda93e, and
added a `list[int]` pipeline test plus unit cases for `Tuple`, `Dict` and `Row`
inputs.
##########
sdks/python/apache_beam/typehints/typehints.py:
##########
@@ -368,6 +368,16 @@ def is_typing_generic(type_param):
return isinstance(type_param, typing._GenericAlias)
+def _is_unchecked_protocol(type_param):
+ """Determines if an object is a typing.Protocol class that is not
+ runtime_checkable, which isinstance() and issubclass() reject.
+ """
+ return (
+ isinstance(type_param, type) and
+ getattr(type_param, '_is_protocol', False) and
+ not getattr(type_param, '_is_runtime_protocol', False))
Review Comment:
Done in efda93e. `check_constraint` still uses `_is_unchecked_protocol`, and
`is_consistent_with` uses a helper that probes `issubclass(object, base)`. On
3.12+ it also checks `__non_callable_proto_members__`: once Beam's pickler
restores a Protocol by value (defined in `__main__` or inside a function),
`issubclass` returns False instead of raising, so the probe alone still failed
the pipeline test with a `@property` protocol.
##########
sdks/python/apache_beam/typehints/typecheck_test.py:
##########
@@ -134,6 +135,19 @@ def test_wrapper_pipeline_type_check(self):
with self.assertRaisesRegex(ValueError, r'int.*is not iterable'):
_ = self.p | beam.Create([1, 2, 3]) | beam.ParDo(dofn)
+ def test_protocol_type_hint(self):
+ # https://github.com/apache/beam/issues/20986
+ class HasUpper(typing.Protocol):
+ def upper(self) -> str:
+ ...
+
+ def fn(e: HasUpper) -> str:
+ return e.upper()
+
+ result = self.p | beam.Create(['a', 'b']) | beam.Map(fn)
+ assert_that(result, equal_to(['A', 'B']))
+ self.p.run()
Review Comment:
Added `test_protocol_type_hint` to `PerformanceRuntimeTypeCheckTest` in
efda93e.
--
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]