◐ Shell
clean mode source ↗

gh-130870 Fix _eval_type Handling for GenericAlias with Unflattened Arguments and Union Types by sharktide · Pull Request #130897 · python/cpython

@JelleZijlstra You want a failing test? I'll give you a failing test:

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)

Out without the fix: (Note that this was when I had f string assertionError messages. I removed them)

FAIL: test_callable_alias_preserves_subclass (__main__.TestCallableAlias.test_callable_alias_preserves_subclass)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\rihaan.meher\Documents\GitHub\cpython\zzz.py", line 30, in test_callable_alias_preserves_subclass
    self.assertEqual(hints['c'].__class__, C.__class__, f"Expected {C.__class__}, got {hints['c'].__class__}")
AssertionError: <class 'types.GenericAlias'> != <class 'collections.abc._CallableGenericAlias'> : Expected <class 'collections.abc._CallableGenericAlias'>, got <class 'types.GenericAlias'>

With my PR, this passes.

I added it to test_typing.py

Essentially what this PR does:

  • Preserving Type Information: If Callable is incorrectly converted to GenericAlias, it loses its subclass-specific behavior, which could affect type introspection and runtime checks.

  • Ensuring Correct Type Resolution: ForwardRef('int') should be properly resolved to int, maintaining expected behavior when evaluating type hints.

  • Preventing Silent Type Corruption: If Callable is mishandled, it could lead to unexpected behavior in libraries and applications relying on precise type annotations.