| Viewing file:  comparetozero.py (3.09 KB)      -rw-r--r-- Select action/file-type:
 
  (+) |  (+) |  (+) | Code (+) | Session (+) |  (+) | SDB (+) |  (+) |  (+) |  (+) |  (+) |  (+) | 
 
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html# For details: https://github.com/PyCQA/pylint/blob/main/LICENSE
 # Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt
 
 """Looks for comparisons to zero."""
 
 from __future__ import annotations
 
 import itertools
 from typing import TYPE_CHECKING
 
 import astroid
 from astroid import nodes
 
 from pylint import checkers
 from pylint.checkers import utils
 from pylint.interfaces import HIGH
 
 if TYPE_CHECKING:
 from pylint.lint import PyLinter
 
 
 def _is_constant_zero(node: str | nodes.NodeNG) -> bool:
 # We have to check that node.value is not False because node.value == 0 is True
 # when node.value is False
 return (
 isinstance(node, astroid.Const) and node.value == 0 and node.value is not False
 )
 
 
 class CompareToZeroChecker(checkers.BaseChecker):
 """Checks for comparisons to zero.
 
 Most of the time you should use the fact that integers with a value of 0 are false.
 An exception to this rule is when 0 is allowed in the program and has a
 different meaning than None!
 """
 
 # configuration section name
 name = "compare-to-zero"
 msgs = {
 "C2001": (
 '"%s" can be simplified to "%s" as 0 is falsey',
 "compare-to-zero",
 "Used when Pylint detects comparison to a 0 constant.",
 )
 }
 
 options = ()
 
 @utils.only_required_for_messages("compare-to-zero")
 def visit_compare(self, node: nodes.Compare) -> None:
 # pylint: disable=duplicate-code
 _operators = ["!=", "==", "is not", "is"]
 # note: astroid.Compare has the left most operand in node.left
 # while the rest are a list of tuples in node.ops
 # the format of the tuple is ('compare operator sign', node)
 # here we squash everything into `ops` to make it easier for processing later
 ops: list[tuple[str, nodes.NodeNG]] = [("", node.left)]
 ops.extend(node.ops)
 iter_ops = iter(ops)
 all_ops = list(itertools.chain(*iter_ops))
 
 for ops_idx in range(len(all_ops) - 2):
 op_1 = all_ops[ops_idx]
 op_2 = all_ops[ops_idx + 1]
 op_3 = all_ops[ops_idx + 2]
 error_detected = False
 
 # 0 ?? X
 if _is_constant_zero(op_1) and op_2 in _operators:
 error_detected = True
 op = op_3
 # X ?? 0
 elif op_2 in _operators and _is_constant_zero(op_3):
 error_detected = True
 op = op_1
 
 if error_detected:
 original = f"{op_1.as_string()} {op_2} {op_3.as_string()}"
 suggestion = (
 op.as_string()
 if op_2 in {"!=", "is not"}
 else f"not {op.as_string()}"
 )
 self.add_message(
 "compare-to-zero",
 args=(original, suggestion),
 node=node,
 confidence=HIGH,
 )
 
 
 def register(linter: PyLinter) -> None:
 linter.register_checker(CompareToZeroChecker(linter))
 
 |