diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 6ef633e4545aef..c23ca933ec908f 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -3,6 +3,7 @@ import collections import collections.abc from collections import defaultdict +from collections.abc import Callable as ABCallable from functools import lru_cache, wraps, reduce import gc import inspect @@ -10668,9 +10669,23 @@ def test_eq(self): with self.assertWarns(DeprecationWarning): self.assertNotEqual(int, typing._UnionGenericAlias) - def test_hashable(self): - self.assertEqual(hash(typing._UnionGenericAlias), hash(Union)) +class TestCallableAlias(BaseTestCase): + def test_callable_alias_preserves_subclass(self): + C = ABCallable[[str, ForwardRef('int')], int] + class A: + c: C + # Explicitly pass global namespace to ensure correct resolution + hints = get_type_hints(A, globalns=globals()) + + # Ensure evaluated type retains the correct subclass (_CallableGenericAlias) + self.assertEqual(hints['c'].__class__, C.__class__) + + # Ensure evaluated type retains correct origin + self.assertEqual(hints['c'].__origin__, C.__origin__) + # Instead of comparing raw ForwardRef, check if the resolution is correct + expected_args = tuple(int if isinstance(arg, ForwardRef) else arg for arg in C.__args__) + self.assertEqual(hints['c'].__args__, expected_args) def load_tests(loader, tests, pattern): import doctest diff --git a/Lib/typing.py b/Lib/typing.py index 3d64480e1431c1..7c546ec7fb8c10 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -472,7 +472,9 @@ def _eval_type(t, globalns, localns, type_params=_sentinel, *, recursive_guard=f if ev_args == t.__args__: return t if isinstance(t, GenericAlias): - return GenericAlias(t.__origin__, ev_args) + if _should_unflatten_callable_args(t, ev_args): + return t.__class__(t.__origin__, (ev_args[:-1], ev_args[-1])) + return t.__class__(t.__origin__, ev_args) if isinstance(t, Union): return functools.reduce(operator.or_, ev_args) else: diff --git a/Misc/NEWS.d/next/Library/2025-03-05-21-48-22.gh-issue-130870.uDz6AQ.rst b/Misc/NEWS.d/next/Library/2025-03-05-21-48-22.gh-issue-130870.uDz6AQ.rst new file mode 100644 index 00000000000000..e52af134eeff63 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-03-05-21-48-22.gh-issue-130870.uDz6AQ.rst @@ -0,0 +1 @@ +Ensure that typing.Callable retains its subclass (_CallableGenericAlias) instead of being incorrectly converted to GenericAlias.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: