diff options
author | Pierre Sassoulas <pierre.sassoulas@gmail.com> | 2020-09-05 08:34:04 +0200 |
---|---|---|
committer | Pierre Sassoulas <pierre.sassoulas@gmail.com> | 2020-09-05 09:35:14 +0200 |
commit | cebd64081cc74c23e4b80678c335bccbf18a145f (patch) | |
tree | 09a8b16b52ea53026064d433b97f8f9067aef06e | |
parent | 3c257cd675e6e6e5ff621fc4e3576c399cd6b92b (diff) | |
download | pylint-git-cebd64081cc74c23e4b80678c335bccbf18a145f.tar.gz |
Move the NotChecker to its own file
-rw-r--r-- | pylint/checkers/refactoring/__init__.py | 81 | ||||
-rw-r--r-- | pylint/checkers/refactoring/not_checker.py | 89 |
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) + ) |