summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Sassoulas <pierre.sassoulas@gmail.com>2020-09-05 08:34:04 +0200
committerPierre Sassoulas <pierre.sassoulas@gmail.com>2020-09-05 09:35:14 +0200
commitcebd64081cc74c23e4b80678c335bccbf18a145f (patch)
tree09a8b16b52ea53026064d433b97f8f9067aef06e
parent3c257cd675e6e6e5ff621fc4e3576c399cd6b92b (diff)
downloadpylint-git-cebd64081cc74c23e4b80678c335bccbf18a145f.tar.gz
Move the NotChecker to its own file
-rw-r--r--pylint/checkers/refactoring/__init__.py81
-rw-r--r--pylint/checkers/refactoring/not_checker.py89
2 files changed, 91 insertions, 79 deletions
diff --git a/pylint/checkers/refactoring/__init__.py b/pylint/checkers/refactoring/__init__.py
index 9a66a71e7..3fded2a3e 100644
--- a/pylint/checkers/refactoring/__init__.py
+++ b/pylint/checkers/refactoring/__init__.py
@@ -34,7 +34,7 @@
# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
"""Looks for code which can be refactored."""
-import builtins
+
import collections
import copy
import itertools
@@ -48,6 +48,7 @@ from astroid import decorators
from pylint import checkers, interfaces
from pylint import utils as lint_utils
from pylint.checkers import utils
+from pylint.checkers.refactoring.not_checker import NotChecker
from pylint.checkers.utils import node_frame_class
KNOWN_INFINITE_ITERATORS = {"itertools.count"}
@@ -1514,84 +1515,6 @@ class RecommandationChecker(checkers.BaseChecker):
return
-class NotChecker(checkers.BaseChecker):
- """checks for too many not in comparison expressions
-
- - "not not" should trigger a warning
- - "not" followed by a comparison should trigger a warning
- """
-
- __implements__ = (interfaces.IAstroidChecker,)
- msgs = {
- "C0113": (
- 'Consider changing "%s" to "%s"',
- "unneeded-not",
- "Used when a boolean expression contains an unneeded negation.",
- )
- }
- name = "refactoring"
- reverse_op = {
- "<": ">=",
- "<=": ">",
- ">": "<=",
- ">=": "<",
- "==": "!=",
- "!=": "==",
- "in": "not in",
- "is": "is not",
- }
- # sets are not ordered, so for example "not set(LEFT_VALS) <= set(RIGHT_VALS)" is
- # not equivalent to "set(LEFT_VALS) > set(RIGHT_VALS)"
- skipped_nodes = (astroid.Set,)
- # 'builtins' py3, '__builtin__' py2
- skipped_classnames = [
- "%s.%s" % (builtins.__name__, qname) for qname in ("set", "frozenset")
- ]
-
- @utils.check_messages("unneeded-not")
- def visit_unaryop(self, node):
- if node.op != "not":
- return
- operand = node.operand
-
- if isinstance(operand, astroid.UnaryOp) and operand.op == "not":
- self.add_message(
- "unneeded-not",
- node=node,
- args=(node.as_string(), operand.operand.as_string()),
- )
- elif isinstance(operand, astroid.Compare):
- left = operand.left
- # ignore multiple comparisons
- if len(operand.ops) > 1:
- return
- operator, right = operand.ops[0]
- if operator not in self.reverse_op:
- return
- # Ignore __ne__ as function of __eq__
- frame = node.frame()
- if frame.name == "__ne__" and operator == "==":
- return
- for _type in (utils.node_type(left), utils.node_type(right)):
- if not _type:
- return
- if isinstance(_type, self.skipped_nodes):
- return
- if (
- isinstance(_type, astroid.Instance)
- and _type.qname() in self.skipped_classnames
- ):
- return
- suggestion = "%s %s %s" % (
- left.as_string(),
- self.reverse_op[operator],
- right.as_string(),
- )
- self.add_message(
- "unneeded-not", node=node, args=(node.as_string(), suggestion)
- )
-
-
class LenChecker(checkers.BaseChecker):
"""Checks for incorrect usage of len() inside conditions.
Pep8 states:
diff --git a/pylint/checkers/refactoring/not_checker.py b/pylint/checkers/refactoring/not_checker.py
new file mode 100644
index 000000000..95cee4b2d
--- /dev/null
+++ b/pylint/checkers/refactoring/not_checker.py
@@ -0,0 +1,89 @@
+# -*- coding: utf-8 -*-
+
+# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
+
+import builtins
+
+import astroid
+
+from pylint import checkers, interfaces
+from pylint.checkers import utils
+
+
+class NotChecker(checkers.BaseChecker):
+ """checks for too many not in comparison expressions
+
+ - "not not" should trigger a warning
+ - "not" followed by a comparison should trigger a warning
+ """
+
+ __implements__ = (interfaces.IAstroidChecker,)
+ msgs = {
+ "C0113": (
+ 'Consider changing "%s" to "%s"',
+ "unneeded-not",
+ "Used when a boolean expression contains an unneeded negation.",
+ )
+ }
+ name = "refactoring"
+ reverse_op = {
+ "<": ">=",
+ "<=": ">",
+ ">": "<=",
+ ">=": "<",
+ "==": "!=",
+ "!=": "==",
+ "in": "not in",
+ "is": "is not",
+ }
+ # sets are not ordered, so for example "not set(LEFT_VALS) <= set(RIGHT_VALS)" is
+ # not equivalent to "set(LEFT_VALS) > set(RIGHT_VALS)"
+ skipped_nodes = (astroid.Set,)
+ # 'builtins' py3, '__builtin__' py2
+ skipped_classnames = [
+ "%s.%s" % (builtins.__name__, qname) for qname in ("set", "frozenset")
+ ]
+
+ @utils.check_messages("unneeded-not")
+ def visit_unaryop(self, node):
+ if node.op != "not":
+ return
+ operand = node.operand
+
+ if isinstance(operand, astroid.UnaryOp) and operand.op == "not":
+ self.add_message(
+ "unneeded-not",
+ node=node,
+ args=(node.as_string(), operand.operand.as_string()),
+ )
+ elif isinstance(operand, astroid.Compare):
+ left = operand.left
+ # ignore multiple comparisons
+ if len(operand.ops) > 1:
+ return
+ operator, right = operand.ops[0]
+ if operator not in self.reverse_op:
+ return
+ # Ignore __ne__ as function of __eq__
+ frame = node.frame()
+ if frame.name == "__ne__" and operator == "==":
+ return
+ for _type in (utils.node_type(left), utils.node_type(right)):
+ if not _type:
+ return
+ if isinstance(_type, self.skipped_nodes):
+ return
+ if (
+ isinstance(_type, astroid.Instance)
+ and _type.qname() in self.skipped_classnames
+ ):
+ return
+ suggestion = "%s %s %s" % (
+ left.as_string(),
+ self.reverse_op[operator],
+ right.as_string(),
+ )
+ self.add_message(
+ "unneeded-not", node=node, args=(node.as_string(), suggestion)
+ )