def leave_Comparison(self, original_node: cst.Comparison, updated_node: cst.Comparison) -> cst.BaseExpression: remaining_targets: List[cst.ComparisonTarget] = [] for target in original_node.comparisons: if m.matches( target, m.ComparisonTarget(comparator=m.Name("False"), operator=m.Equal()), ): return cst.UnaryOperation(operator=cst.Not(), expression=original_node.left) if not m.matches( target, m.ComparisonTarget(comparator=m.Name("True"), operator=m.Equal()), ): remaining_targets.append(target) # FIXME: Explicitly check for `a == False == True ...` case and # short-circuit it to `not a`. if not remaining_targets: return original_node.left return updated_node.with_changes(comparisons=remaining_targets)
def replace_unnecessary_reversed_around_sorted(self, _, updated_node): """Fix flake8-comprehensions C413. Unnecessary reversed call around sorted(). """ call = updated_node.args[0].value args = list(call.args) for i, arg in enumerate(args): if m.matches(arg.keyword, m.Name("reverse")): try: val = bool( literal_eval(self.module.code_for_node(arg.value))) except Exception: args[i] = arg.with_changes( value=cst.UnaryOperation(cst.Not(), arg.value)) else: if not val: args[i] = arg.with_changes(value=cst.Name("True")) else: del args[i] args[i - 1] = remove_trailing_comma(args[i - 1]) break else: args.append( cst.Arg(keyword=cst.Name("reverse"), value=cst.Name("True"))) return call.with_changes(args=args)
def _get_assert_replacement(self, node: cst.Assert): message = node.msg or str(cst.Module(body=[node]).code) return cst.If( test=cst.UnaryOperation( operator=cst.Not(), expression=node.test, # Todo: parenthesize? ), body=cst.IndentedBlock(body=[ cst.SimpleStatementLine(body=[ cst.Raise(exc=cst.Call( func=cst.Name(value="AssertionError", ), args=[ cst.Arg(value=cst.SimpleString(value=repr(message), ), ), ], ), ), ]), ], ), )
class UnaryOperationTest(CSTNodeTest): @data_provider( ( # Simple unary operations (cst.UnaryOperation(cst.Plus(), cst.Name("foo")), "+foo"), (cst.UnaryOperation(cst.Minus(), cst.Name("foo")), "-foo"), (cst.UnaryOperation(cst.BitInvert(), cst.Name("foo")), "~foo"), (cst.UnaryOperation(cst.Not(), cst.Name("foo")), "not foo"), # Parenthesized unary operation ( cst.UnaryOperation( lpar=(cst.LeftParen(),), operator=cst.Not(), expression=cst.Name("foo"), rpar=(cst.RightParen(),), ), "(not foo)", CodeRange((1, 1), (1, 8)), ), ( cst.UnaryOperation( operator=cst.Not(whitespace_after=cst.SimpleWhitespace("")), expression=cst.Name( "foo", lpar=(cst.LeftParen(),), rpar=(cst.RightParen(),) ), ), "not(foo)", CodeRange((1, 0), (1, 8)), ), # Make sure that spacing works ( cst.UnaryOperation( lpar=(cst.LeftParen(whitespace_after=cst.SimpleWhitespace(" ")),), operator=cst.Not(whitespace_after=cst.SimpleWhitespace(" ")), expression=cst.Name("foo"), rpar=(cst.RightParen(whitespace_before=cst.SimpleWhitespace(" ")),), ), "( not foo )", CodeRange((1, 2), (1, 10)), ), ) ) def test_valid( self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None ) -> None: self.validate_node(node, code, parse_expression, expected_position=position) @data_provider( ( ( lambda: cst.UnaryOperation( cst.Plus(), cst.Name("foo"), lpar=(cst.LeftParen(),) ), "left paren without right paren", ), ( lambda: cst.UnaryOperation( cst.Plus(), cst.Name("foo"), rpar=(cst.RightParen(),) ), "right paren without left paren", ), ( lambda: cst.UnaryOperation( operator=cst.Not(whitespace_after=cst.SimpleWhitespace("")), expression=cst.Name("foo"), ), "at least one space after not operator", ), ) ) def test_invalid( self, get_node: Callable[[], cst.CSTNode], expected_re: str ) -> None: self.assert_invalid(get_node, expected_re)
def visit_IfExp_orelse(self, node: cst.IfExp) -> None: self.cond_stack.append(cst.UnaryOperation(cst.Not(), node.test))