class LeafSmallStatementsTest(CSTNodeTest): @data_provider(((cst.Pass(), "pass"), (cst.Break(), "break"), (cst.Continue(), "continue"))) def test_valid(self, node: cst.CSTNode, code: str) -> None: self.validate_node(node, code)
class SimpleStatementTest(CSTNodeTest): @data_provider(( # a single-element SimpleStatementLine # pyre-fixme[6]: Incompatible parameter type { "node": cst.SimpleStatementLine((cst.Pass(), )), "code": "pass\n", "parser": parse_statement, }, # a multi-element SimpleStatementLine { "node": cst.SimpleStatementLine( (cst.Pass(semicolon=cst.Semicolon()), cst.Continue())), "code": "pass;continue\n", "parser": parse_statement, }, # a multi-element SimpleStatementLine with whitespace { "node": cst.SimpleStatementLine(( cst.Pass(semicolon=cst.Semicolon( whitespace_before=cst.SimpleWhitespace(" "), whitespace_after=cst.SimpleWhitespace(" "), )), cst.Continue(), )), "code": "pass ; continue\n", "parser": parse_statement, }, # A more complicated SimpleStatementLine { "node": cst.SimpleStatementLine(( cst.Pass(semicolon=cst.Semicolon()), cst.Continue(semicolon=cst.Semicolon()), cst.Break(), )), "code": "pass;continue;break\n", "parser": parse_statement, "expected_position": CodeRange.create((1, 0), (1, 19)), }, # a multi-element SimpleStatementLine, inferred semicolons { "node": cst.SimpleStatementLine((cst.Pass(), cst.Continue(), cst.Break())), "code": "pass; continue; break\n", "parser": None, # No test for parsing, since we are using sentinels. }, # some expression statements { "node": cst.SimpleStatementLine((cst.Expr(cst.Name("None")), )), "code": "None\n", "parser": parse_statement, }, { "node": cst.SimpleStatementLine((cst.Expr(cst.Name("True")), )), "code": "True\n", "parser": parse_statement, }, { "node": cst.SimpleStatementLine((cst.Expr(cst.Name("False")), )), "code": "False\n", "parser": parse_statement, }, { "node": cst.SimpleStatementLine((cst.Expr(cst.Ellipsis()), )), "code": "...\n", "parser": parse_statement, }, # Test some numbers { "node": cst.SimpleStatementLine((cst.Expr(cst.Integer("5")), )), "code": "5\n", "parser": parse_statement, }, { "node": cst.SimpleStatementLine((cst.Expr(cst.Float("5.5")), )), "code": "5.5\n", "parser": parse_statement, }, { "node": cst.SimpleStatementLine((cst.Expr(cst.Imaginary("5j")), )), "code": "5j\n", "parser": parse_statement, }, # Test some numbers with parens { "node": cst.SimpleStatementLine((cst.Expr( cst.Integer("5", lpar=(cst.LeftParen(), ), rpar=(cst.RightParen(), ))), )), "code": "(5)\n", "parser": parse_statement, "expected_position": CodeRange.create((1, 0), (1, 3)), }, { "node": cst.SimpleStatementLine((cst.Expr( cst.Float("5.5", lpar=(cst.LeftParen(), ), rpar=(cst.RightParen(), ))), )), "code": "(5.5)\n", "parser": parse_statement, }, { "node": cst.SimpleStatementLine((cst.Expr( cst.Imaginary("5j", lpar=(cst.LeftParen(), ), rpar=(cst.RightParen(), ))), )), "code": "(5j)\n", "parser": parse_statement, }, # Test some strings { "node": cst.SimpleStatementLine((cst.Expr(cst.SimpleString('"abc"')), )), "code": '"abc"\n', "parser": parse_statement, }, { "node": cst.SimpleStatementLine((cst.Expr( cst.ConcatenatedString(cst.SimpleString('"abc"'), cst.SimpleString('"def"'))), )), "code": '"abc""def"\n', "parser": parse_statement, }, { "node": cst.SimpleStatementLine((cst.Expr( cst.ConcatenatedString( left=cst.SimpleString('"abc"'), whitespace_between=cst.SimpleWhitespace(" "), right=cst.ConcatenatedString( left=cst.SimpleString('"def"'), whitespace_between=cst.SimpleWhitespace(" "), right=cst.SimpleString('"ghi"'), ), )), )), "code": '"abc" "def" "ghi"\n', "parser": parse_statement, "expected_position": CodeRange.create((1, 0), (1, 17)), }, # Test parenthesis rules { "node": cst.SimpleStatementLine((cst.Expr( cst.Ellipsis(lpar=(cst.LeftParen(), ), rpar=(cst.RightParen(), ))), )), "code": "(...)\n", "parser": parse_statement, }, # Test parenthesis with whitespace ownership { "node": cst.SimpleStatementLine((cst.Expr( cst.Ellipsis( lpar=(cst.LeftParen( whitespace_after=cst.SimpleWhitespace(" ")), ), rpar=(cst.RightParen( whitespace_before=cst.SimpleWhitespace(" ")), ), )), )), "code": "( ... )\n", "parser": parse_statement, }, { "node": cst.SimpleStatementLine((cst.Expr( cst.Ellipsis( lpar=( cst.LeftParen( whitespace_after=cst.SimpleWhitespace(" ")), cst.LeftParen( whitespace_after=cst.SimpleWhitespace(" ")), cst.LeftParen( whitespace_after=cst.SimpleWhitespace(" ")), ), rpar=( cst.RightParen( whitespace_before=cst.SimpleWhitespace(" ")), cst.RightParen( whitespace_before=cst.SimpleWhitespace(" ")), cst.RightParen( whitespace_before=cst.SimpleWhitespace(" ")), ), )), )), "code": "( ( ( ... ) ) )\n", "parser": parse_statement, "expected_position": CodeRange.create((1, 0), (1, 21)), }, # Test parenthesis rules with expressions { "node": cst.SimpleStatementLine((cst.Expr( cst.Ellipsis( lpar=(cst.LeftParen( whitespace_after=cst.ParenthesizedWhitespace( first_line=cst.TrailingWhitespace(), empty_lines=(cst.EmptyLine( comment=cst.Comment("# Wow, a comment!")), ), indent=True, last_line=cst.SimpleWhitespace(" "), )), ), rpar=(cst.RightParen( whitespace_before=cst.ParenthesizedWhitespace( first_line=cst.TrailingWhitespace(), empty_lines=(), indent=True, last_line=cst.SimpleWhitespace(""), )), ), )), )), "code": "(\n# Wow, a comment!\n ...\n)\n", "parser": parse_statement, "expected_position": CodeRange.create((1, 0), (4, 1)), }, # test trailing whitespace { "node": cst.SimpleStatementLine( (cst.Pass(), ), trailing_whitespace=cst.TrailingWhitespace( whitespace=cst.SimpleWhitespace(" "), comment=cst.Comment("# trailing comment"), ), ), "code": "pass # trailing comment\n", "parser": parse_statement, "expected_position": CodeRange.create((1, 0), (1, 4)), }, # test leading comment { "node": cst.SimpleStatementLine( (cst.Pass(), ), leading_lines=(cst.EmptyLine( comment=cst.Comment("# comment")), ), ), "code": "# comment\npass\n", "parser": parse_statement, "expected_position": CodeRange.create((2, 0), (2, 4)), }, # test indentation { "node": DummyIndentedBlock( " ", cst.SimpleStatementLine( (cst.Pass(), ), leading_lines=(cst.EmptyLine( comment=cst.Comment("# comment")), ), ), ), "code": " # comment\n pass\n", "expected_position": CodeRange.create((2, 4), (2, 8)), }, # test suite variant { "node": cst.SimpleStatementSuite((cst.Pass(), )), "code": " pass\n", "expected_position": CodeRange.create((1, 1), (1, 5)), }, { "node": cst.SimpleStatementSuite( (cst.Pass(), ), leading_whitespace=cst.SimpleWhitespace("")), "code": "pass\n", "expected_position": CodeRange.create((1, 0), (1, 4)), }, )) def test_valid(self, **kwargs: Any) -> None: self.validate_node(**kwargs)
class SmallStatementTest(CSTNodeTest): @data_provider(( # pyre-fixme[6]: Incompatible parameter type { "node": cst.Pass(), "code": "pass" }, { "node": cst.Pass(semicolon=cst.Semicolon()), "code": "pass;" }, { "node": cst.Pass(semicolon=cst.Semicolon( whitespace_before=cst.SimpleWhitespace(" "), whitespace_after=cst.SimpleWhitespace(" "), )), "code": "pass ; ", "expected_position": CodeRange((1, 0), (1, 4)), }, { "node": cst.Continue(), "code": "continue" }, { "node": cst.Continue(semicolon=cst.Semicolon()), "code": "continue;" }, { "node": cst.Continue(semicolon=cst.Semicolon( whitespace_before=cst.SimpleWhitespace(" "), whitespace_after=cst.SimpleWhitespace(" "), )), "code": "continue ; ", "expected_position": CodeRange((1, 0), (1, 8)), }, { "node": cst.Break(), "code": "break" }, { "node": cst.Break(semicolon=cst.Semicolon()), "code": "break;" }, { "node": cst.Break(semicolon=cst.Semicolon( whitespace_before=cst.SimpleWhitespace(" "), whitespace_after=cst.SimpleWhitespace(" "), )), "code": "break ; ", "expected_position": CodeRange((1, 0), (1, 5)), }, { "node": cst.Expr( cst.BinaryOperation(cst.Name("x"), cst.Add(), cst.Name("y"))), "code": "x + y", }, { "node": cst.Expr( cst.BinaryOperation(cst.Name("x"), cst.Add(), cst.Name("y")), semicolon=cst.Semicolon(), ), "code": "x + y;", }, { "node": cst.Expr( cst.BinaryOperation(cst.Name("x"), cst.Add(), cst.Name("y")), semicolon=cst.Semicolon( whitespace_before=cst.SimpleWhitespace(" "), whitespace_after=cst.SimpleWhitespace(" "), ), ), "code": "x + y ; ", "expected_position": CodeRange((1, 0), (1, 5)), }, )) def test_valid(self, **kwargs: Any) -> None: self.validate_node(**kwargs)
class IndentedBlockTest(CSTNodeTest): @data_provider(( # Standard render ( cst.IndentedBlock((cst.SimpleStatementLine((cst.Pass(), )), )), "\n pass\n", None, ), # Render with empty (cst.IndentedBlock(()), "\n pass\n", None), # Render with empty subnodes (cst.IndentedBlock((cst.SimpleStatementLine( ()), )), "\n pass\n", None), # Test render with custom indent ( cst.IndentedBlock((cst.SimpleStatementLine((cst.Pass(), )), ), indent="\t"), "\n\tpass\n", None, ), # Test comments ( cst.IndentedBlock( (cst.SimpleStatementLine((cst.Pass(), )), ), header=cst.TrailingWhitespace( whitespace=cst.SimpleWhitespace(" "), comment=cst.Comment("# header comment"), ), ), " # header comment\n pass\n", None, ), ( cst.IndentedBlock( (cst.SimpleStatementLine((cst.Pass(), )), ), footer=(cst.EmptyLine( comment=cst.Comment("# footer comment")), ), ), "\n pass\n # footer comment\n", None, ), ( cst.IndentedBlock( (cst.SimpleStatementLine((cst.Pass(), )), ), footer=(cst.EmptyLine( whitespace=cst.SimpleWhitespace(" "), comment=cst.Comment("# footer comment"), ), ), ), "\n pass\n # footer comment\n", None, ), ( cst.IndentedBlock(( cst.SimpleStatementLine((cst.Continue(), )), cst.SimpleStatementLine((cst.Pass(), )), )), "\n continue\n pass\n", None, ), # Basic parsing test ( cst.If( cst.Name("conditional"), cst.IndentedBlock((cst.SimpleStatementLine((cst.Pass(), )), )), ), "if conditional:\n pass\n", parse_statement, ), # Multi-level parsing test ( cst.If( cst.Name("conditional"), cst.IndentedBlock(( cst.SimpleStatementLine((cst.Pass(), )), cst.If( cst.Name("other_conditional"), cst.IndentedBlock((cst.SimpleStatementLine( (cst.Pass(), )), )), ), )), ), "if conditional:\n pass\n if other_conditional:\n pass\n", parse_statement, ), # Inconsistent indentation parsing test ( cst.If( cst.Name("conditional"), cst.IndentedBlock(( cst.SimpleStatementLine((cst.Pass(), )), cst.If( cst.Name("other_conditional"), cst.IndentedBlock( (cst.SimpleStatementLine((cst.Pass(), )), ), indent=" ", ), ), )), ), "if conditional:\n pass\n if other_conditional:\n pass\n", parse_statement, ), )) def test_valid( self, node: cst.CSTNode, code: str, parser: Optional[Callable[[str], cst.CSTNode]], ) -> None: self.validate_node(node, code, parser) @data_provider(( ( lambda: cst.IndentedBlock( (cst.SimpleStatementLine((cst.Pass(), )), ), indent=""), "non-zero width indent", ), ( lambda: cst.IndentedBlock( (cst.SimpleStatementLine((cst.Pass(), )), ), indent="this isn't valid whitespace!", ), "only whitespace", ), )) def test_invalid(self, get_node: Callable[[], cst.CSTNode], expected_re: str) -> None: self.assert_invalid(get_node, expected_re)