github-actions[bot] commented on code in PR #40747:
URL: https://github.com/apache/beam/pull/40747#discussion_r4360718614
##########
sdks/python/apache_beam/typehints/decorators.py:
##########
@@ -866,7 +867,16 @@ def getcallargs_forhints(func, *type_args, **type_kwargs):
else:
# Unbound: must have a default or be variadic.
if param.annotation != param.empty:
- bound_args[param.name] = param.annotation
+ annotation = param.annotation
+ if _contains_forward_ref(annotation):
+ # Resolve string annotations (e.g. from functools.partial-bound
+ # keywords under `from __future__ import annotations`) the same way
+ # IOTypeHints.from_callable does, so they compare equal to the
+ # resolved hints.
+ if namespaces is None:
+ namespaces = _annotation_namespaces(func)
+ annotation = _resolve_annotation(annotation, *namespaces)
+ bound_args[param.name] = annotation
Review Comment:
**🟠High**: `IOTypeHints.from_callable` passes the resolved parameter
annotation through `convert_to_beam_type(param.annotation)`, whereas
`getcallargs_forhints` assigns the raw `annotation` directly to
`bound_args[param.name]`. This causes two issues when
`PTransformWithSideInputs.type_check_inputs` compares `bindings` against
`hints`:
1. **Unresolvable forward references (e.g. `TYPE_CHECKING`-only imports
under `from __future__ import annotations`):** `_resolve_annotation` falls back
to returning the raw string when a `NameError` occurs.
`IOTypeHints.from_callable` converts that string to `typehints.Any` via
`convert_to_beam_type`, whereas `getcallargs_forhints` leaves a raw `str` in
`bound_args`. If `getcallargs_forhints` populates `hints` for an optional side
input (e.g. when `@with_input_types` only specifies the main input) and a side
input is provided, `typehints.is_consistent_with` passes the string to
`issubclass(sub, base)` and raises `TypeError: issubclass() arg 2 must be a
class, a tuple of classes, or a union`.
2. **`TypedDict` and Python 3.12 `TypeAliasType` (`type` statement)
annotations on `functools.partial` keyword arguments:**
`IOTypeHints.from_callable` converts `TypedDict` to `Dict[str, Any]` and
unwraps `TypeAliasType` via `convert_to_beam_type`, while
`getcallargs_forhints` leaves the raw `TypedDict` / `TypeAliasType` in
`bindings`. Because `typehints.normalize()` does not convert user-module
`TypedDict` or `TypeAliasType` objects,
`typehints.is_consistent_with(bindings[arg], hints[arg])` returns `False` and
raises a spurious `TypeCheckError`.
Passing `annotation` through `convert_to_beam_type` here ensures
`getcallargs_forhints` produces the exact same Beam type hints as
`IOTypeHints.from_callable`.
```suggestion
bound_args[param.name] = convert_to_beam_type(annotation)
```
--
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]