Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested use of Unpack in alias from TypeAliasType causes TypeError on Python 3.11 #474

Closed
Daraan opened this issue Sep 27, 2024 · 2 comments · Fixed by #480
Closed

Nested use of Unpack in alias from TypeAliasType causes TypeError on Python 3.11 #474

Daraan opened this issue Sep 27, 2024 · 2 comments · Fixed by #480

Comments

@Daraan
Copy link
Contributor

Daraan commented Sep 27, 2024

I've written some tests to test nesting of Unpack with TypeAliasTypes, which causes TypeError: Substitution of bare TypeVarTuple is not supported during the recursive substitution.

This is currently only relevant for 3.11 as for lower versions Issue #103 needs to be addressed first.

    @skipUnless(TYPING_3_11_0, "Needs Issue #103 first")
    def test_nested_unpack(self):
        T = TypeVar('T')
        Ts = TypeVarTuple("Ts")

        Variadic = TypeAliasType("Variadic", Tuple[int, Unpack[Ts]], type_params=(Ts,))
        Variadic[int, Tuple[str, int]]  # this is ok

        TupleAliasTs = Variadic[Tuple[Unpack[Ts], int]]

# -------------------------------------------------

        # Tuple[int, Tuple[str, int]]
        # all below tests also fail so abort here early.
        TupleAliasTs[str]  # <--- TypeError: Substitution of bare TypeVarTuple is not supported

# -------------------------------------------------

        TupleAliasTsT = Variadic[Tuple[Unpack[Ts], T]]
        with self.subTest("Single parameter for tuple alias"):
            # Tuple[int, Tuple[str, object]]
            nested_tuple_A = TupleAliasTsT[str, object]
            nested_tuple_A_unpack = TupleAliasTsT[Unpack[Tuple[str]], object]
            self.assertEqual(nested_tuple_A, nested_tuple_A_unpack)

        with self.subTest("Test invalid args", args=([str, int], object)):
            # TypeError on some versions as types should be passed
            invalid_nested_tuple = TupleAliasTsT[[str, int], object]  # invalid form
        with self.subTest("With Callable Ts"):
            # Tuple[int, (str, int) -> object]
            CallableAliasTsT = Variadic[Callable[[Unpack[Ts]], T]]
            CallableAliasTsT[[str, int], object]  # valid nested tuple

        # Equivalent Forms
        with self.subTest("Equivalence of variadic arguments"):
            nested_tuple_bare = TupleAliasTsT[str, int, object]
            nested_tuple_B_1xUnpack = TupleAliasTsT[Unpack[Tuple[str, int]], object]
            nested_tuple_B_2xUnpack = TupleAliasTsT[Unpack[Tuple[str]], Unpack[Tuple[int]], object]
            self.assertEqual(nested_tuple_B_1xUnpack, nested_tuple_bare)
            self.assertEqual(nested_tuple_B_1xUnpack, nested_tuple_B_2xUnpack)
            self.assertNotEqual(invalid_nested_tuple, nested_tuple_B_1xUnpack)

Traceback:

TupleAliasTs[str]
~~~~~~~~~~~~^^^^^
File "/home/me/test/envs/python3.11/lib/python3.11/typing.py", line 379, in inner
return func(*args, **kwds)
        ^^^^^^^^^^^^^^^^^^^
File "/home/me/test/envs/python3.11/lib/python3.11/typing.py", line 1431, in __getitem__
new_args = self._determine_new_args(args)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/me/test/envs/python3.11/lib/python3.11/typing.py", line 1462, in _determine_new_args
return tuple(self._make_substitution(self.__args__, new_arg_by_param))
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/me/test/envs/python3.11/lib/python3.11/typing.py", line 1486, in _make_substitution
new_arg = old_arg[tuple(subargs)]
            ~~~~~~~^^^^^^^^^^^^^^^^
File "/home/me/test/envs/python3.11/lib/python3.11/typing.py", line 379, in inner
return func(*args, **kwds)
        ^^^^^^^^^^^^^^^^^^^
File "/home/me/test/envs/python3.11/lib/python3.11/typing.py", line 1431, in __getitem__
new_args = self._determine_new_args(args)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/me/test/envs/python3.11/lib/python3.11/typing.py", line 1462, in _determine_new_args
return tuple(self._make_substitution(self.__args__, new_arg_by_param))
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/me/test/envs/python3.11/lib/python3.11/typing.py", line 1474, in _make_substitution
new_arg = substfunc(new_arg_by_param[old_arg])
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/me/test/envs/python3.11/lib/python3.11/typing.py", line 1103, in __typing_subst__
raise TypeError("Substitution of bare TypeVarTuple is not supported")
TypeError: Substitution of bare TypeVarTuple is not supported
@JelleZijlstra
Copy link
Member

Thanks, that does seem like a bug we should address.

Daraan added a commit to Daraan/typing_extensions that referenced this issue Sep 30, 2024
@Daraan
Copy link
Contributor Author

Daraan commented Oct 4, 2024

I've traced this back to a minimal variant that happens during the substitution causing the same error:

Unpack[Ts][str]  # should equal str

I've found a fix and wrap it in a PR in the next hours.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants