You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[typing: PEP 646]: *tuple[int, int] is improperly evaluated by get_type_hints #101015
NOTE: This bug is in typing's internal API and I don't think there's issues in the public API (but haven't looked hard). However, this issue pops up quickly if you try to do anything wrt PEP 646 typing at runtime.
Minimal example
fromtypingimportForwardReffromtypingimportTypeVarTupleTs=TypeVarTuple("Ts")
typ=ForwardRef("*Ts")._evaluate({}, {"Ts": Ts}, frozenset())
asserttyp==next(iter(Ts)) # <-- PASSES AS EXPECTEDtyp=ForwardRef("*tuple[int]")._evaluate({}, {}, frozenset())
asserttyp==tuple[int] # <-- PASSES BUT SHOULDN'Tasserttyp==next(iter(tuple[int])) # <-- SHOULD PASS BUT DOESN'T
changed the title [-]`typing._eval_type` removes unpack information of `types.GenericAlias`[/-][+][typing: PEP 646]: a forward reference to `*tuple[int, int]` is improperly evaluated by `get_type_hints`[/+]on Jan 14, 2023
changed the title [-][typing: PEP 646]: a forward reference to `*tuple[int, int]` is improperly evaluated by `get_type_hints`[/-][+][typing: PEP 646]: `*tuple[int, int]` is improperly evaluated by `get_type_hints`[/+]on Jan 14, 2023
The bug is not unique to forward references. Here, obtaining the annotations directly via .__annotations__ gives the correct result, but going via get_type_hints gives the incorrect result. No forward references here:
I don't have a setup to test changes so going by intuition to simplify the change: If you try only the fix I proposed in _eval_type using next(iter(...)), are there still errors? ForwardRef.__forward_value__ comes from _eval_type and if the latter returns a correctly unpacked type, it shouldn't be necessary to re-apply it or introducing is_unpack.
Activity
pythongh-101015: Fix `typing.ForwardRef` with `*tuple` unpack
pythongh-101015: Fix `typing.ForwardRef` with `*tuple` unpack
pythongh-101015: Fix `typing.ForwardRef` with `*tuple` unpack
sobolevn commentedon Jan 14, 2023
It happens because of this line:
cpython/Lib/typing.py
Lines 827 to 831 in ef633e5
Moreover, it is not ever tested 😒
If I delete this line all tests pass.
Moreover, it has different semantic for
*tuple[int, str]and*Ts, as you have shown.This happens because
TypeVarTupleautomatically addsUnpackhere:cpython/Lib/typing.py
Lines 1056 to 1057 in ef633e5
I've sent a proposal with the fix, but I am not 100% happy with it. Please, share your feedback!
AlexWaygood commentedon Jan 14, 2023
Can somebody provide an example of the bug that doesn't use private APIs such as
typing._eval_typeorForwardRef._evaluate?sobolevn commentedon Jan 14, 2023
See my PR:
It was
{'args': tuple[int, str]}before, example from the currentmain:[-]`typing._eval_type` removes unpack information of `types.GenericAlias`[/-][+][typing: PEP 646]: a forward reference to `*tuple[int, int]` is improperly evaluated by `get_type_hints`[/+][-][typing: PEP 646]: a forward reference to `*tuple[int, int]` is improperly evaluated by `get_type_hints`[/-][+][typing: PEP 646]: `*tuple[int, int]` is improperly evaluated by `get_type_hints`[/+]AlexWaygood commentedon Jan 14, 2023
Thanks @sobolevn, that's very helpful! Cc. @mrahtz for interest.
AlexWaygood commentedon Jan 14, 2023
The bug is not unique to forward references. Here, obtaining the annotations directly via
.__annotations__gives the correct result, but going viaget_type_hintsgives the incorrect result. No forward references here:sobolevn commentedon Jan 14, 2023
Yes, that's a good catch. My PR does not solve the second problem. Fixing it!
sobolevn commentedon Jan 14, 2023
Now it does. With even more hacks 😒
hjalmarlucius commentedon Jan 14, 2023
I don't have a setup to test changes so going by intuition to simplify the change: If you try only the fix I proposed in
_eval_typeusingnext(iter(...)), are there still errors?ForwardRef.__forward_value__comes from_eval_typeand if the latter returns a correctly unpacked type, it shouldn't be necessary to re-apply it or introducingis_unpack.sobolevn commentedon Jan 14, 2023
@hjalmarlucius I've managed to remove new
ForwardRefflag. However,next(iter(...))seems like a very unclear hack :)I prefer to keep my code with
__unpacked__.gh-101015: Fix `typing.get_type_hints` with unpacked `*tuple` (PEP 64…
pythongh-101015: Fix `typing.get_type_hints` with unpacked `*tuple` (…
gh-101015: Fix `typing.get_type_hints` with unpacked `*tuple` (PEP 64…
AlexWaygood commentedon Jan 23, 2023
Thanks @hjalmarlucius for the report, and @sobolevn for the fix!