Skip to content

Commit

Permalink
[Backport maintenance/3.2.x] Don't emit incorrect-variance for type p…
Browse files Browse the repository at this point in the history
…arameters (PEP 695) (#9640)

Backport fbc1ed3 from #9638.
  • Loading branch information
Pierre-Sassoulas authored May 17, 2024
2 parents ee6b62f + cdcc509 commit b2ea316
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 3 deletions.
5 changes: 5 additions & 0 deletions doc/whatsnew/fragments/9638.false_positive
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Don't emit ``typevar-name-incorrect-variance`` warnings for PEP 695 style TypeVars.
The variance is inferred automatically by the type checker.
Adding ``_co`` or ``_contra`` suffix can help to reason about TypeVar.

Refs #9638
11 changes: 9 additions & 2 deletions pylint/checkers/base/name_checker/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class TypeVarVariance(Enum):
covariant = auto()
contravariant = auto()
double_variant = auto()
inferred = auto()


def _get_properties(config: argparse.Namespace) -> tuple[set[str], set[str]]:
Expand Down Expand Up @@ -623,6 +624,7 @@ def _assigns_typealias(node: nodes.NodeNG | None) -> bool:

def _check_typevar(self, name: str, node: nodes.AssignName) -> None:
"""Check for TypeVar lint violations."""
variance: TypeVarVariance = TypeVarVariance.invariant
if isinstance(node.parent, nodes.Assign):
keywords = node.assign_type().value.keywords
args = node.assign_type().value.args
Expand All @@ -634,8 +636,8 @@ def _check_typevar(self, name: str, node: nodes.AssignName) -> None:
else: # PEP 695 generic type nodes
keywords = ()
args = ()
variance = TypeVarVariance.inferred

variance = TypeVarVariance.invariant
name_arg = None
for kw in keywords:
if variance == TypeVarVariance.double_variant:
Expand All @@ -659,7 +661,12 @@ def _check_typevar(self, name: str, node: nodes.AssignName) -> None:
if name_arg is None and args and isinstance(args[0], nodes.Const):
name_arg = args[0].value

if variance == TypeVarVariance.double_variant:
if variance == TypeVarVariance.inferred:
# Ignore variance check for PEP 695 type parameters.
# The variance is inferred by the type checker.
# Adding _co or _contra suffix can help to reason about TypeVar.
pass
elif variance == TypeVarVariance.double_variant:
self.add_message(
"typevar-double-variance",
node=node,
Expand Down
6 changes: 6 additions & 0 deletions tests/functional/t/type/typevar_naming_style_py312.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
"""PEP 695 generic typing nodes"""

from collections.abc import Sequence

type Point[T] = tuple[T, ...]
type Point[t] = tuple[t, ...] # [invalid-name]

# Don't report typevar-name-incorrect-variance for type parameter
# The variance is determined by the type checker
type Array[T_co] = Sequence[T_co]
2 changes: 1 addition & 1 deletion tests/functional/t/type/typevar_naming_style_py312.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
invalid-name:4:11:4:12::"Type variable name ""t"" doesn't conform to predefined naming style":HIGH
invalid-name:6:11:6:12::"Type variable name ""t"" doesn't conform to predefined naming style":HIGH

0 comments on commit b2ea316

Please sign in to comment.