Skip to content

Commit

Permalink
Disambiguate between str and enum member args to typing.Literal (pyli…
Browse files Browse the repository at this point in the history
…nt-dev#7414)

Co-authored-by: Daniël van Noord <13665637+DanielNoord@users.noreply.github.com>
  • Loading branch information
2 people authored and Pierre-Sassoulas committed Oct 10, 2022
1 parent 8f3227f commit eb7a6ae
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 15 deletions.
4 changes: 4 additions & 0 deletions doc/whatsnew/fragments/3299.bugfix
@@ -0,0 +1,4 @@
Fix bug in scanning of names inside arguments to `typing.Literal`.
See https://peps.python.org/pep-0586/#literals-enums-and-forward-references for details.

Refs #3299
21 changes: 9 additions & 12 deletions pylint/checkers/variables.py
Expand Up @@ -2945,28 +2945,25 @@ def visit_const(self, node: nodes.Const) -> None:
return
if not utils.is_node_in_type_annotation_context(node):
return
if not node.value.isidentifier():
try:
annotation = extract_node(node.value)
self._store_type_annotation_node(annotation)
except ValueError:
# e.g. node.value is white space
return
except astroid.AstroidSyntaxError:
# e.g. "?" or ":" in typing.Literal["?", ":"]
return

# Check if parent's or grandparent's first child is typing.Literal
parent = node.parent
if isinstance(parent, nodes.Tuple):
parent = parent.parent

if isinstance(parent, nodes.Subscript):
origin = next(parent.get_children(), None)
if origin is not None and utils.is_typing_literal(origin):
return

self._type_annotation_names.append(node.value)
try:
annotation = extract_node(node.value)
self._store_type_annotation_node(annotation)
except ValueError:
# e.g. node.value is white space
pass
except astroid.AstroidSyntaxError:
# e.g. "?" or ":" in typing.Literal["?", ":"]
pass


def register(linter: PyLinter) -> None:
Expand Down
Expand Up @@ -21,6 +21,11 @@ def example3(_: "os.PathLike[str]") -> None:
def example4(_: "PathLike[str]") -> None:
"""unused-import shouldn't be emitted for PathLike."""

# pylint shouldn't crash with the following strings in a type annotation context
example5: Set[""]
example6: Set[" "]
example7: Set["?"]

class Class:
"""unused-import shouldn't be emitted for Namespace"""
cls: "Namespace"
Expand Up @@ -2,8 +2,10 @@

from argparse import ArgumentParser # [unused-import]
from argparse import Namespace # [unused-import]
from typing import Literal as Lit
import http # [unused-import]
from http import HTTPStatus
import typing as t
from typing import Literal as Lit

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

# pylint shouldn't crash with the following strings in a type annotation context
example3: Lit["", " ", "?"] = "?"


# See https://peps.python.org/pep-0586/#literals-enums-and-forward-references
example4: t.Literal["http.HTTPStatus.OK", "http.HTTPStatus.NOT_FOUND"]
example5: "t.Literal[HTTPStatus.OK, HTTPStatus.NOT_FOUND]"
@@ -1,4 +1,5 @@
unused-import:3:0:3:35::Unused ArgumentParser imported from argparse:UNDEFINED
unused-import:4:0:4:30::Unused Namespace imported from argparse:UNDEFINED
unused-variable:13:4:13:9:unused_variable_example:Unused variable 'hello':UNDEFINED
unused-variable:14:4:14:9:unused_variable_example:Unused variable 'world':UNDEFINED
unused-import:5:0:5:11::Unused import http:UNDEFINED
unused-variable:15:4:15:9:unused_variable_example:Unused variable 'hello':UNDEFINED
unused-variable:16:4:16:9:unused_variable_example:Unused variable 'world':UNDEFINED

0 comments on commit eb7a6ae

Please sign in to comment.