From e3b64c56ab1f3488f6b025915508f6de0157a64b Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Thu, 16 Oct 2025 08:17:06 -0400 Subject: [PATCH 1/3] Fix FP for invalid-name for TypedDicts --- doc/whatsnew/fragments/10672.false_positive | 3 +++ pylint/checkers/base/name_checker/checker.py | 15 ++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 doc/whatsnew/fragments/10672.false_positive diff --git a/doc/whatsnew/fragments/10672.false_positive b/doc/whatsnew/fragments/10672.false_positive new file mode 100644 index 0000000000..3a992c64b8 --- /dev/null +++ b/doc/whatsnew/fragments/10672.false_positive @@ -0,0 +1,3 @@ +Fix false positive for :ref:`invalid-name` for ``TypedDict`` instances. + +Closes #10672 diff --git a/pylint/checkers/base/name_checker/checker.py b/pylint/checkers/base/name_checker/checker.py index 2fcef7fc7b..29fb52d051 100644 --- a/pylint/checkers/base/name_checker/checker.py +++ b/pylint/checkers/base/name_checker/checker.py @@ -490,13 +490,14 @@ def visit_assignname( # pylint: disable=too-many-branches,too-many-statements # Check classes (TypeVar's are classes so they need to be excluded first) elif isinstance(inferred_assign_type, nodes.ClassDef) or ( isinstance(inferred_assign_type, bases.Instance) - and "EnumMeta" - in { - ancestor.name - for ancestor in cast( - InferenceResult, inferred_assign_type - ).mro() - } + and {"EnumMeta", "TypedDict"}.intersection( + { + ancestor.name + for ancestor in cast( + InferenceResult, inferred_assign_type + ).mro() + } + ) ): self._check_name("class", node.name, node) From 7280a7126344838eb55bec6c83be6450c2d7b3ab Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Thu, 16 Oct 2025 09:23:25 -0400 Subject: [PATCH 2/3] Apply suggestion from @Pierre-Sassoulas Co-authored-by: Pierre Sassoulas --- doc/whatsnew/fragments/10672.false_positive | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/whatsnew/fragments/10672.false_positive b/doc/whatsnew/fragments/10672.false_positive index 3a992c64b8..e27f916c29 100644 --- a/doc/whatsnew/fragments/10672.false_positive +++ b/doc/whatsnew/fragments/10672.false_positive @@ -1,3 +1,3 @@ -Fix false positive for :ref:`invalid-name` for ``TypedDict`` instances. +Fix false positive for ``invalid-name`` for ``TypedDict`` instances. Closes #10672 From 6ca6a9fd0b511a2a99697b66831f34bb597fdd7f Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Thu, 16 Oct 2025 09:25:05 -0400 Subject: [PATCH 3/3] Add test --- tests/functional/i/invalid/invalid_name.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/functional/i/invalid/invalid_name.py b/tests/functional/i/invalid/invalid_name.py index 9e002fc3f0..7db42f7fb3 100644 --- a/tests/functional/i/invalid/invalid_name.py +++ b/tests/functional/i/invalid/invalid_name.py @@ -121,3 +121,7 @@ class FooBarSubclass(FooBar): from enum import Enum Color = Enum('Color', [('RED', 1), ('GREEN', 2), ('BLUE', 3)]) + + +from typing import TypedDict +MyExampleType = TypedDict("MyExampleType", {"some_field": str})