Exemple #1
0
    def leave_FunctionDef(self, original_node: cst.FunctionDef,
                          updated_node: cst.FunctionDef) -> cst.FunctionDef:
        docstring = None
        docstring_node = get_docstring_node(updated_node.body)
        if docstring_node:
            if isinstance(docstring_node.value,
                          (cst.SimpleString, cst.ConcatenatedString)):
                docstring = docstring_node.value.evaluated_value
        if not docstring:
            return updated_node
        new_docstring, types = gather_types(docstring)
        if types.get(RETURN):
            updated_node = updated_node.with_changes(returns=cst.Annotation(
                cst.Name(types.pop(RETURN))), )

        if types:

            def get_annotation(p: cst.Param) -> Optional[cst.Annotation]:
                pname = p.name.value
                if types.get(pname):
                    return cst.Annotation(cst.parse_expression(types[pname]))
                return None

            updated_node = updated_node.with_changes(params=update_parameters(
                updated_node.params, get_annotation, False))

        new_docstring_node = cst.SimpleString('"""%s"""' % new_docstring)
        return updated_node.deep_replace(docstring_node,
                                         cst.Expr(new_docstring_node))
 def leave_Return(
     self, original_node: cst.Return, updated_node: cst.Return
 ) -> Union[cst.Return, RemovalSentinel,
            FlattenSentinel[cst.BaseSmallStatement]]:
     return FlattenSentinel([
         cst.Expr(parse_expression("print('returning')")),
         updated_node,
     ])
Exemple #3
0
    def test_deprecated_non_element_construction(self) -> None:
        module = cst.Module(body=[
            cst.SimpleStatementLine(body=[
                cst.Expr(value=cst.Subscript(
                    value=cst.Name(value="foo"),
                    slice=cst.Index(value=cst.Integer(value="1")),
                ))
            ])
        ])

        self.assertEqual(module.code, "foo[1]\n")
Exemple #4
0
    def test_parse_multiple_statements(self) -> None:
        # pylint: disable=pointless-statement
        def test_function(x, y):
            x
            y

        # pylint: enable=pointless-statement
        self.assert_node_equal(
            function_parser.parse(test_function)[0],
            libcst.SimpleStatementLine(body=[libcst.Expr(libcst.Name("x"))]),
        )
 def test_statement(self) -> None:
     # Test that we can insert various types of statements into a
     # statement list.
     module = parse_template_module(
         "{statement1}\n{statement2}\n{statement3}\n",
         statement1=cst.If(
             test=cst.Name("foo"), body=cst.SimpleStatementSuite((cst.Pass(),),),
         ),
         statement2=cst.SimpleStatementLine((cst.Expr(cst.Call(cst.Name("bar"))),),),
         statement3=cst.Pass(),
     )
     self.assertEqual(
         module.code, "if foo: pass\nbar()\npass\n",
     )
Exemple #6
0
def to_module(node: _T) -> cst.Module:
    if isinstance(node, cst.SimpleStatementSuite):
        return cst.Module(body=node.body)
    elif isinstance(node, cst.IndentedBlock):
        return cst.Module(body=node.body)

    if isinstance(node, cst.BaseExpression):
        node = cst.Expr(value=node)

    if isinstance(node, (cst.BaseStatement, cst.BaseSmallStatement)):
        node = cst.Module(body=(node, ))

    if isinstance(node, cst.Module):
        return node

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

    @data_provider(
        (
            (
                lambda: cst.Tuple([], lpar=[], rpar=[]),
                "A zero-length tuple must be wrapped in parentheses.",
            ),
            (
                lambda: cst.Tuple(
                    [cst.Element(cst.Name("mismatched"))],
                    lpar=[cst.LeftParen(), cst.LeftParen()],
                    rpar=[cst.RightParen()],
                ),
                "unbalanced parens",
            ),
            (
                lambda: cst.For(
                    target=cst.Tuple([cst.Element(cst.Name("el"))], lpar=[], rpar=[]),
                    iter=cst.Name("it"),
                    body=cst.SimpleStatementSuite([cst.Pass()]),
                    whitespace_after_for=cst.SimpleWhitespace(""),
                ),
                "Must have at least one space after 'for' keyword.",
            ),
            (
                lambda: cst.For(
                    target=cst.Tuple([cst.Element(cst.Name("el"))], lpar=[], rpar=[]),
                    iter=cst.Name("it"),
                    body=cst.SimpleStatementSuite([cst.Pass()]),
                    whitespace_before_in=cst.SimpleWhitespace(""),
                ),
                "Must have at least one space before 'in' keyword.",
            ),
            # an additional check for StarredElement, since it's a separate codepath
            (
                lambda: cst.For(
                    target=cst.Tuple(
                        [cst.StarredElement(cst.Name("el"))], lpar=[], rpar=[]
                    ),
                    iter=cst.Name("it"),
                    body=cst.SimpleStatementSuite([cst.Pass()]),
                    whitespace_before_in=cst.SimpleWhitespace(""),
                ),
                "Must have at least one space before 'in' keyword.",
            ),
        )
    )
    def test_invalid(
        self, get_node: Callable[[], cst.CSTNode], expected_re: str
    ) -> None:
        self.assert_invalid(get_node, expected_re)
Exemple #8
0
class AwaitTest(CSTNodeTest):
    @data_provider((
        # Some simple calls
        {
            "node":
            cst.Await(cst.Name("test")),
            "code":
            "await test",
            "parser":
            lambda code: parse_expression(
                code, config=PartialParserConfig(python_version="3.7")),
            "expected_position":
            None,
        },
        {
            "node":
            cst.Await(cst.Call(cst.Name("test"))),
            "code":
            "await test()",
            "parser":
            lambda code: parse_expression(
                code, config=PartialParserConfig(python_version="3.7")),
            "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":
            lambda code: parse_expression(
                code, config=PartialParserConfig(python_version="3.7")),
            "expected_position":
            CodeRange((1, 2), (1, 13)),
        },
    ))
    def test_valid_py37(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((
        # Some simple calls
        {
            "node":
            cst.FunctionDef(
                cst.Name("foo"),
                cst.Parameters(),
                cst.IndentedBlock((cst.SimpleStatementLine(
                    (cst.Expr(cst.Await(cst.Name("test"))), )), )),
                asynchronous=cst.Asynchronous(),
            ),
            "code":
            "async def foo():\n    await test\n",
            "parser":
            lambda code: parse_statement(
                code, config=PartialParserConfig(python_version="3.6")),
            "expected_position":
            None,
        },
        {
            "node":
            cst.FunctionDef(
                cst.Name("foo"),
                cst.Parameters(),
                cst.IndentedBlock((cst.SimpleStatementLine(
                    (cst.Expr(cst.Await(cst.Call(cst.Name("test")))), )), )),
                asynchronous=cst.Asynchronous(),
            ),
            "code":
            "async def foo():\n    await test()\n",
            "parser":
            lambda code: parse_statement(
                code, config=PartialParserConfig(python_version="3.6")),
            "expected_position":
            None,
        },
        # Whitespace
        {
            "node":
            cst.FunctionDef(
                cst.Name("foo"),
                cst.Parameters(),
                cst.IndentedBlock((cst.SimpleStatementLine((cst.Expr(
                    cst.Await(
                        cst.Name("test"),
                        whitespace_after_await=cst.SimpleWhitespace("  "),
                        lpar=(cst.LeftParen(
                            whitespace_after=cst.SimpleWhitespace(" ")), ),
                        rpar=(cst.RightParen(
                            whitespace_before=cst.SimpleWhitespace(" ")), ),
                    )), )), )),
                asynchronous=cst.Asynchronous(),
            ),
            "code":
            "async def foo():\n    ( await  test )\n",
            "parser":
            lambda code: parse_statement(
                code, config=PartialParserConfig(python_version="3.6")),
            "expected_position":
            None,
        },
    ))
    def test_valid_py36(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)
class SmallStatementTest(CSTNodeTest):
    @data_provider((
        # pyre-fixme[6]: Incompatible parameter type
        {
            "node": cst.Pass(),
            "code": "pass"
        },
        {
            "node": cst.Pass(semicolon=cst.Semicolon()),
            "code": "pass;"
        },
        {
            "node":
            cst.Pass(semicolon=cst.Semicolon(
                whitespace_before=cst.SimpleWhitespace("  "),
                whitespace_after=cst.SimpleWhitespace("    "),
            )),
            "code":
            "pass  ;    ",
            "expected_position":
            CodeRange((1, 0), (1, 4)),
        },
        {
            "node": cst.Continue(),
            "code": "continue"
        },
        {
            "node": cst.Continue(semicolon=cst.Semicolon()),
            "code": "continue;"
        },
        {
            "node":
            cst.Continue(semicolon=cst.Semicolon(
                whitespace_before=cst.SimpleWhitespace("  "),
                whitespace_after=cst.SimpleWhitespace("    "),
            )),
            "code":
            "continue  ;    ",
            "expected_position":
            CodeRange((1, 0), (1, 8)),
        },
        {
            "node": cst.Break(),
            "code": "break"
        },
        {
            "node": cst.Break(semicolon=cst.Semicolon()),
            "code": "break;"
        },
        {
            "node":
            cst.Break(semicolon=cst.Semicolon(
                whitespace_before=cst.SimpleWhitespace("  "),
                whitespace_after=cst.SimpleWhitespace("    "),
            )),
            "code":
            "break  ;    ",
            "expected_position":
            CodeRange((1, 0), (1, 5)),
        },
        {
            "node":
            cst.Expr(
                cst.BinaryOperation(cst.Name("x"), cst.Add(), cst.Name("y"))),
            "code":
            "x + y",
        },
        {
            "node":
            cst.Expr(
                cst.BinaryOperation(cst.Name("x"), cst.Add(), cst.Name("y")),
                semicolon=cst.Semicolon(),
            ),
            "code":
            "x + y;",
        },
        {
            "node":
            cst.Expr(
                cst.BinaryOperation(cst.Name("x"), cst.Add(), cst.Name("y")),
                semicolon=cst.Semicolon(
                    whitespace_before=cst.SimpleWhitespace("  "),
                    whitespace_after=cst.SimpleWhitespace("    "),
                ),
            ),
            "code":
            "x + y  ;    ",
            "expected_position":
            CodeRange((1, 0), (1, 5)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)
Exemple #10
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((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((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":
            lambda code: parse_expression(
                code, config=PartialParserConfig(python_version="3.7")),
        },
        # Python 3.6 async GeneratorExp
        {
            "node":
            cst.FunctionDef(
                cst.Name("foo"),
                cst.Parameters(),
                cst.IndentedBlock((cst.SimpleStatementLine((cst.Expr(
                    cst.GeneratorExp(
                        cst.Name("a"),
                        cst.CompFor(
                            target=cst.Name("b"),
                            iter=cst.Name("c"),
                            asynchronous=cst.Asynchronous(),
                        ),
                    )), )), )),
                asynchronous=cst.Asynchronous(),
            ),
            "code":
            "async def foo():\n    (a async for b in c)\n",
            "parser":
            lambda code: parse_statement(
                code, config=PartialParserConfig(python_version="3.6")),
        },
        # 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((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((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((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((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)
Exemple #11
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)
Exemple #12
0
 def body(self, indent: int) -> typing.Iterable[cst.BaseSmallStatement]:
     yield cst.Expr(self.docstring(indent))
     yield cst.Expr(cst.Ellipsis())
Exemple #13
0
 def _expression_to_string(expression: libcst.BaseExpression) -> str:
     return libcst.Module([
         libcst.SimpleStatementLine([libcst.Expr(expression)])
     ]).code.strip()