def test_valid( self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None ) -> None: self.validate_node( node, code, lambda code: ensure_type( ensure_type(parse_statement(code), cst.SimpleStatementLine).body[0], cst.Expr, ).value, )
def test_concatenated_string_evaluated_value(self) -> None: code = '"This " "is " "a " "concatenated " "string."' node = ensure_type(cst.parse_expression(code), cst.ConcatenatedString) self.assertEqual(node.evaluated_value, "This is a concatenated string.") code = 'b"A concatenated" b" byte."' node = ensure_type(cst.parse_expression(code), cst.ConcatenatedString) self.assertEqual(node.evaluated_value, b"A concatenated byte.") code = '"var=" f" {var}"' node = ensure_type(cst.parse_expression(code), cst.ConcatenatedString) self.assertEqual(node.evaluated_value, None) code = '"var" "=" f" {var}"' node = ensure_type(cst.parse_expression(code), cst.ConcatenatedString) self.assertEqual(node.evaluated_value, None)
def test_get_absolute_module( self, module: Optional[str], importfrom: str, output: Optional[str], ) -> None: node = ensure_type(cst.parse_statement(importfrom), cst.SimpleStatementLine) assert len(node.body) == 1, "Unexpected number of statements!" import_node = ensure_type(node.body[0], cst.ImportFrom) self.assertEqual(get_absolute_module_for_import(module, import_node), output) if output is None: with self.assertRaises(Exception): get_absolute_module_for_import_or_raise(module, import_node) else: self.assertEqual( get_absolute_module_for_import_or_raise(module, import_node), output )
def test_valid(self, **kwargs: Any) -> None: self.validate_node( parser=lambda code: ensure_type( parse_statement(code), cst.SimpleStatementLine ).body[0], **kwargs, )
def test_function_docstring(self, code: str, docstring: Optional[str]) -> None: self.assertEqual( ensure_type(cst.parse_statement(dedent(code)), cst.FunctionDef).get_docstring(), docstring, )
def visit_Element(self, node: libcst.Element) -> bool: # See if this is a entry that is a string. extraction = self.extract( node, m.Element(m.SaveMatchedNode(m.SimpleString(), "string"))) if extraction: string = ensure_type(extraction["string"], libcst.SimpleString) self.explicit_exported_objects.add(string.evaluated_value) # Don't need to visit children return False
class ExpressionTest(UnitTest): @data_provider(( ("a string", "a string"), (cst.Name("a_name"), "a_name"), (cst.parse_expression("a.b.c"), "a.b.c"), (cst.parse_expression("a.b()"), "a.b"), (cst.parse_expression("a.b.c[i]"), "a.b.c"), (cst.parse_statement("def fun(): pass"), "fun"), (cst.parse_statement("class cls: pass"), "cls"), ( cst.Decorator( ensure_type(cst.parse_expression("a.b.c.d"), cst.Attribute)), "a.b.c.d", ), (cst.parse_statement("(a.b()).c()"), None), # not a supported Node type )) def test_get_full_name_for_expression( self, input: Union[str, cst.CSTNode], output: Optional[str], ) -> None: self.assertEqual(get_full_name_for_node(input), output) if output is None: with self.assertRaises(Exception): get_full_name_for_node_or_raise(input) else: self.assertEqual(get_full_name_for_node_or_raise(input), output) def test_simplestring_evaluated_value(self) -> None: raw_string = '"a string."' node = ensure_type(cst.parse_expression(raw_string), cst.SimpleString) self.assertEqual(node.value, raw_string) self.assertEqual(node.evaluated_value, literal_eval(raw_string)) def test_integer_evaluated_value(self) -> None: raw_value = "5" node = ensure_type(cst.parse_expression(raw_value), cst.Integer) self.assertEqual(node.value, raw_value) self.assertEqual(node.evaluated_value, literal_eval(raw_value)) def test_float_evaluated_value(self) -> None: raw_value = "5.5" node = ensure_type(cst.parse_expression(raw_value), cst.Float) self.assertEqual(node.value, raw_value) self.assertEqual(node.evaluated_value, literal_eval(raw_value)) def test_complex_evaluated_value(self) -> None: raw_value = "5j" node = ensure_type(cst.parse_expression(raw_value), cst.Imaginary) self.assertEqual(node.value, raw_value) self.assertEqual(node.evaluated_value, literal_eval(raw_value))
def test_complex_evaluated_value(self) -> None: raw_value = "5j" node = ensure_type(cst.parse_expression(raw_value), cst.Imaginary) self.assertEqual(node.value, raw_value) self.assertEqual(node.evaluated_value, literal_eval(raw_value))
def test_float_evaluated_value(self) -> None: raw_value = "5.5" node = ensure_type(cst.parse_expression(raw_value), cst.Float) self.assertEqual(node.value, raw_value) self.assertEqual(node.evaluated_value, literal_eval(raw_value))
def test_integer_evaluated_value(self) -> None: raw_value = "5" node = ensure_type(cst.parse_expression(raw_value), cst.Integer) self.assertEqual(node.value, raw_value) self.assertEqual(node.evaluated_value, literal_eval(raw_value))
def test_simplestring_evaluated_value(self) -> None: raw_string = '"a string."' node = ensure_type(cst.parse_expression(raw_string), cst.SimpleString) self.assertEqual(node.value, raw_string) self.assertEqual(node.evaluated_value, literal_eval(raw_string))
def _assert_parser(code: str) -> cst.Assert: return ensure_type( ensure_type(parse_statement(code), cst.SimpleStatementLine).body[0], cst.Assert)
def visit_Call(self, node: cst.Call) -> None: # `self.assertTrue(x is not None)` -> `self.assertIsNotNone(x)` if m.matches( node, m.Call( func=m.Attribute(value=m.Name("self"), attr=m.Name("assertTrue")), args=[ m.Arg( m.Comparison(comparisons=[ m.ComparisonTarget(m.IsNot(), comparator=m.Name("None")) ])) ], ), ): new_call = node.with_changes( func=cst.Attribute(value=cst.Name("self"), attr=cst.Name("assertIsNotNone")), args=[ cst.Arg( ensure_type(node.args[0].value, cst.Comparison).left) ], ) self.report(node, replacement=new_call) # `self.assertTrue(not x is None)` -> `self.assertIsNotNone(x)` elif m.matches( node, m.Call( func=m.Attribute(value=m.Name("self"), attr=m.Name("assertTrue")), args=[ m.Arg(value=m.UnaryOperation( operator=m.Not(), expression=m.Comparison(comparisons=[ m.ComparisonTarget(m.Is(), comparator=m.Name("None")) ]), )) ], ), ): new_call = node.with_changes( func=cst.Attribute(value=cst.Name("self"), attr=cst.Name("assertIsNotNone")), args=[ cst.Arg( ensure_type( ensure_type(node.args[0].value, cst.UnaryOperation).expression, cst.Comparison, ).left) ], ) self.report(node, replacement=new_call) # `self.assertFalse(x is None)` -> `self.assertIsNotNone(x)` elif m.matches( node, m.Call( func=m.Attribute(value=m.Name("self"), attr=m.Name("assertFalse")), args=[ m.Arg( m.Comparison(comparisons=[ m.ComparisonTarget(m.Is(), comparator=m.Name("None")) ])) ], ), ): new_call = node.with_changes( func=cst.Attribute(value=cst.Name("self"), attr=cst.Name("assertIsNotNone")), args=[ cst.Arg( ensure_type(node.args[0].value, cst.Comparison).left) ], ) self.report(node, replacement=new_call) # `self.assertTrue(x is None)` -> `self.assertIsNotNone(x)) elif m.matches( node, m.Call( func=m.Attribute(value=m.Name("self"), attr=m.Name("assertTrue")), args=[ m.Arg( m.Comparison(comparisons=[ m.ComparisonTarget(m.Is(), comparator=m.Name("None")) ])) ], ), ): new_call = node.with_changes( func=cst.Attribute(value=cst.Name("self"), attr=cst.Name("assertIsNone")), args=[ cst.Arg( ensure_type(node.args[0].value, cst.Comparison).left) ], ) self.report(node, replacement=new_call) # `self.assertFalse(x is not None)` -> `self.assertIsNone(x)` elif m.matches( node, m.Call( func=m.Attribute(value=m.Name("self"), attr=m.Name("assertFalse")), args=[ m.Arg( m.Comparison(comparisons=[ m.ComparisonTarget(m.IsNot(), comparator=m.Name("None")) ])) ], ), ): new_call = node.with_changes( func=cst.Attribute(value=cst.Name("self"), attr=cst.Name("assertIsNone")), args=[ cst.Arg( ensure_type(node.args[0].value, cst.Comparison).left) ], ) self.report(node, replacement=new_call) # `self.assertFalse(not x is None)` -> `self.assertIsNone(x)` elif m.matches( node, m.Call( func=m.Attribute(value=m.Name("self"), attr=m.Name("assertFalse")), args=[ m.Arg(value=m.UnaryOperation( operator=m.Not(), expression=m.Comparison(comparisons=[ m.ComparisonTarget(m.Is(), comparator=m.Name("None")) ]), )) ], ), ): new_call = node.with_changes( func=cst.Attribute(value=cst.Name("self"), attr=cst.Name("assertIsNone")), args=[ cst.Arg( ensure_type( ensure_type(node.args[0].value, cst.UnaryOperation).expression, cst.Comparison, ).left) ], ) self.report(node, replacement=new_call)
expr = body while isinstance(expr, (cst.BaseSuite, cst.SimpleStatementLine)): if len(expr.body) == 0: # fixme: what to do if there is no body assert 1, "body does not start with block or docstring" expr = expr.body[0] if not isinstance(expr, cst.Expr): # fixme: what to do if there is no initial docstr Expression in the body assert 1, "there is no Expression in the body" print(source_tree.code_for_node(expr)) # new_docstr = parse_template_expression("'new docs string'", config=config) new_docstr = expr.with_changes( value=parse_template_expression("new \ndoc\nstring", config=config)) print(source_tree.code_for_node(new_docstr)) newtree = ensure_type(source_tree.deep_replace(expr, new_docstr), Module) print(newtree.code) print("Done") # source_tree.code_for_node( body ) # body.deep_replace() # source_tree.code_for_node( body ) # classdef.ch
def visit_Call(self, node: cst.Call) -> None: # Todo: Make use of single extract instead of having several # if else statemenets to make the code more robust and readable. if m.matches( node, m.Call( func=m.Attribute(value=m.Name("self"), attr=m.Name("assertTrue")), args=[ m.Arg( m.Comparison(comparisons=[ m.ComparisonTarget(operator=m.In()) ])) ], ), ): # self.assertTrue(a in b) -> self.assertIn(a, b) new_call = node.with_changes( func=cst.Attribute(value=cst.Name("self"), attr=cst.Name("assertIn")), args=[ cst.Arg( ensure_type(node.args[0].value, cst.Comparison).left), cst.Arg( ensure_type(node.args[0].value, cst.Comparison).comparisons[0].comparator), ], ) self.report(node, replacement=new_call) else: # ... -> self.assertNotIn(a, b) matched, arg1, arg2 = False, None, None if m.matches( node, m.Call( func=m.Attribute(value=m.Name("self"), attr=m.Name("assertTrue")), args=[ m.Arg( m.UnaryOperation( operator=m.Not(), expression=m.Comparison(comparisons=[ m.ComparisonTarget(operator=m.In()) ]), )) ], ), ): # self.assertTrue(not a in b) -> self.assertNotIn(a, b) matched = True arg1 = cst.Arg( ensure_type( ensure_type(node.args[0].value, cst.UnaryOperation).expression, cst.Comparison, ).left) arg2 = cst.Arg( ensure_type( ensure_type(node.args[0].value, cst.UnaryOperation).expression, cst.Comparison, ).comparisons[0].comparator) elif m.matches( node, m.Call( func=m.Attribute(value=m.Name("self"), attr=m.Name("assertTrue")), args=[ m.Arg( m.Comparison(comparisons=[ m.ComparisonTarget(m.NotIn()) ])) ], ), ): # self.assertTrue(a not in b) -> self.assertNotIn(a, b) matched = True arg1 = cst.Arg( ensure_type(node.args[0].value, cst.Comparison).left) arg2 = cst.Arg( ensure_type(node.args[0].value, cst.Comparison).comparisons[0].comparator) elif m.matches( node, m.Call( func=m.Attribute(value=m.Name("self"), attr=m.Name("assertFalse")), args=[ m.Arg( m.Comparison( comparisons=[m.ComparisonTarget(m.In())])) ], ), ): # self.assertFalse(a in b) -> self.assertNotIn(a, b) matched = True arg1 = cst.Arg( ensure_type(node.args[0].value, cst.Comparison).left) arg2 = cst.Arg( ensure_type(node.args[0].value, cst.Comparison).comparisons[0].comparator) if matched: new_call = node.with_changes( func=cst.Attribute(value=cst.Name("self"), attr=cst.Name("assertNotIn")), args=[arg1, arg2], ) self.report(node, replacement=new_call)
def visit_Call(self, node: cst.Call) -> None: match_compare_is_none = m.ComparisonTarget( m.SaveMatchedNode( m.OneOf(m.Is(), m.IsNot()), "comparison_type", ), comparator=m.Name("None"), ) result = m.extract( node, m.Call( func=m.Attribute( value=m.Name("self"), attr=m.SaveMatchedNode( m.OneOf(m.Name("assertTrue"), m.Name("assertFalse")), "assertion_name", ), ), args=[ m.Arg( m.SaveMatchedNode( m.OneOf( m.Comparison( comparisons=[match_compare_is_none]), m.UnaryOperation( operator=m.Not(), expression=m.Comparison( comparisons=[match_compare_is_none]), ), ), "argument", )) ], ), ) if result: assertion_name = result["assertion_name"] if isinstance(assertion_name, Sequence): assertion_name = assertion_name[0] argument = result["argument"] if isinstance(argument, Sequence): argument = argument[0] comparison_type = result["comparison_type"] if isinstance(comparison_type, Sequence): comparison_type = comparison_type[0] if m.matches(argument, m.Comparison()): assertion_argument = ensure_type(argument, cst.Comparison).left else: assertion_argument = ensure_type( ensure_type(argument, cst.UnaryOperation).expression, cst.Comparison).left negations_seen = 0 if m.matches(assertion_name, m.Name("assertFalse")): negations_seen += 1 if m.matches(argument, m.UnaryOperation()): negations_seen += 1 if m.matches(comparison_type, m.IsNot()): negations_seen += 1 new_attr = "assertIsNone" if negations_seen % 2 == 0 else "assertIsNotNone" new_call = node.with_changes( func=cst.Attribute(value=cst.Name("self"), attr=cst.Name(new_attr)), args=[cst.Arg(assertion_argument)], ) if new_call is not node: self.report(node, replacement=new_call)