Skip to content

Commit 49e15ab

Browse files
lggruspeDanielNoord
authored andcommitted
Disambiguate between str and enum member args to typing.Literal (#7414)
Co-authored-by: Daniël van Noord <[email protected]>
1 parent 07f484f commit 49e15ab

File tree

5 files changed

+29
-15
lines changed

5 files changed

+29
-15
lines changed

doc/whatsnew/fragments/3299.bugfix

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fix bug in scanning of names inside arguments to `typing.Literal`.
2+
See https://peps.python.org/pep-0586/#literals-enums-and-forward-references for details.
3+
4+
Refs #3299

pylint/checkers/variables.py

+9-12
Original file line numberDiff line numberDiff line change
@@ -2945,28 +2945,25 @@ def visit_const(self, node: nodes.Const) -> None:
29452945
return
29462946
if not utils.is_node_in_type_annotation_context(node):
29472947
return
2948-
if not node.value.isidentifier():
2949-
try:
2950-
annotation = extract_node(node.value)
2951-
self._store_type_annotation_node(annotation)
2952-
except ValueError:
2953-
# e.g. node.value is white space
2954-
return
2955-
except astroid.AstroidSyntaxError:
2956-
# e.g. "?" or ":" in typing.Literal["?", ":"]
2957-
return
29582948

29592949
# Check if parent's or grandparent's first child is typing.Literal
29602950
parent = node.parent
29612951
if isinstance(parent, nodes.Tuple):
29622952
parent = parent.parent
2963-
29642953
if isinstance(parent, nodes.Subscript):
29652954
origin = next(parent.get_children(), None)
29662955
if origin is not None and utils.is_typing_literal(origin):
29672956
return
29682957

2969-
self._type_annotation_names.append(node.value)
2958+
try:
2959+
annotation = extract_node(node.value)
2960+
self._store_type_annotation_node(annotation)
2961+
except ValueError:
2962+
# e.g. node.value is white space
2963+
pass
2964+
except astroid.AstroidSyntaxError:
2965+
# e.g. "?" or ":" in typing.Literal["?", ":"]
2966+
pass
29702967

29712968

29722969
def register(linter: PyLinter) -> None:

tests/functional/u/unused/unused_name_in_string_literal_type_annotation.py

+5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ def example3(_: "os.PathLike[str]") -> None:
2121
def example4(_: "PathLike[str]") -> None:
2222
"""unused-import shouldn't be emitted for PathLike."""
2323

24+
# pylint shouldn't crash with the following strings in a type annotation context
25+
example5: Set[""]
26+
example6: Set[" "]
27+
example7: Set["?"]
28+
2429
class Class:
2530
"""unused-import shouldn't be emitted for Namespace"""
2631
cls: "Namespace"

tests/functional/u/unused/unused_name_in_string_literal_type_annotation_py38.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
from argparse import ArgumentParser # [unused-import]
44
from argparse import Namespace # [unused-import]
5-
from typing import Literal as Lit
5+
import http # [unused-import]
6+
from http import HTTPStatus
67
import typing as t
8+
from typing import Literal as Lit
79

810
# str inside Literal shouldn't be treated as names
911
example1: t.Literal["ArgumentParser", Lit["Namespace", "ArgumentParser"]]
@@ -18,3 +20,8 @@ def unused_variable_example():
1820

1921
# pylint shouldn't crash with the following strings in a type annotation context
2022
example3: Lit["", " ", "?"] = "?"
23+
24+
25+
# See https://peps.python.org/pep-0586/#literals-enums-and-forward-references
26+
example4: t.Literal["http.HTTPStatus.OK", "http.HTTPStatus.NOT_FOUND"]
27+
example5: "t.Literal[HTTPStatus.OK, HTTPStatus.NOT_FOUND]"
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
unused-import:3:0:3:35::Unused ArgumentParser imported from argparse:UNDEFINED
22
unused-import:4:0:4:30::Unused Namespace imported from argparse:UNDEFINED
3-
unused-variable:13:4:13:9:unused_variable_example:Unused variable 'hello':UNDEFINED
4-
unused-variable:14:4:14:9:unused_variable_example:Unused variable 'world':UNDEFINED
3+
unused-import:5:0:5:11::Unused import http:UNDEFINED
4+
unused-variable:15:4:15:9:unused_variable_example:Unused variable 'hello':UNDEFINED
5+
unused-variable:16:4:16:9:unused_variable_example:Unused variable 'world':UNDEFINED

0 commit comments

Comments
 (0)