from collections.abc import Callable from typing import Any, AnyStr, ParamSpec, TypeVar, TypeVarTuple from somewhere import Something S = TypeVar("S", str, bytes) # constrained type variable T = TypeVar("T", bound=float) Ts = TypeVarTuple("Ts") P = ParamSpec("P") def f(t: T) -> T: return t def g(ts: tuple[*Ts]) -> tuple[*Ts]: return ts def h( p: Callable[P, T], # Comment in the middle of a parameter list should be preserved another_param, and_another, ) -> Callable[P, T]: return p def i(s: S) -> S: return s # NOTE this case is the reason the fix is marked unsafe. If we can't confirm # that one of the type parameters (`Something` in this case) is a TypeVar, # which we can't do across module boundaries, we will not convert it to a # generic type parameter. This leads to code that mixes old-style standalone # TypeVars with the new-style generic syntax and will be rejected by type # checkers def broken_fix(okay: T, bad: Something) -> tuple[T, Something]: return (okay, bad) def any_str_param(s: AnyStr) -> AnyStr: return s # these cases are not handled # TODO(brent) default requires 3.13 V = TypeVar("V", default=Any, bound=str) def default_var(v: V) -> V: return v def outer(): def inner(t: T) -> T: return t