示例#1
0
class ReturnCreateTest(CSTNodeTest):
    @data_provider((
        {
            "node": cst.SimpleStatementLine([cst.Return()]),
            "code": "return\n",
            "expected_position": CodeRange.create((1, 0), (1, 6)),
        },
        {
            "node": cst.SimpleStatementLine([cst.Return(cst.Name("abc"))]),
            "code": "return abc\n",
            "expected_position": CodeRange.create((1, 0), (1, 10)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider(({
        "get_node":
        lambda: cst.Return(cst.Name("abc"),
                           whitespace_after_return=cst.SimpleWhitespace("")),
        "expected_re":
        "Must have at least one space after 'return'.",
    }, ))
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
示例#2
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)
示例#3
0
class SmallStatementTest(CSTNodeTest):
    @data_provider(
        (
            # pyre-fixme[6]: Incompatible parameter type
            {"node": cst.Pass(), "code": "pass"},
            {"node": cst.Pass(semicolon=cst.Semicolon()), "code": "pass;"},
            {
                "node": cst.Pass(
                    semicolon=cst.Semicolon(
                        whitespace_before=cst.SimpleWhitespace("  "),
                        whitespace_after=cst.SimpleWhitespace("    "),
                    )
                ),
                "code": "pass  ;    ",
                "expected_position": CodeRange.create((1, 0), (1, 4)),
            },
            {"node": cst.Continue(), "code": "continue"},
            {"node": cst.Continue(semicolon=cst.Semicolon()), "code": "continue;"},
            {
                "node": cst.Continue(
                    semicolon=cst.Semicolon(
                        whitespace_before=cst.SimpleWhitespace("  "),
                        whitespace_after=cst.SimpleWhitespace("    "),
                    )
                ),
                "code": "continue  ;    ",
                "expected_position": CodeRange.create((1, 0), (1, 8)),
            },
            {"node": cst.Break(), "code": "break"},
            {"node": cst.Break(semicolon=cst.Semicolon()), "code": "break;"},
            {
                "node": cst.Break(
                    semicolon=cst.Semicolon(
                        whitespace_before=cst.SimpleWhitespace("  "),
                        whitespace_after=cst.SimpleWhitespace("    "),
                    )
                ),
                "code": "break  ;    ",
                "expected_position": CodeRange.create((1, 0), (1, 5)),
            },
            {
                "node": cst.Expr(
                    cst.BinaryOperation(cst.Name("x"), cst.Add(), cst.Name("y"))
                ),
                "code": "x + y",
            },
            {
                "node": cst.Expr(
                    cst.BinaryOperation(cst.Name("x"), cst.Add(), cst.Name("y")),
                    semicolon=cst.Semicolon(),
                ),
                "code": "x + y;",
            },
            {
                "node": cst.Expr(
                    cst.BinaryOperation(cst.Name("x"), cst.Add(), cst.Name("y")),
                    semicolon=cst.Semicolon(
                        whitespace_before=cst.SimpleWhitespace("  "),
                        whitespace_after=cst.SimpleWhitespace("    "),
                    ),
                ),
                "code": "x + y  ;    ",
                "expected_position": CodeRange.create((1, 0), (1, 5)),
            },
        )
    )
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)
示例#4
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.create((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.create((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.create((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)
示例#5
0
class ModuleTest(CSTNodeTest):
    @data_provider((
        # simplest possible program
        (cst.Module((cst.SimpleStatementLine((cst.Pass(), )), )), "pass\n"),
        # test default_newline
        (
            cst.Module((cst.SimpleStatementLine((cst.Pass(), )), ),
                       default_newline="\r"),
            "pass\r",
        ),
        # test header/footer
        (
            cst.Module(
                (cst.SimpleStatementLine((cst.Pass(), )), ),
                header=(cst.EmptyLine(comment=cst.Comment("# header")), ),
                footer=(cst.EmptyLine(comment=cst.Comment("# footer")), ),
            ),
            "# header\npass\n# footer\n",
        ),
        # test has_trailing_newline
        (
            cst.Module(
                (cst.SimpleStatementLine((cst.Pass(), )), ),
                has_trailing_newline=False,
            ),
            "pass",
        ),
        # an empty file
        (cst.Module((), has_trailing_newline=False), ""),
        # a file with only comments
        (
            cst.Module(
                (),
                header=(cst.EmptyLine(
                    comment=cst.Comment("# nothing to see here")), ),
            ),
            "# nothing to see here\n",
        ),
        # TODO: test default_indent
    ))
    def test_code_and_bytes_properties(self, module: cst.Module,
                                       expected: str) -> None:
        self.assertEqual(module.code, expected)
        self.assertEqual(module.bytes, expected.encode("utf-8"))

    @data_provider((
        (cst.Module(()), cst.Newline(), "\n"),
        (cst.Module((), default_newline="\r\n"), cst.Newline(), "\r\n"),
        # has_trailing_newline has no effect on code_for_node
        (cst.Module((), has_trailing_newline=False), cst.Newline(), "\n"),
        # TODO: test default_indent
    ))
    def test_code_for_node(self, module: cst.Module, node: cst.CSTNode,
                           expected: str) -> None:
        self.assertEqual(module.code_for_node(node), expected)

    @data_provider({
        "empty_program": {
            "code": "",
            "expected": cst.Module([], has_trailing_newline=False),
        },
        "empty_program_with_newline": {
            "code": "\n",
            "expected": cst.Module([], has_trailing_newline=True),
        },
        "empty_program_with_comments": {
            "code":
            "# some comment\n",
            "expected":
            cst.Module(
                [],
                header=[cst.EmptyLine(comment=cst.Comment("# some comment"))]),
        },
        "simple_pass": {
            "code": "pass\n",
            "expected": cst.Module([cst.SimpleStatementLine([cst.Pass()])]),
        },
        "simple_pass_with_header_footer": {
            "code":
            "# header\npass # trailing\n# footer\n",
            "expected":
            cst.Module(
                [
                    cst.SimpleStatementLine(
                        [cst.Pass()],
                        trailing_whitespace=cst.TrailingWhitespace(
                            whitespace=cst.SimpleWhitespace(" "),
                            comment=cst.Comment("# trailing"),
                        ),
                    )
                ],
                header=[cst.EmptyLine(comment=cst.Comment("# header"))],
                footer=[cst.EmptyLine(comment=cst.Comment("# footer"))],
            ),
        },
    })
    def test_parser(self, *, code: str, expected: cst.Module) -> None:
        self.assertEqual(parse_module(code), expected)

    @data_provider({
        "empty": {
            "code": "",
            "expected": CodeRange.create((1, 0), (1, 0))
        },
        "empty_with_newline": {
            "code": "\n",
            "expected": CodeRange.create((1, 0), (2, 0)),
        },
        "empty_program_with_comments": {
            "code": "# 2345",
            "expected": CodeRange.create((1, 0), (2, 0)),
        },
        "simple_pass": {
            "code": "pass\n",
            "expected": CodeRange.create((1, 0), (2, 0)),
        },
        "simple_pass_with_header_footer": {
            "code": "# header\npass # trailing\n# footer\n",
            "expected": CodeRange.create((1, 0), (4, 0)),
        },
    })
    def test_module_position(self, *, code: str, expected: CodeRange) -> None:
        module = parse_module(code)
        provider = SyntacticPositionProvider()
        module.code_for_node(module, provider)

        self.assertEqual(provider._computed[module], expected)

        # TODO: remove this
        self.assertEqual(module._metadata[SyntacticPositionProvider], expected)

    def cmp_position(self, actual: CodeRange, start: Tuple[int, int],
                     end: Tuple[int, int]) -> None:
        self.assertEqual(actual, CodeRange.create(start, end))

    def test_function_position(self) -> None:
        module = parse_module("def foo():\n    pass")
        provider = SyntacticPositionProvider()
        module.code_for_node(module, provider)

        fn = cast(cst.FunctionDef, module.body[0])
        stmt = cast(cst.SimpleStatementLine, fn.body.body[0])
        pass_stmt = cast(cst.Pass, stmt.body[0])
        self.cmp_position(provider._computed[stmt], (2, 4), (2, 8))
        self.cmp_position(provider._computed[pass_stmt], (2, 4), (2, 8))

    def test_nested_indent_position(self) -> None:
        module = parse_module(
            "if True:\n    if False:\n        x = 1\nelse:\n    return")
        provider = SyntacticPositionProvider()
        module.code_for_node(module, provider)

        outer_if = cast(cst.If, module.body[0])
        inner_if = cast(cst.If, outer_if.body.body[0])
        assign = cast(cst.SimpleStatementLine, inner_if.body.body[0]).body[0]

        outer_else = cast(cst.Else, outer_if.orelse)
        return_stmt = cast(cst.SimpleStatementLine,
                           outer_else.body.body[0]).body[0]

        self.cmp_position(provider._computed[outer_if], (1, 0), (5, 10))
        self.cmp_position(provider._computed[inner_if], (2, 4), (3, 13))
        self.cmp_position(provider._computed[assign], (3, 8), (3, 13))
        self.cmp_position(provider._computed[outer_else], (4, 0), (5, 10))
        self.cmp_position(provider._computed[return_stmt], (5, 4), (5, 10))

    def test_multiline_string_position(self) -> None:
        module = parse_module('"abc"\\\n"def"')
        provider = SyntacticPositionProvider()
        module.code_for_node(module, provider)

        stmt = cast(cst.SimpleStatementLine, module.body[0])
        expr = cast(cst.Expr, stmt.body[0])
        string = expr.value

        self.cmp_position(provider._computed[stmt], (1, 0), (2, 5))
        self.cmp_position(provider._computed[expr], (1, 0), (2, 5))
        self.cmp_position(provider._computed[string], (1, 0), (2, 5))
示例#6
0
class YieldConstructionTest(CSTNodeTest):
    @data_provider(
        (
            # Simple yield
            (cst.Yield(), "yield"),
            # yield expression
            (cst.Yield(cst.Name("a")), "yield a"),
            # yield from expression
            (cst.Yield(cst.From(cst.Call(cst.Name("a")))), "yield from a()"),
            # Parenthesizing tests
            (
                cst.Yield(
                    lpar=(cst.LeftParen(),),
                    value=cst.Integer("5"),
                    rpar=(cst.RightParen(),),
                ),
                "(yield 5)",
            ),
            # Whitespace oddities tests
            (
                cst.Yield(
                    cst.Name("a", lpar=(cst.LeftParen(),), rpar=(cst.RightParen(),)),
                    whitespace_after_yield=cst.SimpleWhitespace(""),
                ),
                "yield(a)",
                CodeRange.create((1, 0), (1, 8)),
            ),
            (
                cst.Yield(
                    cst.From(
                        cst.Call(
                            cst.Name("a"),
                            lpar=(cst.LeftParen(),),
                            rpar=(cst.RightParen(),),
                        ),
                        whitespace_after_from=cst.SimpleWhitespace(""),
                    )
                ),
                "yield from(a())",
            ),
            # Whitespace rendering/parsing tests
            (
                cst.Yield(
                    lpar=(cst.LeftParen(whitespace_after=cst.SimpleWhitespace(" ")),),
                    value=cst.Integer("5"),
                    whitespace_after_yield=cst.SimpleWhitespace("  "),
                    rpar=(cst.RightParen(whitespace_before=cst.SimpleWhitespace(" ")),),
                ),
                "( yield  5 )",
            ),
            (
                cst.Yield(
                    lpar=(cst.LeftParen(whitespace_after=cst.SimpleWhitespace(" ")),),
                    value=cst.From(
                        cst.Call(cst.Name("bla")),
                        whitespace_after_from=cst.SimpleWhitespace("  "),
                    ),
                    whitespace_after_yield=cst.SimpleWhitespace("  "),
                    rpar=(cst.RightParen(whitespace_before=cst.SimpleWhitespace(" ")),),
                ),
                "( yield  from  bla() )",
                CodeRange.create((1, 2), (1, 20)),
            ),
            # From expression position tests
            (
                cst.From(
                    cst.Integer("5"), whitespace_after_from=cst.SimpleWhitespace(" ")
                ),
                "from 5",
                CodeRange.create((1, 0), (1, 6)),
            ),
        )
    )
    def test_valid(
        self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
    ) -> None:
        self.validate_node(node, code, expected_position=position)

    @data_provider(
        (
            # Paren validation
            (
                lambda: cst.Yield(lpar=(cst.LeftParen(),)),
                "left paren without right paren",
            ),
            (
                lambda: cst.Yield(rpar=(cst.RightParen(),)),
                "right paren without left paren",
            ),
            # Make sure we have adequate space after yield
            (
                lambda: cst.Yield(
                    cst.Name("a"), whitespace_after_yield=cst.SimpleWhitespace("")
                ),
                "Must have at least one space after 'yield' keyword",
            ),
            (
                lambda: cst.Yield(
                    cst.From(cst.Call(cst.Name("a"))),
                    whitespace_after_yield=cst.SimpleWhitespace(""),
                ),
                "Must have at least one space after 'yield' keyword",
            ),
            # MAke sure we have adequate space after from
            (
                lambda: cst.Yield(
                    cst.From(
                        cst.Call(cst.Name("a")),
                        whitespace_after_from=cst.SimpleWhitespace(""),
                    )
                ),
                "Must have at least one space after 'from' keyword",
            ),
        )
    )
    def test_invalid(
        self, get_node: Callable[[], cst.CSTNode], expected_re: str
    ) -> None:
        self.assert_invalid(get_node, expected_re)
示例#7
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)
示例#8
0
class RaiseConstructionTest(CSTNodeTest):
    @data_provider((
        # Simple raise
        # pyre-fixme[6]: Incompatible parameter type
        {
            "node": cst.Raise(),
            "code": "raise"
        },
        # Raise exception
        {
            "node": cst.Raise(cst.Call(cst.Name("Exception"))),
            "code": "raise Exception()",
            "expected_position": CodeRange.create((1, 0), (1, 17)),
        },
        # Raise exception from cause
        {
            "node":
            cst.Raise(cst.Call(cst.Name("Exception")),
                      cst.From(cst.Name("cause"))),
            "code":
            "raise Exception() from cause",
        },
        # Whitespace oddities test
        {
            "node":
            cst.Raise(
                cst.Call(
                    cst.Name("Exception"),
                    lpar=(cst.LeftParen(), ),
                    rpar=(cst.RightParen(), ),
                ),
                cst.From(
                    cst.Name("cause",
                             lpar=(cst.LeftParen(), ),
                             rpar=(cst.RightParen(), )),
                    whitespace_before_from=cst.SimpleWhitespace(""),
                    whitespace_after_from=cst.SimpleWhitespace(""),
                ),
                whitespace_after_raise=cst.SimpleWhitespace(""),
            ),
            "code":
            "raise(Exception())from(cause)",
            "expected_position":
            CodeRange.create((1, 0), (1, 29)),
        },
        {
            "node":
            cst.Raise(
                cst.Call(cst.Name("Exception")),
                cst.From(
                    cst.Name("cause"),
                    whitespace_before_from=cst.SimpleWhitespace(""),
                ),
            ),
            "code":
            "raise Exception()from cause",
            "expected_position":
            CodeRange.create((1, 0), (1, 27)),
        },
        # Whitespace rendering test
        {
            "node":
            cst.Raise(
                exc=cst.Call(cst.Name("Exception")),
                cause=cst.From(
                    cst.Name("cause"),
                    whitespace_before_from=cst.SimpleWhitespace("  "),
                    whitespace_after_from=cst.SimpleWhitespace("  "),
                ),
                whitespace_after_raise=cst.SimpleWhitespace("  "),
            ),
            "code":
            "raise  Exception()  from  cause",
            "expected_position":
            CodeRange.create((1, 0), (1, 31)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider((
        # Validate construction
        {
            "get_node": lambda: cst.Raise(cause=cst.From(cst.Name("cause"))),
            "expected_re":
            "Must have an 'exc' when specifying 'clause'. on Raise",
        },
        # Validate whitespace handling
        {
            "get_node":
            lambda: cst.Raise(
                cst.Call(cst.Name("Exception")),
                whitespace_after_raise=cst.SimpleWhitespace(""),
            ),
            "expected_re":
            "Must have at least one space after 'raise'",
        },
        {
            "get_node":
            lambda: cst.Raise(
                cst.Name("exc"),
                cst.From(
                    cst.Name("cause"),
                    whitespace_before_from=cst.SimpleWhitespace(""),
                ),
            ),
            "expected_re":
            "Must have at least one space before 'from'",
        },
        {
            "get_node":
            lambda: cst.Raise(
                cst.Name("exc"),
                cst.From(
                    cst.Name("cause"),
                    whitespace_after_from=cst.SimpleWhitespace(""),
                ),
            ),
            "expected_re":
            "Must have at least one space after 'from'",
        },
    ))
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
示例#9
0
class TryTest(CSTNodeTest):
    @data_provider((
        # Simple try/except block
        # pyre-fixme[6]: Incompatible parameter type
        {
            "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.create((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.create((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.create((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.create((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.create((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.create((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.create((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.create((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.create((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,
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider((
        # pyre-fixme[6]: Incompatible parameter type
        {
            "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)
示例#10
0
class AwaitTest(CSTNodeTest):
    @data_provider((
        # Some simple calls
        # pyre-fixme[6]: Incompatible parameter type
        {
            "node": cst.Await(cst.Name("test")),
            "code": "await test",
            "parser": parse_expression,
            "expected_position": None,
        },
        {
            "node": cst.Await(cst.Call(cst.Name("test"))),
            "code": "await test()",
            "parser": parse_expression,
            "expected_position": None,
        },
        # Whitespace
        {
            "node":
            cst.Await(
                cst.Name("test"),
                whitespace_after_await=cst.SimpleWhitespace("  "),
                lpar=(cst.LeftParen(
                    whitespace_after=cst.SimpleWhitespace(" ")), ),
                rpar=(cst.RightParen(
                    whitespace_before=cst.SimpleWhitespace(" ")), ),
            ),
            "code":
            "( await  test )",
            "parser":
            parse_expression,
            "expected_position":
            CodeRange.create((1, 2), (1, 13)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        # We don't have sentinel nodes for atoms, so we know that 100% of atoms
        # can be parsed identically to their creation.
        self.validate_node(**kwargs)

    @data_provider((
        # Expression wrapping parenthesis rules
        {
            "get_node":
            (lambda: cst.Await(cst.Name("foo"), lpar=(cst.LeftParen(), ))),
            "expected_re":
            "left paren without right paren",
        },
        {
            "get_node":
            (lambda: cst.Await(cst.Name("foo"), rpar=(cst.RightParen(), ))),
            "expected_re":
            "right paren without left paren",
        },
        {
            "get_node":
            (lambda: cst.Await(cst.Name("foo"),
                               whitespace_after_await=cst.SimpleWhitespace(""))
             ),
            "expected_re":
            "at least one space after await",
        },
    ))
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
示例#11
0
class AugAssignTest(CSTNodeTest):
    @data_provider((
        # Simple assignment constructor case.
        # pyre-fixme[6]: Incompatible parameter type
        {
            "node":
            cst.AugAssign(cst.Name("foo"), cst.AddAssign(), cst.Integer("5")),
            "code":
            "foo += 5",
            "parser":
            None,
            "expected_position":
            CodeRange.create((1, 0), (1, 8)),
        },
        {
            "node":
            cst.AugAssign(cst.Name("bar"), cst.MultiplyAssign(),
                          cst.Name("foo")),
            "code":
            "bar *= foo",
            "parser":
            None,
            "expected_position":
            None,
        },
        # Whitespace constructor test
        {
            "node":
            cst.AugAssign(
                target=cst.Name("foo"),
                operator=cst.LeftShiftAssign(
                    whitespace_before=cst.SimpleWhitespace("  "),
                    whitespace_after=cst.SimpleWhitespace("  "),
                ),
                value=cst.Integer("5"),
            ),
            "code":
            "foo  <<=  5",
            "parser":
            None,
            "expected_position":
            CodeRange.create((1, 0), (1, 11)),
        },
        # Simple assignment parser case.
        {
            "node":
            cst.SimpleStatementLine((cst.AugAssign(cst.Name("foo"),
                                                   cst.AddAssign(),
                                                   cst.Integer("5")), )),
            "code":
            "foo += 5\n",
            "parser":
            parse_statement,
            "expected_position":
            None,
        },
        {
            "node":
            cst.SimpleStatementLine((cst.AugAssign(cst.Name("bar"),
                                                   cst.MultiplyAssign(),
                                                   cst.Name("foo")), )),
            "code":
            "bar *= foo\n",
            "parser":
            parse_statement,
            "expected_position":
            None,
        },
        # Whitespace parser test
        {
            "node":
            cst.SimpleStatementLine((cst.AugAssign(
                target=cst.Name("foo"),
                operator=cst.LeftShiftAssign(
                    whitespace_before=cst.SimpleWhitespace("  "),
                    whitespace_after=cst.SimpleWhitespace("  "),
                ),
                value=cst.Integer("5"),
            ), )),
            "code":
            "foo  <<=  5\n",
            "parser":
            parse_statement,
            "expected_position":
            None,
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)
示例#12
0
class AssignTest(CSTNodeTest):
    @data_provider((
        # Simple assignment creation case.
        # pyre-fixme[6]: Incompatible parameter type
        {
            "node":
            cst.Assign((cst.AssignTarget(cst.Name("foo")), ),
                       cst.Integer("5")),
            "code":
            "foo = 5",
            "parser":
            None,
            "expected_position":
            CodeRange.create((1, 0), (1, 7)),
        },
        # Multiple targets creation
        {
            "node":
            cst.Assign(
                (
                    cst.AssignTarget(cst.Name("foo")),
                    cst.AssignTarget(cst.Name("bar")),
                ),
                cst.Integer("5"),
            ),
            "code":
            "foo = bar = 5",
            "parser":
            None,
            "expected_position":
            CodeRange.create((1, 0), (1, 13)),
        },
        # Whitespace test for creating nodes
        {
            "node":
            cst.Assign(
                (cst.AssignTarget(
                    cst.Name("foo"),
                    whitespace_before_equal=cst.SimpleWhitespace(""),
                    whitespace_after_equal=cst.SimpleWhitespace(""),
                ), ),
                cst.Integer("5"),
            ),
            "code":
            "foo=5",
            "parser":
            None,
            "expected_position":
            CodeRange.create((1, 0), (1, 5)),
        },
        # Simple assignment parser case.
        {
            "node":
            cst.SimpleStatementLine((cst.Assign(
                (cst.AssignTarget(cst.Name("foo")), ), cst.Integer("5")), )),
            "code":
            "foo = 5\n",
            "parser":
            parse_statement,
            "expected_position":
            None,
        },
        # Multiple targets parser
        {
            "node":
            cst.SimpleStatementLine((cst.Assign(
                (
                    cst.AssignTarget(cst.Name("foo")),
                    cst.AssignTarget(cst.Name("bar")),
                ),
                cst.Integer("5"),
            ), )),
            "code":
            "foo = bar = 5\n",
            "parser":
            parse_statement,
            "expected_position":
            None,
        },
        # Whitespace test parser
        {
            "node":
            cst.SimpleStatementLine((cst.Assign(
                (cst.AssignTarget(
                    cst.Name("foo"),
                    whitespace_before_equal=cst.SimpleWhitespace(""),
                    whitespace_after_equal=cst.SimpleWhitespace(""),
                ), ),
                cst.Integer("5"),
            ), )),
            "code":
            "foo=5\n",
            "parser":
            parse_statement,
            "expected_position":
            None,
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider(({
        "get_node": (lambda: cst.Assign(targets=(), value=cst.Integer("5"))),
        "expected_re":
        "at least one AssignTarget",
    }, ))
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
示例#13
0
class AnnAssignTest(CSTNodeTest):
    @data_provider((
        # Simple assignment creation case.
        # pyre-fixme[6]: Incompatible parameter type
        {
            "node":
            cst.AnnAssign(cst.Name("foo"), cst.Annotation(cst.Name("str")),
                          cst.Integer("5")),
            "code":
            "foo: str = 5",
            "parser":
            None,
            "expected_position":
            CodeRange.create((1, 0), (1, 12)),
        },
        # Annotation creation without assignment
        {
            "node": cst.AnnAssign(cst.Name("foo"),
                                  cst.Annotation(cst.Name("str"))),
            "code": "foo: str",
            "parser": None,
            "expected_position": CodeRange.create((1, 0), (1, 8)),
        },
        # Complex annotation creation
        {
            "node":
            cst.AnnAssign(
                cst.Name("foo"),
                cst.Annotation(
                    cst.Subscript(cst.Name("Optional"),
                                  cst.Index(cst.Name("str")))),
                cst.Integer("5"),
            ),
            "code":
            "foo: Optional[str] = 5",
            "parser":
            None,
            "expected_position":
            CodeRange.create((1, 0), (1, 22)),
        },
        # Simple assignment parser case.
        {
            "node":
            cst.SimpleStatementLine((cst.AnnAssign(
                target=cst.Name("foo"),
                annotation=cst.Annotation(
                    annotation=cst.Name("str"),
                    whitespace_before_indicator=cst.SimpleWhitespace(""),
                ),
                equal=cst.AssignEqual(),
                value=cst.Integer("5"),
            ), )),
            "code":
            "foo: str = 5\n",
            "parser":
            parse_statement,
            "expected_position":
            None,
        },
        # Annotation without assignment
        {
            "node":
            cst.SimpleStatementLine((cst.AnnAssign(
                target=cst.Name("foo"),
                annotation=cst.Annotation(
                    annotation=cst.Name("str"),
                    whitespace_before_indicator=cst.SimpleWhitespace(""),
                ),
                value=None,
            ), )),
            "code":
            "foo: str\n",
            "parser":
            parse_statement,
            "expected_position":
            None,
        },
        # Complex annotation
        {
            "node":
            cst.SimpleStatementLine((cst.AnnAssign(
                target=cst.Name("foo"),
                annotation=cst.Annotation(
                    annotation=cst.Subscript(cst.Name("Optional"),
                                             cst.Index(cst.Name("str"))),
                    whitespace_before_indicator=cst.SimpleWhitespace(""),
                ),
                equal=cst.AssignEqual(),
                value=cst.Integer("5"),
            ), )),
            "code":
            "foo: Optional[str] = 5\n",
            "parser":
            parse_statement,
            "expected_position":
            None,
        },
        # Whitespace test
        {
            "node":
            cst.AnnAssign(
                target=cst.Name("foo"),
                annotation=cst.Annotation(
                    annotation=cst.Subscript(cst.Name("Optional"),
                                             cst.Index(cst.Name("str"))),
                    whitespace_before_indicator=cst.SimpleWhitespace(" "),
                    whitespace_after_indicator=cst.SimpleWhitespace("  "),
                ),
                equal=cst.AssignEqual(
                    whitespace_before=cst.SimpleWhitespace("  "),
                    whitespace_after=cst.SimpleWhitespace("  "),
                ),
                value=cst.Integer("5"),
            ),
            "code":
            "foo :  Optional[str]  =  5",
            "parser":
            None,
            "expected_position":
            CodeRange.create((1, 0), (1, 26)),
        },
        {
            "node":
            cst.SimpleStatementLine((cst.AnnAssign(
                target=cst.Name("foo"),
                annotation=cst.Annotation(
                    annotation=cst.Subscript(cst.Name("Optional"),
                                             cst.Index(cst.Name("str"))),
                    whitespace_before_indicator=cst.SimpleWhitespace(" "),
                    whitespace_after_indicator=cst.SimpleWhitespace("  "),
                ),
                equal=cst.AssignEqual(
                    whitespace_before=cst.SimpleWhitespace("  "),
                    whitespace_after=cst.SimpleWhitespace("  "),
                ),
                value=cst.Integer("5"),
            ), )),
            "code":
            "foo :  Optional[str]  =  5\n",
            "parser":
            parse_statement,
            "expected_position":
            None,
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider(({
        "get_node": (lambda: cst.AnnAssign(
            target=cst.Name("foo"),
            annotation=cst.Annotation(cst.Name("str")),
            equal=cst.AssignEqual(),
            value=None,
        )),
        "expected_re":
        "Must have a value when specifying an AssignEqual.",
    }, ))
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
示例#14
0
class UnaryOperationTest(CSTNodeTest):
    @data_provider((
        # Simple unary operations
        (cst.UnaryOperation(cst.Plus(), cst.Name("foo")), "+foo"),
        (cst.UnaryOperation(cst.Minus(), cst.Name("foo")), "-foo"),
        (cst.UnaryOperation(cst.BitInvert(), cst.Name("foo")), "~foo"),
        (cst.UnaryOperation(cst.Not(), cst.Name("foo")), "not foo"),
        # Parenthesized unary operation
        (
            cst.UnaryOperation(
                lpar=(cst.LeftParen(), ),
                operator=cst.Not(),
                expression=cst.Name("foo"),
                rpar=(cst.RightParen(), ),
            ),
            "(not foo)",
            CodeRange.create((1, 1), (1, 8)),
        ),
        (
            cst.UnaryOperation(
                operator=cst.Not(whitespace_after=cst.SimpleWhitespace("")),
                expression=cst.Name("foo",
                                    lpar=(cst.LeftParen(), ),
                                    rpar=(cst.RightParen(), )),
            ),
            "not(foo)",
            CodeRange.create((1, 0), (1, 8)),
        ),
        # Make sure that spacing works
        (
            cst.UnaryOperation(
                lpar=(cst.LeftParen(
                    whitespace_after=cst.SimpleWhitespace(" ")), ),
                operator=cst.Not(whitespace_after=cst.SimpleWhitespace("  ")),
                expression=cst.Name("foo"),
                rpar=(cst.RightParen(
                    whitespace_before=cst.SimpleWhitespace(" ")), ),
            ),
            "( not  foo )",
            CodeRange.create((1, 2), (1, 10)),
        ),
    ))
    def test_valid(self,
                   node: cst.CSTNode,
                   code: str,
                   position: Optional[CodeRange] = None) -> None:
        self.validate_node(node,
                           code,
                           parse_expression,
                           expected_position=position)

    @data_provider((
        (
            lambda: cst.UnaryOperation(
                cst.Plus(), cst.Name("foo"), lpar=(cst.LeftParen(), )),
            "left paren without right paren",
        ),
        (
            lambda: cst.UnaryOperation(
                cst.Plus(), cst.Name("foo"), rpar=(cst.RightParen(), )),
            "right paren without left paren",
        ),
        (
            lambda: cst.UnaryOperation(
                operator=cst.Not(whitespace_after=cst.SimpleWhitespace("")),
                expression=cst.Name("foo"),
            ),
            "at least one space after not operator",
        ),
    ))
    def test_invalid(self, get_node: Callable[[], cst.CSTNode],
                     expected_re: str) -> None:
        self.assert_invalid(get_node, expected_re)
示例#15
0
class DelTest(CSTNodeTest):
    @data_provider((
        {
            "node": cst.SimpleStatementLine([cst.Del(cst.Name("abc"))]),
            "code": "del abc\n",
            "parser": parse_statement,
            "expected_position": CodeRange.create((1, 0), (1, 7)),
        },
        {
            "node":
            cst.SimpleStatementLine([
                cst.Del(
                    cst.Name("abc"),
                    whitespace_after_del=cst.SimpleWhitespace("   "),
                )
            ]),
            "code":
            "del   abc\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange.create((1, 0), (1, 9)),
        },
        {
            "node":
            cst.SimpleStatementLine([
                cst.Del(
                    cst.Name("abc",
                             lpar=[cst.LeftParen()],
                             rpar=[cst.RightParen()]),
                    whitespace_after_del=cst.SimpleWhitespace(""),
                )
            ]),
            "code":
            "del(abc)\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange.create((1, 0), (1, 8)),
        },
        {
            "node":
            cst.SimpleStatementLine(
                [cst.Del(cst.Name("abc"), semicolon=cst.Semicolon())]),
            "code":
            "del abc;\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange.create((1, 0), (1, 7)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider(({
        "get_node":
        lambda: cst.Del(cst.Name("abc"),
                        whitespace_after_del=cst.SimpleWhitespace("")),
        "expected_re":
        "Must have at least one space after 'del'.",
    }, ))
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
示例#16
0
class ImportCreateTest(CSTNodeTest):
    @data_provider((
        # Simple import statement
        # pyre-fixme[6]: Incompatible parameter type
        {
            "node": cst.Import(names=(cst.ImportAlias(cst.Name("foo")), )),
            "code": "import foo",
        },
        {
            "node":
            cst.Import(names=(cst.ImportAlias(
                cst.Attribute(cst.Name("foo"), cst.Name("bar"))), )),
            "code":
            "import foo.bar",
        },
        {
            "node":
            cst.Import(names=(cst.ImportAlias(
                cst.Attribute(cst.Name("foo"), cst.Name("bar"))), )),
            "code":
            "import foo.bar",
        },
        # Comma-separated list of imports
        {
            "node":
            cst.Import(names=(
                cst.ImportAlias(cst.Attribute(cst.Name("foo"), cst.Name(
                    "bar"))),
                cst.ImportAlias(cst.Attribute(cst.Name("foo"), cst.Name(
                    "baz"))),
            )),
            "code":
            "import foo.bar, foo.baz",
            "expected_position":
            CodeRange.create((1, 0), (1, 23)),
        },
        # Import with an alias
        {
            "node":
            cst.Import(names=(cst.ImportAlias(
                cst.Attribute(cst.Name("foo"), cst.Name("bar")),
                asname=cst.AsName(cst.Name("baz")),
            ), )),
            "code":
            "import foo.bar as baz",
        },
        # Import with an alias, comma separated
        {
            "node":
            cst.Import(names=(
                cst.ImportAlias(
                    cst.Attribute(cst.Name("foo"), cst.Name("bar")),
                    asname=cst.AsName(cst.Name("baz")),
                ),
                cst.ImportAlias(
                    cst.Attribute(cst.Name("foo"), cst.Name("baz")),
                    asname=cst.AsName(cst.Name("bar")),
                ),
            )),
            "code":
            "import foo.bar as baz, foo.baz as bar",
        },
        # Combine for fun and profit
        {
            "node":
            cst.Import(names=(
                cst.ImportAlias(
                    cst.Attribute(cst.Name("foo"), cst.Name("bar")),
                    asname=cst.AsName(cst.Name("baz")),
                ),
                cst.ImportAlias(
                    cst.Attribute(cst.Name("insta"), cst.Name("gram"))),
                cst.ImportAlias(cst.Attribute(cst.Name("foo"), cst.Name(
                    "baz"))),
                cst.ImportAlias(cst.Name("unittest"),
                                asname=cst.AsName(cst.Name("ut"))),
            )),
            "code":
            "import foo.bar as baz, insta.gram, foo.baz, unittest as ut",
        },
        # Verify whitespace works everywhere.
        {
            "node":
            cst.Import(
                names=(
                    cst.ImportAlias(
                        cst.Attribute(
                            cst.Name("foo"),
                            cst.Name("bar"),
                            dot=cst.Dot(
                                whitespace_before=cst.SimpleWhitespace(" "),
                                whitespace_after=cst.SimpleWhitespace(" "),
                            ),
                        ),
                        asname=cst.AsName(
                            cst.Name("baz"),
                            whitespace_before_as=cst.SimpleWhitespace("  "),
                            whitespace_after_as=cst.SimpleWhitespace("  "),
                        ),
                        comma=cst.Comma(
                            whitespace_before=cst.SimpleWhitespace(" "),
                            whitespace_after=cst.SimpleWhitespace("  "),
                        ),
                    ),
                    cst.ImportAlias(
                        cst.Name("unittest"),
                        asname=cst.AsName(
                            cst.Name("ut"),
                            whitespace_before_as=cst.SimpleWhitespace("  "),
                            whitespace_after_as=cst.SimpleWhitespace("  "),
                        ),
                    ),
                ),
                whitespace_after_import=cst.SimpleWhitespace("  "),
            ),
            "code":
            "import  foo . bar  as  baz ,  unittest  as  ut",
            "expected_position":
            CodeRange.create((1, 0), (1, 46)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider((
        {
            "get_node": lambda: cst.Import(names=()),
            "expected_re": "at least one ImportAlias",
        },
        {
            "get_node":
            lambda: cst.Import(names=(cst.ImportAlias(cst.Name("")), )),
            "expected_re": "empty name identifier",
        },
        {
            "get_node":
            lambda: cst.Import(names=(cst.ImportAlias(
                cst.Attribute(cst.Name(""), cst.Name("bla"))), )),
            "expected_re":
            "empty name identifier",
        },
        {
            "get_node":
            lambda: cst.Import(names=(cst.ImportAlias(
                cst.Attribute(cst.Name("bla"), cst.Name(""))), )),
            "expected_re":
            "empty name identifier",
        },
        {
            "get_node":
            lambda: cst.Import(names=(cst.ImportAlias(
                cst.Attribute(cst.Name("foo"), cst.Name("bar")),
                comma=cst.Comma(),
            ), )),
            "expected_re":
            "trailing comma",
        },
        {
            "get_node":
            lambda: cst.Import(
                names=(cst.ImportAlias(
                    cst.Attribute(cst.Name("foo"), cst.Name("bar"))), ),
                whitespace_after_import=cst.SimpleWhitespace(""),
            ),
            "expected_re":
            "at least one space",
        },
    ))
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
示例#17
0
class ImportFromCreateTest(CSTNodeTest):
    @data_provider((
        # Simple from import statement
        # pyre-fixme[6]: Incompatible parameter type
        {
            "node":
            cst.ImportFrom(module=cst.Name("foo"),
                           names=(cst.ImportAlias(cst.Name("bar")), )),
            "code":
            "from foo import bar",
        },
        # From import statement with alias
        {
            "node":
            cst.ImportFrom(
                module=cst.Name("foo"),
                names=(cst.ImportAlias(cst.Name("bar"),
                                       asname=cst.AsName(cst.Name("baz"))), ),
            ),
            "code":
            "from foo import bar as baz",
        },
        # Multiple imports
        {
            "node":
            cst.ImportFrom(
                module=cst.Name("foo"),
                names=(
                    cst.ImportAlias(cst.Name("bar")),
                    cst.ImportAlias(cst.Name("baz")),
                ),
            ),
            "code":
            "from foo import bar, baz",
        },
        # Trailing comma
        {
            "node":
            cst.ImportFrom(
                module=cst.Name("foo"),
                names=(
                    cst.ImportAlias(cst.Name("bar"), comma=cst.Comma()),
                    cst.ImportAlias(cst.Name("baz"), comma=cst.Comma()),
                ),
            ),
            "code":
            "from foo import bar,baz,",
            "expected_position":
            CodeRange.create((1, 0), (1, 23)),
        },
        # Star import statement
        {
            "node": cst.ImportFrom(module=cst.Name("foo"),
                                   names=cst.ImportStar()),
            "code": "from foo import *",
            "expected_position": CodeRange.create((1, 0), (1, 17)),
        },
        # Simple relative import statement
        {
            "node":
            cst.ImportFrom(
                relative=(cst.Dot(), ),
                module=cst.Name("foo"),
                names=(cst.ImportAlias(cst.Name("bar")), ),
            ),
            "code":
            "from .foo import bar",
        },
        {
            "node":
            cst.ImportFrom(
                relative=(cst.Dot(), cst.Dot()),
                module=cst.Name("foo"),
                names=(cst.ImportAlias(cst.Name("bar")), ),
            ),
            "code":
            "from ..foo import bar",
        },
        # Relative only import
        {
            "node":
            cst.ImportFrom(
                relative=(cst.Dot(), cst.Dot()),
                module=None,
                names=(cst.ImportAlias(cst.Name("bar")), ),
            ),
            "code":
            "from .. import bar",
        },
        # Parenthesis
        {
            "node":
            cst.ImportFrom(
                module=cst.Name("foo"),
                lpar=cst.LeftParen(),
                names=(cst.ImportAlias(cst.Name("bar"),
                                       asname=cst.AsName(cst.Name("baz"))), ),
                rpar=cst.RightParen(),
            ),
            "code":
            "from foo import (bar as baz)",
            "expected_position":
            CodeRange.create((1, 0), (1, 28)),
        },
        # Verify whitespace works everywhere.
        {
            "node":
            cst.ImportFrom(
                relative=(
                    cst.Dot(
                        whitespace_before=cst.SimpleWhitespace(" "),
                        whitespace_after=cst.SimpleWhitespace(" "),
                    ),
                    cst.Dot(
                        whitespace_before=cst.SimpleWhitespace(" "),
                        whitespace_after=cst.SimpleWhitespace(" "),
                    ),
                ),
                module=cst.Name("foo"),
                lpar=cst.LeftParen(whitespace_after=cst.SimpleWhitespace(" ")),
                names=(
                    cst.ImportAlias(
                        cst.Name("bar"),
                        asname=cst.AsName(
                            cst.Name("baz"),
                            whitespace_before_as=cst.SimpleWhitespace("  "),
                            whitespace_after_as=cst.SimpleWhitespace("  "),
                        ),
                        comma=cst.Comma(
                            whitespace_before=cst.SimpleWhitespace(" "),
                            whitespace_after=cst.SimpleWhitespace("  "),
                        ),
                    ),
                    cst.ImportAlias(
                        cst.Name("unittest"),
                        asname=cst.AsName(
                            cst.Name("ut"),
                            whitespace_before_as=cst.SimpleWhitespace("  "),
                            whitespace_after_as=cst.SimpleWhitespace("  "),
                        ),
                    ),
                ),
                rpar=cst.RightParen(
                    whitespace_before=cst.SimpleWhitespace(" ")),
                whitespace_after_from=cst.SimpleWhitespace("  "),
                whitespace_before_import=cst.SimpleWhitespace("  "),
                whitespace_after_import=cst.SimpleWhitespace("  "),
            ),
            "code":
            "from   .  . foo  import  ( bar  as  baz ,  unittest  as  ut )",
            "expected_position":
            CodeRange.create((1, 0), (1, 61)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider((
        {
            "get_node":
            lambda: cst.ImportFrom(module=None,
                                   names=(cst.ImportAlias(cst.Name("bar")), )),
            "expected_re":
            "Must have a module specified",
        },
        {
            "get_node":
            lambda: cst.ImportFrom(module=cst.Name("foo"), names=()),
            "expected_re": "at least one ImportAlias",
        },
        {
            "get_node":
            lambda: cst.ImportFrom(
                module=cst.Name("foo"),
                names=(cst.ImportAlias(cst.Name("bar")), ),
                lpar=cst.LeftParen(),
            ),
            "expected_re":
            "left paren without right paren",
        },
        {
            "get_node":
            lambda: cst.ImportFrom(
                module=cst.Name("foo"),
                names=(cst.ImportAlias(cst.Name("bar")), ),
                rpar=cst.RightParen(),
            ),
            "expected_re":
            "right paren without left paren",
        },
        {
            "get_node":
            lambda: cst.ImportFrom(module=cst.Name("foo"),
                                   names=cst.ImportStar(),
                                   lpar=cst.LeftParen()),
            "expected_re":
            "cannot have parens",
        },
        {
            "get_node":
            lambda: cst.ImportFrom(
                module=cst.Name("foo"),
                names=cst.ImportStar(),
                rpar=cst.RightParen(),
            ),
            "expected_re":
            "cannot have parens",
        },
        {
            "get_node":
            lambda: cst.ImportFrom(
                module=cst.Name("foo"),
                names=(cst.ImportAlias(cst.Name("bar")), ),
                whitespace_after_from=cst.SimpleWhitespace(""),
            ),
            "expected_re":
            "one space after from",
        },
        {
            "get_node":
            lambda: cst.ImportFrom(
                module=cst.Name("foo"),
                names=(cst.ImportAlias(cst.Name("bar")), ),
                whitespace_before_import=cst.SimpleWhitespace(""),
            ),
            "expected_re":
            "one space before import",
        },
        {
            "get_node":
            lambda: cst.ImportFrom(
                module=cst.Name("foo"),
                names=(cst.ImportAlias(cst.Name("bar")), ),
                whitespace_after_import=cst.SimpleWhitespace(""),
            ),
            "expected_re":
            "one space after import",
        },
    ))
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
示例#18
0
class DictTest(CSTNodeTest):
    @data_provider([
        # zero-element dict
        {
            "node": cst.Dict([]),
            "code": "{}",
            "parser": parse_expression,
            "expected_position": CodeRange.create((1, 0), (1, 2)),
        },
        # one-element dict, sentinel comma value
        {
            "node": cst.Dict([cst.DictElement(cst.Name("k"), cst.Name("v"))]),
            "code": "{k: v}",
            "parser": parse_expression,
            "expected_position": CodeRange.create((1, 0), (1, 6)),
        },
        {
            "node": cst.Dict([cst.StarredDictElement(cst.Name("expanded"))]),
            "code": "{**expanded}",
            "parser": parse_expression,
            "expected_position": CodeRange.create((1, 0), (1, 12)),
        },
        # two-element dict, sentinel comma value
        {
            "node":
            cst.Dict([
                cst.DictElement(cst.Name("k1"), cst.Name("v1")),
                cst.DictElement(cst.Name("k2"), cst.Name("v2")),
            ]),
            "code":
            "{k1: v1, k2: v2}",
            "parser":
            None,
            "expected_position":
            CodeRange.create((1, 0), (1, 16)),
        },
        # custom whitespace between brackets
        {
            "node":
            cst.Dict(
                [cst.DictElement(cst.Name("k"), cst.Name("v"))],
                lbrace=cst.LeftCurlyBrace(
                    whitespace_after=cst.SimpleWhitespace("\t")),
                rbrace=cst.RightCurlyBrace(
                    whitespace_before=cst.SimpleWhitespace("\t\t")),
            ),
            "code":
            "{\tk: v\t\t}",
            "parser":
            parse_expression,
            "expected_position":
            CodeRange.create((1, 0), (1, 9)),
        },
        # with parenthesis
        {
            "node":
            cst.Dict(
                [cst.DictElement(cst.Name("k"), cst.Name("v"))],
                lpar=[cst.LeftParen()],
                rpar=[cst.RightParen()],
            ),
            "code":
            "({k: v})",
            "parser":
            parse_expression,
            "expected_position":
            CodeRange.create((1, 1), (1, 7)),
        },
        # starred element
        {
            "node":
            cst.Dict([
                cst.StarredDictElement(cst.Name("one")),
                cst.StarredDictElement(cst.Name("two")),
            ]),
            "code":
            "{**one, **two}",
            "parser":
            None,
            "expected_position":
            CodeRange.create((1, 0), (1, 14)),
        },
        # custom comma on DictElement
        {
            "node":
            cst.Dict([
                cst.DictElement(cst.Name("k"),
                                cst.Name("v"),
                                comma=cst.Comma())
            ]),
            "code":
            "{k: v,}",
            "parser":
            parse_expression,
            "expected_position":
            CodeRange.create((1, 0), (1, 7)),
        },
        # custom comma on StarredDictElement
        {
            "node":
            cst.Dict([
                cst.StarredDictElement(cst.Name("expanded"), comma=cst.Comma())
            ]),
            "code":
            "{**expanded,}",
            "parser":
            parse_expression,
            "expected_position":
            CodeRange.create((1, 0), (1, 13)),
        },
        # custom whitespace on DictElement
        {
            "node":
            cst.Dict([
                cst.DictElement(
                    cst.Name("k"),
                    cst.Name("v"),
                    whitespace_before_colon=cst.SimpleWhitespace("\t"),
                    whitespace_after_colon=cst.SimpleWhitespace("\t\t"),
                )
            ]),
            "code":
            "{k\t:\t\tv}",
            "parser":
            parse_expression,
            "expected_position":
            CodeRange.create((1, 0), (1, 8)),
        },
        # custom whitespace on StarredDictElement
        {
            "node":
            cst.Dict([
                cst.DictElement(cst.Name("k"),
                                cst.Name("v"),
                                comma=cst.Comma()),
                cst.StarredDictElement(
                    cst.Name("expanded"),
                    whitespace_before_value=cst.SimpleWhitespace("  "),
                ),
            ]),
            "code":
            "{k: v,**  expanded}",
            "parser":
            parse_expression,
            "expected_position":
            CodeRange.create((1, 0), (1, 19)),
        },
        # missing spaces around dict is always okay
        {
            "node":
            cst.GeneratorExp(
                cst.Name("a"),
                cst.CompFor(
                    cst.Name("b"),
                    cst.Dict([cst.DictElement(cst.Name("k"), cst.Name("v"))]),
                    ifs=[
                        cst.CompIf(
                            cst.Name("c"),
                            whitespace_before=cst.SimpleWhitespace(""),
                        )
                    ],
                    whitespace_after_in=cst.SimpleWhitespace(""),
                ),
            ),
            "parser":
            parse_expression,
            "code":
            "(a for b in{k: v}if c)",
        },
    ])
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider([
        # unbalanced Dict
        {
            "get_node": lambda: cst.Dict([], lpar=[cst.LeftParen()]),
            "expected_re": "left paren without right paren",
        }
    ])
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
示例#19
0
class ComparisonTest(CSTNodeTest):
    @data_provider((
        # Simple comparison statements
        (
            cst.Comparison(
                cst.Name("foo"),
                (cst.ComparisonTarget(cst.LessThan(), cst.Integer("5")), ),
            ),
            "foo < 5",
        ),
        (
            cst.Comparison(
                cst.Name("foo"),
                (cst.ComparisonTarget(cst.NotEqual(), cst.Integer("5")), ),
            ),
            "foo != 5",
        ),
        (
            cst.Comparison(
                cst.Name("foo"),
                (cst.ComparisonTarget(cst.Is(), cst.Name("True")), )),
            "foo is True",
        ),
        (
            cst.Comparison(
                cst.Name("foo"),
                (cst.ComparisonTarget(cst.IsNot(), cst.Name("False")), ),
            ),
            "foo is not False",
        ),
        (
            cst.Comparison(
                cst.Name("foo"),
                (cst.ComparisonTarget(cst.In(), cst.Name("bar")), )),
            "foo in bar",
        ),
        (
            cst.Comparison(
                cst.Name("foo"),
                (cst.ComparisonTarget(cst.NotIn(), cst.Name("bar")), ),
            ),
            "foo not in bar",
        ),
        # Comparison with parens
        (
            cst.Comparison(
                lpar=(cst.LeftParen(), ),
                left=cst.Name("foo"),
                comparisons=(cst.ComparisonTarget(
                    operator=cst.NotIn(), comparator=cst.Name("bar")), ),
                rpar=(cst.RightParen(), ),
            ),
            "(foo not in bar)",
        ),
        (
            cst.Comparison(
                left=cst.Name("a",
                              lpar=(cst.LeftParen(), ),
                              rpar=(cst.RightParen(), )),
                comparisons=(
                    cst.ComparisonTarget(
                        operator=cst.Is(
                            whitespace_before=cst.SimpleWhitespace(""),
                            whitespace_after=cst.SimpleWhitespace(""),
                        ),
                        comparator=cst.Name("b",
                                            lpar=(cst.LeftParen(), ),
                                            rpar=(cst.RightParen(), )),
                    ),
                    cst.ComparisonTarget(
                        operator=cst.Is(
                            whitespace_before=cst.SimpleWhitespace(""),
                            whitespace_after=cst.SimpleWhitespace(""),
                        ),
                        comparator=cst.Name("c",
                                            lpar=(cst.LeftParen(), ),
                                            rpar=(cst.RightParen(), )),
                    ),
                ),
            ),
            "(a)is(b)is(c)",
        ),
        # Valid expressions that look like they shouldn't parse
        (
            cst.Comparison(
                left=cst.Integer("5"),
                comparisons=(cst.ComparisonTarget(
                    operator=cst.NotIn(
                        whitespace_before=cst.SimpleWhitespace("")),
                    comparator=cst.Name("bar"),
                ), ),
            ),
            "5not in bar",
        ),
        # Validate that spacing works properly
        (
            cst.Comparison(
                lpar=(cst.LeftParen(
                    whitespace_after=cst.SimpleWhitespace(" ")), ),
                left=cst.Name("foo"),
                comparisons=(cst.ComparisonTarget(
                    operator=cst.NotIn(
                        whitespace_before=cst.SimpleWhitespace("  "),
                        whitespace_between=cst.SimpleWhitespace("  "),
                        whitespace_after=cst.SimpleWhitespace("  "),
                    ),
                    comparator=cst.Name("bar"),
                ), ),
                rpar=(cst.RightParen(
                    whitespace_before=cst.SimpleWhitespace(" ")), ),
            ),
            "( foo  not  in  bar )",
        ),
        # Do some complex nodes
        (
            cst.Comparison(
                left=cst.Name("baz"),
                comparisons=(cst.ComparisonTarget(
                    operator=cst.Equal(),
                    comparator=cst.Comparison(
                        lpar=(cst.LeftParen(), ),
                        left=cst.Name("foo"),
                        comparisons=(cst.ComparisonTarget(
                            operator=cst.NotIn(),
                            comparator=cst.Name("bar")), ),
                        rpar=(cst.RightParen(), ),
                    ),
                ), ),
            ),
            "baz == (foo not in bar)",
            CodeRange.create((1, 0), (1, 23)),
        ),
        (
            cst.Comparison(
                left=cst.Name("a"),
                comparisons=(
                    cst.ComparisonTarget(operator=cst.GreaterThan(),
                                         comparator=cst.Name("b")),
                    cst.ComparisonTarget(operator=cst.GreaterThan(),
                                         comparator=cst.Name("c")),
                ),
            ),
            "a > b > c",
            CodeRange.create((1, 0), (1, 9)),
        ),
        # Is safe to use with word operators if it's leading/trailing children are
        (
            cst.IfExp(
                body=cst.Comparison(
                    left=cst.Name("a"),
                    comparisons=(cst.ComparisonTarget(
                        operator=cst.GreaterThan(),
                        comparator=cst.Name(
                            "b",
                            lpar=(cst.LeftParen(), ),
                            rpar=(cst.RightParen(), ),
                        ),
                    ), ),
                ),
                test=cst.Comparison(
                    left=cst.Name("c",
                                  lpar=(cst.LeftParen(), ),
                                  rpar=(cst.RightParen(), )),
                    comparisons=(cst.ComparisonTarget(
                        operator=cst.GreaterThan(),
                        comparator=cst.Name("d")), ),
                ),
                orelse=cst.Name("e"),
                whitespace_before_if=cst.SimpleWhitespace(""),
                whitespace_after_if=cst.SimpleWhitespace(""),
            ),
            "a > (b)if(c) > d else e",
        ),
        # is safe to use with word operators if entirely surrounded in parenthesis
        (
            cst.IfExp(
                body=cst.Name("a"),
                test=cst.Comparison(
                    left=cst.Name("b"),
                    comparisons=(cst.ComparisonTarget(
                        operator=cst.GreaterThan(),
                        comparator=cst.Name("c")), ),
                    lpar=(cst.LeftParen(), ),
                    rpar=(cst.RightParen(), ),
                ),
                orelse=cst.Name("d"),
                whitespace_after_if=cst.SimpleWhitespace(""),
                whitespace_before_else=cst.SimpleWhitespace(""),
            ),
            "a if(b > c)else d",
        ),
    ))
    def test_valid(self,
                   node: cst.CSTNode,
                   code: str,
                   position: Optional[CodeRange] = None) -> None:
        self.validate_node(node,
                           code,
                           parse_expression,
                           expected_position=position)

    @data_provider((
        (
            lambda: cst.Comparison(
                cst.Name("foo"),
                (cst.ComparisonTarget(cst.LessThan(), cst.Integer("5")), ),
                lpar=(cst.LeftParen(), ),
            ),
            "left paren without right paren",
        ),
        (
            lambda: cst.Comparison(
                cst.Name("foo"),
                (cst.ComparisonTarget(cst.LessThan(), cst.Integer("5")), ),
                rpar=(cst.RightParen(), ),
            ),
            "right paren without left paren",
        ),
        (
            lambda: cst.Comparison(cst.Name("foo"), ()),
            "at least one ComparisonTarget",
        ),
        (
            lambda: cst.Comparison(
                left=cst.Name("foo"),
                comparisons=(cst.ComparisonTarget(
                    operator=cst.NotIn(whitespace_before=cst.SimpleWhitespace(
                        "")),
                    comparator=cst.Name("bar"),
                ), ),
            ),
            "at least one space around comparison operator",
        ),
        (
            lambda: cst.Comparison(
                left=cst.Name("foo"),
                comparisons=(cst.ComparisonTarget(
                    operator=cst.NotIn(whitespace_after=cst.SimpleWhitespace(
                        "")),
                    comparator=cst.Name("bar"),
                ), ),
            ),
            "at least one space around comparison operator",
        ),
        # multi-target comparisons
        (
            lambda: cst.Comparison(
                left=cst.Name("a"),
                comparisons=(
                    cst.ComparisonTarget(operator=cst.Is(),
                                         comparator=cst.Name("b")),
                    cst.ComparisonTarget(
                        operator=cst.Is(whitespace_before=cst.SimpleWhitespace(
                            "")),
                        comparator=cst.Name("c"),
                    ),
                ),
            ),
            "at least one space around comparison operator",
        ),
        (
            lambda: cst.Comparison(
                left=cst.Name("a"),
                comparisons=(
                    cst.ComparisonTarget(operator=cst.Is(),
                                         comparator=cst.Name("b")),
                    cst.ComparisonTarget(
                        operator=cst.Is(whitespace_after=cst.SimpleWhitespace(
                            "")),
                        comparator=cst.Name("c"),
                    ),
                ),
            ),
            "at least one space around comparison operator",
        ),
        # whitespace around the comparision itself
        # a ifb > c else d
        (
            lambda: cst.IfExp(
                body=cst.Name("a"),
                test=cst.Comparison(
                    left=cst.Name("b"),
                    comparisons=(cst.
                                 ComparisonTarget(operator=cst.GreaterThan(),
                                                  comparator=cst.Name("c")), ),
                ),
                orelse=cst.Name("d"),
                whitespace_after_if=cst.SimpleWhitespace(""),
            ),
            "Must have at least one space after 'if' keyword.",
        ),
        # a if b > celse d
        (
            lambda: cst.IfExp(
                body=cst.Name("a"),
                test=cst.Comparison(
                    left=cst.Name("b"),
                    comparisons=(cst.
                                 ComparisonTarget(operator=cst.GreaterThan(),
                                                  comparator=cst.Name("c")), ),
                ),
                orelse=cst.Name("d"),
                whitespace_before_else=cst.SimpleWhitespace(""),
            ),
            "Must have at least one space before 'else' keyword.",
        ),
    ))
    def test_invalid(self, get_node: Callable[[], cst.CSTNode],
                     expected_re: str) -> None:
        self.assert_invalid(get_node, expected_re)
示例#20
0
class GlobalConstructionTest(CSTNodeTest):
    @data_provider(
        (
            # Single global statement
            # pyre-fixme[6]: Incompatible parameter type
            {"node": cst.Global((cst.NameItem(cst.Name("a")),)), "code": "global a"},
            # Multiple entries in global statement
            {
                "node": cst.Global(
                    (cst.NameItem(cst.Name("a")), cst.NameItem(cst.Name("b")))
                ),
                "code": "global a, b",
            },
            # Whitespace rendering test
            {
                "node": cst.Global(
                    (
                        cst.NameItem(
                            cst.Name("a"),
                            comma=cst.Comma(
                                whitespace_before=cst.SimpleWhitespace("  "),
                                whitespace_after=cst.SimpleWhitespace("  "),
                            ),
                        ),
                        cst.NameItem(cst.Name("b")),
                    ),
                    whitespace_after_global=cst.SimpleWhitespace("  "),
                ),
                "code": "global  a  ,  b",
                "expected_position": CodeRange.create((1, 0), (1, 15)),
            },
        )
    )
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider(
        (
            # Validate construction
            {
                "get_node": lambda: cst.Global(()),
                "expected_re": "A Global statement must have at least one NameItem",
            },
            # Validate whitespace handling
            {
                "get_node": lambda: cst.Global(
                    (cst.NameItem(cst.Name("a")),),
                    whitespace_after_global=cst.SimpleWhitespace(""),
                ),
                "expected_re": "Must have at least one space after 'global' keyword",
            },
            # Validate comma handling
            {
                "get_node": lambda: cst.Global(
                    (cst.NameItem(cst.Name("a"), comma=cst.Comma()),)
                ),
                "expected_re": "The last NameItem in a Global cannot have a trailing comma",
            },
            # Validate paren handling
            {
                "get_node": lambda: cst.Global(
                    (
                        cst.NameItem(
                            cst.Name(
                                "a", lpar=(cst.LeftParen(),), rpar=(cst.RightParen(),)
                            )
                        ),
                    )
                ),
                "expected_re": "Cannot have parens around names in NameItem",
            },
        )
    )
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
示例#21
0
 def visit_Pass(self, node: cst.Pass) -> None:
     range = self.get_metadata(SyntacticPositionProvider, node)
     test.assertEqual(range, CodeRange.create((1, 0), (1, 4)))
示例#22
0
class BinaryOperationTest(CSTNodeTest):
    @data_provider(
        (
            # Simple binary operations
            # pyre-fixme[6]: Incompatible parameter type
            {
                "node": cst.BinaryOperation(
                    cst.Name("foo"), cst.Add(), cst.Float("5.5")
                ),
                "code": "foo + 5.5",
                "parser": parse_expression,
                "expected_position": None,
            },
            {
                "node": cst.BinaryOperation(
                    cst.Name("foo"), cst.Subtract(), cst.Float("5.5")
                ),
                "code": "foo - 5.5",
                "parser": parse_expression,
                "expected_position": None,
            },
            {
                "node": cst.BinaryOperation(
                    cst.Name("foo"), cst.LeftShift(), cst.Integer("5")
                ),
                "code": "foo << 5",
                "parser": parse_expression,
                "expected_position": None,
            },
            {
                "node": cst.BinaryOperation(
                    cst.Name("foo"), cst.RightShift(), cst.Integer("5")
                ),
                "code": "foo >> 5",
                "parser": parse_expression,
                "expected_position": None,
            },
            {
                "node": cst.BinaryOperation(
                    cst.Name("foo"), cst.BitAnd(), cst.Name("bar")
                ),
                "code": "foo & bar",
                "parser": parse_expression,
                "expected_position": None,
            },
            {
                "node": cst.BinaryOperation(
                    cst.Name("foo"), cst.BitXor(), cst.Name("bar")
                ),
                "code": "foo ^ bar",
                "parser": parse_expression,
                "expected_position": None,
            },
            {
                "node": cst.BinaryOperation(
                    cst.Name("foo"), cst.BitOr(), cst.Name("bar")
                ),
                "code": "foo | bar",
                "parser": parse_expression,
                "expected_position": None,
            },
            {
                "node": cst.BinaryOperation(
                    cst.Name("foo"), cst.Multiply(), cst.Float("5.5")
                ),
                "code": "foo * 5.5",
                "parser": parse_expression,
                "expected_position": None,
            },
            {
                "node": cst.BinaryOperation(
                    cst.Name("foo"), cst.MatrixMultiply(), cst.Float("5.5")
                ),
                "code": "foo @ 5.5",
                "parser": parse_expression,
                "expected_position": None,
            },
            {
                "node": cst.BinaryOperation(
                    cst.Name("foo"), cst.Divide(), cst.Float("5.5")
                ),
                "code": "foo / 5.5",
                "parser": parse_expression,
                "expected_position": None,
            },
            {
                "node": cst.BinaryOperation(
                    cst.Name("foo"), cst.Modulo(), cst.Float("5.5")
                ),
                "code": "foo % 5.5",
                "parser": parse_expression,
                "expected_position": None,
            },
            {
                "node": cst.BinaryOperation(
                    cst.Name("foo"), cst.FloorDivide(), cst.Float("5.5")
                ),
                "code": "foo // 5.5",
                "parser": parse_expression,
                "expected_position": None,
            },
            # Parenthesized binary operation
            {
                "node": cst.BinaryOperation(
                    lpar=(cst.LeftParen(),),
                    left=cst.Name("foo"),
                    operator=cst.LeftShift(),
                    right=cst.Integer("5"),
                    rpar=(cst.RightParen(),),
                ),
                "code": "(foo << 5)",
                "parser": parse_expression,
                "expected_position": None,
            },
            # Make sure that spacing works
            {
                "node": cst.BinaryOperation(
                    lpar=(cst.LeftParen(whitespace_after=cst.SimpleWhitespace(" ")),),
                    left=cst.Name("foo"),
                    operator=cst.Multiply(
                        whitespace_before=cst.SimpleWhitespace("  "),
                        whitespace_after=cst.SimpleWhitespace("  "),
                    ),
                    right=cst.Name("bar"),
                    rpar=(cst.RightParen(whitespace_before=cst.SimpleWhitespace(" ")),),
                ),
                "code": "( foo  *  bar )",
                "parser": parse_expression,
                "expected_position": CodeRange.create((1, 2), (1, 13)),
            },
        )
    )
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider(
        (
            {
                "get_node": (
                    lambda: cst.BinaryOperation(
                        cst.Name("foo"),
                        cst.Add(),
                        cst.Name("bar"),
                        lpar=(cst.LeftParen(),),
                    )
                ),
                "expected_re": "left paren without right paren",
            },
            {
                "get_node": (
                    lambda: cst.BinaryOperation(
                        cst.Name("foo"),
                        cst.Add(),
                        cst.Name("bar"),
                        rpar=(cst.RightParen(),),
                    )
                ),
                "expected_re": "right paren without left paren",
            },
        )
    )
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
示例#23
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)
示例#24
0
class LambdaCreationTest(CSTNodeTest):
    @data_provider((
        # Simple lambda
        (cst.Lambda(cst.Parameters(), cst.Integer("5")), "lambda: 5"),
        # Test basic positional params
        (
            cst.Lambda(
                cst.Parameters(params=(cst.Param(cst.Name("bar")),
                                       cst.Param(cst.Name("baz")))),
                cst.Integer("5"),
            ),
            "lambda bar, baz: 5",
        ),
        # Test basic positional default params
        (
            cst.Lambda(
                cst.Parameters(default_params=(
                    cst.Param(cst.Name("bar"),
                              default=cst.SimpleString('"one"')),
                    cst.Param(cst.Name("baz"), default=cst.Integer("5")),
                )),
                cst.Integer("5"),
            ),
            'lambda bar = "one", baz = 5: 5',
        ),
        # Mixed positional and default params.
        (
            cst.Lambda(
                cst.Parameters(
                    params=(cst.Param(cst.Name("bar")), ),
                    default_params=(cst.Param(cst.Name("baz"),
                                              default=cst.Integer("5")), ),
                ),
                cst.Integer("5"),
            ),
            "lambda bar, baz = 5: 5",
        ),
        # Test kwonly params
        (
            cst.Lambda(
                cst.Parameters(kwonly_params=(
                    cst.Param(cst.Name("bar"),
                              default=cst.SimpleString('"one"')),
                    cst.Param(cst.Name("baz")),
                )),
                cst.Integer("5"),
            ),
            'lambda *, bar = "one", baz: 5',
        ),
        # Mixed params and kwonly_params
        (
            cst.Lambda(
                cst.Parameters(
                    params=(
                        cst.Param(cst.Name("first")),
                        cst.Param(cst.Name("second")),
                    ),
                    kwonly_params=(
                        cst.Param(cst.Name("bar"),
                                  default=cst.SimpleString('"one"')),
                        cst.Param(cst.Name("baz")),
                        cst.Param(cst.Name("biz"),
                                  default=cst.SimpleString('"two"')),
                    ),
                ),
                cst.Integer("5"),
            ),
            'lambda first, second, *, bar = "one", baz, biz = "two": 5',
        ),
        # Mixed default_params and kwonly_params
        (
            cst.Lambda(
                cst.Parameters(
                    default_params=(
                        cst.Param(cst.Name("first"), default=cst.Float("1.0")),
                        cst.Param(cst.Name("second"),
                                  default=cst.Float("1.5")),
                    ),
                    kwonly_params=(
                        cst.Param(cst.Name("bar"),
                                  default=cst.SimpleString('"one"')),
                        cst.Param(cst.Name("baz")),
                        cst.Param(cst.Name("biz"),
                                  default=cst.SimpleString('"two"')),
                    ),
                ),
                cst.Integer("5"),
            ),
            'lambda first = 1.0, second = 1.5, *, bar = "one", baz, biz = "two": 5',
        ),
        # Mixed params, default_params, and kwonly_params
        (
            cst.Lambda(
                cst.Parameters(
                    params=(
                        cst.Param(cst.Name("first")),
                        cst.Param(cst.Name("second")),
                    ),
                    default_params=(
                        cst.Param(cst.Name("third"), default=cst.Float("1.0")),
                        cst.Param(cst.Name("fourth"),
                                  default=cst.Float("1.5")),
                    ),
                    kwonly_params=(
                        cst.Param(cst.Name("bar"),
                                  default=cst.SimpleString('"one"')),
                        cst.Param(cst.Name("baz")),
                        cst.Param(cst.Name("biz"),
                                  default=cst.SimpleString('"two"')),
                    ),
                ),
                cst.Integer("5"),
            ),
            'lambda first, second, third = 1.0, fourth = 1.5, *, bar = "one", baz, biz = "two": 5',
            CodeRange.create((1, 0), (1, 84)),
        ),
        # Test star_arg
        (
            cst.Lambda(
                cst.Parameters(star_arg=cst.Param(cst.Name("params"))),
                cst.Integer("5"),
            ),
            "lambda *params: 5",
        ),
        # Typed star_arg, include kwonly_params
        (
            cst.Lambda(
                cst.Parameters(
                    star_arg=cst.Param(cst.Name("params")),
                    kwonly_params=(
                        cst.Param(cst.Name("bar"),
                                  default=cst.SimpleString('"one"')),
                        cst.Param(cst.Name("baz")),
                        cst.Param(cst.Name("biz"),
                                  default=cst.SimpleString('"two"')),
                    ),
                ),
                cst.Integer("5"),
            ),
            'lambda *params, bar = "one", baz, biz = "two": 5',
        ),
        # Mixed params default_params, star_arg and kwonly_params
        (
            cst.Lambda(
                cst.Parameters(
                    params=(
                        cst.Param(cst.Name("first")),
                        cst.Param(cst.Name("second")),
                    ),
                    default_params=(
                        cst.Param(cst.Name("third"), default=cst.Float("1.0")),
                        cst.Param(cst.Name("fourth"),
                                  default=cst.Float("1.5")),
                    ),
                    star_arg=cst.Param(cst.Name("params")),
                    kwonly_params=(
                        cst.Param(cst.Name("bar"),
                                  default=cst.SimpleString('"one"')),
                        cst.Param(cst.Name("baz")),
                        cst.Param(cst.Name("biz"),
                                  default=cst.SimpleString('"two"')),
                    ),
                ),
                cst.Integer("5"),
            ),
            'lambda first, second, third = 1.0, fourth = 1.5, *params, bar = "one", baz, biz = "two": 5',
        ),
        # Test star_arg and star_kwarg
        (
            cst.Lambda(
                cst.Parameters(star_kwarg=cst.Param(cst.Name("kwparams"))),
                cst.Integer("5"),
            ),
            "lambda **kwparams: 5",
        ),
        # Test star_arg and kwarg
        (
            cst.Lambda(
                cst.Parameters(
                    star_arg=cst.Param(cst.Name("params")),
                    star_kwarg=cst.Param(cst.Name("kwparams")),
                ),
                cst.Integer("5"),
            ),
            "lambda *params, **kwparams: 5",
        ),
        # Inner whitespace
        (
            cst.Lambda(
                lpar=(cst.LeftParen(
                    whitespace_after=cst.SimpleWhitespace(" ")), ),
                whitespace_after_lambda=cst.SimpleWhitespace("  "),
                params=cst.Parameters(),
                colon=cst.Colon(whitespace_after=cst.SimpleWhitespace(" ")),
                body=cst.Integer("5"),
                rpar=(cst.RightParen(
                    whitespace_before=cst.SimpleWhitespace(" ")), ),
            ),
            "( lambda  : 5 )",
            CodeRange.create((1, 2), (1, 13)),
        ),
    ))
    def test_valid(self,
                   node: cst.CSTNode,
                   code: str,
                   position: Optional[CodeRange] = None) -> None:
        self.validate_node(node, code, expected_position=position)

    @data_provider((
        (
            lambda: cst.Lambda(
                cst.Parameters(params=(cst.Param(cst.Name("arg")), )),
                cst.Integer("5"),
                lpar=(cst.LeftParen(), ),
            ),
            "left paren without right paren",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(params=(cst.Param(cst.Name("arg")), )),
                cst.Integer("5"),
                rpar=(cst.RightParen(), ),
            ),
            "right paren without left paren",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(params=(cst.Param(cst.Name("arg")), )),
                cst.Integer("5"),
                whitespace_after_lambda=cst.SimpleWhitespace(""),
            ),
            "at least one space after lambda",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(default_params=(cst.Param(
                    cst.Name("arg"), default=cst.Integer("5")), )),
                cst.Integer("5"),
                whitespace_after_lambda=cst.SimpleWhitespace(""),
            ),
            "at least one space after lambda",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(star_arg=cst.Param(cst.Name("arg"))),
                cst.Integer("5"),
                whitespace_after_lambda=cst.SimpleWhitespace(""),
            ),
            "at least one space after lambda",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(kwonly_params=(cst.Param(cst.Name("arg")), )),
                cst.Integer("5"),
                whitespace_after_lambda=cst.SimpleWhitespace(""),
            ),
            "at least one space after lambda",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(star_kwarg=cst.Param(cst.Name("arg"))),
                cst.Integer("5"),
                whitespace_after_lambda=cst.SimpleWhitespace(""),
            ),
            "at least one space after lambda",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(star_kwarg=cst.Param(cst.Name("bar"),
                                                    equal=cst.AssignEqual())),
                cst.Integer("5"),
            ),
            "Must have a default when specifying an AssignEqual.",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(star_kwarg=cst.Param(cst.Name("bar"),
                                                    star="***")),
                cst.Integer("5"),
            ),
            r"Must specify either '', '\*' or '\*\*' for star.",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(params=(cst.Param(
                    cst.Name("bar"), default=cst.SimpleString('"one"')), )),
                cst.Integer("5"),
            ),
            "Cannot have defaults for params",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(default_params=(cst.Param(cst.Name("bar")), )),
                cst.Integer("5"),
            ),
            "Must have defaults for default_params",
        ),
        (
            lambda: cst.Lambda(cst.Parameters(star_arg=cst.ParamStar()),
                               cst.Integer("5")),
            "Must have at least one kwonly param if ParamStar is used.",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(params=(cst.Param(cst.Name("bar"), star="*"), )
                               ),
                cst.Integer("5"),
            ),
            "Expecting a star prefix of ''",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(default_params=(cst.Param(
                    cst.Name("bar"),
                    default=cst.SimpleString('"one"'),
                    star="*",
                ), )),
                cst.Integer("5"),
            ),
            "Expecting a star prefix of ''",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(kwonly_params=(cst.Param(cst.Name("bar"),
                                                        star="*"), )),
                cst.Integer("5"),
            ),
            "Expecting a star prefix of ''",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(star_arg=cst.Param(cst.Name("bar"), star="**")),
                cst.Integer("5"),
            ),
            r"Expecting a star prefix of '\*'",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(star_kwarg=cst.Param(cst.Name("bar"), star="*")
                               ),
                cst.Integer("5"),
            ),
            r"Expecting a star prefix of '\*\*'",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(params=(cst.Param(
                    cst.Name("arg"),
                    annotation=cst.Annotation(cst.Name("str")),
                ), )),
                cst.Integer("5"),
                whitespace_after_lambda=cst.SimpleWhitespace(""),
            ),
            "Lambda params cannot have type annotations",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(default_params=(cst.Param(
                    cst.Name("arg"),
                    default=cst.Integer("5"),
                    annotation=cst.Annotation(cst.Name("str")),
                ), )),
                cst.Integer("5"),
                whitespace_after_lambda=cst.SimpleWhitespace(""),
            ),
            "Lambda params cannot have type annotations",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(star_arg=cst.Param(cst.Name("arg"),
                                                  annotation=cst.Annotation(
                                                      cst.Name("str")))),
                cst.Integer("5"),
                whitespace_after_lambda=cst.SimpleWhitespace(""),
            ),
            "Lambda params cannot have type annotations",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(kwonly_params=(cst.Param(
                    cst.Name("arg"),
                    annotation=cst.Annotation(cst.Name("str")),
                ), )),
                cst.Integer("5"),
                whitespace_after_lambda=cst.SimpleWhitespace(""),
            ),
            "Lambda params cannot have type annotations",
        ),
        (
            lambda: cst.Lambda(
                cst.Parameters(star_kwarg=cst.Param(cst.Name("arg"),
                                                    annotation=cst.Annotation(
                                                        cst.Name("str")))),
                cst.Integer("5"),
                whitespace_after_lambda=cst.SimpleWhitespace(""),
            ),
            "Lambda params cannot have type annotations",
        ),
    ))
    def test_invalid(self, get_node: Callable[[], cst.CSTNode],
                     expected_re: str) -> None:
        self.assert_invalid(get_node, expected_re)
示例#25
0
 def cmp_position(self, actual: CodeRange, start: Tuple[int, int],
                  end: Tuple[int, int]) -> None:
     self.assertEqual(actual, CodeRange.create(start, end))
示例#26
0
class NumberTest(CSTNodeTest):
    @data_provider((
        # Simple number
        (cst.Integer("5"), "5", parse_expression),
        # Negted number
        (
            cst.UnaryOperation(operator=cst.Minus(),
                               expression=cst.Integer("5")),
            "-5",
            parse_expression,
            CodeRange.create((1, 0), (1, 2)),
        ),
        # In parenthesis
        (
            cst.UnaryOperation(
                lpar=(cst.LeftParen(), ),
                operator=cst.Minus(),
                expression=cst.Integer("5"),
                rpar=(cst.RightParen(), ),
            ),
            "(-5)",
            parse_expression,
            CodeRange.create((1, 1), (1, 3)),
        ),
        (
            cst.UnaryOperation(
                lpar=(cst.LeftParen(), ),
                operator=cst.Minus(),
                expression=cst.Integer("5",
                                       lpar=(cst.LeftParen(), ),
                                       rpar=(cst.RightParen(), )),
                rpar=(cst.RightParen(), ),
            ),
            "(-(5))",
            parse_expression,
            CodeRange.create((1, 1), (1, 5)),
        ),
        (
            cst.UnaryOperation(
                operator=cst.Minus(),
                expression=cst.UnaryOperation(operator=cst.Minus(),
                                              expression=cst.Integer("5")),
            ),
            "--5",
            parse_expression,
            CodeRange.create((1, 0), (1, 3)),
        ),
        # multiple nested parenthesis
        (
            cst.Integer(
                "5",
                lpar=(cst.LeftParen(), cst.LeftParen()),
                rpar=(cst.RightParen(), cst.RightParen()),
            ),
            "((5))",
            parse_expression,
            CodeRange.create((1, 2), (1, 3)),
        ),
        (
            cst.UnaryOperation(
                lpar=(cst.LeftParen(), ),
                operator=cst.Plus(),
                expression=cst.Integer(
                    "5",
                    lpar=(cst.LeftParen(), cst.LeftParen()),
                    rpar=(cst.RightParen(), cst.RightParen()),
                ),
                rpar=(cst.RightParen(), ),
            ),
            "(+((5)))",
            parse_expression,
            CodeRange.create((1, 1), (1, 7)),
        ),
    ))
    def test_valid(
        self,
        node: cst.CSTNode,
        code: str,
        parser: Optional[Callable[[str], cst.CSTNode]],
        position: Optional[CodeRange] = None,
    ) -> None:
        self.validate_node(node, code, parser, expected_position=position)

    @data_provider((
        (
            lambda: cst.Integer("5", lpar=(cst.LeftParen(), )),
            "left paren without right paren",
        ),
        (
            lambda: cst.Integer("5", rpar=(cst.RightParen(), )),
            "right paren without left paren",
        ),
        (
            lambda: cst.Float("5.5", lpar=(cst.LeftParen(), )),
            "left paren without right paren",
        ),
        (
            lambda: cst.Float("5.5", rpar=(cst.RightParen(), )),
            "right paren without left paren",
        ),
        (
            lambda: cst.Imaginary("5i", lpar=(cst.LeftParen(), )),
            "left paren without right paren",
        ),
        (
            lambda: cst.Imaginary("5i", rpar=(cst.RightParen(), )),
            "right paren without left paren",
        ),
    ))
    def test_invalid(self, get_node: Callable[[], cst.CSTNode],
                     expected_re: str) -> None:
        self.assert_invalid(get_node, expected_re)
示例#27
0
class SimpleCompTest(CSTNodeTest):
    @data_provider(
        [
            # simple GeneratorExp
            {
                "node": cst.GeneratorExp(
                    cst.Name("a"), cst.CompFor(target=cst.Name("b"), iter=cst.Name("c"))
                ),
                "code": "(a for b in c)",
                "parser": parse_expression,
                "expected_position": CodeRange.create((1, 1), (1, 13)),
            },
            # simple ListComp
            {
                "node": cst.ListComp(
                    cst.Name("a"), cst.CompFor(target=cst.Name("b"), iter=cst.Name("c"))
                ),
                "code": "[a for b in c]",
                "parser": parse_expression,
                "expected_position": CodeRange.create((1, 0), (1, 14)),
            },
            # simple SetComp
            {
                "node": cst.SetComp(
                    cst.Name("a"), cst.CompFor(target=cst.Name("b"), iter=cst.Name("c"))
                ),
                "code": "{a for b in c}",
                "parser": parse_expression,
            },
            # async GeneratorExp
            {
                "node": cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        asynchronous=cst.Asynchronous(),
                    ),
                ),
                "code": "(a async for b in c)",
                "parser": parse_expression,
            },
            # a generator doesn't have to own it's own parenthesis
            {
                "node": cst.Call(
                    cst.Name("func"),
                    [
                        cst.Arg(
                            cst.GeneratorExp(
                                cst.Name("a"),
                                cst.CompFor(target=cst.Name("b"), iter=cst.Name("c")),
                                lpar=[],
                                rpar=[],
                            )
                        )
                    ],
                ),
                "code": "func(a for b in c)",
                "parser": parse_expression,
            },
            # add a few 'if' clauses
            {
                "node": cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        ifs=[
                            cst.CompIf(cst.Name("d")),
                            cst.CompIf(cst.Name("e")),
                            cst.CompIf(cst.Name("f")),
                        ],
                    ),
                ),
                "code": "(a for b in c if d if e if f)",
                "parser": parse_expression,
                "expected_position": CodeRange.create((1, 1), (1, 28)),
            },
            # nested/inner for-in clause
            {
                "node": cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        inner_for_in=cst.CompFor(
                            target=cst.Name("d"), iter=cst.Name("e")
                        ),
                    ),
                ),
                "code": "(a for b in c for d in e)",
                "parser": parse_expression,
            },
            # nested/inner for-in clause with an 'if' clause
            {
                "node": cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        ifs=[cst.CompIf(cst.Name("d"))],
                        inner_for_in=cst.CompFor(
                            target=cst.Name("e"), iter=cst.Name("f")
                        ),
                    ),
                ),
                "code": "(a for b in c if d for e in f)",
                "parser": parse_expression,
            },
            # custom whitespace
            {
                "node": cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        ifs=[
                            cst.CompIf(
                                cst.Name("d"),
                                whitespace_before=cst.SimpleWhitespace("\t"),
                                whitespace_before_test=cst.SimpleWhitespace("\t\t"),
                            )
                        ],
                        whitespace_before=cst.SimpleWhitespace("  "),
                        whitespace_after_for=cst.SimpleWhitespace("   "),
                        whitespace_before_in=cst.SimpleWhitespace("    "),
                        whitespace_after_in=cst.SimpleWhitespace("     "),
                    ),
                    lpar=[cst.LeftParen(whitespace_after=cst.SimpleWhitespace("\f"))],
                    rpar=[
                        cst.RightParen(whitespace_before=cst.SimpleWhitespace("\f\f"))
                    ],
                ),
                "code": "(\fa  for   b    in     c\tif\t\td\f\f)",
                "parser": parse_expression,
                "expected_position": CodeRange.create((1, 2), (1, 30)),
            },
            # custom whitespace around ListComp's brackets
            {
                "node": cst.ListComp(
                    cst.Name("a"),
                    cst.CompFor(target=cst.Name("b"), iter=cst.Name("c")),
                    lbracket=cst.LeftSquareBracket(
                        whitespace_after=cst.SimpleWhitespace("\t")
                    ),
                    rbracket=cst.RightSquareBracket(
                        whitespace_before=cst.SimpleWhitespace("\t\t")
                    ),
                    lpar=[cst.LeftParen(whitespace_after=cst.SimpleWhitespace("\f"))],
                    rpar=[
                        cst.RightParen(whitespace_before=cst.SimpleWhitespace("\f\f"))
                    ],
                ),
                "code": "(\f[\ta for b in c\t\t]\f\f)",
                "parser": parse_expression,
                "expected_position": CodeRange.create((1, 2), (1, 19)),
            },
            # custom whitespace around SetComp's braces
            {
                "node": cst.SetComp(
                    cst.Name("a"),
                    cst.CompFor(target=cst.Name("b"), iter=cst.Name("c")),
                    lbrace=cst.LeftCurlyBrace(
                        whitespace_after=cst.SimpleWhitespace("\t")
                    ),
                    rbrace=cst.RightCurlyBrace(
                        whitespace_before=cst.SimpleWhitespace("\t\t")
                    ),
                    lpar=[cst.LeftParen(whitespace_after=cst.SimpleWhitespace("\f"))],
                    rpar=[
                        cst.RightParen(whitespace_before=cst.SimpleWhitespace("\f\f"))
                    ],
                ),
                "code": "(\f{\ta for b in c\t\t}\f\f)",
                "parser": parse_expression,
            },
            # no whitespace between elements
            {
                "node": cst.GeneratorExp(
                    cst.Name("a", lpar=[cst.LeftParen()], rpar=[cst.RightParen()]),
                    cst.CompFor(
                        target=cst.Name(
                            "b", lpar=[cst.LeftParen()], rpar=[cst.RightParen()]
                        ),
                        iter=cst.Name(
                            "c", lpar=[cst.LeftParen()], rpar=[cst.RightParen()]
                        ),
                        ifs=[
                            cst.CompIf(
                                cst.Name(
                                    "d", lpar=[cst.LeftParen()], rpar=[cst.RightParen()]
                                ),
                                whitespace_before=cst.SimpleWhitespace(""),
                                whitespace_before_test=cst.SimpleWhitespace(""),
                            )
                        ],
                        inner_for_in=cst.CompFor(
                            target=cst.Name(
                                "e", lpar=[cst.LeftParen()], rpar=[cst.RightParen()]
                            ),
                            iter=cst.Name(
                                "f", lpar=[cst.LeftParen()], rpar=[cst.RightParen()]
                            ),
                            whitespace_before=cst.SimpleWhitespace(""),
                            whitespace_after_for=cst.SimpleWhitespace(""),
                            whitespace_before_in=cst.SimpleWhitespace(""),
                            whitespace_after_in=cst.SimpleWhitespace(""),
                        ),
                        whitespace_before=cst.SimpleWhitespace(""),
                        whitespace_after_for=cst.SimpleWhitespace(""),
                        whitespace_before_in=cst.SimpleWhitespace(""),
                        whitespace_after_in=cst.SimpleWhitespace(""),
                    ),
                    lpar=[cst.LeftParen()],
                    rpar=[cst.RightParen()],
                ),
                "code": "((a)for(b)in(c)if(d)for(e)in(f))",
                "parser": parse_expression,
                "expected_position": CodeRange.create((1, 1), (1, 31)),
            },
            # no whitespace before/after GeneratorExp is valid
            {
                "node": cst.Comparison(
                    cst.GeneratorExp(
                        cst.Name("a"),
                        cst.CompFor(target=cst.Name("b"), iter=cst.Name("c")),
                    ),
                    [
                        cst.ComparisonTarget(
                            cst.Is(
                                whitespace_before=cst.SimpleWhitespace(""),
                                whitespace_after=cst.SimpleWhitespace(""),
                            ),
                            cst.GeneratorExp(
                                cst.Name("d"),
                                cst.CompFor(target=cst.Name("e"), iter=cst.Name("f")),
                            ),
                        )
                    ],
                ),
                "code": "(a for b in c)is(d for e in f)",
                "parser": parse_expression,
            },
            # no whitespace before/after ListComp is valid
            {
                "node": cst.Comparison(
                    cst.ListComp(
                        cst.Name("a"),
                        cst.CompFor(target=cst.Name("b"), iter=cst.Name("c")),
                    ),
                    [
                        cst.ComparisonTarget(
                            cst.Is(
                                whitespace_before=cst.SimpleWhitespace(""),
                                whitespace_after=cst.SimpleWhitespace(""),
                            ),
                            cst.ListComp(
                                cst.Name("d"),
                                cst.CompFor(target=cst.Name("e"), iter=cst.Name("f")),
                            ),
                        )
                    ],
                ),
                "code": "[a for b in c]is[d for e in f]",
                "parser": parse_expression,
            },
            # no whitespace before/after SetComp is valid
            {
                "node": cst.Comparison(
                    cst.SetComp(
                        cst.Name("a"),
                        cst.CompFor(target=cst.Name("b"), iter=cst.Name("c")),
                    ),
                    [
                        cst.ComparisonTarget(
                            cst.Is(
                                whitespace_before=cst.SimpleWhitespace(""),
                                whitespace_after=cst.SimpleWhitespace(""),
                            ),
                            cst.SetComp(
                                cst.Name("d"),
                                cst.CompFor(target=cst.Name("e"), iter=cst.Name("f")),
                            ),
                        )
                    ],
                ),
                "code": "{a for b in c}is{d for e in f}",
                "parser": parse_expression,
            },
        ]
    )
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider(
        (
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(target=cst.Name("b"), iter=cst.Name("c")),
                    lpar=[cst.LeftParen(), cst.LeftParen()],
                    rpar=[cst.RightParen()],
                ),
                "unbalanced parens",
            ),
            (
                lambda: cst.ListComp(
                    cst.Name("a"),
                    cst.CompFor(target=cst.Name("b"), iter=cst.Name("c")),
                    lpar=[cst.LeftParen(), cst.LeftParen()],
                    rpar=[cst.RightParen()],
                ),
                "unbalanced parens",
            ),
            (
                lambda: cst.SetComp(
                    cst.Name("a"),
                    cst.CompFor(target=cst.Name("b"), iter=cst.Name("c")),
                    lpar=[cst.LeftParen(), cst.LeftParen()],
                    rpar=[cst.RightParen()],
                ),
                "unbalanced parens",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        whitespace_before=cst.SimpleWhitespace(""),
                    ),
                ),
                "Must have at least one space before 'for' keyword.",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        asynchronous=cst.Asynchronous(),
                        whitespace_before=cst.SimpleWhitespace(""),
                    ),
                ),
                "Must have at least one space before 'async' keyword.",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        whitespace_after_for=cst.SimpleWhitespace(""),
                    ),
                ),
                "Must have at least one space after 'for' keyword.",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        whitespace_before_in=cst.SimpleWhitespace(""),
                    ),
                ),
                "Must have at least one space before 'in' keyword.",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        whitespace_after_in=cst.SimpleWhitespace(""),
                    ),
                ),
                "Must have at least one space after 'in' keyword.",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        ifs=[
                            cst.CompIf(
                                cst.Name("d"),
                                whitespace_before=cst.SimpleWhitespace(""),
                            )
                        ],
                    ),
                ),
                "Must have at least one space before 'if' keyword.",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        ifs=[
                            cst.CompIf(
                                cst.Name("d"),
                                whitespace_before_test=cst.SimpleWhitespace(""),
                            )
                        ],
                    ),
                ),
                "Must have at least one space after 'if' keyword.",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        inner_for_in=cst.CompFor(
                            target=cst.Name("d"),
                            iter=cst.Name("e"),
                            whitespace_before=cst.SimpleWhitespace(""),
                        ),
                    ),
                ),
                "Must have at least one space before 'for' keyword.",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        inner_for_in=cst.CompFor(
                            target=cst.Name("d"),
                            iter=cst.Name("e"),
                            asynchronous=cst.Asynchronous(),
                            whitespace_before=cst.SimpleWhitespace(""),
                        ),
                    ),
                ),
                "Must have at least one space before 'async' keyword.",
            ),
        )
    )
    def test_invalid(
        self, get_node: Callable[[], cst.CSTNode], expected_re: str
    ) -> None:
        self.assert_invalid(get_node, expected_re)
示例#28
0
class CallTest(CSTNodeTest):
    @data_provider((
        # Simple call
        # pyre-fixme[6]: Incompatible parameter type
        {
            "node": cst.Call(cst.Name("foo")),
            "code": "foo()",
            "parser": parse_expression,
            "expected_position": None,
        },
        {
            "node":
            cst.Call(cst.Name("foo"),
                     whitespace_before_args=cst.SimpleWhitespace(" ")),
            "code":
            "foo( )",
            "parser":
            parse_expression,
            "expected_position":
            None,
        },
        # Call with attribute dereference
        {
            "node": cst.Call(cst.Attribute(cst.Name("foo"), cst.Name("bar"))),
            "code": "foo.bar()",
            "parser": parse_expression,
            "expected_position": None,
        },
        # Positional arguments render test
        {
            "node": cst.Call(cst.Name("foo"), (cst.Arg(cst.Integer("1")), )),
            "code": "foo(1)",
            "parser": None,
            "expected_position": None,
        },
        {
            "node":
            cst.Call(
                cst.Name("foo"),
                (
                    cst.Arg(cst.Integer("1")),
                    cst.Arg(cst.Integer("2")),
                    cst.Arg(cst.Integer("3")),
                ),
            ),
            "code":
            "foo(1, 2, 3)",
            "parser":
            None,
            "expected_position":
            None,
        },
        # Positional arguments parse test
        {
            "node": cst.Call(cst.Name("foo"),
                             (cst.Arg(value=cst.Integer("1")), )),
            "code": "foo(1)",
            "parser": parse_expression,
            "expected_position": None,
        },
        {
            "node":
            cst.Call(
                cst.Name("foo"),
                (cst.Arg(
                    value=cst.Integer("1"),
                    whitespace_after_arg=cst.SimpleWhitespace(" "),
                ), ),
                whitespace_after_func=cst.SimpleWhitespace(" "),
                whitespace_before_args=cst.SimpleWhitespace(" "),
            ),
            "code":
            "foo ( 1 )",
            "parser":
            parse_expression,
            "expected_position":
            None,
        },
        {
            "node":
            cst.Call(
                cst.Name("foo"),
                (cst.Arg(
                    value=cst.Integer("1"),
                    comma=cst.Comma(
                        whitespace_after=cst.SimpleWhitespace(" ")),
                ), ),
                whitespace_after_func=cst.SimpleWhitespace(" "),
                whitespace_before_args=cst.SimpleWhitespace(" "),
            ),
            "code":
            "foo ( 1, )",
            "parser":
            parse_expression,
            "expected_position":
            None,
        },
        {
            "node":
            cst.Call(
                cst.Name("foo"),
                (
                    cst.Arg(
                        value=cst.Integer("1"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        value=cst.Integer("2"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(value=cst.Integer("3")),
                ),
            ),
            "code":
            "foo(1, 2, 3)",
            "parser":
            parse_expression,
            "expected_position":
            None,
        },
        # Keyword arguments render test
        {
            "node":
            cst.Call(
                cst.Name("foo"),
                (cst.Arg(keyword=cst.Name("one"), value=cst.Integer("1")), ),
            ),
            "code":
            "foo(one = 1)",
            "parser":
            None,
            "expected_position":
            None,
        },
        {
            "node":
            cst.Call(
                cst.Name("foo"),
                (
                    cst.Arg(keyword=cst.Name("one"), value=cst.Integer("1")),
                    cst.Arg(keyword=cst.Name("two"), value=cst.Integer("2")),
                    cst.Arg(keyword=cst.Name("three"), value=cst.Integer("3")),
                ),
            ),
            "code":
            "foo(one = 1, two = 2, three = 3)",
            "parser":
            None,
            "expected_position":
            None,
        },
        # Keyword arguments parser test
        {
            "node":
            cst.Call(
                cst.Name("foo"),
                (cst.Arg(
                    keyword=cst.Name("one"),
                    equal=cst.AssignEqual(),
                    value=cst.Integer("1"),
                ), ),
            ),
            "code":
            "foo(one = 1)",
            "parser":
            parse_expression,
            "expected_position":
            None,
        },
        {
            "node":
            cst.Call(
                cst.Name("foo"),
                (
                    cst.Arg(
                        keyword=cst.Name("one"),
                        equal=cst.AssignEqual(),
                        value=cst.Integer("1"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        keyword=cst.Name("two"),
                        equal=cst.AssignEqual(),
                        value=cst.Integer("2"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        keyword=cst.Name("three"),
                        equal=cst.AssignEqual(),
                        value=cst.Integer("3"),
                    ),
                ),
            ),
            "code":
            "foo(one = 1, two = 2, three = 3)",
            "parser":
            parse_expression,
            "expected_position":
            None,
        },
        # Iterator expansion render test
        {
            "node":
            cst.Call(cst.Name("foo"),
                     (cst.Arg(star="*", value=cst.Name("one")), )),
            "code":
            "foo(*one)",
            "parser":
            None,
            "expected_position":
            None,
        },
        {
            "node":
            cst.Call(
                cst.Name("foo"),
                (
                    cst.Arg(star="*", value=cst.Name("one")),
                    cst.Arg(star="*", value=cst.Name("two")),
                    cst.Arg(star="*", value=cst.Name("three")),
                ),
            ),
            "code":
            "foo(*one, *two, *three)",
            "parser":
            None,
            "expected_position":
            None,
        },
        # Iterator expansion parser test
        {
            "node":
            cst.Call(cst.Name("foo"),
                     (cst.Arg(star="*", value=cst.Name("one")), )),
            "code":
            "foo(*one)",
            "parser":
            parse_expression,
            "expected_position":
            None,
        },
        {
            "node":
            cst.Call(
                cst.Name("foo"),
                (
                    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")),
                ),
            ),
            "code":
            "foo(*one, *two, *three)",
            "parser":
            parse_expression,
            "expected_position":
            None,
        },
        # Dictionary expansion render test
        {
            "node":
            cst.Call(cst.Name("foo"),
                     (cst.Arg(star="**", value=cst.Name("one")), )),
            "code":
            "foo(**one)",
            "parser":
            None,
            "expected_position":
            None,
        },
        {
            "node":
            cst.Call(
                cst.Name("foo"),
                (
                    cst.Arg(star="**", value=cst.Name("one")),
                    cst.Arg(star="**", value=cst.Name("two")),
                    cst.Arg(star="**", value=cst.Name("three")),
                ),
            ),
            "code":
            "foo(**one, **two, **three)",
            "parser":
            None,
            "expected_position":
            None,
        },
        # Dictionary expansion parser test
        {
            "node":
            cst.Call(cst.Name("foo"),
                     (cst.Arg(star="**", value=cst.Name("one")), )),
            "code":
            "foo(**one)",
            "parser":
            parse_expression,
            "expected_position":
            None,
        },
        {
            "node":
            cst.Call(
                cst.Name("foo"),
                (
                    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")),
                ),
            ),
            "code":
            "foo(**one, **two, **three)",
            "parser":
            parse_expression,
            "expected_position":
            None,
        },
        # Complicated mingling rules render test
        {
            "node":
            cst.Call(
                cst.Name("foo"),
                (
                    cst.Arg(value=cst.Name("pos1")),
                    cst.Arg(star="*", value=cst.Name("list1")),
                    cst.Arg(value=cst.Name("pos2")),
                    cst.Arg(value=cst.Name("pos3")),
                    cst.Arg(star="*", value=cst.Name("list2")),
                    cst.Arg(value=cst.Name("pos4")),
                    cst.Arg(star="*", value=cst.Name("list3")),
                    cst.Arg(keyword=cst.Name("kw1"), value=cst.Integer("1")),
                    cst.Arg(star="*", value=cst.Name("list4")),
                    cst.Arg(keyword=cst.Name("kw2"), value=cst.Integer("2")),
                    cst.Arg(star="*", value=cst.Name("list5")),
                    cst.Arg(keyword=cst.Name("kw3"), value=cst.Integer("3")),
                    cst.Arg(star="**", value=cst.Name("dict1")),
                    cst.Arg(keyword=cst.Name("kw4"), value=cst.Integer("4")),
                    cst.Arg(star="**", value=cst.Name("dict2")),
                ),
            ),
            "code":
            "foo(pos1, *list1, pos2, pos3, *list2, pos4, *list3, kw1 = 1, *list4, kw2 = 2, *list5, kw3 = 3, **dict1, kw4 = 4, **dict2)",
            "parser":
            None,
            "expected_position":
            None,
        },
        # Complicated mingling rules parser test
        {
            "node":
            cst.Call(
                cst.Name("foo"),
                (
                    cst.Arg(
                        value=cst.Name("pos1"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        star="*",
                        value=cst.Name("list1"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        value=cst.Name("pos2"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        value=cst.Name("pos3"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        star="*",
                        value=cst.Name("list2"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        value=cst.Name("pos4"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        star="*",
                        value=cst.Name("list3"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        keyword=cst.Name("kw1"),
                        equal=cst.AssignEqual(),
                        value=cst.Integer("1"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        star="*",
                        value=cst.Name("list4"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        keyword=cst.Name("kw2"),
                        equal=cst.AssignEqual(),
                        value=cst.Integer("2"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        star="*",
                        value=cst.Name("list5"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        keyword=cst.Name("kw3"),
                        equal=cst.AssignEqual(),
                        value=cst.Integer("3"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        star="**",
                        value=cst.Name("dict1"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        keyword=cst.Name("kw4"),
                        equal=cst.AssignEqual(),
                        value=cst.Integer("4"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(star="**", value=cst.Name("dict2")),
                ),
            ),
            "code":
            "foo(pos1, *list1, pos2, pos3, *list2, pos4, *list3, kw1 = 1, *list4, kw2 = 2, *list5, kw3 = 3, **dict1, kw4 = 4, **dict2)",
            "parser":
            parse_expression,
            "expected_position":
            None,
        },
        # Test whitespace
        {
            "node":
            cst.Call(
                lpar=(cst.LeftParen(
                    whitespace_after=cst.SimpleWhitespace(" ")), ),
                func=cst.Name("foo"),
                whitespace_after_func=cst.SimpleWhitespace(" "),
                whitespace_before_args=cst.SimpleWhitespace(" "),
                args=(
                    cst.Arg(
                        keyword=None,
                        value=cst.Name("pos1"),
                        comma=cst.Comma(
                            whitespace_before=cst.SimpleWhitespace(" "),
                            whitespace_after=cst.SimpleWhitespace("  "),
                        ),
                    ),
                    cst.Arg(
                        star="*",
                        whitespace_after_star=cst.SimpleWhitespace("  "),
                        keyword=None,
                        value=cst.Name("list1"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        keyword=cst.Name("kw1"),
                        equal=cst.AssignEqual(
                            whitespace_before=cst.SimpleWhitespace(""),
                            whitespace_after=cst.SimpleWhitespace(""),
                        ),
                        value=cst.Integer("1"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace(" ")),
                    ),
                    cst.Arg(
                        star="**",
                        keyword=None,
                        whitespace_after_star=cst.SimpleWhitespace(" "),
                        value=cst.Name("dict1"),
                        whitespace_after_arg=cst.SimpleWhitespace(" "),
                    ),
                ),
                rpar=(cst.RightParen(
                    whitespace_before=cst.SimpleWhitespace(" ")), ),
            ),
            "code":
            "( foo ( pos1 ,  *  list1, kw1=1, ** dict1 ) )",
            "parser":
            parse_expression,
            "expected_position":
            CodeRange.create((1, 2), (1, 43)),
        },
        # Test args
        {
            "node":
            cst.Arg(
                star="*",
                whitespace_after_star=cst.SimpleWhitespace("  "),
                keyword=None,
                value=cst.Name("list1"),
                comma=cst.Comma(whitespace_after=cst.SimpleWhitespace(" ")),
            ),
            "code":
            "*  list1, ",
            "parser":
            None,
            "expected_position":
            CodeRange.create((1, 0), (1, 8)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider((
        # Basic expression parenthesizing tests.
        {
            "get_node":
            lambda: cst.Call(func=cst.Name("foo"), lpar=(cst.LeftParen(), )),
            "expected_re":
            "left paren without right paren",
        },
        {
            "get_node":
            lambda: cst.Call(func=cst.Name("foo"), rpar=(cst.RightParen(), )),
            "expected_re":
            "right paren without left paren",
        },
        # Test that we handle keyword stuff correctly.
        {
            "get_node":
            lambda: cst.Call(
                func=cst.Name("foo"),
                args=(cst.Arg(equal=cst.AssignEqual(),
                              value=cst.SimpleString("'baz'")), ),
            ),
            "expected_re":
            "Must have a keyword when specifying an AssignEqual",
        },
        # Test that we separate *, ** and keyword args correctly
        {
            "get_node":
            lambda: cst.Call(
                func=cst.Name("foo"),
                args=(cst.Arg(
                    star="*",
                    keyword=cst.Name("bar"),
                    value=cst.SimpleString("'baz'"),
                ), ),
            ),
            "expected_re":
            "Cannot specify a star and a keyword together",
        },
        # Test for expected star inputs only
        {
            "get_node":
            lambda: cst.Call(
                func=cst.Name("foo"),
                # pyre-ignore: Ignore type on 'star' since we're testing behavior
                # when somebody isn't using a type checker.
                args=(cst.Arg(star="***", value=cst.SimpleString("'baz'")), ),
            ),
            "expected_re":
            r"Must specify either '', '\*' or '\*\*' for star",
        },
        # Test ordering exceptions
        {
            "get_node":
            lambda: cst.Call(
                func=cst.Name("foo"),
                args=(
                    cst.Arg(star="**", value=cst.Name("bar")),
                    cst.Arg(star="*", value=cst.Name("baz")),
                ),
            ),
            "expected_re":
            "Cannot have iterable argument unpacking after keyword argument unpacking",
        },
        {
            "get_node":
            lambda: cst.Call(
                func=cst.Name("foo"),
                args=(
                    cst.Arg(star="**", value=cst.Name("bar")),
                    cst.Arg(value=cst.Name("baz")),
                ),
            ),
            "expected_re":
            "Cannot have positional argument after keyword argument unpacking",
        },
        {
            "get_node":
            lambda: cst.Call(
                func=cst.Name("foo"),
                args=(
                    cst.Arg(keyword=cst.Name("arg"),
                            value=cst.SimpleString("'baz'")),
                    cst.Arg(value=cst.SimpleString("'bar'")),
                ),
            ),
            "expected_re":
            "Cannot have positional argument after keyword argument",
        },
    ))
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
示例#29
0
class BooleanOperationTest(CSTNodeTest):
    @data_provider(
        (
            # Simple boolean operations
            # pyre-fixme[6]: Incompatible parameter type
            {
                "node": cst.BooleanOperation(
                    cst.Name("foo"), cst.And(), cst.Name("bar")
                ),
                "code": "foo and bar",
                "parser": parse_expression,
                "expected_position": None,
            },
            {
                "node": cst.BooleanOperation(
                    cst.Name("foo"), cst.Or(), cst.Name("bar")
                ),
                "code": "foo or bar",
                "parser": parse_expression,
                "expected_position": None,
            },
            # Parenthesized boolean operation
            {
                "node": cst.BooleanOperation(
                    lpar=(cst.LeftParen(),),
                    left=cst.Name("foo"),
                    operator=cst.Or(),
                    right=cst.Name("bar"),
                    rpar=(cst.RightParen(),),
                ),
                "code": "(foo or bar)",
                "parser": parse_expression,
                "expected_position": None,
            },
            {
                "node": cst.BooleanOperation(
                    left=cst.Name(
                        "foo", lpar=(cst.LeftParen(),), rpar=(cst.RightParen(),)
                    ),
                    operator=cst.Or(
                        whitespace_before=cst.SimpleWhitespace(""),
                        whitespace_after=cst.SimpleWhitespace(""),
                    ),
                    right=cst.Name(
                        "bar", lpar=(cst.LeftParen(),), rpar=(cst.RightParen(),)
                    ),
                ),
                "code": "(foo)or(bar)",
                "parser": parse_expression,
                "expected_position": CodeRange.create((1, 0), (1, 12)),
            },
            # Make sure that spacing works
            {
                "node": cst.BooleanOperation(
                    lpar=(cst.LeftParen(whitespace_after=cst.SimpleWhitespace(" ")),),
                    left=cst.Name("foo"),
                    operator=cst.And(
                        whitespace_before=cst.SimpleWhitespace("  "),
                        whitespace_after=cst.SimpleWhitespace("  "),
                    ),
                    right=cst.Name("bar"),
                    rpar=(cst.RightParen(whitespace_before=cst.SimpleWhitespace(" ")),),
                ),
                "code": "( foo  and  bar )",
                "parser": parse_expression,
                "expected_position": None,
            },
        )
    )
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider(
        (
            {
                "get_node": lambda: cst.BooleanOperation(
                    cst.Name("foo"), cst.And(), cst.Name("bar"), lpar=(cst.LeftParen(),)
                ),
                "expected_re": "left paren without right paren",
            },
            {
                "get_node": lambda: cst.BooleanOperation(
                    cst.Name("foo"),
                    cst.And(),
                    cst.Name("bar"),
                    rpar=(cst.RightParen(),),
                ),
                "expected_re": "right paren without left paren",
            },
            {
                "get_node": lambda: cst.BooleanOperation(
                    left=cst.Name("foo"),
                    operator=cst.Or(
                        whitespace_before=cst.SimpleWhitespace(""),
                        whitespace_after=cst.SimpleWhitespace(""),
                    ),
                    right=cst.Name("bar"),
                ),
                "expected_re": "at least one space around boolean operator",
            },
        )
    )
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
示例#30
0
class IfTest(CSTNodeTest):
    @data_provider((
        # Simple if without elif or else
        # pyre-fixme[6]: Incompatible parameter type
        {
            "node":
            cst.If(cst.Name("conditional"),
                   cst.SimpleStatementSuite((cst.Pass(), ))),
            "code":
            "if conditional: pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange.create((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.create((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.create((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.create((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.create((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.create((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.create((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.create((1, 0), (5, 10)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)