From 636583d5808eacbdd2eb1a669786ea987fd56d66 Mon Sep 17 00:00:00 2001 From: Friday Date: Tue, 17 Feb 2026 12:06:33 +0000 Subject: [PATCH] Fix F821 false positive for aliased Annotated and Literal imports Use _is_typing() in addition to _is_name_or_attr() when checking for Literal and Annotated subscripts. _is_typing() resolves import aliases through the scope stack, so `from typing import Annotated as Ann` is correctly recognized. The _is_name_or_attr() fallback is kept to preserve the existing false-negative-safe behavior for non-typing modules that happen to export names called Literal or Annotated. Closes #789 Co-Authored-By: Claude Opus 4.6 --- pyflakes/checker.py | 10 ++++++++-- pyflakes/test/test_type_annotations.py | 26 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/pyflakes/checker.py b/pyflakes/checker.py index 629dacf0..71b134a1 100644 --- a/pyflakes/checker.py +++ b/pyflakes/checker.py @@ -1372,10 +1372,16 @@ def ignore(self, node): NAMEDEXPR = handleChildren def SUBSCRIPT(self, node): - if _is_name_or_attr(node.value, 'Literal'): + if ( + _is_typing(node.value, 'Literal', self.scopeStack) + or _is_name_or_attr(node.value, 'Literal') + ): with self._enter_annotation(AnnotationState.NONE): self.handleChildren(node) - elif _is_name_or_attr(node.value, 'Annotated'): + elif ( + _is_typing(node.value, 'Annotated', self.scopeStack) + or _is_name_or_attr(node.value, 'Annotated') + ): self.handleNode(node.value, node) # py39+ diff --git a/pyflakes/test/test_type_annotations.py b/pyflakes/test/test_type_annotations.py index f4f8ded5..1979e1bc 100644 --- a/pyflakes/test/test_type_annotations.py +++ b/pyflakes/test/test_type_annotations.py @@ -598,6 +598,32 @@ def f(x: Literal['some string', 'foo bar']) -> None: return None """) + def test_annotated_type_typing_alias(self): + """Annotated imported under an alias should not produce F821.""" + self.flakes(""" + from typing_extensions import Annotated as WithSchema + + def f(x: WithSchema[int, 'hello']) -> None: + return None + """) + + def test_annotated_type_typing_alias_forward_type(self): + self.flakes(""" + from typing import Annotated as Ann + + def f(x: Ann['integer', 1]) -> None: + return None + """, m.UndefinedName) + + def test_literal_type_typing_alias(self): + """Literal imported under an alias should not produce F821.""" + self.flakes(""" + from typing import Literal as Lit + + def f(x: Lit['some string']) -> None: + return None + """) + def test_deferred_twice_annotation(self): self.flakes(""" from queue import Queue