def test_suite(self) -> None:
        # Test that we can insert various types of statement suites into a
        # spot accepting a suite.
        module = parse_template_module(
            "if x is True: {suite}\n",
            suite=cst.SimpleStatementSuite(body=(cst.Pass(),),),
        )
        self.assertEqual(
            module.code, "if x is True: pass\n",
        )

        module = parse_template_module(
            "if x is True: {suite}\n",
            suite=cst.IndentedBlock(body=(cst.SimpleStatementLine((cst.Pass(),),),),),
        )
        self.assertEqual(
            module.code, "if x is True:\n    pass\n",
        )

        module = parse_template_module(
            "if x is True:\n    {suite}\n",
            suite=cst.SimpleStatementSuite(body=(cst.Pass(),),),
        )
        self.assertEqual(
            module.code, "if x is True: pass\n",
        )

        module = parse_template_module(
            "if x is True:\n    {suite}\n",
            suite=cst.IndentedBlock(body=(cst.SimpleStatementLine((cst.Pass(),),),),),
        )
        self.assertEqual(
            module.code, "if x is True:\n    pass\n",
        )
    def test_deep_replace_complex(self) -> None:
        old_code = """
            def a():
                def b():
                    def c():
                        pass
        """
        new_code = """
            def a():
                def b():
                    def d(): break
        """

        module = cst.parse_module(dedent(old_code))
        outer_fun = cst.ensure_type(module.body[0], cst.FunctionDef)
        middle_fun = cst.ensure_type(
            cst.ensure_type(outer_fun.body, cst.IndentedBlock).body[0],
            cst.FunctionDef)
        inner_fun = cst.ensure_type(
            cst.ensure_type(middle_fun.body, cst.IndentedBlock).body[0],
            cst.FunctionDef)
        new_module = cst.ensure_type(
            module.deep_replace(
                inner_fun,
                cst.FunctionDef(
                    name=cst.Name("d"),
                    params=cst.Parameters(),
                    body=cst.SimpleStatementSuite(body=(cst.Break(), )),
                ),
            ),
            cst.Module,
        )
        self.assertEqual(new_module.code, dedent(new_code))
Beispiel #3
0
class ElseTest(CSTNodeTest):
    @data_provider(
        (
            {
                "node": cst.Else(cst.SimpleStatementSuite((cst.Pass(),))),
                "code": "else: pass\n",
                "expected_position": CodeRange.create((1, 0), (1, 10)),
            },
            {
                "node": cst.Else(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    whitespace_before_colon=cst.SimpleWhitespace("  "),
                ),
                "code": "else  : pass\n",
                "expected_position": CodeRange.create((1, 0), (1, 12)),
            },
        )
    )
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)
 def test_statement(self) -> None:
     # Test that we can insert various types of statements into a
     # statement list.
     module = parse_template_module(
         "{statement1}\n{statement2}\n{statement3}\n",
         statement1=cst.If(
             test=cst.Name("foo"), body=cst.SimpleStatementSuite((cst.Pass(),),),
         ),
         statement2=cst.SimpleStatementLine((cst.Expr(cst.Call(cst.Name("bar"))),),),
         statement3=cst.Pass(),
     )
     self.assertEqual(
         module.code, "if foo: pass\nbar()\npass\n",
     )
Beispiel #5
0
 def test_adding_parens(self) -> None:
     node = cst.With(
         (
             cst.WithItem(
                 cst.Call(cst.Name("foo")),
                 comma=cst.Comma(
                     whitespace_after=cst.ParenthesizedWhitespace(), ),
             ),
             cst.WithItem(cst.Call(cst.Name("bar")), comma=cst.Comma()),
         ),
         cst.SimpleStatementSuite((cst.Pass(), )),
         lpar=cst.LeftParen(whitespace_after=cst.SimpleWhitespace(" ")),
         rpar=cst.RightParen(whitespace_before=cst.SimpleWhitespace(" ")),
     )
     module = cst.Module([])
     self.assertEqual(
         module.code_for_node(node),
         ("with ( foo(),\n"
          "bar(), ): pass\n")  # noqa
     )
Beispiel #6
0
class NamedExprTest(CSTNodeTest):
    @data_provider((
        # Simple named expression
        {
            "node": cst.NamedExpr(cst.Name("x"), cst.Float("5.5")),
            "code": "x := 5.5",
            "parser":
            None,  # Walrus operator is illegal as top-level statement
            "expected_position": None,
        },
        # Parenthesized named expression
        {
            "node":
            cst.NamedExpr(
                lpar=(cst.LeftParen(), ),
                target=cst.Name("foo"),
                value=cst.Integer("5"),
                rpar=(cst.RightParen(), ),
            ),
            "code":
            "(foo := 5)",
            "parser":
            _parse_expression_force_38,
            "expected_position":
            CodeRange((1, 1), (1, 9)),
        },
        # Make sure that spacing works
        {
            "node":
            cst.NamedExpr(
                lpar=(cst.LeftParen(
                    whitespace_after=cst.SimpleWhitespace(" ")), ),
                target=cst.Name("foo"),
                whitespace_before_walrus=cst.SimpleWhitespace("  "),
                whitespace_after_walrus=cst.SimpleWhitespace("  "),
                value=cst.Name("bar"),
                rpar=(cst.RightParen(
                    whitespace_before=cst.SimpleWhitespace(" ")), ),
            ),
            "code":
            "( foo  :=  bar )",
            "parser":
            _parse_expression_force_38,
            "expected_position":
            CodeRange((1, 2), (1, 14)),
        },
        # Make sure we can use these where allowed in if/while statements
        {
            "node":
            cst.While(
                test=cst.NamedExpr(
                    target=cst.Name(value="x"),
                    value=cst.Call(func=cst.Name(value="some_input")),
                ),
                body=cst.SimpleStatementSuite(body=[cst.Pass()]),
            ),
            "code":
            "while x := some_input(): pass\n",
            "parser":
            _parse_statement_force_38,
            "expected_position":
            None,
        },
        {
            "node":
            cst.If(
                test=cst.NamedExpr(
                    target=cst.Name(value="x"),
                    value=cst.Call(func=cst.Name(value="some_input")),
                ),
                body=cst.SimpleStatementSuite(body=[cst.Pass()]),
            ),
            "code":
            "if x := some_input(): pass\n",
            "parser":
            _parse_statement_force_38,
            "expected_position":
            None,
        },
        {
            "node":
            cst.If(
                test=cst.NamedExpr(
                    target=cst.Name(value="x"),
                    value=cst.Integer(value="1"),
                    whitespace_before_walrus=cst.SimpleWhitespace(""),
                    whitespace_after_walrus=cst.SimpleWhitespace(""),
                ),
                body=cst.SimpleStatementSuite(body=[cst.Pass()]),
            ),
            "code":
            "if x:=1: pass\n",
            "parser":
            _parse_statement_force_38,
            "expected_position":
            None,
        },
        # Function args
        {
            "node":
            cst.Call(
                func=cst.Name(value="f"),
                args=[
                    cst.Arg(value=cst.NamedExpr(
                        target=cst.Name(value="y"),
                        value=cst.Integer(value="1"),
                        whitespace_before_walrus=cst.SimpleWhitespace(""),
                        whitespace_after_walrus=cst.SimpleWhitespace(""),
                    )),
                ],
            ),
            "code":
            "f(y:=1)",
            "parser":
            _parse_expression_force_38,
            "expected_position":
            None,
        },
        # Whitespace handling on args is fragile
        {
            "node":
            cst.Call(
                func=cst.Name(value="f"),
                args=[
                    cst.Arg(
                        value=cst.Name(value="x"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace("  ")),
                    ),
                    cst.Arg(
                        value=cst.NamedExpr(
                            target=cst.Name(value="y"),
                            value=cst.Integer(value="1"),
                            whitespace_before_walrus=cst.SimpleWhitespace(
                                "   "),
                            whitespace_after_walrus=cst.SimpleWhitespace(
                                "    "),
                        ),
                        whitespace_after_arg=cst.SimpleWhitespace("     "),
                    ),
                ],
            ),
            "code":
            "f(x,  y   :=    1     )",
            "parser":
            _parse_expression_force_38,
            "expected_position":
            None,
        },
        {
            "node":
            cst.Call(
                func=cst.Name(value="f"),
                args=[
                    cst.Arg(
                        value=cst.NamedExpr(
                            target=cst.Name(value="y"),
                            value=cst.Integer(value="1"),
                            whitespace_before_walrus=cst.SimpleWhitespace(
                                "   "),
                            whitespace_after_walrus=cst.SimpleWhitespace(
                                "    "),
                        ),
                        whitespace_after_arg=cst.SimpleWhitespace("     "),
                    ),
                ],
                whitespace_before_args=cst.SimpleWhitespace("  "),
            ),
            "code":
            "f(  y   :=    1     )",
            "parser":
            _parse_expression_force_38,
            "expected_position":
            None,
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider((
        {
            "get_node": (lambda: cst.NamedExpr(
                cst.Name("foo"), cst.Name("bar"), lpar=(cst.LeftParen(), ))),
            "expected_re":
            "left paren without right paren",
        },
        {
            "get_node": (lambda: cst.NamedExpr(
                cst.Name("foo"), cst.Name("bar"), rpar=(cst.RightParen(), ))),
            "expected_re":
            "right paren without left paren",
        },
    ))
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
Beispiel #7
0
class ClassDefParserTest(CSTNodeTest):
    @data_provider((
        # Simple classdef
        # pyre-fixme[6]: Incompatible parameter type
        {
            "node":
            cst.ClassDef(cst.Name("Foo"),
                         cst.SimpleStatementSuite((cst.Pass(), ))),
            "code":
            "class Foo: pass\n",
        },
        {
            "node":
            cst.ClassDef(
                cst.Name("Foo"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                lpar=cst.LeftParen(),
                rpar=cst.RightParen(),
            ),
            "code":
            "class Foo(): pass\n",
        },
        # Positional arguments render test
        {
            "node":
            cst.ClassDef(
                cst.Name("Foo"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                lpar=cst.LeftParen(),
                bases=(cst.Arg(cst.Name("obj")), ),
                rpar=cst.RightParen(),
            ),
            "code":
            "class Foo(obj): pass\n",
        },
        {
            "node":
            cst.ClassDef(
                cst.Name("Foo"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                lpar=cst.LeftParen(),
                bases=(
                    cst.Arg(
                        cst.Name("Bar"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        cst.Name("Baz"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(cst.Name("object")),
                ),
                rpar=cst.RightParen(),
            ),
            "code":
            "class Foo(Bar, Baz, object): pass\n",
        },
        # Keyword arguments render test
        {
            "node":
            cst.ClassDef(
                cst.Name("Foo"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                lpar=cst.LeftParen(),
                keywords=(cst.Arg(
                    keyword=cst.Name("metaclass"),
                    equal=cst.AssignEqual(),
                    value=cst.Name("Bar"),
                ), ),
                rpar=cst.RightParen(),
            ),
            "code":
            "class Foo(metaclass = Bar): pass\n",
        },
        # Iterator expansion render test
        {
            "node":
            cst.ClassDef(
                cst.Name("Foo"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                lpar=cst.LeftParen(),
                bases=(cst.Arg(star="*", value=cst.Name("one")), ),
                rpar=cst.RightParen(),
            ),
            "code":
            "class Foo(*one): pass\n",
        },
        {
            "node":
            cst.ClassDef(
                cst.Name("Foo"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                lpar=cst.LeftParen(),
                bases=(
                    cst.Arg(
                        star="*",
                        value=cst.Name("one"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        star="*",
                        value=cst.Name("two"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(star="*", value=cst.Name("three")),
                ),
                rpar=cst.RightParen(),
            ),
            "code":
            "class Foo(*one, *two, *three): pass\n",
        },
        # Dictionary expansion render test
        {
            "node":
            cst.ClassDef(
                cst.Name("Foo"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                lpar=cst.LeftParen(),
                keywords=(cst.Arg(star="**", value=cst.Name("one")), ),
                rpar=cst.RightParen(),
            ),
            "code":
            "class Foo(**one): pass\n",
        },
        {
            "node":
            cst.ClassDef(
                cst.Name("Foo"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                lpar=cst.LeftParen(),
                keywords=(
                    cst.Arg(
                        star="**",
                        value=cst.Name("one"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        star="**",
                        value=cst.Name("two"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(star="**", value=cst.Name("three")),
                ),
                rpar=cst.RightParen(),
            ),
            "code":
            "class Foo(**one, **two, **three): pass\n",
        },
        # Decorator render tests
        {
            "node":
            cst.ClassDef(
                cst.Name("Foo"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                decorators=(cst.Decorator(cst.Name("foo")), ),
                lpar=cst.LeftParen(),
                rpar=cst.RightParen(),
            ),
            "code":
            "@foo\nclass Foo(): pass\n",
            "expected_position":
            CodeRange((2, 0), (2, 17)),
        },
        {
            "node":
            cst.ClassDef(
                leading_lines=(
                    cst.EmptyLine(),
                    cst.EmptyLine(comment=cst.Comment("# leading comment 1")),
                ),
                decorators=(
                    cst.Decorator(cst.Name("foo"), leading_lines=()),
                    cst.Decorator(
                        cst.Name("bar"),
                        leading_lines=(cst.EmptyLine(
                            comment=cst.Comment("# leading comment 2")), ),
                    ),
                    cst.Decorator(
                        cst.Name("baz"),
                        leading_lines=(cst.EmptyLine(
                            comment=cst.Comment("# leading comment 3")), ),
                    ),
                ),
                lines_after_decorators=(cst.EmptyLine(
                    comment=cst.Comment("# class comment")), ),
                name=cst.Name("Foo"),
                body=cst.SimpleStatementSuite((cst.Pass(), )),
                lpar=cst.LeftParen(),
                rpar=cst.RightParen(),
            ),
            "code":
            "\n# leading comment 1\n@foo\n# leading comment 2\n@bar\n# leading comment 3\n@baz\n# class comment\nclass Foo(): pass\n",
            "expected_position":
            CodeRange((9, 0), (9, 17)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs, parser=parse_statement)
Beispiel #8
0
class ClassDefCreationTest(CSTNodeTest):
    @data_provider((
        # Simple classdef
        # pyre-fixme[6]: Incompatible parameter type
        {
            "node":
            cst.ClassDef(cst.Name("Foo"),
                         cst.SimpleStatementSuite((cst.Pass(), ))),
            "code":
            "class Foo: pass\n",
            "expected_position":
            CodeRange((1, 0), (1, 15)),
        },
        {
            "node":
            cst.ClassDef(
                cst.Name("Foo"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                lpar=cst.LeftParen(),
                rpar=cst.RightParen(),
            ),
            "code":
            "class Foo(): pass\n",
        },
        # Positional arguments render test
        {
            "node":
            cst.ClassDef(
                cst.Name("Foo"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                bases=(cst.Arg(cst.Name("obj")), ),
            ),
            "code":
            "class Foo(obj): pass\n",
        },
        {
            "node":
            cst.ClassDef(
                cst.Name("Foo"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                bases=(
                    cst.Arg(cst.Name("Bar")),
                    cst.Arg(cst.Name("Baz")),
                    cst.Arg(cst.Name("object")),
                ),
            ),
            "code":
            "class Foo(Bar, Baz, object): pass\n",
        },
        # Keyword arguments render test
        {
            "node":
            cst.ClassDef(
                cst.Name("Foo"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                keywords=(cst.Arg(keyword=cst.Name("metaclass"),
                                  value=cst.Name("Bar")), ),
            ),
            "code":
            "class Foo(metaclass = Bar): pass\n",
            "expected_position":
            CodeRange((1, 0), (1, 32)),
        },
        # Iterator expansion render test
        {
            "node":
            cst.ClassDef(
                cst.Name("Foo"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                bases=(cst.Arg(star="*", value=cst.Name("one")), ),
            ),
            "code":
            "class Foo(*one): pass\n",
        },
        {
            "node":
            cst.ClassDef(
                cst.Name("Foo"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                bases=(
                    cst.Arg(star="*", value=cst.Name("one")),
                    cst.Arg(star="*", value=cst.Name("two")),
                    cst.Arg(star="*", value=cst.Name("three")),
                ),
            ),
            "code":
            "class Foo(*one, *two, *three): pass\n",
        },
        # Dictionary expansion render test
        {
            "node":
            cst.ClassDef(
                cst.Name("Foo"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                keywords=(cst.Arg(star="**", value=cst.Name("one")), ),
            ),
            "code":
            "class Foo(**one): pass\n",
        },
        {
            "node":
            cst.ClassDef(
                cst.Name("Foo"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                keywords=(
                    cst.Arg(star="**", value=cst.Name("one")),
                    cst.Arg(star="**", value=cst.Name("two")),
                    cst.Arg(star="**", value=cst.Name("three")),
                ),
            ),
            "code":
            "class Foo(**one, **two, **three): pass\n",
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider((
        # Basic parenthesis tests.
        (
            lambda: cst.ClassDef(
                name=cst.Name("Foo"),
                body=cst.SimpleStatementSuite((cst.Pass(), )),
                lpar=cst.LeftParen(),
            ),
            "Do not mix concrete LeftParen/RightParen with MaybeSentinel",
        ),
        (
            lambda: cst.ClassDef(
                name=cst.Name("Foo"),
                body=cst.SimpleStatementSuite((cst.Pass(), )),
                rpar=cst.RightParen(),
            ),
            "Do not mix concrete LeftParen/RightParen with MaybeSentinel",
        ),
        # Whitespace validation
        (
            lambda: cst.ClassDef(
                name=cst.Name("Foo"),
                body=cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_after_class=cst.SimpleWhitespace(""),
            ),
            "at least one space between 'class' and name",
        ),
    ))
    def test_invalid(self, get_node: Callable[[], cst.CSTNode],
                     expected_re: str) -> None:
        self.assert_invalid(get_node, expected_re)
Beispiel #9
0
class ForTest(CSTNodeTest):
    @data_provider((
        # Simple for block
        {
            "node":
            cst.For(
                cst.Name("target"),
                cst.Call(cst.Name("iter")),
                cst.SimpleStatementSuite((cst.Pass(), )),
            ),
            "code":
            "for target in iter(): pass\n",
            "parser":
            parse_statement,
        },
        # Simple async for block
        {
            "node":
            cst.For(
                cst.Name("target"),
                cst.Call(cst.Name("iter")),
                cst.SimpleStatementSuite((cst.Pass(), )),
                asynchronous=cst.Asynchronous(),
            ),
            "code":
            "async for target in iter(): pass\n",
            "parser":
            lambda code: parse_statement(
                code, config=PartialParserConfig(python_version="3.7")),
        },
        # Python 3.6 async for block
        {
            "node":
            cst.FunctionDef(
                cst.Name("foo"),
                cst.Parameters(),
                cst.IndentedBlock((cst.For(
                    cst.Name("target"),
                    cst.Call(cst.Name("iter")),
                    cst.SimpleStatementSuite((cst.Pass(), )),
                    asynchronous=cst.Asynchronous(),
                ), )),
                asynchronous=cst.Asynchronous(),
            ),
            "code":
            "async def foo():\n    async for target in iter(): pass\n",
            "parser":
            lambda code: parse_statement(
                code, config=PartialParserConfig(python_version="3.6")),
        },
        # For block with else
        {
            "node":
            cst.For(
                cst.Name("target"),
                cst.Call(cst.Name("iter")),
                cst.SimpleStatementSuite((cst.Pass(), )),
                cst.Else(cst.SimpleStatementSuite((cst.Pass(), ))),
            ),
            "code":
            "for target in iter(): pass\nelse: pass\n",
            "parser":
            parse_statement,
        },
        # indentation
        {
            "node":
            DummyIndentedBlock(
                "    ",
                cst.For(
                    cst.Name("target"),
                    cst.Call(cst.Name("iter")),
                    cst.SimpleStatementSuite((cst.Pass(), )),
                ),
            ),
            "code":
            "    for target in iter(): pass\n",
            "parser":
            None,
        },
        # for an indented body
        {
            "node":
            DummyIndentedBlock(
                "    ",
                cst.For(
                    cst.Name("target"),
                    cst.Call(cst.Name("iter")),
                    cst.IndentedBlock((cst.SimpleStatementLine(
                        (cst.Pass(), )), )),
                ),
            ),
            "code":
            "    for target in iter():\n        pass\n",
            "parser":
            None,
            "expected_position":
            CodeRange((1, 4), (2, 12)),
        },
        # leading_lines
        {
            "node":
            cst.For(
                cst.Name("target"),
                cst.Call(cst.Name("iter")),
                cst.IndentedBlock((cst.SimpleStatementLine((cst.Pass(), )), )),
                cst.Else(
                    cst.IndentedBlock((cst.SimpleStatementLine(
                        (cst.Pass(), )), )),
                    leading_lines=(cst.EmptyLine(
                        comment=cst.Comment("# else comment")), ),
                ),
                leading_lines=(cst.EmptyLine(
                    comment=cst.Comment("# leading comment")), ),
            ),
            "code":
            "# leading comment\nfor target in iter():\n    pass\n# else comment\nelse:\n    pass\n",
            "parser":
            None,
            "expected_position":
            CodeRange((2, 0), (6, 8)),
        },
        # Weird spacing rules
        {
            "node":
            cst.For(
                cst.Name("target",
                         lpar=(cst.LeftParen(), ),
                         rpar=(cst.RightParen(), )),
                cst.Call(
                    cst.Name("iter"),
                    lpar=(cst.LeftParen(), ),
                    rpar=(cst.RightParen(), ),
                ),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_after_for=cst.SimpleWhitespace(""),
                whitespace_before_in=cst.SimpleWhitespace(""),
                whitespace_after_in=cst.SimpleWhitespace(""),
            ),
            "code":
            "for(target)in(iter()): pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (1, 27)),
        },
        # Whitespace
        {
            "node":
            cst.For(
                cst.Name("target"),
                cst.Call(cst.Name("iter")),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_after_for=cst.SimpleWhitespace("  "),
                whitespace_before_in=cst.SimpleWhitespace("  "),
                whitespace_after_in=cst.SimpleWhitespace("  "),
                whitespace_before_colon=cst.SimpleWhitespace("  "),
            ),
            "code":
            "for  target  in  iter()  : pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (1, 31)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider((
        {
            "get_node":
            lambda: cst.For(
                cst.Name("target"),
                cst.Call(cst.Name("iter")),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_after_for=cst.SimpleWhitespace(""),
            ),
            "expected_re":
            "Must have at least one space after 'for' keyword",
        },
        {
            "get_node":
            lambda: cst.For(
                cst.Name("target"),
                cst.Call(cst.Name("iter")),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_before_in=cst.SimpleWhitespace(""),
            ),
            "expected_re":
            "Must have at least one space before 'in' keyword",
        },
        {
            "get_node":
            lambda: cst.For(
                cst.Name("target"),
                cst.Call(cst.Name("iter")),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_after_in=cst.SimpleWhitespace(""),
            ),
            "expected_re":
            "Must have at least one space after 'in' keyword",
        },
    ))
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
Beispiel #10
0
class WithTest(CSTNodeTest):
    @data_provider((
        # Simple with block
        {
            "node":
            cst.With(
                (cst.WithItem(cst.Call(cst.Name("context_mgr"))), ),
                cst.SimpleStatementSuite((cst.Pass(), )),
            ),
            "code":
            "with context_mgr(): pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (1, 24)),
        },
        # Simple async with block
        {
            "node":
            cst.With(
                (cst.WithItem(cst.Call(cst.Name("context_mgr"))), ),
                cst.SimpleStatementSuite((cst.Pass(), )),
                asynchronous=cst.Asynchronous(),
            ),
            "code":
            "async with context_mgr(): pass\n",
            "parser":
            lambda code: parse_statement(
                code, config=PartialParserConfig(python_version="3.7")),
        },
        # Python 3.6 async with block
        {
            "node":
            cst.FunctionDef(
                cst.Name("foo"),
                cst.Parameters(),
                cst.IndentedBlock((cst.With(
                    (cst.WithItem(cst.Call(cst.Name("context_mgr"))), ),
                    cst.SimpleStatementSuite((cst.Pass(), )),
                    asynchronous=cst.Asynchronous(),
                ), )),
                asynchronous=cst.Asynchronous(),
            ),
            "code":
            "async def foo():\n    async with context_mgr(): pass\n",
            "parser":
            lambda code: parse_statement(
                code, config=PartialParserConfig(python_version="3.6")),
        },
        # Multiple context managers
        {
            "node":
            cst.With(
                (
                    cst.WithItem(cst.Call(cst.Name("foo"))),
                    cst.WithItem(cst.Call(cst.Name("bar"))),
                ),
                cst.SimpleStatementSuite((cst.Pass(), )),
            ),
            "code":
            "with foo(), bar(): pass\n",
            "parser":
            None,
        },
        {
            "node":
            cst.With(
                (
                    cst.WithItem(
                        cst.Call(cst.Name("foo")),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.WithItem(cst.Call(cst.Name("bar"))),
                ),
                cst.SimpleStatementSuite((cst.Pass(), )),
            ),
            "code":
            "with foo(), bar(): pass\n",
            "parser":
            parse_statement,
        },
        # With block containing variable for context manager.
        {
            "node":
            cst.With(
                (cst.WithItem(
                    cst.Call(cst.Name("context_mgr")),
                    cst.AsName(cst.Name("ctx")),
                ), ),
                cst.SimpleStatementSuite((cst.Pass(), )),
            ),
            "code":
            "with context_mgr() as ctx: pass\n",
            "parser":
            parse_statement,
        },
        # indentation
        {
            "node":
            DummyIndentedBlock(
                "    ",
                cst.With(
                    (cst.WithItem(cst.Call(cst.Name("context_mgr"))), ),
                    cst.SimpleStatementSuite((cst.Pass(), )),
                ),
            ),
            "code":
            "    with context_mgr(): pass\n",
            "parser":
            None,
            "expected_position":
            CodeRange((1, 4), (1, 28)),
        },
        # with an indented body
        {
            "node":
            DummyIndentedBlock(
                "    ",
                cst.With(
                    (cst.WithItem(cst.Call(cst.Name("context_mgr"))), ),
                    cst.IndentedBlock((cst.SimpleStatementLine(
                        (cst.Pass(), )), )),
                ),
            ),
            "code":
            "    with context_mgr():\n        pass\n",
            "parser":
            None,
            "expected_position":
            CodeRange((1, 4), (2, 12)),
        },
        # leading_lines
        {
            "node":
            cst.With(
                (cst.WithItem(cst.Call(cst.Name("context_mgr"))), ),
                cst.SimpleStatementSuite((cst.Pass(), )),
                leading_lines=(cst.EmptyLine(
                    comment=cst.Comment("# leading comment")), ),
            ),
            "code":
            "# leading comment\nwith context_mgr(): pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((2, 0), (2, 24)),
        },
        # Weird spacing rules
        {
            "node":
            cst.With(
                (cst.WithItem(
                    cst.Call(
                        cst.Name("context_mgr"),
                        lpar=(cst.LeftParen(), ),
                        rpar=(cst.RightParen(), ),
                    )), ),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_after_with=cst.SimpleWhitespace(""),
            ),
            "code":
            "with(context_mgr()): pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (1, 25)),
        },
        # Whitespace
        {
            "node":
            cst.With(
                (cst.WithItem(
                    cst.Call(cst.Name("context_mgr")),
                    cst.AsName(
                        cst.Name("ctx"),
                        whitespace_before_as=cst.SimpleWhitespace("  "),
                        whitespace_after_as=cst.SimpleWhitespace("  "),
                    ),
                ), ),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_after_with=cst.SimpleWhitespace("  "),
                whitespace_before_colon=cst.SimpleWhitespace("  "),
            ),
            "code":
            "with  context_mgr()  as  ctx  : pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (1, 36)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider((
        {
            "get_node":
            lambda: cst.With((),
                             cst.IndentedBlock((cst.SimpleStatementLine(
                                 (cst.Pass(), )), ))),
            "expected_re":
            "A With statement must have at least one WithItem",
        },
        {
            "get_node":
            lambda: cst.With(
                (cst.WithItem(
                    cst.Call(cst.Name("foo")),
                    comma=cst.Comma(whitespace_after=cst.SimpleWhitespace(" ")
                                    ),
                ), ),
                cst.IndentedBlock((cst.SimpleStatementLine((cst.Pass(), )), )),
            ),
            "expected_re":
            "The last WithItem in a With cannot have a trailing comma",
        },
        {
            "get_node":
            lambda: cst.With(
                (cst.WithItem(cst.Call(cst.Name("context_mgr"))), ),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_after_with=cst.SimpleWhitespace(""),
            ),
            "expected_re":
            "Must have at least one space after with keyword",
        },
    ))
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)

    @data_provider((
        {
            "code": "with a, b: pass",
            "parser": parse_statement_as(python_version="3.1"),
            "expect_success": True,
        },
        {
            "code": "with a, b: pass",
            "parser": parse_statement_as(python_version="3.0"),
            "expect_success": False,
        },
    ))
    def test_versions(self, **kwargs: Any) -> None:
        self.assert_parses(**kwargs)
Beispiel #11
0
class TupleTest(CSTNodeTest):
    @data_provider(
        [
            # zero-element tuple
            {"node": cst.Tuple([]), "code": "()", "parser": parse_expression},
            # one-element tuple, sentinel comma value
            {
                "node": cst.Tuple([cst.Element(cst.Name("single_element"))]),
                "code": "(single_element,)",
                "parser": None,
            },
            {
                "node": cst.Tuple([cst.StarredElement(cst.Name("single_element"))]),
                "code": "(*single_element,)",
                "parser": None,
            },
            # two-element tuple, sentinel comma value
            {
                "node": cst.Tuple(
                    [cst.Element(cst.Name("one")), cst.Element(cst.Name("two"))]
                ),
                "code": "(one, two)",
                "parser": None,
            },
            # remove parenthesis
            {
                "node": cst.Tuple(
                    [cst.Element(cst.Name("one")), cst.Element(cst.Name("two"))],
                    lpar=[],
                    rpar=[],
                ),
                "code": "one, two",
                "parser": None,
            },
            # add extra parenthesis
            {
                "node": cst.Tuple(
                    [cst.Element(cst.Name("one")), cst.Element(cst.Name("two"))],
                    lpar=[cst.LeftParen(), cst.LeftParen()],
                    rpar=[cst.RightParen(), cst.RightParen()],
                ),
                "code": "((one, two))",
                "parser": None,
            },
            # starred element
            {
                "node": cst.Tuple(
                    [
                        cst.StarredElement(cst.Name("one")),
                        cst.StarredElement(cst.Name("two")),
                    ]
                ),
                "code": "(*one, *two)",
                "parser": None,
            },
            # custom comma on Element
            {
                "node": cst.Tuple(
                    [
                        cst.Element(cst.Name("one"), comma=cst.Comma()),
                        cst.Element(cst.Name("two"), comma=cst.Comma()),
                    ]
                ),
                "code": "(one,two,)",
                "parser": parse_expression,
            },
            # custom comma on StarredElement
            {
                "node": cst.Tuple(
                    [
                        cst.StarredElement(cst.Name("one"), comma=cst.Comma()),
                        cst.StarredElement(cst.Name("two"), comma=cst.Comma()),
                    ]
                ),
                "code": "(*one,*two,)",
                "parser": parse_expression,
                "expected_position": CodeRange((1, 1), (1, 11)),
            },
            # custom parenthesis on StarredElement
            {
                "node": cst.Tuple(
                    [
                        cst.StarredElement(
                            cst.Name("abc"),
                            lpar=[cst.LeftParen()],
                            rpar=[cst.RightParen()],
                            comma=cst.Comma(),
                        )
                    ]
                ),
                "code": "((*abc),)",
                "parser": parse_expression,
                "expected_position": CodeRange((1, 1), (1, 8)),
            },
            # custom whitespace on StarredElement
            {
                "node": cst.Tuple(
                    [
                        cst.Element(cst.Name("one"), comma=cst.Comma()),
                        cst.StarredElement(
                            cst.Name("two"),
                            whitespace_before_value=cst.SimpleWhitespace("  "),
                            lpar=[cst.LeftParen()],
                            rpar=[cst.RightParen()],
                        ),
                    ],
                    lpar=[],
                    rpar=[],  # rpar can't own the trailing whitespace if it's not there
                ),
                "code": "one,(*  two)",
                "parser": parse_expression,
                "expected_position": CodeRange((1, 0), (1, 12)),
            },
            # missing spaces around tuple, okay with parenthesis
            {
                "node": cst.For(
                    target=cst.Tuple(
                        [
                            cst.Element(cst.Name("k"), comma=cst.Comma()),
                            cst.Element(cst.Name("v")),
                        ]
                    ),
                    iter=cst.Name("abc"),
                    body=cst.SimpleStatementSuite([cst.Pass()]),
                    whitespace_after_for=cst.SimpleWhitespace(""),
                    whitespace_before_in=cst.SimpleWhitespace(""),
                ),
                "code": "for(k,v)in abc: pass\n",
                "parser": parse_statement,
            },
            # no spaces around tuple, but using values that are parenthesized
            {
                "node": cst.For(
                    target=cst.Tuple(
                        [
                            cst.Element(
                                cst.Name(
                                    "k", lpar=[cst.LeftParen()], rpar=[cst.RightParen()]
                                ),
                                comma=cst.Comma(),
                            ),
                            cst.Element(
                                cst.Name(
                                    "v", lpar=[cst.LeftParen()], rpar=[cst.RightParen()]
                                )
                            ),
                        ],
                        lpar=[],
                        rpar=[],
                    ),
                    iter=cst.Name("abc"),
                    body=cst.SimpleStatementSuite([cst.Pass()]),
                    whitespace_after_for=cst.SimpleWhitespace(""),
                    whitespace_before_in=cst.SimpleWhitespace(""),
                ),
                "code": "for(k),(v)in abc: pass\n",
                "parser": parse_statement,
            },
            # starred elements are safe to use without a space before them
            {
                "node": cst.For(
                    target=cst.Tuple(
                        [cst.StarredElement(cst.Name("foo"), comma=cst.Comma())],
                        lpar=[],
                        rpar=[],
                    ),
                    iter=cst.Name("bar"),
                    body=cst.SimpleStatementSuite([cst.Pass()]),
                    whitespace_after_for=cst.SimpleWhitespace(""),
                ),
                "code": "for*foo, in bar: pass\n",
                "parser": parse_statement,
            },
            # a trailing comma doesn't mess up TrailingWhitespace
            {
                "node": cst.SimpleStatementLine(
                    [
                        cst.Expr(
                            cst.Tuple(
                                [
                                    cst.Element(cst.Name("one"), comma=cst.Comma()),
                                    cst.Element(cst.Name("two"), comma=cst.Comma()),
                                ],
                                lpar=[],
                                rpar=[],
                            )
                        )
                    ],
                    trailing_whitespace=cst.TrailingWhitespace(
                        whitespace=cst.SimpleWhitespace("  "),
                        comment=cst.Comment("# comment"),
                    ),
                ),
                "code": "one,two,  # comment\n",
                "parser": parse_statement,
            },
        ]
    )
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider(
        (
            (
                lambda: cst.Tuple([], lpar=[], rpar=[]),
                "A zero-length tuple must be wrapped in parentheses.",
            ),
            (
                lambda: cst.Tuple(
                    [cst.Element(cst.Name("mismatched"))],
                    lpar=[cst.LeftParen(), cst.LeftParen()],
                    rpar=[cst.RightParen()],
                ),
                "unbalanced parens",
            ),
            (
                lambda: cst.For(
                    target=cst.Tuple([cst.Element(cst.Name("el"))], lpar=[], rpar=[]),
                    iter=cst.Name("it"),
                    body=cst.SimpleStatementSuite([cst.Pass()]),
                    whitespace_after_for=cst.SimpleWhitespace(""),
                ),
                "Must have at least one space after 'for' keyword.",
            ),
            (
                lambda: cst.For(
                    target=cst.Tuple([cst.Element(cst.Name("el"))], lpar=[], rpar=[]),
                    iter=cst.Name("it"),
                    body=cst.SimpleStatementSuite([cst.Pass()]),
                    whitespace_before_in=cst.SimpleWhitespace(""),
                ),
                "Must have at least one space before 'in' keyword.",
            ),
            # an additional check for StarredElement, since it's a separate codepath
            (
                lambda: cst.For(
                    target=cst.Tuple(
                        [cst.StarredElement(cst.Name("el"))], lpar=[], rpar=[]
                    ),
                    iter=cst.Name("it"),
                    body=cst.SimpleStatementSuite([cst.Pass()]),
                    whitespace_before_in=cst.SimpleWhitespace(""),
                ),
                "Must have at least one space before 'in' keyword.",
            ),
        )
    )
    def test_invalid(
        self, get_node: Callable[[], cst.CSTNode], expected_re: str
    ) -> None:
        self.assert_invalid(get_node, expected_re)
Beispiel #12
0
class ListTest(CSTNodeTest):

    # A lot of Element/StarredElement tests are provided by the tests for Tuple, so we
    # we don't need to duplicate them here.
    @data_provider([
        # zero-element list
        {
            "node": cst.List([]),
            "code": "[]",
            "parser": parse_expression
        },
        # one-element list, sentinel comma value
        {
            "node": cst.List([cst.Element(cst.Name("single_element"))]),
            "code": "[single_element]",
            "parser": parse_expression,
        },
        # custom whitespace between brackets
        {
            "node":
            cst.List(
                [cst.Element(cst.Name("single_element"))],
                lbracket=cst.LeftSquareBracket(
                    whitespace_after=cst.SimpleWhitespace("\t")),
                rbracket=cst.RightSquareBracket(
                    whitespace_before=cst.SimpleWhitespace("    ")),
            ),
            "code":
            "[\tsingle_element    ]",
            "parser":
            parse_expression,
            "expected_position":
            CodeRange.create((1, 0), (1, 21)),
        },
        # two-element list, sentinel comma value
        {
            "node":
            cst.List(
                [cst.Element(cst.Name("one")),
                 cst.Element(cst.Name("two"))]),
            "code":
            "[one, two]",
            "parser":
            None,
        },
        # with parenthesis
        {
            "node":
            cst.List(
                [cst.Element(cst.Name("one"))],
                lpar=[cst.LeftParen()],
                rpar=[cst.RightParen()],
            ),
            "code":
            "([one])",
            "parser":
            None,
            "expected_position":
            CodeRange.create((1, 1), (1, 6)),
        },
        # starred element
        {
            "node":
            cst.List([
                cst.StarredElement(cst.Name("one")),
                cst.StarredElement(cst.Name("two")),
            ]),
            "code":
            "[*one, *two]",
            "parser":
            None,
            "expected_position":
            CodeRange.create((1, 0), (1, 12)),
        },
        # missing spaces around list, always okay
        {
            "node":
            cst.For(
                target=cst.List([
                    cst.Element(cst.Name("k"), comma=cst.Comma()),
                    cst.Element(cst.Name("v")),
                ]),
                iter=cst.Name("abc"),
                body=cst.SimpleStatementSuite([cst.Pass()]),
                whitespace_after_for=cst.SimpleWhitespace(""),
                whitespace_before_in=cst.SimpleWhitespace(""),
            ),
            "code":
            "for[k,v]in abc: pass\n",
            "parser":
            parse_statement,
        },
    ])
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider(((
        lambda: cst.List(
            [cst.Element(cst.Name("mismatched"))],
            lpar=[cst.LeftParen(), cst.LeftParen()],
            rpar=[cst.RightParen()],
        ),
        "unbalanced parens",
    ), ))
    def test_invalid(self, get_node: Callable[[], cst.CSTNode],
                     expected_re: str) -> None:
        self.assert_invalid(get_node, expected_re)
Beispiel #13
0
class WithTest(CSTNodeTest):
    maxDiff: int = 2000

    @data_provider((
        # Simple with block
        {
            "node":
            cst.With(
                (cst.WithItem(cst.Call(cst.Name("context_mgr"))), ),
                cst.SimpleStatementSuite((cst.Pass(), )),
            ),
            "code":
            "with context_mgr(): pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (1, 24)),
        },
        # Simple async with block
        {
            "node":
            cst.With(
                (cst.WithItem(cst.Call(cst.Name("context_mgr"))), ),
                cst.SimpleStatementSuite((cst.Pass(), )),
                asynchronous=cst.Asynchronous(),
            ),
            "code":
            "async with context_mgr(): pass\n",
            "parser":
            lambda code: parse_statement(
                code, config=PartialParserConfig(python_version="3.7")),
        },
        # Python 3.6 async with block
        {
            "node":
            cst.FunctionDef(
                cst.Name("foo"),
                cst.Parameters(),
                cst.IndentedBlock((cst.With(
                    (cst.WithItem(cst.Call(cst.Name("context_mgr"))), ),
                    cst.SimpleStatementSuite((cst.Pass(), )),
                    asynchronous=cst.Asynchronous(),
                ), )),
                asynchronous=cst.Asynchronous(),
            ),
            "code":
            "async def foo():\n    async with context_mgr(): pass\n",
            "parser":
            lambda code: parse_statement(
                code, config=PartialParserConfig(python_version="3.6")),
        },
        # Multiple context managers
        {
            "node":
            cst.With(
                (
                    cst.WithItem(cst.Call(cst.Name("foo"))),
                    cst.WithItem(cst.Call(cst.Name("bar"))),
                ),
                cst.SimpleStatementSuite((cst.Pass(), )),
            ),
            "code":
            "with foo(), bar(): pass\n",
            "parser":
            None,
        },
        {
            "node":
            cst.With(
                (
                    cst.WithItem(
                        cst.Call(cst.Name("foo")),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.WithItem(cst.Call(cst.Name("bar"))),
                ),
                cst.SimpleStatementSuite((cst.Pass(), )),
            ),
            "code":
            "with foo(), bar(): pass\n",
            "parser":
            parse_statement,
        },
        # With block containing variable for context manager.
        {
            "node":
            cst.With(
                (cst.WithItem(
                    cst.Call(cst.Name("context_mgr")),
                    cst.AsName(cst.Name("ctx")),
                ), ),
                cst.SimpleStatementSuite((cst.Pass(), )),
            ),
            "code":
            "with context_mgr() as ctx: pass\n",
            "parser":
            parse_statement,
        },
        # indentation
        {
            "node":
            DummyIndentedBlock(
                "    ",
                cst.With(
                    (cst.WithItem(cst.Call(cst.Name("context_mgr"))), ),
                    cst.SimpleStatementSuite((cst.Pass(), )),
                ),
            ),
            "code":
            "    with context_mgr(): pass\n",
            "parser":
            None,
            "expected_position":
            CodeRange((1, 4), (1, 28)),
        },
        # with an indented body
        {
            "node":
            DummyIndentedBlock(
                "    ",
                cst.With(
                    (cst.WithItem(cst.Call(cst.Name("context_mgr"))), ),
                    cst.IndentedBlock((cst.SimpleStatementLine(
                        (cst.Pass(), )), )),
                ),
            ),
            "code":
            "    with context_mgr():\n        pass\n",
            "parser":
            None,
            "expected_position":
            CodeRange((1, 4), (2, 12)),
        },
        # leading_lines
        {
            "node":
            cst.With(
                (cst.WithItem(cst.Call(cst.Name("context_mgr"))), ),
                cst.SimpleStatementSuite((cst.Pass(), )),
                leading_lines=(cst.EmptyLine(
                    comment=cst.Comment("# leading comment")), ),
            ),
            "code":
            "# leading comment\nwith context_mgr(): pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((2, 0), (2, 24)),
        },
        # Whitespace
        {
            "node":
            cst.With(
                (cst.WithItem(
                    cst.Call(cst.Name("context_mgr")),
                    cst.AsName(
                        cst.Name("ctx"),
                        whitespace_before_as=cst.SimpleWhitespace("  "),
                        whitespace_after_as=cst.SimpleWhitespace("  "),
                    ),
                ), ),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_after_with=cst.SimpleWhitespace("  "),
                whitespace_before_colon=cst.SimpleWhitespace("  "),
            ),
            "code":
            "with  context_mgr()  as  ctx  : pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (1, 36)),
        },
        # Weird spacing rules, that parse differently depending on whether
        # we are using a grammar that included parenthesized with statements.
        {
            "node":
            cst.With(
                (cst.WithItem(
                    cst.Call(
                        cst.Name("context_mgr"),
                        lpar=() if is_native() else (cst.LeftParen(), ),
                        rpar=() if is_native() else (cst.RightParen(), ),
                    )), ),
                cst.SimpleStatementSuite((cst.Pass(), )),
                lpar=(cst.LeftParen()
                      if is_native() else MaybeSentinel.DEFAULT),
                rpar=(cst.RightParen()
                      if is_native() else MaybeSentinel.DEFAULT),
                whitespace_after_with=cst.SimpleWhitespace(""),
            ),
            "code":
            "with(context_mgr()): pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (1, 25)),
        },
        # Multi-line parenthesized with.
        {
            "node":
            cst.With(
                (
                    cst.WithItem(
                        cst.Call(cst.Name("foo")),
                        comma=cst.
                        Comma(whitespace_after=cst.ParenthesizedWhitespace(
                            first_line=cst.TrailingWhitespace(
                                whitespace=cst.SimpleWhitespace(value="", ),
                                comment=None,
                                newline=cst.Newline(value=None, ),
                            ),
                            empty_lines=[],
                            indent=True,
                            last_line=cst.SimpleWhitespace(value="       ", ),
                        )),
                    ),
                    cst.WithItem(cst.Call(cst.Name("bar")), comma=cst.Comma()),
                ),
                cst.SimpleStatementSuite((cst.Pass(), )),
                lpar=cst.LeftParen(whitespace_after=cst.SimpleWhitespace(" ")),
                rpar=cst.RightParen(
                    whitespace_before=cst.SimpleWhitespace(" ")),
            ),
            "code": ("with ( foo(),\n"
                     "       bar(), ): pass\n"),  # noqa
            "parser":
            parse_statement if is_native() else None,
            "expected_position":
            CodeRange((1, 0), (2, 21)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider((
        {
            "get_node":
            lambda: cst.With((),
                             cst.IndentedBlock((cst.SimpleStatementLine(
                                 (cst.Pass(), )), ))),
            "expected_re":
            "A With statement must have at least one WithItem",
        },
        {
            "get_node":
            lambda: cst.With(
                (cst.WithItem(
                    cst.Call(cst.Name("foo")),
                    comma=cst.Comma(whitespace_after=cst.SimpleWhitespace(" ")
                                    ),
                ), ),
                cst.IndentedBlock((cst.SimpleStatementLine((cst.Pass(), )), )),
            ),
            "expected_re":
            "The last WithItem in an unparenthesized With cannot " +
            "have a trailing comma.",
        },
        {
            "get_node":
            lambda: cst.With(
                (cst.WithItem(cst.Call(cst.Name("context_mgr"))), ),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_after_with=cst.SimpleWhitespace(""),
            ),
            "expected_re":
            "Must have at least one space after with keyword",
        },
        {
            "get_node":
            lambda: cst.With(
                (cst.WithItem(cst.Call(cst.Name("context_mgr"))), ),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_after_with=cst.SimpleWhitespace(""),
                lpar=cst.LeftParen(),
            ),
            "expected_re":
            "Do not mix concrete LeftParen/RightParen with " + "MaybeSentinel",
        },
        {
            "get_node":
            lambda: cst.With(
                (cst.WithItem(cst.Call(cst.Name("context_mgr"))), ),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_after_with=cst.SimpleWhitespace(""),
                rpar=cst.RightParen(),
            ),
            "expected_re":
            "Do not mix concrete LeftParen/RightParen with " + "MaybeSentinel",
        },
    ))
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)

    @data_provider((
        {
            "code": "with a, b: pass",
            "parser": parse_statement_as(python_version="3.1"),
            "expect_success": True,
        },
        {
            "code": "with a, b: pass",
            "parser": parse_statement_as(python_version="3.0"),
            "expect_success": False,
        },
    ))
    def test_versions(self, **kwargs: Any) -> None:
        if is_native() and not kwargs.get("expect_success", True):
            self.skipTest("parse errors are disabled for native parser")
        self.assert_parses(**kwargs)

    def test_adding_parens(self) -> None:
        node = cst.With(
            (
                cst.WithItem(
                    cst.Call(cst.Name("foo")),
                    comma=cst.Comma(
                        whitespace_after=cst.ParenthesizedWhitespace(), ),
                ),
                cst.WithItem(cst.Call(cst.Name("bar")), comma=cst.Comma()),
            ),
            cst.SimpleStatementSuite((cst.Pass(), )),
            lpar=cst.LeftParen(whitespace_after=cst.SimpleWhitespace(" ")),
            rpar=cst.RightParen(whitespace_before=cst.SimpleWhitespace(" ")),
        )
        module = cst.Module([])
        self.assertEqual(
            module.code_for_node(node),
            ("with ( foo(),\n"
             "bar(), ): pass\n")  # noqa
        )
Beispiel #14
0
class IfTest(CSTNodeTest):
    @data_provider((
        # Simple if without elif or else
        {
            "node":
            cst.If(cst.Name("conditional"),
                   cst.SimpleStatementSuite((cst.Pass(), ))),
            "code":
            "if conditional: pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (1, 20)),
        },
        # else clause
        {
            "node":
            cst.If(
                cst.Name("conditional"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(), ))),
            ),
            "code":
            "if conditional: pass\nelse: pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (2, 10)),
        },
        # elif clause
        {
            "node":
            cst.If(
                cst.Name("conditional"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                orelse=cst.If(
                    cst.Name("other_conditional"),
                    cst.SimpleStatementSuite((cst.Pass(), )),
                    orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(), ))),
                ),
            ),
            "code":
            "if conditional: pass\nelif other_conditional: pass\nelse: pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (3, 10)),
        },
        # indentation
        {
            "node":
            DummyIndentedBlock(
                "    ",
                cst.If(
                    cst.Name("conditional"),
                    cst.SimpleStatementSuite((cst.Pass(), )),
                    orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(), ))),
                ),
            ),
            "code":
            "    if conditional: pass\n    else: pass\n",
            "parser":
            None,
            "expected_position":
            CodeRange((1, 4), (2, 14)),
        },
        # with an indented body
        {
            "node":
            DummyIndentedBlock(
                "    ",
                cst.If(
                    cst.Name("conditional"),
                    cst.IndentedBlock((cst.SimpleStatementLine(
                        (cst.Pass(), )), )),
                ),
            ),
            "code":
            "    if conditional:\n        pass\n",
            "parser":
            None,
            "expected_position":
            CodeRange((1, 4), (2, 12)),
        },
        # leading_lines
        {
            "node":
            cst.If(
                cst.Name("conditional"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                leading_lines=(cst.EmptyLine(
                    comment=cst.Comment("# leading comment")), ),
            ),
            "code":
            "# leading comment\nif conditional: pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((2, 0), (2, 20)),
        },
        # whitespace before/after test and else
        {
            "node":
            cst.If(
                cst.Name("conditional"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_before_test=cst.SimpleWhitespace("   "),
                whitespace_after_test=cst.SimpleWhitespace("  "),
                orelse=cst.Else(
                    cst.SimpleStatementSuite((cst.Pass(), )),
                    whitespace_before_colon=cst.SimpleWhitespace(" "),
                ),
            ),
            "code":
            "if   conditional  : pass\nelse : pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (2, 11)),
        },
        # empty lines between if/elif/else clauses, not captured by the suite.
        {
            "node":
            cst.If(
                cst.Name("test_a"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                orelse=cst.If(
                    cst.Name("test_b"),
                    cst.SimpleStatementSuite((cst.Pass(), )),
                    leading_lines=(cst.EmptyLine(), ),
                    orelse=cst.Else(
                        cst.SimpleStatementSuite((cst.Pass(), )),
                        leading_lines=(cst.EmptyLine(), ),
                    ),
                ),
            ),
            "code":
            "if test_a: pass\n\nelif test_b: pass\n\nelse: pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (5, 10)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)
Beispiel #15
0
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)
Beispiel #16
0
class TryTest(CSTNodeTest):
    @data_provider(
        (
            # Simple try/except block
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_except=cst.SimpleWhitespace(""),
                        ),
                    ),
                ),
                "code": "try: pass\nexcept: pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((1, 0), (2, 12)),
            },
            # Try/except with a class
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            type=cst.Name("Exception"),
                        ),
                    ),
                ),
                "code": "try: pass\nexcept Exception: pass\n",
                "parser": parse_statement,
            },
            # Try/except with a named class
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            type=cst.Name("Exception"),
                            name=cst.AsName(cst.Name("exc")),
                        ),
                    ),
                ),
                "code": "try: pass\nexcept Exception as exc: pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((1, 0), (2, 29)),
            },
            # Try/except with multiple clauses
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            type=cst.Name("TypeError"),
                            name=cst.AsName(cst.Name("e")),
                        ),
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            type=cst.Name("KeyError"),
                            name=cst.AsName(cst.Name("e")),
                        ),
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_except=cst.SimpleWhitespace(""),
                        ),
                    ),
                ),
                "code": "try: pass\n"
                + "except TypeError as e: pass\n"
                + "except KeyError as e: pass\n"
                + "except: pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((1, 0), (4, 12)),
            },
            # Simple try/finally block
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    finalbody=cst.Finally(cst.SimpleStatementSuite((cst.Pass(),))),
                ),
                "code": "try: pass\nfinally: pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((1, 0), (2, 13)),
            },
            # Simple try/except/finally block
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_except=cst.SimpleWhitespace(""),
                        ),
                    ),
                    finalbody=cst.Finally(cst.SimpleStatementSuite((cst.Pass(),))),
                ),
                "code": "try: pass\nexcept: pass\nfinally: pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((1, 0), (3, 13)),
            },
            # Simple try/except/else block
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_except=cst.SimpleWhitespace(""),
                        ),
                    ),
                    orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(),))),
                ),
                "code": "try: pass\nexcept: pass\nelse: pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((1, 0), (3, 10)),
            },
            # Simple try/except/else block/finally
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_except=cst.SimpleWhitespace(""),
                        ),
                    ),
                    orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(),))),
                    finalbody=cst.Finally(cst.SimpleStatementSuite((cst.Pass(),))),
                ),
                "code": "try: pass\nexcept: pass\nelse: pass\nfinally: pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((1, 0), (4, 13)),
            },
            # Verify whitespace in various locations
            {
                "node": cst.Try(
                    leading_lines=(cst.EmptyLine(comment=cst.Comment("# 1")),),
                    body=cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            leading_lines=(cst.EmptyLine(comment=cst.Comment("# 2")),),
                            type=cst.Name("TypeError"),
                            name=cst.AsName(
                                cst.Name("e"),
                                whitespace_before_as=cst.SimpleWhitespace("  "),
                                whitespace_after_as=cst.SimpleWhitespace("  "),
                            ),
                            whitespace_after_except=cst.SimpleWhitespace("  "),
                            whitespace_before_colon=cst.SimpleWhitespace(" "),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                    ),
                    orelse=cst.Else(
                        leading_lines=(cst.EmptyLine(comment=cst.Comment("# 3")),),
                        body=cst.SimpleStatementSuite((cst.Pass(),)),
                        whitespace_before_colon=cst.SimpleWhitespace(" "),
                    ),
                    finalbody=cst.Finally(
                        leading_lines=(cst.EmptyLine(comment=cst.Comment("# 4")),),
                        body=cst.SimpleStatementSuite((cst.Pass(),)),
                        whitespace_before_colon=cst.SimpleWhitespace(" "),
                    ),
                    whitespace_before_colon=cst.SimpleWhitespace(" "),
                ),
                "code": "# 1\ntry : pass\n# 2\nexcept  TypeError  as  e : pass\n# 3\nelse : pass\n# 4\nfinally : pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((2, 0), (8, 14)),
            },
            # Please don't write code like this
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            type=cst.Name("TypeError"),
                            name=cst.AsName(cst.Name("e")),
                        ),
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            type=cst.Name("KeyError"),
                            name=cst.AsName(cst.Name("e")),
                        ),
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_except=cst.SimpleWhitespace(""),
                        ),
                    ),
                    orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(),))),
                    finalbody=cst.Finally(cst.SimpleStatementSuite((cst.Pass(),))),
                ),
                "code": "try: pass\n"
                + "except TypeError as e: pass\n"
                + "except KeyError as e: pass\n"
                + "except: pass\n"
                + "else: pass\n"
                + "finally: pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((1, 0), (6, 13)),
            },
            # Verify indentation
            {
                "node": DummyIndentedBlock(
                    "    ",
                    cst.Try(
                        cst.SimpleStatementSuite((cst.Pass(),)),
                        handlers=(
                            cst.ExceptHandler(
                                cst.SimpleStatementSuite((cst.Pass(),)),
                                type=cst.Name("TypeError"),
                                name=cst.AsName(cst.Name("e")),
                            ),
                            cst.ExceptHandler(
                                cst.SimpleStatementSuite((cst.Pass(),)),
                                type=cst.Name("KeyError"),
                                name=cst.AsName(cst.Name("e")),
                            ),
                            cst.ExceptHandler(
                                cst.SimpleStatementSuite((cst.Pass(),)),
                                whitespace_after_except=cst.SimpleWhitespace(""),
                            ),
                        ),
                        orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(),))),
                        finalbody=cst.Finally(cst.SimpleStatementSuite((cst.Pass(),))),
                    ),
                ),
                "code": "    try: pass\n"
                + "    except TypeError as e: pass\n"
                + "    except KeyError as e: pass\n"
                + "    except: pass\n"
                + "    else: pass\n"
                + "    finally: pass\n",
                "parser": None,
            },
            # Verify indentation in bodies
            {
                "node": DummyIndentedBlock(
                    "    ",
                    cst.Try(
                        cst.IndentedBlock((cst.SimpleStatementLine((cst.Pass(),)),)),
                        handlers=(
                            cst.ExceptHandler(
                                cst.IndentedBlock(
                                    (cst.SimpleStatementLine((cst.Pass(),)),)
                                ),
                                whitespace_after_except=cst.SimpleWhitespace(""),
                            ),
                        ),
                        orelse=cst.Else(
                            cst.IndentedBlock((cst.SimpleStatementLine((cst.Pass(),)),))
                        ),
                        finalbody=cst.Finally(
                            cst.IndentedBlock((cst.SimpleStatementLine((cst.Pass(),)),))
                        ),
                    ),
                ),
                "code": "    try:\n"
                + "        pass\n"
                + "    except:\n"
                + "        pass\n"
                + "    else:\n"
                + "        pass\n"
                + "    finally:\n"
                + "        pass\n",
                "parser": None,
            },
            # No space when using grouping parens
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_except=cst.SimpleWhitespace(""),
                            type=cst.Name(
                                "Exception",
                                lpar=(cst.LeftParen(),),
                                rpar=(cst.RightParen(),),
                            ),
                        ),
                    ),
                ),
                "code": "try: pass\nexcept(Exception): pass\n",
                "parser": parse_statement,
            },
            # No space when using tuple
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_except=cst.SimpleWhitespace(""),
                            type=cst.Tuple(
                                [
                                    cst.Element(
                                        cst.Name("IOError"),
                                        comma=cst.Comma(
                                            whitespace_after=cst.SimpleWhitespace(" ")
                                        ),
                                    ),
                                    cst.Element(cst.Name("ImportError")),
                                ]
                            ),
                        ),
                    ),
                ),
                "code": "try: pass\nexcept(IOError, ImportError): pass\n",
                "parser": parse_statement,
            },
        )
    )
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider(
        (
            {
                "get_node": lambda: cst.AsName(cst.Name("")),
                "expected_re": "empty name identifier",
            },
            {
                "get_node": lambda: cst.AsName(
                    cst.Name("bla"), whitespace_after_as=cst.SimpleWhitespace("")
                ),
                "expected_re": "between 'as'",
            },
            {
                "get_node": lambda: cst.AsName(
                    cst.Name("bla"), whitespace_before_as=cst.SimpleWhitespace("")
                ),
                "expected_re": "before 'as'",
            },
            {
                "get_node": lambda: cst.ExceptHandler(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    name=cst.AsName(cst.Name("bla")),
                ),
                "expected_re": "name for an empty type",
            },
            {
                "get_node": lambda: cst.ExceptHandler(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    type=cst.Name("TypeError"),
                    whitespace_after_except=cst.SimpleWhitespace(""),
                ),
                "expected_re": "at least one space after except",
            },
            {
                "get_node": lambda: cst.Try(cst.SimpleStatementSuite((cst.Pass(),))),
                "expected_re": "at least one ExceptHandler or Finally",
            },
            {
                "get_node": lambda: cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(),))),
                    finalbody=cst.Finally(cst.SimpleStatementSuite((cst.Pass(),))),
                ),
                "expected_re": "at least one ExceptHandler in order to have an Else",
            },
        )
    )
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
Beispiel #17
0
class TryStarTest(CSTNodeTest):
    @data_provider((
        # Try/except with a class
        {
            "node":
            cst.TryStar(
                cst.SimpleStatementSuite((cst.Pass(), )),
                handlers=(cst.ExceptStarHandler(
                    cst.SimpleStatementSuite((cst.Pass(), )),
                    type=cst.Name("Exception"),
                ), ),
            ),
            "code":
            "try: pass\nexcept* Exception: pass\n",
            "parser":
            native_parse_statement,
        },
        # Try/except with a named class
        {
            "node":
            cst.TryStar(
                cst.SimpleStatementSuite((cst.Pass(), )),
                handlers=(cst.ExceptStarHandler(
                    cst.SimpleStatementSuite((cst.Pass(), )),
                    type=cst.Name("Exception"),
                    name=cst.AsName(cst.Name("exc")),
                ), ),
            ),
            "code":
            "try: pass\nexcept* Exception as exc: pass\n",
            "parser":
            native_parse_statement,
            "expected_position":
            CodeRange((1, 0), (2, 30)),
        },
        # Try/except with multiple clauses
        {
            "node":
            cst.TryStar(
                cst.SimpleStatementSuite((cst.Pass(), )),
                handlers=(
                    cst.ExceptStarHandler(
                        cst.SimpleStatementSuite((cst.Pass(), )),
                        type=cst.Name("TypeError"),
                        name=cst.AsName(cst.Name("e")),
                    ),
                    cst.ExceptStarHandler(
                        cst.SimpleStatementSuite((cst.Pass(), )),
                        type=cst.Name("KeyError"),
                        name=cst.AsName(cst.Name("e")),
                    ),
                ),
            ),
            "code":
            "try: pass\n" + "except* TypeError as e: pass\n" +
            "except* KeyError as e: pass\n",
            "parser":
            native_parse_statement,
            "expected_position":
            CodeRange((1, 0), (3, 27)),
        },
        # Simple try/except/finally block
        {
            "node":
            cst.TryStar(
                cst.SimpleStatementSuite((cst.Pass(), )),
                handlers=(cst.ExceptStarHandler(
                    cst.SimpleStatementSuite((cst.Pass(), )),
                    type=cst.Name("KeyError"),
                    whitespace_after_except=cst.SimpleWhitespace(""),
                ), ),
                finalbody=cst.Finally(cst.SimpleStatementSuite(
                    (cst.Pass(), ))),
            ),
            "code":
            "try: pass\nexcept* KeyError: pass\nfinally: pass\n",
            "parser":
            native_parse_statement,
            "expected_position":
            CodeRange((1, 0), (3, 13)),
        },
        # Simple try/except/else block
        {
            "node":
            cst.TryStar(
                cst.SimpleStatementSuite((cst.Pass(), )),
                handlers=(cst.ExceptStarHandler(
                    cst.SimpleStatementSuite((cst.Pass(), )),
                    type=cst.Name("KeyError"),
                    whitespace_after_except=cst.SimpleWhitespace(""),
                ), ),
                orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(), ))),
            ),
            "code":
            "try: pass\nexcept* KeyError: pass\nelse: pass\n",
            "parser":
            native_parse_statement,
            "expected_position":
            CodeRange((1, 0), (3, 10)),
        },
        # Verify whitespace in various locations
        {
            "node":
            cst.TryStar(
                leading_lines=(cst.EmptyLine(comment=cst.Comment("# 1")), ),
                body=cst.SimpleStatementSuite((cst.Pass(), )),
                handlers=(cst.ExceptStarHandler(
                    leading_lines=(cst.EmptyLine(
                        comment=cst.Comment("# 2")), ),
                    type=cst.Name("TypeError"),
                    name=cst.AsName(
                        cst.Name("e"),
                        whitespace_before_as=cst.SimpleWhitespace("  "),
                        whitespace_after_as=cst.SimpleWhitespace("  "),
                    ),
                    whitespace_after_except=cst.SimpleWhitespace("  "),
                    whitespace_after_star=cst.SimpleWhitespace(""),
                    whitespace_before_colon=cst.SimpleWhitespace(" "),
                    body=cst.SimpleStatementSuite((cst.Pass(), )),
                ), ),
                orelse=cst.Else(
                    leading_lines=(cst.EmptyLine(
                        comment=cst.Comment("# 3")), ),
                    body=cst.SimpleStatementSuite((cst.Pass(), )),
                    whitespace_before_colon=cst.SimpleWhitespace(" "),
                ),
                finalbody=cst.Finally(
                    leading_lines=(cst.EmptyLine(
                        comment=cst.Comment("# 4")), ),
                    body=cst.SimpleStatementSuite((cst.Pass(), )),
                    whitespace_before_colon=cst.SimpleWhitespace(" "),
                ),
                whitespace_before_colon=cst.SimpleWhitespace(" "),
            ),
            "code":
            "# 1\ntry : pass\n# 2\nexcept  *TypeError  as  e : pass\n# 3\nelse : pass\n# 4\nfinally : pass\n",
            "parser":
            native_parse_statement,
            "expected_position":
            CodeRange((2, 0), (8, 14)),
        },
        # Now all together
        {
            "node":
            cst.TryStar(
                cst.SimpleStatementSuite((cst.Pass(), )),
                handlers=(
                    cst.ExceptStarHandler(
                        cst.SimpleStatementSuite((cst.Pass(), )),
                        type=cst.Name("TypeError"),
                        name=cst.AsName(cst.Name("e")),
                    ),
                    cst.ExceptStarHandler(
                        cst.SimpleStatementSuite((cst.Pass(), )),
                        type=cst.Name("KeyError"),
                        name=cst.AsName(cst.Name("e")),
                    ),
                ),
                orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(), ))),
                finalbody=cst.Finally(cst.SimpleStatementSuite(
                    (cst.Pass(), ))),
            ),
            "code":
            "try: pass\n" + "except* TypeError as e: pass\n" +
            "except* KeyError as e: pass\n" + "else: pass\n" +
            "finally: pass\n",
            "parser":
            native_parse_statement,
            "expected_position":
            CodeRange((1, 0), (5, 13)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)
Beispiel #18
0
class WhileTest(CSTNodeTest):
    @data_provider((
        # Simple while block
        # pyre-fixme[6]: Incompatible parameter type
        {
            "node":
            cst.While(cst.Call(cst.Name("iter")),
                      cst.SimpleStatementSuite((cst.Pass(), ))),
            "code":
            "while iter(): pass\n",
            "parser":
            parse_statement,
        },
        # While block with else
        {
            "node":
            cst.While(
                cst.Call(cst.Name("iter")),
                cst.SimpleStatementSuite((cst.Pass(), )),
                cst.Else(cst.SimpleStatementSuite((cst.Pass(), ))),
            ),
            "code":
            "while iter(): pass\nelse: pass\n",
            "parser":
            parse_statement,
        },
        # indentation
        {
            "node":
            DummyIndentedBlock(
                "    ",
                cst.While(
                    cst.Call(cst.Name("iter")),
                    cst.SimpleStatementSuite((cst.Pass(), )),
                ),
            ),
            "code":
            "    while iter(): pass\n",
            "parser":
            None,
            "expected_position":
            CodeRange((1, 4), (1, 22)),
        },
        # while an indented body
        {
            "node":
            DummyIndentedBlock(
                "    ",
                cst.While(
                    cst.Call(cst.Name("iter")),
                    cst.IndentedBlock((cst.SimpleStatementLine(
                        (cst.Pass(), )), )),
                ),
            ),
            "code":
            "    while iter():\n        pass\n",
            "parser":
            None,
            "expected_position":
            CodeRange((1, 4), (2, 12)),
        },
        # leading_lines
        {
            "node":
            cst.While(
                cst.Call(cst.Name("iter")),
                cst.IndentedBlock((cst.SimpleStatementLine((cst.Pass(), )), )),
                leading_lines=(cst.EmptyLine(
                    comment=cst.Comment("# leading comment")), ),
            ),
            "code":
            "# leading comment\nwhile iter():\n    pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((2, 0), (3, 8)),
        },
        {
            "node":
            cst.While(
                cst.Call(cst.Name("iter")),
                cst.IndentedBlock((cst.SimpleStatementLine((cst.Pass(), )), )),
                cst.Else(
                    cst.IndentedBlock((cst.SimpleStatementLine(
                        (cst.Pass(), )), )),
                    leading_lines=(cst.EmptyLine(
                        comment=cst.Comment("# else comment")), ),
                ),
                leading_lines=(cst.EmptyLine(
                    comment=cst.Comment("# leading comment")), ),
            ),
            "code":
            "# leading comment\nwhile iter():\n    pass\n# else comment\nelse:\n    pass\n",
            "parser":
            None,
            "expected_position":
            CodeRange((2, 0), (6, 8)),
        },
        # Weird spacing rules
        {
            "node":
            cst.While(
                cst.Call(
                    cst.Name("iter"),
                    lpar=(cst.LeftParen(), ),
                    rpar=(cst.RightParen(), ),
                ),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_after_while=cst.SimpleWhitespace(""),
            ),
            "code":
            "while(iter()): pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (1, 19)),
        },
        # Whitespace
        {
            "node":
            cst.While(
                cst.Call(cst.Name("iter")),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_after_while=cst.SimpleWhitespace("  "),
                whitespace_before_colon=cst.SimpleWhitespace("  "),
            ),
            "code":
            "while  iter()  : pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (1, 21)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider(({
        "get_node":
        lambda: cst.While(
            cst.Call(cst.Name("iter")),
            cst.SimpleStatementSuite((cst.Pass(), )),
            whitespace_after_while=cst.SimpleWhitespace(""),
        ),
        "expected_re":
        "Must have at least one space after 'while' keyword",
    }, ))
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
Beispiel #19
0
class MatchTest(CSTNodeTest):
    @data_provider(
        (
            # Values and singletons
            {
                "node": cst.Match(
                    subject=cst.Name("x"),
                    cases=[
                        cst.MatchCase(
                            pattern=cst.MatchSingleton(cst.Name("None")),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(
                            pattern=cst.MatchValue(cst.SimpleString('"foo"')),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                    ],
                ),
                "code": "match x:\n"
                + "    case None: pass\n"
                + '    case "foo": pass\n',
                "parser": parser,
            },
            # Parenthesized value
            {
                "node": cst.Match(
                    subject=cst.Name(
                        value="x",
                    ),
                    cases=[
                        cst.MatchCase(
                            pattern=cst.MatchAs(
                                pattern=cst.MatchValue(
                                    value=cst.Integer(
                                        value="1",
                                        lpar=[
                                            cst.LeftParen(),
                                        ],
                                        rpar=[
                                            cst.RightParen(),
                                        ],
                                    ),
                                ),
                                name=cst.Name(
                                    value="z",
                                ),
                                whitespace_before_as=cst.SimpleWhitespace(" "),
                                whitespace_after_as=cst.SimpleWhitespace(" "),
                            ),
                            body=cst.SimpleStatementSuite([cst.Pass()]),
                        ),
                    ],
                ),
                "code": "match x:\n    case (1) as z: pass\n",
                "parser": parser,
            },
            # List patterns
            {
                "node": cst.Match(
                    subject=cst.Name("x"),
                    cases=[
                        cst.MatchCase(  # empty list
                            pattern=cst.MatchList(
                                [],
                                lbracket=cst.LeftSquareBracket(),
                                rbracket=cst.RightSquareBracket(),
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # single element list
                            pattern=cst.MatchList(
                                [
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None"))
                                    )
                                ],
                                lbracket=cst.LeftSquareBracket(),
                                rbracket=cst.RightSquareBracket(),
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # single element list with trailing comma
                            pattern=cst.MatchList(
                                [
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                        cst.Comma(),
                                    )
                                ],
                                lbracket=cst.LeftSquareBracket(),
                                rbracket=cst.RightSquareBracket(),
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                    ],
                ),
                "code": (
                    "match x:\n"
                    + "    case []: pass\n"
                    + "    case [None]: pass\n"
                    + "    case [None,]: pass\n"
                ),
                "parser": parser,
            },
            # Tuple patterns
            {
                "node": cst.Match(
                    subject=cst.Name("x"),
                    cases=[
                        cst.MatchCase(  # empty tuple
                            pattern=cst.MatchTuple(
                                [],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # two element tuple
                            pattern=cst.MatchTuple(
                                [
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                        cst.Comma(),
                                    ),
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                    ),
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # single element tuple with trailing comma
                            pattern=cst.MatchTuple(
                                [
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                        cst.Comma(),
                                    )
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # two element tuple
                            pattern=cst.MatchTuple(
                                [
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                        cst.Comma(),
                                    ),
                                    cst.MatchStar(
                                        comma=cst.Comma(),
                                    ),
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                    ),
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                    ],
                ),
                "code": (
                    "match x:\n"
                    + "    case (): pass\n"
                    + "    case (None,None): pass\n"
                    + "    case (None,): pass\n"
                    + "    case (None,*_,None): pass\n"
                ),
                "parser": parser,
            },
            # Mapping patterns
            {
                "node": cst.Match(
                    subject=cst.Name("x"),
                    cases=[
                        cst.MatchCase(  # empty mapping
                            pattern=cst.MatchMapping(
                                [],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # two element mapping
                            pattern=cst.MatchMapping(
                                [
                                    cst.MatchMappingElement(
                                        key=cst.SimpleString('"a"'),
                                        pattern=cst.MatchSingleton(cst.Name("None")),
                                        comma=cst.Comma(),
                                    ),
                                    cst.MatchMappingElement(
                                        key=cst.SimpleString('"b"'),
                                        pattern=cst.MatchSingleton(cst.Name("None")),
                                    ),
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # single element mapping with trailing comma
                            pattern=cst.MatchMapping(
                                [
                                    cst.MatchMappingElement(
                                        key=cst.SimpleString('"a"'),
                                        pattern=cst.MatchSingleton(cst.Name("None")),
                                        comma=cst.Comma(),
                                    )
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # rest
                            pattern=cst.MatchMapping(
                                rest=cst.Name("rest"),
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                    ],
                ),
                "code": (
                    "match x:\n"
                    + "    case {}: pass\n"
                    + '    case {"a": None,"b": None}: pass\n'
                    + '    case {"a": None,}: pass\n'
                    + "    case {**rest}: pass\n"
                ),
                "parser": parser,
            },
            # Class patterns
            {
                "node": cst.Match(
                    subject=cst.Name("x"),
                    cases=[
                        cst.MatchCase(  # empty class
                            pattern=cst.MatchClass(
                                cls=cst.Attribute(cst.Name("a"), cst.Name("b")),
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # single pattern class
                            pattern=cst.MatchClass(
                                cls=cst.Attribute(cst.Name("a"), cst.Name("b")),
                                patterns=[
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None"))
                                    )
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # single pattern class with trailing comma
                            pattern=cst.MatchClass(
                                cls=cst.Attribute(cst.Name("a"), cst.Name("b")),
                                patterns=[
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                        comma=cst.Comma(),
                                    )
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # single keyword pattern class
                            pattern=cst.MatchClass(
                                cls=cst.Attribute(cst.Name("a"), cst.Name("b")),
                                kwds=[
                                    cst.MatchKeywordElement(
                                        key=cst.Name("foo"),
                                        pattern=cst.MatchSingleton(cst.Name("None")),
                                    )
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # single keyword pattern class with trailing comma
                            pattern=cst.MatchClass(
                                cls=cst.Attribute(cst.Name("a"), cst.Name("b")),
                                kwds=[
                                    cst.MatchKeywordElement(
                                        key=cst.Name("foo"),
                                        pattern=cst.MatchSingleton(cst.Name("None")),
                                        comma=cst.Comma(),
                                    )
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # now all at once
                            pattern=cst.MatchClass(
                                cls=cst.Attribute(cst.Name("a"), cst.Name("b")),
                                patterns=[
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                        cst.Comma(),
                                    ),
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                        cst.Comma(),
                                    ),
                                ],
                                kwds=[
                                    cst.MatchKeywordElement(
                                        key=cst.Name("foo"),
                                        pattern=cst.MatchSingleton(cst.Name("None")),
                                        comma=cst.Comma(),
                                    ),
                                    cst.MatchKeywordElement(
                                        key=cst.Name("bar"),
                                        pattern=cst.MatchSingleton(cst.Name("None")),
                                        comma=cst.Comma(),
                                    ),
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                    ],
                ),
                "code": (
                    "match x:\n"
                    + "    case a.b(): pass\n"
                    + "    case a.b(None): pass\n"
                    + "    case a.b(None,): pass\n"
                    + "    case a.b(foo=None): pass\n"
                    + "    case a.b(foo=None,): pass\n"
                    + "    case a.b(None,None,foo=None,bar=None,): pass\n"
                ),
                "parser": parser,
            },
            # as pattern
            {
                "node": cst.Match(
                    subject=cst.Name("x"),
                    cases=[
                        cst.MatchCase(
                            pattern=cst.MatchAs(),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(
                            pattern=cst.MatchAs(name=cst.Name("foo")),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(
                            pattern=cst.MatchAs(
                                pattern=cst.MatchSingleton(cst.Name("None")),
                                name=cst.Name("bar"),
                                whitespace_before_as=cst.SimpleWhitespace(" "),
                                whitespace_after_as=cst.SimpleWhitespace(" "),
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                    ],
                ),
                "code": "match x:\n"
                + "    case _: pass\n"
                + "    case foo: pass\n"
                + "    case None as bar: pass\n",
                "parser": parser,
            },
            # or pattern
            {
                "node": cst.Match(
                    subject=cst.Name("x"),
                    cases=[
                        cst.MatchCase(
                            pattern=cst.MatchOr(
                                [
                                    cst.MatchOrElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                        cst.BitOr(),
                                    ),
                                    cst.MatchOrElement(
                                        cst.MatchSingleton(cst.Name("False")),
                                        cst.BitOr(),
                                    ),
                                    cst.MatchOrElement(
                                        cst.MatchSingleton(cst.Name("True"))
                                    ),
                                ]
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        )
                    ],
                ),
                "code": "match x:\n    case None | False | True: pass\n",
                "parser": parser,
            },
            {  # exercise sentinels
                "node": cst.Match(
                    subject=cst.Name("x"),
                    cases=[
                        cst.MatchCase(
                            pattern=cst.MatchList(
                                [cst.MatchStar(), cst.MatchStar()],
                                lbracket=None,
                                rbracket=None,
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(
                            pattern=cst.MatchTuple(
                                [
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None"))
                                    )
                                ]
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(
                            pattern=cst.MatchAs(
                                pattern=cst.MatchTuple(
                                    [
                                        cst.MatchSequenceElement(
                                            cst.MatchSingleton(cst.Name("None"))
                                        )
                                    ]
                                ),
                                name=cst.Name("bar"),
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(
                            pattern=cst.MatchOr(
                                [
                                    cst.MatchOrElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                    ),
                                    cst.MatchOrElement(
                                        cst.MatchSingleton(cst.Name("False")),
                                    ),
                                    cst.MatchOrElement(
                                        cst.MatchSingleton(cst.Name("True"))
                                    ),
                                ]
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                    ],
                ),
                "code": "match x:\n"
                + "    case *_, *_: pass\n"
                + "    case (None,): pass\n"
                + "    case (None,) as bar: pass\n"
                + "    case None | False | True: pass\n",
                "parser": None,
            },
            # Match without whitespace between keyword and the expr
            {
                "node": cst.Match(
                    subject=cst.Name(
                        "x", lpar=[cst.LeftParen()], rpar=[cst.RightParen()]
                    ),
                    cases=[
                        cst.MatchCase(
                            pattern=cst.MatchSingleton(
                                cst.Name(
                                    "None",
                                    lpar=[cst.LeftParen()],
                                    rpar=[cst.RightParen()],
                                )
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_case=cst.SimpleWhitespace(
                                value="",
                            ),
                        ),
                    ],
                    whitespace_after_match=cst.SimpleWhitespace(
                        value="",
                    ),
                ),
                "code": "match(x):\n    case(None): pass\n",
                "parser": parser,
            },
        )
    )
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)