def visit_compare(self, node: nodes.Compare) -> None: _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 = [("", node.left)] ops.extend(node.ops) iter_ops: Iterable[Any] = iter(ops) ops = list(itertools.chain(*iter_ops)) for ops_idx in range(len(ops) - 2): op_1 = ops[ops_idx] op_2 = ops[ops_idx + 1] op_3 = ops[ops_idx + 2] error_detected = False # x ?? "" if utils.is_empty_str_literal(op_1) and op_2 in _operators: error_detected = True # '' ?? X elif op_2 in _operators and utils.is_empty_str_literal(op_3): error_detected = True if error_detected: self.add_message("compare-to-empty-string", node=node)
def test_is_empty_literal() -> None: list_node = astroid.extract_node("a = []") assert utils.is_base_container(list_node.value) not_empty_list_node = astroid.extract_node("a = [1,2,3]") assert not utils.is_base_container(not_empty_list_node.value) tuple_node = astroid.extract_node("a = ()") assert utils.is_base_container(tuple_node.value) not_empty_tuple_node = astroid.extract_node("a = (1,2)") assert not utils.is_base_container(not_empty_tuple_node.value) dict_node = astroid.extract_node("a = {}") assert utils.is_empty_dict_literal(dict_node.value) not_empty_dict_node = astroid.extract_node("a = {1:1}") assert not utils.is_empty_dict_literal(not_empty_dict_node.value) string_node = astroid.extract_node("a = ''") assert utils.is_empty_str_literal(string_node.value) not_empty_string_node = astroid.extract_node("a = 'hello'") assert not utils.is_empty_str_literal(not_empty_string_node.value)