summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Mueller <30130371+cdce8p@users.noreply.github.com>2021-03-27 00:15:40 +0100
committerPierre Sassoulas <pierre.sassoulas@gmail.com>2021-03-28 22:48:56 +0200
commit454b3defc39a90a60ddc81dd1cf40b4360b0028f (patch)
tree0940b48697e4e8c877c762a796965e83b0ac3a68
parentb6764a41c1f5d76c4cdea6008ef4456c78ebd8bc (diff)
downloadpylint-git-454b3defc39a90a60ddc81dd1cf40b4360b0028f.tar.gz
Refactor and cleanup of PEP 604 check
-rw-r--r--pylint/checkers/typecheck.py81
1 files changed, 47 insertions, 34 deletions
diff --git a/pylint/checkers/typecheck.py b/pylint/checkers/typecheck.py
index 6d73c34ec..1724ed705 100644
--- a/pylint/checkers/typecheck.py
+++ b/pylint/checkers/typecheck.py
@@ -101,6 +101,11 @@ BUILTINS = builtins.__name__
STR_FORMAT = {"%s.str.format" % BUILTINS}
ASYNCIO_COROUTINE = "asyncio.coroutines.coroutine"
BUILTIN_TUPLE = "builtins.tuple"
+TYPE_ANNOTATION_NODES_TYPES = (
+ astroid.AnnAssign,
+ astroid.Arguments,
+ astroid.FunctionDef,
+)
def _unflatten(iterable):
@@ -1652,50 +1657,58 @@ accessed. Python regular expressions are accepted.",
@check_messages("unsupported-binary-operation")
def visit_binop(self, node: astroid.BinOp):
- # Test alternative Union syntax PEP 604 - int | None
- msg = "unsupported operand type(s) for |"
- if node.op == "|" and (
- not is_postponed_evaluation_enabled(node)
- and isinstance(
- node.parent, (astroid.AnnAssign, astroid.Arguments, astroid.FunctionDef)
- )
- or not PY310_PLUS
- and isinstance(
- node.parent,
- (
- astroid.Assign,
- astroid.Call,
- astroid.Keyword,
- astroid.Dict,
- astroid.Tuple,
- astroid.Set,
- astroid.List,
- astroid.BinOp,
- ),
- )
+ if node.op == "|":
+ self._detect_unsupported_alternative_union_syntax(node)
+
+ def _detect_unsupported_alternative_union_syntax(self, node: astroid.BinOp) -> None:
+ """Detect if unsupported alternative Union syntax (PEP 604) was used."""
+ if PY310_PLUS: # 310+ supports the new syntax
+ return
+
+ if isinstance(
+ node.parent, TYPE_ANNOTATION_NODES_TYPES
+ ) and not is_postponed_evaluation_enabled(node):
+ # Use in type annotations only allowed if
+ # postponed evaluation is enabled.
+ self._check_unsupported_alternative_union_syntax(node)
+
+ if isinstance(
+ node.parent,
+ (
+ astroid.Assign,
+ astroid.Call,
+ astroid.Keyword,
+ astroid.Dict,
+ astroid.Tuple,
+ astroid.Set,
+ astroid.List,
+ astroid.BinOp,
+ ),
):
+ # Check other contexts the syntax might appear, but are invalid.
+ # Make sure to filter context if postponed evaluation is enabled
+ # and parent is allowed node type.
allowed_nested_syntax = False
if is_postponed_evaluation_enabled(node):
parent_node = node.parent
while True:
- if isinstance(
- parent_node,
- (astroid.AnnAssign, astroid.Arguments, astroid.FunctionDef),
- ):
+ if isinstance(parent_node, TYPE_ANNOTATION_NODES_TYPES):
allowed_nested_syntax = True
break
parent_node = parent_node.parent
if isinstance(parent_node, astroid.Module):
break
- if allowed_nested_syntax is False:
- for n in (node.left, node.right):
- n = helpers.object_type(n)
- if isinstance(n, astroid.ClassDef):
- if is_classdef_type(n):
- self.add_message(
- "unsupported-binary-operation", args=msg, node=node
- )
- break
+ if not allowed_nested_syntax:
+ self._check_unsupported_alternative_union_syntax(node)
+
+ def _check_unsupported_alternative_union_syntax(self, node: astroid.BinOp) -> None:
+ """Check if left or right node is of type `type`."""
+ msg = msg = "unsupported operand type(s) for |"
+ for n in (node.left, node.right):
+ n = helpers.object_type(n)
+ if isinstance(n, astroid.ClassDef) and is_classdef_type(n):
+ self.add_message("unsupported-binary-operation", args=msg, node=node)
+ break
@check_messages("unsupported-binary-operation")
def _visit_binop(self, node):