Skip to content

Rule UP040 incorrect fix when TypeVar is used multiple times #9904

@ostr00000

Description

@ostr00000

Initial code

This is code in stub file decorators.pyi:

import logging
from collections.abc import Callable
from typing import TypeAlias, TypeVar

_BaseFun = TypeVar('_BaseFun', bound=Callable)
_Decorator: TypeAlias = Callable[[_BaseFun], _BaseFun]

def logCurrentTask(
    *, logger: logging.Logger | None = None, msg: str = ''
) -> _Decorator: ...

Ruff command

After running ruff with command:

ruff check ./decorators.pyi --isolated --select UP040 --target-version py312 --fix

TypeVar is replaced to generic type alias.

Code after fix

The code after change is:

import logging
from collections.abc import Callable
from typing import TypeAlias, TypeVar

_BaseFun = TypeVar('_BaseFun', bound=Callable)
type _Decorator[_BaseFun: Callable, _BaseFun: Callable] = Callable[[_BaseFun], _BaseFun]

def logCurrentTask(
    *, logger: logging.Logger | None = None, msg: str = ''
) -> _Decorator: ...

What is wrong

Type alias _Decorator has two declarations with same name _BaseFun which is incorrect syntax.
The PEP 695 states:

Type parameter names within a generic class, function, or type alias must be unique within that same class, function, or type alias

Possible fix

Need to check for duplicates.

Ruff version

ruff --version

ruff 0.2.1

Additional thinking

Not required to this issue, but it may be worth to notify user about remaining, old TypeVar or even remove it when rule UP040 is applying.
Although the variable is not used anymore, it remains in code, possibly unnoticed (I assume that currently only stubs are processed for this rule, but in future it may change).
The old object remains in global scope, which is not detected by most linters/type checkers.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions