Esempio n. 1
0
class ReturnCreateTest(CSTNodeTest):
    @data_provider((
        {
            "node": cst.SimpleStatementLine([cst.Return()]),
            "code": "return\n",
            "expected_position": CodeRange((1, 0), (1, 6)),
        },
        {
            "node": cst.SimpleStatementLine([cst.Return(cst.Name("abc"))]),
            "code": "return abc\n",
            "expected_position": CodeRange((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)
 def _create_issue(self, node: cst.Module) -> None:
     file_range = self.get_metadata(PositionProvider, node)
     code_range = CodeRange(start=file_range.start, end=file_range.start)
     issue = CodeQualityIssue(
         code_range, self.path, "PYRE_STRICT", "Unsafe Pyre file."
     )
     self.issues.append(issue)
Esempio n. 3
0
    def test_position(self) -> None:
        # create a dummy node
        node = cst.Pass()

        # simulate codegen behavior for the dummy node
        # generates the code " pass "
        state = PositionProvidingCodegenState(" " * 4, "\n", PositionProvider())
        start = CodePosition(state.line, state.column)
        state.add_token(" ")
        with state.record_syntactic_position(node):
            state.add_token("pass")
        state.add_token(" ")
        end = CodePosition(state.line, state.column)
        state.record_position(node, CodeRange(start, end))

        # check syntactic position ignores whitespace
        self.assertEqual(state.provider._computed[node], CodeRange((1, 1), (1, 5)))
Esempio n. 4
0
 def test_coverage_percentage(self) -> None:
     coverage_result = to_coverage_result(
         CoveredAndUncoveredLines({1, 2}, {3, 4}),
         uncovered_ranges=[
             CodeRange(CodePosition(line=3, column=3),
                       CodePosition(line=4, column=4))
         ],
     )
     self.assertEqual(coverage_result.covered_percent, 50.0)
     self.assertEqual(len(coverage_result.uncovered_ranges), 1)
Esempio n. 5
0
    def test_whitespace_inclusive_position(self) -> None:
        # create a dummy node
        node = cst.Pass()

        # simulate codegen behavior for the dummy node
        # generates the code " pass "
        state = WhitespaceInclusivePositionProvidingCodegenState(
            " " * 4, "\n", WhitespaceInclusivePositionProvider()
        )
        start = CodePosition(state.line, state.column)
        state.add_token(" ")
        with state.record_syntactic_position(node):
            state.add_token("pass")
        state.add_token(" ")
        end = CodePosition(state.line, state.column)
        state.record_position(node, CodeRange(start, end))

        # check whitespace is correctly recorded
        self.assertEqual(state.provider._computed[node], CodeRange((1, 0), (1, 6)))
Esempio n. 6
0
 def test_return_code_range(self) -> None:
     collector = self._build_and_visit_annotation_collector("""
         def foobar():
             pass
         """)
     returns = list(collector.returns())
     self.assertEqual(len(returns), 1)
     self.assertEqual(
         returns[0].code_range,
         CodeRange(CodePosition(2, 4), CodePosition(2, 10)),
     )
Esempio n. 7
0
    def visit_Call(self, node: libcst.Call) -> None:
        node_range = self.get_metadata(PositionProvider, node)

        start_node = node.func
        while isinstance(start_node, libcst.Attribute):
            start_node = start_node.attr
        start_node_range = self.get_metadata(PositionProvider, start_node)
        start_position = start_node_range.start
        end_position = node_range.end
        node_range = CodeRange(start=start_position, end=end_position)

        self.function_calls.append((node, node_range))
Esempio n. 8
0
class ElseTest(CSTNodeTest):
    @data_provider((
        {
            "node": cst.Else(cst.SimpleStatementSuite((cst.Pass(), ))),
            "code": "else: pass\n",
            "expected_position": CodeRange((1, 0), (1, 10)),
        },
        {
            "node":
            cst.Else(
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_before_colon=cst.SimpleWhitespace("  "),
            ),
            "code":
            "else  : pass\n",
            "expected_position":
            CodeRange((1, 0), (1, 12)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)
Esempio n. 9
0
 def test_coverage_diagnostics(self) -> None:
     self.assertEqual(
         uncovered_range_to_diagnostic(
             CodeRange(CodePosition(line=1, column=1),
                       CodePosition(line=2, column=2))),
         lsp.Diagnostic(
             range=lsp.Range(
                 start=lsp.Position(line=0, character=1),
                 end=lsp.Position(line=1, character=2),
             ),
             message=(
                 "This function is not type checked. "
                 "Consider adding parameter or return type annotations."),
         ),
     )
Esempio n. 10
0
    def test_equal_range(self) -> None:
        test = self
        expected_range = CodeRange((1, 4), (1, 6))

        class EqualPositionVisitor(CSTVisitor):
            METADATA_DEPENDENCIES = (PositionProvider,)

            def visit_Equal(self, node: cst.Equal) -> None:
                test.assertEqual(
                    self.get_metadata(PositionProvider, node), expected_range
                )

            def visit_NotEqual(self, node: cst.NotEqual) -> None:
                test.assertEqual(
                    self.get_metadata(PositionProvider, node), expected_range
                )

        MetadataWrapper(parse_module("var == 1")).visit(EqualPositionVisitor())
        MetadataWrapper(parse_module("var != 1")).visit(EqualPositionVisitor())
Esempio n. 11
0
class TryTest(CSTNodeTest):
    @data_provider(
        (
            # Simple try/except block
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_except=cst.SimpleWhitespace(""),
                        ),
                    ),
                ),
                "code": "try: pass\nexcept: pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((1, 0), (2, 12)),
            },
            # Try/except with a class
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            type=cst.Name("Exception"),
                        ),
                    ),
                ),
                "code": "try: pass\nexcept Exception: pass\n",
                "parser": parse_statement,
            },
            # Try/except with a named class
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            type=cst.Name("Exception"),
                            name=cst.AsName(cst.Name("exc")),
                        ),
                    ),
                ),
                "code": "try: pass\nexcept Exception as exc: pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((1, 0), (2, 29)),
            },
            # Try/except with multiple clauses
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            type=cst.Name("TypeError"),
                            name=cst.AsName(cst.Name("e")),
                        ),
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            type=cst.Name("KeyError"),
                            name=cst.AsName(cst.Name("e")),
                        ),
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_except=cst.SimpleWhitespace(""),
                        ),
                    ),
                ),
                "code": "try: pass\n"
                + "except TypeError as e: pass\n"
                + "except KeyError as e: pass\n"
                + "except: pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((1, 0), (4, 12)),
            },
            # Simple try/finally block
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    finalbody=cst.Finally(cst.SimpleStatementSuite((cst.Pass(),))),
                ),
                "code": "try: pass\nfinally: pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((1, 0), (2, 13)),
            },
            # Simple try/except/finally block
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_except=cst.SimpleWhitespace(""),
                        ),
                    ),
                    finalbody=cst.Finally(cst.SimpleStatementSuite((cst.Pass(),))),
                ),
                "code": "try: pass\nexcept: pass\nfinally: pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((1, 0), (3, 13)),
            },
            # Simple try/except/else block
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_except=cst.SimpleWhitespace(""),
                        ),
                    ),
                    orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(),))),
                ),
                "code": "try: pass\nexcept: pass\nelse: pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((1, 0), (3, 10)),
            },
            # Simple try/except/else block/finally
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_except=cst.SimpleWhitespace(""),
                        ),
                    ),
                    orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(),))),
                    finalbody=cst.Finally(cst.SimpleStatementSuite((cst.Pass(),))),
                ),
                "code": "try: pass\nexcept: pass\nelse: pass\nfinally: pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((1, 0), (4, 13)),
            },
            # Verify whitespace in various locations
            {
                "node": cst.Try(
                    leading_lines=(cst.EmptyLine(comment=cst.Comment("# 1")),),
                    body=cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            leading_lines=(cst.EmptyLine(comment=cst.Comment("# 2")),),
                            type=cst.Name("TypeError"),
                            name=cst.AsName(
                                cst.Name("e"),
                                whitespace_before_as=cst.SimpleWhitespace("  "),
                                whitespace_after_as=cst.SimpleWhitespace("  "),
                            ),
                            whitespace_after_except=cst.SimpleWhitespace("  "),
                            whitespace_before_colon=cst.SimpleWhitespace(" "),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                    ),
                    orelse=cst.Else(
                        leading_lines=(cst.EmptyLine(comment=cst.Comment("# 3")),),
                        body=cst.SimpleStatementSuite((cst.Pass(),)),
                        whitespace_before_colon=cst.SimpleWhitespace(" "),
                    ),
                    finalbody=cst.Finally(
                        leading_lines=(cst.EmptyLine(comment=cst.Comment("# 4")),),
                        body=cst.SimpleStatementSuite((cst.Pass(),)),
                        whitespace_before_colon=cst.SimpleWhitespace(" "),
                    ),
                    whitespace_before_colon=cst.SimpleWhitespace(" "),
                ),
                "code": "# 1\ntry : pass\n# 2\nexcept  TypeError  as  e : pass\n# 3\nelse : pass\n# 4\nfinally : pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((2, 0), (8, 14)),
            },
            # Please don't write code like this
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            type=cst.Name("TypeError"),
                            name=cst.AsName(cst.Name("e")),
                        ),
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            type=cst.Name("KeyError"),
                            name=cst.AsName(cst.Name("e")),
                        ),
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_except=cst.SimpleWhitespace(""),
                        ),
                    ),
                    orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(),))),
                    finalbody=cst.Finally(cst.SimpleStatementSuite((cst.Pass(),))),
                ),
                "code": "try: pass\n"
                + "except TypeError as e: pass\n"
                + "except KeyError as e: pass\n"
                + "except: pass\n"
                + "else: pass\n"
                + "finally: pass\n",
                "parser": parse_statement,
                "expected_position": CodeRange((1, 0), (6, 13)),
            },
            # Verify indentation
            {
                "node": DummyIndentedBlock(
                    "    ",
                    cst.Try(
                        cst.SimpleStatementSuite((cst.Pass(),)),
                        handlers=(
                            cst.ExceptHandler(
                                cst.SimpleStatementSuite((cst.Pass(),)),
                                type=cst.Name("TypeError"),
                                name=cst.AsName(cst.Name("e")),
                            ),
                            cst.ExceptHandler(
                                cst.SimpleStatementSuite((cst.Pass(),)),
                                type=cst.Name("KeyError"),
                                name=cst.AsName(cst.Name("e")),
                            ),
                            cst.ExceptHandler(
                                cst.SimpleStatementSuite((cst.Pass(),)),
                                whitespace_after_except=cst.SimpleWhitespace(""),
                            ),
                        ),
                        orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(),))),
                        finalbody=cst.Finally(cst.SimpleStatementSuite((cst.Pass(),))),
                    ),
                ),
                "code": "    try: pass\n"
                + "    except TypeError as e: pass\n"
                + "    except KeyError as e: pass\n"
                + "    except: pass\n"
                + "    else: pass\n"
                + "    finally: pass\n",
                "parser": None,
            },
            # Verify indentation in bodies
            {
                "node": DummyIndentedBlock(
                    "    ",
                    cst.Try(
                        cst.IndentedBlock((cst.SimpleStatementLine((cst.Pass(),)),)),
                        handlers=(
                            cst.ExceptHandler(
                                cst.IndentedBlock(
                                    (cst.SimpleStatementLine((cst.Pass(),)),)
                                ),
                                whitespace_after_except=cst.SimpleWhitespace(""),
                            ),
                        ),
                        orelse=cst.Else(
                            cst.IndentedBlock((cst.SimpleStatementLine((cst.Pass(),)),))
                        ),
                        finalbody=cst.Finally(
                            cst.IndentedBlock((cst.SimpleStatementLine((cst.Pass(),)),))
                        ),
                    ),
                ),
                "code": "    try:\n"
                + "        pass\n"
                + "    except:\n"
                + "        pass\n"
                + "    else:\n"
                + "        pass\n"
                + "    finally:\n"
                + "        pass\n",
                "parser": None,
            },
            # No space when using grouping parens
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_except=cst.SimpleWhitespace(""),
                            type=cst.Name(
                                "Exception",
                                lpar=(cst.LeftParen(),),
                                rpar=(cst.RightParen(),),
                            ),
                        ),
                    ),
                ),
                "code": "try: pass\nexcept(Exception): pass\n",
                "parser": parse_statement,
            },
            # No space when using tuple
            {
                "node": cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    handlers=(
                        cst.ExceptHandler(
                            cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_except=cst.SimpleWhitespace(""),
                            type=cst.Tuple(
                                [
                                    cst.Element(
                                        cst.Name("IOError"),
                                        comma=cst.Comma(
                                            whitespace_after=cst.SimpleWhitespace(" ")
                                        ),
                                    ),
                                    cst.Element(cst.Name("ImportError")),
                                ]
                            ),
                        ),
                    ),
                ),
                "code": "try: pass\nexcept(IOError, ImportError): pass\n",
                "parser": parse_statement,
            },
        )
    )
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider(
        (
            {
                "get_node": lambda: cst.AsName(cst.Name("")),
                "expected_re": "empty name identifier",
            },
            {
                "get_node": lambda: cst.AsName(
                    cst.Name("bla"), whitespace_after_as=cst.SimpleWhitespace("")
                ),
                "expected_re": "between 'as'",
            },
            {
                "get_node": lambda: cst.AsName(
                    cst.Name("bla"), whitespace_before_as=cst.SimpleWhitespace("")
                ),
                "expected_re": "before 'as'",
            },
            {
                "get_node": lambda: cst.ExceptHandler(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    name=cst.AsName(cst.Name("bla")),
                ),
                "expected_re": "name for an empty type",
            },
            {
                "get_node": lambda: cst.ExceptHandler(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    type=cst.Name("TypeError"),
                    whitespace_after_except=cst.SimpleWhitespace(""),
                ),
                "expected_re": "at least one space after except",
            },
            {
                "get_node": lambda: cst.Try(cst.SimpleStatementSuite((cst.Pass(),))),
                "expected_re": "at least one ExceptHandler or Finally",
            },
            {
                "get_node": lambda: cst.Try(
                    cst.SimpleStatementSuite((cst.Pass(),)),
                    orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(),))),
                    finalbody=cst.Finally(cst.SimpleStatementSuite((cst.Pass(),))),
                ),
                "expected_re": "at least one ExceptHandler in order to have an Else",
            },
        )
    )
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
Esempio n. 12
0
class IfTest(CSTNodeTest):
    @data_provider((
        # Simple if without elif or else
        {
            "node":
            cst.If(cst.Name("conditional"),
                   cst.SimpleStatementSuite((cst.Pass(), ))),
            "code":
            "if conditional: pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (1, 20)),
        },
        # else clause
        {
            "node":
            cst.If(
                cst.Name("conditional"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(), ))),
            ),
            "code":
            "if conditional: pass\nelse: pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (2, 10)),
        },
        # elif clause
        {
            "node":
            cst.If(
                cst.Name("conditional"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                orelse=cst.If(
                    cst.Name("other_conditional"),
                    cst.SimpleStatementSuite((cst.Pass(), )),
                    orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(), ))),
                ),
            ),
            "code":
            "if conditional: pass\nelif other_conditional: pass\nelse: pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (3, 10)),
        },
        # indentation
        {
            "node":
            DummyIndentedBlock(
                "    ",
                cst.If(
                    cst.Name("conditional"),
                    cst.SimpleStatementSuite((cst.Pass(), )),
                    orelse=cst.Else(cst.SimpleStatementSuite((cst.Pass(), ))),
                ),
            ),
            "code":
            "    if conditional: pass\n    else: pass\n",
            "parser":
            None,
            "expected_position":
            CodeRange((1, 4), (2, 14)),
        },
        # with an indented body
        {
            "node":
            DummyIndentedBlock(
                "    ",
                cst.If(
                    cst.Name("conditional"),
                    cst.IndentedBlock((cst.SimpleStatementLine(
                        (cst.Pass(), )), )),
                ),
            ),
            "code":
            "    if conditional:\n        pass\n",
            "parser":
            None,
            "expected_position":
            CodeRange((1, 4), (2, 12)),
        },
        # leading_lines
        {
            "node":
            cst.If(
                cst.Name("conditional"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                leading_lines=(cst.EmptyLine(
                    comment=cst.Comment("# leading comment")), ),
            ),
            "code":
            "# leading comment\nif conditional: pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((2, 0), (2, 20)),
        },
        # whitespace before/after test and else
        {
            "node":
            cst.If(
                cst.Name("conditional"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_before_test=cst.SimpleWhitespace("   "),
                whitespace_after_test=cst.SimpleWhitespace("  "),
                orelse=cst.Else(
                    cst.SimpleStatementSuite((cst.Pass(), )),
                    whitespace_before_colon=cst.SimpleWhitespace(" "),
                ),
            ),
            "code":
            "if   conditional  : pass\nelse : pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (2, 11)),
        },
        # empty lines between if/elif/else clauses, not captured by the suite.
        {
            "node":
            cst.If(
                cst.Name("test_a"),
                cst.SimpleStatementSuite((cst.Pass(), )),
                orelse=cst.If(
                    cst.Name("test_b"),
                    cst.SimpleStatementSuite((cst.Pass(), )),
                    leading_lines=(cst.EmptyLine(), ),
                    orelse=cst.Else(
                        cst.SimpleStatementSuite((cst.Pass(), )),
                        leading_lines=(cst.EmptyLine(), ),
                    ),
                ),
            ),
            "code":
            "if test_a: pass\n\nelif test_b: pass\n\nelse: pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (5, 10)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)
Esempio n. 13
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((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((1, 2), (1, 20)),
        ),
        # From expression position tests
        (
            cst.From(cst.Integer("5"),
                     whitespace_after_from=cst.SimpleWhitespace(" ")),
            "from 5",
            CodeRange((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)
Esempio n. 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((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((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((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)
Esempio n. 15
0
class AugAssignTest(CSTNodeTest):
    @data_provider((
        # Simple assignment constructor case.
        {
            "node":
            cst.AugAssign(cst.Name("foo"), cst.AddAssign(), cst.Integer("5")),
            "code":
            "foo += 5",
            "parser":
            None,
            "expected_position":
            CodeRange((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((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)
Esempio n. 16
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((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((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((1, 1), (1, 5)),
            ),
            (
                cst.UnaryOperation(
                    operator=cst.Minus(),
                    expression=cst.UnaryOperation(
                        operator=cst.Minus(), expression=cst.Integer("5")
                    ),
                ),
                "--5",
                parse_expression,
                CodeRange((1, 0), (1, 3)),
            ),
            # multiple nested parenthesis
            (
                cst.Integer(
                    "5",
                    lpar=(cst.LeftParen(), cst.LeftParen()),
                    rpar=(cst.RightParen(), cst.RightParen()),
                ),
                "((5))",
                parse_expression,
                CodeRange((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((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)
Esempio n. 17
0
class SubscriptTest(CSTNodeTest):
    @data_provider((
        # Simple subscript expression
        (
            cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(cst.Index(cst.Integer("5"))), ),
            ),
            "foo[5]",
            True,
        ),
        # Test creation of subscript with slice/extslice.
        (
            cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(
                    cst.Slice(
                        lower=cst.Integer("1"),
                        upper=cst.Integer("2"),
                        step=cst.Integer("3"),
                    )), ),
            ),
            "foo[1:2:3]",
            False,
        ),
        (
            cst.Subscript(
                cst.Name("foo"),
                (
                    cst.SubscriptElement(
                        cst.Slice(
                            lower=cst.Integer("1"),
                            upper=cst.Integer("2"),
                            step=cst.Integer("3"),
                        )),
                    cst.SubscriptElement(cst.Index(cst.Integer("5"))),
                ),
            ),
            "foo[1:2:3, 5]",
            False,
            CodeRange((1, 0), (1, 13)),
        ),
        # Test parsing of subscript with slice/extslice.
        (
            cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(
                    cst.Slice(
                        lower=cst.Integer("1"),
                        first_colon=cst.Colon(),
                        upper=cst.Integer("2"),
                        second_colon=cst.Colon(),
                        step=cst.Integer("3"),
                    )), ),
            ),
            "foo[1:2:3]",
            True,
        ),
        (
            cst.Subscript(
                cst.Name("foo"),
                (
                    cst.SubscriptElement(
                        cst.Slice(
                            lower=cst.Integer("1"),
                            first_colon=cst.Colon(),
                            upper=cst.Integer("2"),
                            second_colon=cst.Colon(),
                            step=cst.Integer("3"),
                        ),
                        comma=cst.Comma(),
                    ),
                    cst.SubscriptElement(cst.Index(cst.Integer("5"))),
                ),
            ),
            "foo[1:2:3,5]",
            True,
        ),
        # Some more wild slice creations
        (
            cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(
                    cst.Slice(lower=cst.Integer("1"),
                              upper=cst.Integer("2"))), ),
            ),
            "foo[1:2]",
            True,
        ),
        (
            cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(
                    cst.Slice(lower=cst.Integer("1"), upper=None)), ),
            ),
            "foo[1:]",
            True,
        ),
        (
            cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(
                    cst.Slice(lower=None, upper=cst.Integer("2"))), ),
            ),
            "foo[:2]",
            True,
        ),
        (
            cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(
                    cst.Slice(
                        lower=cst.Integer("1"),
                        upper=None,
                        step=cst.Integer("3"),
                    )), ),
            ),
            "foo[1::3]",
            False,
        ),
        (
            cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(
                    cst.Slice(lower=None, upper=None,
                              step=cst.Integer("3"))), ),
            ),
            "foo[::3]",
            False,
            CodeRange((1, 0), (1, 8)),
        ),
        # Some more wild slice parsings
        (
            cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(
                    cst.Slice(lower=cst.Integer("1"),
                              upper=cst.Integer("2"))), ),
            ),
            "foo[1:2]",
            True,
        ),
        (
            cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(
                    cst.Slice(lower=cst.Integer("1"), upper=None)), ),
            ),
            "foo[1:]",
            True,
        ),
        (
            cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(
                    cst.Slice(lower=None, upper=cst.Integer("2"))), ),
            ),
            "foo[:2]",
            True,
        ),
        (
            cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(
                    cst.Slice(
                        lower=cst.Integer("1"),
                        upper=None,
                        second_colon=cst.Colon(),
                        step=cst.Integer("3"),
                    )), ),
            ),
            "foo[1::3]",
            True,
        ),
        (
            cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(
                    cst.Slice(
                        lower=None,
                        upper=None,
                        second_colon=cst.Colon(),
                        step=cst.Integer("3"),
                    )), ),
            ),
            "foo[::3]",
            True,
        ),
        # Valid list clone operations rendering
        (
            cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(cst.Slice(lower=None, upper=None)), ),
            ),
            "foo[:]",
            True,
        ),
        (
            cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(
                    cst.Slice(
                        lower=None,
                        upper=None,
                        second_colon=cst.Colon(),
                        step=None,
                    )), ),
            ),
            "foo[::]",
            True,
        ),
        # Valid list clone operations parsing
        (
            cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(cst.Slice(lower=None, upper=None)), ),
            ),
            "foo[:]",
            True,
        ),
        (
            cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(
                    cst.Slice(
                        lower=None,
                        upper=None,
                        second_colon=cst.Colon(),
                        step=None,
                    )), ),
            ),
            "foo[::]",
            True,
        ),
        # In parenthesis
        (
            cst.Subscript(
                lpar=(cst.LeftParen(), ),
                value=cst.Name("foo"),
                slice=(cst.SubscriptElement(cst.Index(cst.Integer("5"))), ),
                rpar=(cst.RightParen(), ),
            ),
            "(foo[5])",
            True,
        ),
        # Verify spacing
        (
            cst.Subscript(
                lpar=(cst.LeftParen(
                    whitespace_after=cst.SimpleWhitespace(" ")), ),
                value=cst.Name("foo"),
                lbracket=cst.LeftSquareBracket(
                    whitespace_after=cst.SimpleWhitespace(" ")),
                slice=(cst.SubscriptElement(cst.Index(cst.Integer("5"))), ),
                rbracket=cst.RightSquareBracket(
                    whitespace_before=cst.SimpleWhitespace(" ")),
                rpar=(cst.RightParen(
                    whitespace_before=cst.SimpleWhitespace(" ")), ),
                whitespace_after_value=cst.SimpleWhitespace(" "),
            ),
            "( foo [ 5 ] )",
            True,
        ),
        (
            cst.Subscript(
                lpar=(cst.LeftParen(
                    whitespace_after=cst.SimpleWhitespace(" ")), ),
                value=cst.Name("foo"),
                lbracket=cst.LeftSquareBracket(
                    whitespace_after=cst.SimpleWhitespace(" ")),
                slice=(cst.SubscriptElement(
                    cst.Slice(
                        lower=cst.Integer("1"),
                        first_colon=cst.Colon(
                            whitespace_before=cst.SimpleWhitespace(" "),
                            whitespace_after=cst.SimpleWhitespace(" "),
                        ),
                        upper=cst.Integer("2"),
                        second_colon=cst.Colon(
                            whitespace_before=cst.SimpleWhitespace(" "),
                            whitespace_after=cst.SimpleWhitespace(" "),
                        ),
                        step=cst.Integer("3"),
                    )), ),
                rbracket=cst.RightSquareBracket(
                    whitespace_before=cst.SimpleWhitespace(" ")),
                rpar=(cst.RightParen(
                    whitespace_before=cst.SimpleWhitespace(" ")), ),
                whitespace_after_value=cst.SimpleWhitespace(" "),
            ),
            "( foo [ 1 : 2 : 3 ] )",
            True,
        ),
        (
            cst.Subscript(
                lpar=(cst.LeftParen(
                    whitespace_after=cst.SimpleWhitespace(" ")), ),
                value=cst.Name("foo"),
                lbracket=cst.LeftSquareBracket(
                    whitespace_after=cst.SimpleWhitespace(" ")),
                slice=(
                    cst.SubscriptElement(
                        slice=cst.Slice(
                            lower=cst.Integer("1"),
                            first_colon=cst.Colon(
                                whitespace_before=cst.SimpleWhitespace(" "),
                                whitespace_after=cst.SimpleWhitespace(" "),
                            ),
                            upper=cst.Integer("2"),
                            second_colon=cst.Colon(
                                whitespace_before=cst.SimpleWhitespace(" "),
                                whitespace_after=cst.SimpleWhitespace(" "),
                            ),
                            step=cst.Integer("3"),
                        ),
                        comma=cst.Comma(
                            whitespace_before=cst.SimpleWhitespace(" "),
                            whitespace_after=cst.SimpleWhitespace("  "),
                        ),
                    ),
                    cst.SubscriptElement(slice=cst.Index(cst.Integer("5"))),
                ),
                rbracket=cst.RightSquareBracket(
                    whitespace_before=cst.SimpleWhitespace(" ")),
                rpar=(cst.RightParen(
                    whitespace_before=cst.SimpleWhitespace(" ")), ),
                whitespace_after_value=cst.SimpleWhitespace(" "),
            ),
            "( foo [ 1 : 2 : 3 ,  5 ] )",
            True,
            CodeRange((1, 2), (1, 24)),
        ),
        # Test Index, Slice, SubscriptElement
        (cst.Index(cst.Integer("5")), "5", False, CodeRange((1, 0), (1, 1))),
        (
            cst.Slice(lower=None,
                      upper=None,
                      second_colon=cst.Colon(),
                      step=None),
            "::",
            False,
            CodeRange((1, 0), (1, 2)),
        ),
        (
            cst.SubscriptElement(
                slice=cst.Slice(
                    lower=cst.Integer("1"),
                    first_colon=cst.Colon(
                        whitespace_before=cst.SimpleWhitespace(" "),
                        whitespace_after=cst.SimpleWhitespace(" "),
                    ),
                    upper=cst.Integer("2"),
                    second_colon=cst.Colon(
                        whitespace_before=cst.SimpleWhitespace(" "),
                        whitespace_after=cst.SimpleWhitespace(" "),
                    ),
                    step=cst.Integer("3"),
                ),
                comma=cst.Comma(
                    whitespace_before=cst.SimpleWhitespace(" "),
                    whitespace_after=cst.SimpleWhitespace("  "),
                ),
            ),
            "1 : 2 : 3 ,  ",
            False,
            CodeRange((1, 0), (1, 9)),
        ),
    ))
    def test_valid(
        self,
        node: cst.CSTNode,
        code: str,
        check_parsing: bool,
        position: Optional[CodeRange] = None,
    ) -> None:
        if check_parsing:
            self.validate_node(node,
                               code,
                               parse_expression,
                               expected_position=position)
        else:
            self.validate_node(node, code, expected_position=position)

    @data_provider((
        (
            lambda: cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(cst.Index(cst.Integer("5"))), ),
                lpar=(cst.LeftParen(), ),
            ),
            "left paren without right paren",
        ),
        (
            lambda: cst.Subscript(
                cst.Name("foo"),
                (cst.SubscriptElement(cst.Index(cst.Integer("5"))), ),
                rpar=(cst.RightParen(), ),
            ),
            "right paren without left paren",
        ),
        (lambda: cst.Subscript(cst.Name("foo"), ()), "empty SubscriptElement"),
    ))
    def test_invalid(self, get_node: Callable[[], cst.CSTNode],
                     expected_re: str) -> None:
        self.assert_invalid(get_node, expected_re)
Esempio n. 18
0
class NamedExprTest(CSTNodeTest):
    @data_provider((
        # Simple named expression
        {
            "node": cst.NamedExpr(cst.Name("x"), cst.Float("5.5")),
            "code": "x := 5.5",
            "parser":
            None,  # Walrus operator is illegal as top-level statement
            "expected_position": None,
        },
        # Parenthesized named expression
        {
            "node":
            cst.NamedExpr(
                lpar=(cst.LeftParen(), ),
                target=cst.Name("foo"),
                value=cst.Integer("5"),
                rpar=(cst.RightParen(), ),
            ),
            "code":
            "(foo := 5)",
            "parser":
            _parse_expression_force_38,
            "expected_position":
            CodeRange((1, 1), (1, 9)),
        },
        # Make sure that spacing works
        {
            "node":
            cst.NamedExpr(
                lpar=(cst.LeftParen(
                    whitespace_after=cst.SimpleWhitespace(" ")), ),
                target=cst.Name("foo"),
                whitespace_before_walrus=cst.SimpleWhitespace("  "),
                whitespace_after_walrus=cst.SimpleWhitespace("  "),
                value=cst.Name("bar"),
                rpar=(cst.RightParen(
                    whitespace_before=cst.SimpleWhitespace(" ")), ),
            ),
            "code":
            "( foo  :=  bar )",
            "parser":
            _parse_expression_force_38,
            "expected_position":
            CodeRange((1, 2), (1, 14)),
        },
        # Make sure we can use these where allowed in if/while statements
        {
            "node":
            cst.While(
                test=cst.NamedExpr(
                    target=cst.Name(value="x"),
                    value=cst.Call(func=cst.Name(value="some_input")),
                ),
                body=cst.SimpleStatementSuite(body=[cst.Pass()]),
            ),
            "code":
            "while x := some_input(): pass\n",
            "parser":
            _parse_statement_force_38,
            "expected_position":
            None,
        },
        {
            "node":
            cst.If(
                test=cst.NamedExpr(
                    target=cst.Name(value="x"),
                    value=cst.Call(func=cst.Name(value="some_input")),
                ),
                body=cst.SimpleStatementSuite(body=[cst.Pass()]),
            ),
            "code":
            "if x := some_input(): pass\n",
            "parser":
            _parse_statement_force_38,
            "expected_position":
            None,
        },
        {
            "node":
            cst.If(
                test=cst.NamedExpr(
                    target=cst.Name(value="x"),
                    value=cst.Integer(value="1"),
                    whitespace_before_walrus=cst.SimpleWhitespace(""),
                    whitespace_after_walrus=cst.SimpleWhitespace(""),
                ),
                body=cst.SimpleStatementSuite(body=[cst.Pass()]),
            ),
            "code":
            "if x:=1: pass\n",
            "parser":
            _parse_statement_force_38,
            "expected_position":
            None,
        },
        # Function args
        {
            "node":
            cst.Call(
                func=cst.Name(value="f"),
                args=[
                    cst.Arg(value=cst.NamedExpr(
                        target=cst.Name(value="y"),
                        value=cst.Integer(value="1"),
                        whitespace_before_walrus=cst.SimpleWhitespace(""),
                        whitespace_after_walrus=cst.SimpleWhitespace(""),
                    )),
                ],
            ),
            "code":
            "f(y:=1)",
            "parser":
            _parse_expression_force_38,
            "expected_position":
            None,
        },
        # Whitespace handling on args is fragile
        {
            "node":
            cst.Call(
                func=cst.Name(value="f"),
                args=[
                    cst.Arg(
                        value=cst.Name(value="x"),
                        comma=cst.Comma(
                            whitespace_after=cst.SimpleWhitespace("  ")),
                    ),
                    cst.Arg(
                        value=cst.NamedExpr(
                            target=cst.Name(value="y"),
                            value=cst.Integer(value="1"),
                            whitespace_before_walrus=cst.SimpleWhitespace(
                                "   "),
                            whitespace_after_walrus=cst.SimpleWhitespace(
                                "    "),
                        ),
                        whitespace_after_arg=cst.SimpleWhitespace("     "),
                    ),
                ],
            ),
            "code":
            "f(x,  y   :=    1     )",
            "parser":
            _parse_expression_force_38,
            "expected_position":
            None,
        },
        {
            "node":
            cst.Call(
                func=cst.Name(value="f"),
                args=[
                    cst.Arg(
                        value=cst.NamedExpr(
                            target=cst.Name(value="y"),
                            value=cst.Integer(value="1"),
                            whitespace_before_walrus=cst.SimpleWhitespace(
                                "   "),
                            whitespace_after_walrus=cst.SimpleWhitespace(
                                "    "),
                        ),
                        whitespace_after_arg=cst.SimpleWhitespace("     "),
                    ),
                ],
                whitespace_before_args=cst.SimpleWhitespace("  "),
            ),
            "code":
            "f(  y   :=    1     )",
            "parser":
            _parse_expression_force_38,
            "expected_position":
            None,
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider((
        {
            "get_node": (lambda: cst.NamedExpr(
                cst.Name("foo"), cst.Name("bar"), lpar=(cst.LeftParen(), ))),
            "expected_re":
            "left paren without right paren",
        },
        {
            "get_node": (lambda: cst.NamedExpr(
                cst.Name("foo"), cst.Name("bar"), rpar=(cst.RightParen(), ))),
            "expected_re":
            "right paren without left paren",
        },
    ))
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
Esempio n. 19
0
class DictCompTest(CSTNodeTest):
    @data_provider([
        # simple DictComp
        {
            "node":
            cst.DictComp(
                cst.Name("k"),
                cst.Name("v"),
                cst.CompFor(target=cst.Name("a"), iter=cst.Name("b")),
            ),
            "code":
            "{k: v for a in b}",
            "parser":
            parse_expression,
            "expected_position":
            CodeRange((1, 0), (1, 17)),
        },
        # custom whitespace around colon
        {
            "node":
            cst.DictComp(
                cst.Name("k"),
                cst.Name("v"),
                cst.CompFor(target=cst.Name("a"), iter=cst.Name("b")),
                whitespace_before_colon=cst.SimpleWhitespace("\t"),
                whitespace_after_colon=cst.SimpleWhitespace("\t\t"),
            ),
            "code":
            "{k\t:\t\tv for a in b}",
            "parser":
            parse_expression,
            "expected_position":
            CodeRange((1, 0), (1, 19)),
        },
        # custom whitespace inside braces
        {
            "node":
            cst.DictComp(
                cst.Name("k"),
                cst.Name("v"),
                cst.CompFor(target=cst.Name("a"), iter=cst.Name("b")),
                lbrace=cst.LeftCurlyBrace(
                    whitespace_after=cst.SimpleWhitespace("\t")),
                rbrace=cst.RightCurlyBrace(
                    whitespace_before=cst.SimpleWhitespace("\t\t")),
            ),
            "code":
            "{\tk: v for a in b\t\t}",
            "parser":
            parse_expression,
            "expected_position":
            CodeRange((1, 0), (1, 20)),
        },
        # parenthesis
        {
            "node":
            cst.DictComp(
                cst.Name("k"),
                cst.Name("v"),
                cst.CompFor(target=cst.Name("a"), iter=cst.Name("b")),
                lpar=[cst.LeftParen()],
                rpar=[cst.RightParen()],
            ),
            "code":
            "({k: v for a in b})",
            "parser":
            parse_expression,
            "expected_position":
            CodeRange((1, 1), (1, 18)),
        },
        # missing spaces around DictComp is always okay
        {
            "node":
            cst.DictComp(
                cst.Name("a"),
                cst.Name("b"),
                cst.CompFor(
                    target=cst.Name("c"),
                    iter=cst.DictComp(
                        cst.Name("d"),
                        cst.Name("e"),
                        cst.CompFor(target=cst.Name("f"), iter=cst.Name("g")),
                    ),
                    ifs=[
                        cst.CompIf(
                            cst.Name("h"),
                            whitespace_before=cst.SimpleWhitespace(""),
                        )
                    ],
                    whitespace_after_in=cst.SimpleWhitespace(""),
                ),
            ),
            "code":
            "{a: b for c in{d: e for f in g}if h}",
            "parser":
            parse_expression,
            "expected_position":
            CodeRange((1, 0), (1, 36)),
        },
        # no whitespace before `for` clause
        {
            "node":
            cst.DictComp(
                cst.Name("k"),
                cst.Name("v", lpar=[cst.LeftParen()], rpar=[cst.RightParen()]),
                cst.CompFor(
                    target=cst.Name("a"),
                    iter=cst.Name("b"),
                    whitespace_before=cst.SimpleWhitespace(""),
                ),
            ),
            "code":
            "{k: (v)for a in b}",
            "parser":
            parse_expression,
            "expected_position":
            CodeRange((1, 0), (1, 18)),
        },
    ])
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider([
        # unbalanced DictComp
        {
            "get_node":
            lambda: cst.DictComp(
                cst.Name("k"),
                cst.Name("v"),
                cst.CompFor(target=cst.Name("a"), iter=cst.Name("b")),
                lpar=[cst.LeftParen()],
            ),
            "expected_re":
            "left paren without right paren",
        },
        # invalid whitespace before for/async
        {
            "get_node":
            lambda: cst.DictComp(
                cst.Name("k"),
                cst.Name("v"),
                cst.CompFor(
                    target=cst.Name("a"),
                    iter=cst.Name("b"),
                    whitespace_before=cst.SimpleWhitespace(""),
                ),
            ),
            "expected_re":
            "Must have at least one space before 'for' keyword.",
        },
        {
            "get_node":
            lambda: cst.DictComp(
                cst.Name("k"),
                cst.Name("v"),
                cst.CompFor(
                    target=cst.Name("a"),
                    iter=cst.Name("b"),
                    asynchronous=cst.Asynchronous(),
                    whitespace_before=cst.SimpleWhitespace(""),
                ),
            ),
            "expected_re":
            "Must have at least one space before 'async' keyword.",
        },
    ])
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
Esempio n. 20
0
class AnnAssignTest(CSTNodeTest):
    @data_provider((
        # Simple assignment creation case.
        {
            "node":
            cst.AnnAssign(cst.Name("foo"), cst.Annotation(cst.Name("str")),
                          cst.Integer("5")),
            "code":
            "foo: str = 5",
            "parser":
            None,
            "expected_position":
            CodeRange((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((1, 0), (1, 8)),
        },
        # Complex annotation creation
        {
            "node":
            cst.AnnAssign(
                cst.Name("foo"),
                cst.Annotation(
                    cst.Subscript(
                        cst.Name("Optional"),
                        (cst.SubscriptElement(cst.Index(cst.Name("str"))), ),
                    )),
                cst.Integer("5"),
            ),
            "code":
            "foo: Optional[str] = 5",
            "parser":
            None,
            "expected_position":
            CodeRange((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.SubscriptElement(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.SubscriptElement(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((1, 0), (1, 26)),
        },
        {
            "node":
            cst.SimpleStatementLine((cst.AnnAssign(
                target=cst.Name("foo"),
                annotation=cst.Annotation(
                    annotation=cst.Subscript(
                        cst.Name("Optional"),
                        (cst.SubscriptElement(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)
Esempio n. 21
0
class ForTest(CSTNodeTest):
    @data_provider((
        # Simple for block
        {
            "node":
            cst.For(
                cst.Name("target"),
                cst.Call(cst.Name("iter")),
                cst.SimpleStatementSuite((cst.Pass(), )),
            ),
            "code":
            "for target in iter(): pass\n",
            "parser":
            parse_statement,
        },
        # Simple async for block
        {
            "node":
            cst.For(
                cst.Name("target"),
                cst.Call(cst.Name("iter")),
                cst.SimpleStatementSuite((cst.Pass(), )),
                asynchronous=cst.Asynchronous(),
            ),
            "code":
            "async for target in iter(): pass\n",
            "parser":
            lambda code: parse_statement(
                code, config=PartialParserConfig(python_version="3.7")),
        },
        # Python 3.6 async for block
        {
            "node":
            cst.FunctionDef(
                cst.Name("foo"),
                cst.Parameters(),
                cst.IndentedBlock((cst.For(
                    cst.Name("target"),
                    cst.Call(cst.Name("iter")),
                    cst.SimpleStatementSuite((cst.Pass(), )),
                    asynchronous=cst.Asynchronous(),
                ), )),
                asynchronous=cst.Asynchronous(),
            ),
            "code":
            "async def foo():\n    async for target in iter(): pass\n",
            "parser":
            lambda code: parse_statement(
                code, config=PartialParserConfig(python_version="3.6")),
        },
        # For block with else
        {
            "node":
            cst.For(
                cst.Name("target"),
                cst.Call(cst.Name("iter")),
                cst.SimpleStatementSuite((cst.Pass(), )),
                cst.Else(cst.SimpleStatementSuite((cst.Pass(), ))),
            ),
            "code":
            "for target in iter(): pass\nelse: pass\n",
            "parser":
            parse_statement,
        },
        # indentation
        {
            "node":
            DummyIndentedBlock(
                "    ",
                cst.For(
                    cst.Name("target"),
                    cst.Call(cst.Name("iter")),
                    cst.SimpleStatementSuite((cst.Pass(), )),
                ),
            ),
            "code":
            "    for target in iter(): pass\n",
            "parser":
            None,
        },
        # for an indented body
        {
            "node":
            DummyIndentedBlock(
                "    ",
                cst.For(
                    cst.Name("target"),
                    cst.Call(cst.Name("iter")),
                    cst.IndentedBlock((cst.SimpleStatementLine(
                        (cst.Pass(), )), )),
                ),
            ),
            "code":
            "    for target in iter():\n        pass\n",
            "parser":
            None,
            "expected_position":
            CodeRange((1, 4), (2, 12)),
        },
        # leading_lines
        {
            "node":
            cst.For(
                cst.Name("target"),
                cst.Call(cst.Name("iter")),
                cst.IndentedBlock((cst.SimpleStatementLine((cst.Pass(), )), )),
                cst.Else(
                    cst.IndentedBlock((cst.SimpleStatementLine(
                        (cst.Pass(), )), )),
                    leading_lines=(cst.EmptyLine(
                        comment=cst.Comment("# else comment")), ),
                ),
                leading_lines=(cst.EmptyLine(
                    comment=cst.Comment("# leading comment")), ),
            ),
            "code":
            "# leading comment\nfor target in iter():\n    pass\n# else comment\nelse:\n    pass\n",
            "parser":
            None,
            "expected_position":
            CodeRange((2, 0), (6, 8)),
        },
        # Weird spacing rules
        {
            "node":
            cst.For(
                cst.Name("target",
                         lpar=(cst.LeftParen(), ),
                         rpar=(cst.RightParen(), )),
                cst.Call(
                    cst.Name("iter"),
                    lpar=(cst.LeftParen(), ),
                    rpar=(cst.RightParen(), ),
                ),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_after_for=cst.SimpleWhitespace(""),
                whitespace_before_in=cst.SimpleWhitespace(""),
                whitespace_after_in=cst.SimpleWhitespace(""),
            ),
            "code":
            "for(target)in(iter()): pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (1, 27)),
        },
        # Whitespace
        {
            "node":
            cst.For(
                cst.Name("target"),
                cst.Call(cst.Name("iter")),
                cst.SimpleStatementSuite((cst.Pass(), )),
                whitespace_after_for=cst.SimpleWhitespace("  "),
                whitespace_before_in=cst.SimpleWhitespace("  "),
                whitespace_after_in=cst.SimpleWhitespace("  "),
                whitespace_before_colon=cst.SimpleWhitespace("  "),
            ),
            "code":
            "for  target  in  iter()  : pass\n",
            "parser":
            parse_statement,
            "expected_position":
            CodeRange((1, 0), (1, 31)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

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

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

    @data_provider((
        {
            "code": "with a, b: pass",
            "parser": parse_statement_as(python_version="3.1"),
            "expect_success": True,
        },
        {
            "code": "with a, b: pass",
            "parser": parse_statement_as(python_version="3.0"),
            "expect_success": False,
        },
    ))
    def test_versions(self, **kwargs: Any) -> None:
        self.assert_parses(**kwargs)
Esempio n. 23
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)
Esempio n. 24
0
 def cmp_position(self, actual: CodeRange, start: Tuple[int, int],
                  end: Tuple[int, int]) -> None:
     self.assertEqual(actual, CodeRange(start, end))
Esempio n. 25
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),
            "enabled_for_native": False,
        },
        "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,
                    enabled_for_native: bool = True) -> None:
        if is_native() and not enabled_for_native:
            self.skipTest("Disabled for native parser")
        self.assertEqual(parse_module(code), expected)

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

        self.assertEqual(positions[wrapper.module], expected)

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

    def test_function_position(self) -> None:
        wrapper = MetadataWrapper(parse_module("def foo():\n    pass"))
        module = wrapper.module
        positions = wrapper.resolve(PositionProvider)

        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(positions[stmt], (2, 4), (2, 8))
        self.cmp_position(positions[pass_stmt], (2, 4), (2, 8))

    def test_nested_indent_position(self) -> None:
        wrapper = MetadataWrapper(
            parse_module(
                "if True:\n    if False:\n        x = 1\nelse:\n    return"))
        module = wrapper.module
        positions = wrapper.resolve(PositionProvider)

        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(positions[outer_if], (1, 0), (5, 10))
        self.cmp_position(positions[inner_if], (2, 4), (3, 13))
        self.cmp_position(positions[assign], (3, 8), (3, 13))
        self.cmp_position(positions[outer_else], (4, 0), (5, 10))
        self.cmp_position(positions[return_stmt], (5, 4), (5, 10))

    def test_multiline_string_position(self) -> None:
        wrapper = MetadataWrapper(parse_module('"abc"\\\n"def"'))
        module = wrapper.module
        positions = wrapper.resolve(PositionProvider)

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

        self.cmp_position(positions[stmt], (1, 0), (2, 5))
        self.cmp_position(positions[expr], (1, 0), (2, 5))
        self.cmp_position(positions[string], (1, 0), (2, 5))

    def test_module_config_for_parsing(self) -> None:
        module = parse_module("pass\r")
        statement = parse_statement("if True:\r    pass",
                                    config=module.config_for_parsing)
        self.assertEqual(
            statement,
            cst.If(
                test=cst.Name(value="True"),
                body=cst.IndentedBlock(
                    body=[cst.SimpleStatementLine(body=[cst.Pass()])],
                    header=cst.TrailingWhitespace(newline=cst.Newline(
                        # This would be "\r" if we didn't pass the module config forward.
                        value=None)),
                ),
            ),
        )
Esempio n. 26
0
 def visit_Pass(self, node: cst.Pass) -> None:
     test.assertEqual(
         self.get_metadata(PositionProvider, node), CodeRange((1, 0), (1, 4))
     )
Esempio n. 27
0
class NonlocalConstructionTest(CSTNodeTest):
    @data_provider((
        # Single nonlocal statement
        {
            "node": cst.Nonlocal((cst.NameItem(cst.Name("a")), )),
            "code": "nonlocal a",
        },
        # Multiple entries in nonlocal statement
        {
            "node":
            cst.Nonlocal(
                (cst.NameItem(cst.Name("a")), cst.NameItem(cst.Name("b")))),
            "code":
            "nonlocal a, b",
            "expected_position":
            CodeRange((1, 0), (1, 13)),
        },
        # Whitespace rendering test
        {
            "node":
            cst.Nonlocal(
                (
                    cst.NameItem(
                        cst.Name("a"),
                        comma=cst.Comma(
                            whitespace_before=cst.SimpleWhitespace("  "),
                            whitespace_after=cst.SimpleWhitespace("  "),
                        ),
                    ),
                    cst.NameItem(cst.Name("b")),
                ),
                whitespace_after_nonlocal=cst.SimpleWhitespace("  "),
            ),
            "code":
            "nonlocal  a  ,  b",
            "expected_position":
            CodeRange((1, 0), (1, 17)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider((
        # Validate construction
        {
            "get_node": lambda: cst.Nonlocal(()),
            "expected_re":
            "A Nonlocal statement must have at least one NameItem",
        },
        # Validate whitespace handling
        {
            "get_node":
            lambda: cst.Nonlocal(
                (cst.NameItem(cst.Name("a")), ),
                whitespace_after_nonlocal=cst.SimpleWhitespace(""),
            ),
            "expected_re":
            "Must have at least one space after 'nonlocal' keyword",
        },
        # Validate comma handling
        {
            "get_node":
            lambda: cst.Nonlocal(
                (cst.NameItem(cst.Name("a"), comma=cst.Comma()), )),
            "expected_re":
            "The last NameItem in a Nonlocal cannot have a trailing comma",
        },
        # Validate paren handling
        {
            "get_node":
            lambda: cst.Nonlocal((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)
Esempio n. 28
0
class RaiseConstructionTest(CSTNodeTest):
    @data_provider((
        # Simple raise
        {
            "node": cst.Raise(),
            "code": "raise"
        },
        # Raise exception
        {
            "node": cst.Raise(cst.Call(cst.Name("Exception"))),
            "code": "raise Exception()",
            "expected_position": CodeRange((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((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((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((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)
Esempio n. 29
0
class AssertConstructionTest(CSTNodeTest):
    @data_provider((
        # Simple assert
        {
            "node": cst.Assert(cst.Name("True")),
            "code": "assert True",
            "parser": None,
            "expected_position": None,
        },
        # Assert with message
        {
            "node":
            cst.Assert(cst.Name("True"),
                       cst.SimpleString('"Value should be true"')),
            "code":
            'assert True, "Value should be true"',
            "parser":
            None,
            "expected_position":
            None,
        },
        # Whitespace oddities test
        {
            "node":
            cst.Assert(
                cst.Name("True",
                         lpar=(cst.LeftParen(), ),
                         rpar=(cst.RightParen(), )),
                whitespace_after_assert=cst.SimpleWhitespace(""),
            ),
            "code":
            "assert(True)",
            "parser":
            None,
            "expected_position":
            CodeRange((1, 0), (1, 12)),
        },
        # Whitespace rendering test
        {
            "node":
            cst.Assert(
                whitespace_after_assert=cst.SimpleWhitespace("  "),
                test=cst.Name("True"),
                comma=cst.Comma(
                    whitespace_before=cst.SimpleWhitespace("  "),
                    whitespace_after=cst.SimpleWhitespace("  "),
                ),
                msg=cst.SimpleString('"Value should be true"'),
            ),
            "code":
            'assert  True  ,  "Value should be true"',
            "parser":
            None,
            "expected_position":
            CodeRange((1, 0), (1, 39)),
        },
    ))
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)

    @data_provider((
        # Validate whitespace handling
        {
            "get_node": (lambda: cst.Assert(
                cst.Name("True"),
                whitespace_after_assert=cst.SimpleWhitespace(""),
            )),
            "expected_re":
            "Must have at least one space after 'assert'",
        },
        # Validate comma handling
        {
            "get_node":
            (lambda: cst.Assert(test=cst.Name("True"), comma=cst.Comma())),
            "expected_re":
            "Cannot have trailing comma after 'test'",
        },
    ))
    def test_invalid(self, **kwargs: Any) -> None:
        self.assert_invalid(**kwargs)
Esempio n. 30
0
class AssignTest(CSTNodeTest):
    @data_provider((
        # Simple assignment creation case.
        {
            "node":
            cst.Assign((cst.AssignTarget(cst.Name("foo")), ),
                       cst.Integer("5")),
            "code":
            "foo = 5",
            "parser":
            None,
            "expected_position":
            CodeRange((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((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((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)