Esempio n. 1
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. 2
0
class ListTest(CSTNodeTest):

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

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

    @data_provider(
        (
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(target=cst.Name("b"), iter=cst.Name("c")),
                    lpar=[cst.LeftParen(), cst.LeftParen()],
                    rpar=[cst.RightParen()],
                ),
                "unbalanced parens",
            ),
            (
                lambda: cst.ListComp(
                    cst.Name("a"),
                    cst.CompFor(target=cst.Name("b"), iter=cst.Name("c")),
                    lpar=[cst.LeftParen(), cst.LeftParen()],
                    rpar=[cst.RightParen()],
                ),
                "unbalanced parens",
            ),
            (
                lambda: cst.SetComp(
                    cst.Name("a"),
                    cst.CompFor(target=cst.Name("b"), iter=cst.Name("c")),
                    lpar=[cst.LeftParen(), cst.LeftParen()],
                    rpar=[cst.RightParen()],
                ),
                "unbalanced parens",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        whitespace_before=cst.SimpleWhitespace(""),
                    ),
                ),
                "Must have at least one space before 'for' keyword.",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        asynchronous=cst.Asynchronous(),
                        whitespace_before=cst.SimpleWhitespace(""),
                    ),
                ),
                "Must have at least one space before 'async' keyword.",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        whitespace_after_for=cst.SimpleWhitespace(""),
                    ),
                ),
                "Must have at least one space after 'for' keyword.",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        whitespace_before_in=cst.SimpleWhitespace(""),
                    ),
                ),
                "Must have at least one space before 'in' keyword.",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        whitespace_after_in=cst.SimpleWhitespace(""),
                    ),
                ),
                "Must have at least one space after 'in' keyword.",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        ifs=[
                            cst.CompIf(
                                cst.Name("d"),
                                whitespace_before=cst.SimpleWhitespace(""),
                            )
                        ],
                    ),
                ),
                "Must have at least one space before 'if' keyword.",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        ifs=[
                            cst.CompIf(
                                cst.Name("d"),
                                whitespace_before_test=cst.SimpleWhitespace(""),
                            )
                        ],
                    ),
                ),
                "Must have at least one space after 'if' keyword.",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        inner_for_in=cst.CompFor(
                            target=cst.Name("d"),
                            iter=cst.Name("e"),
                            whitespace_before=cst.SimpleWhitespace(""),
                        ),
                    ),
                ),
                "Must have at least one space before 'for' keyword.",
            ),
            (
                lambda: cst.GeneratorExp(
                    cst.Name("a"),
                    cst.CompFor(
                        target=cst.Name("b"),
                        iter=cst.Name("c"),
                        inner_for_in=cst.CompFor(
                            target=cst.Name("d"),
                            iter=cst.Name("e"),
                            asynchronous=cst.Asynchronous(),
                            whitespace_before=cst.SimpleWhitespace(""),
                        ),
                    ),
                ),
                "Must have at least one space before 'async' keyword.",
            ),
        )
    )
    def test_invalid(
        self, get_node: Callable[[], cst.CSTNode], expected_re: str
    ) -> None:
        self.assert_invalid(get_node, expected_re)
Esempio n. 4
0
class MatchTest(CSTNodeTest):
    @data_provider(
        (
            # Values and singletons
            {
                "node": cst.Match(
                    subject=cst.Name("x"),
                    cases=[
                        cst.MatchCase(
                            pattern=cst.MatchSingleton(cst.Name("None")),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(
                            pattern=cst.MatchValue(cst.SimpleString('"foo"')),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                    ],
                ),
                "code": "match x:\n"
                + "    case None: pass\n"
                + '    case "foo": pass\n',
                "parser": parser,
            },
            # Parenthesized value
            {
                "node": cst.Match(
                    subject=cst.Name(
                        value="x",
                    ),
                    cases=[
                        cst.MatchCase(
                            pattern=cst.MatchAs(
                                pattern=cst.MatchValue(
                                    value=cst.Integer(
                                        value="1",
                                        lpar=[
                                            cst.LeftParen(),
                                        ],
                                        rpar=[
                                            cst.RightParen(),
                                        ],
                                    ),
                                ),
                                name=cst.Name(
                                    value="z",
                                ),
                                whitespace_before_as=cst.SimpleWhitespace(" "),
                                whitespace_after_as=cst.SimpleWhitespace(" "),
                            ),
                            body=cst.SimpleStatementSuite([cst.Pass()]),
                        ),
                    ],
                ),
                "code": "match x:\n    case (1) as z: pass\n",
                "parser": parser,
            },
            # List patterns
            {
                "node": cst.Match(
                    subject=cst.Name("x"),
                    cases=[
                        cst.MatchCase(  # empty list
                            pattern=cst.MatchList(
                                [],
                                lbracket=cst.LeftSquareBracket(),
                                rbracket=cst.RightSquareBracket(),
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # single element list
                            pattern=cst.MatchList(
                                [
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None"))
                                    )
                                ],
                                lbracket=cst.LeftSquareBracket(),
                                rbracket=cst.RightSquareBracket(),
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # single element list with trailing comma
                            pattern=cst.MatchList(
                                [
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                        cst.Comma(),
                                    )
                                ],
                                lbracket=cst.LeftSquareBracket(),
                                rbracket=cst.RightSquareBracket(),
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                    ],
                ),
                "code": (
                    "match x:\n"
                    + "    case []: pass\n"
                    + "    case [None]: pass\n"
                    + "    case [None,]: pass\n"
                ),
                "parser": parser,
            },
            # Tuple patterns
            {
                "node": cst.Match(
                    subject=cst.Name("x"),
                    cases=[
                        cst.MatchCase(  # empty tuple
                            pattern=cst.MatchTuple(
                                [],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # two element tuple
                            pattern=cst.MatchTuple(
                                [
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                        cst.Comma(),
                                    ),
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                    ),
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # single element tuple with trailing comma
                            pattern=cst.MatchTuple(
                                [
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                        cst.Comma(),
                                    )
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # two element tuple
                            pattern=cst.MatchTuple(
                                [
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                        cst.Comma(),
                                    ),
                                    cst.MatchStar(
                                        comma=cst.Comma(),
                                    ),
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                    ),
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                    ],
                ),
                "code": (
                    "match x:\n"
                    + "    case (): pass\n"
                    + "    case (None,None): pass\n"
                    + "    case (None,): pass\n"
                    + "    case (None,*_,None): pass\n"
                ),
                "parser": parser,
            },
            # Mapping patterns
            {
                "node": cst.Match(
                    subject=cst.Name("x"),
                    cases=[
                        cst.MatchCase(  # empty mapping
                            pattern=cst.MatchMapping(
                                [],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # two element mapping
                            pattern=cst.MatchMapping(
                                [
                                    cst.MatchMappingElement(
                                        key=cst.SimpleString('"a"'),
                                        pattern=cst.MatchSingleton(cst.Name("None")),
                                        comma=cst.Comma(),
                                    ),
                                    cst.MatchMappingElement(
                                        key=cst.SimpleString('"b"'),
                                        pattern=cst.MatchSingleton(cst.Name("None")),
                                    ),
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # single element mapping with trailing comma
                            pattern=cst.MatchMapping(
                                [
                                    cst.MatchMappingElement(
                                        key=cst.SimpleString('"a"'),
                                        pattern=cst.MatchSingleton(cst.Name("None")),
                                        comma=cst.Comma(),
                                    )
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # rest
                            pattern=cst.MatchMapping(
                                rest=cst.Name("rest"),
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                    ],
                ),
                "code": (
                    "match x:\n"
                    + "    case {}: pass\n"
                    + '    case {"a": None,"b": None}: pass\n'
                    + '    case {"a": None,}: pass\n'
                    + "    case {**rest}: pass\n"
                ),
                "parser": parser,
            },
            # Class patterns
            {
                "node": cst.Match(
                    subject=cst.Name("x"),
                    cases=[
                        cst.MatchCase(  # empty class
                            pattern=cst.MatchClass(
                                cls=cst.Attribute(cst.Name("a"), cst.Name("b")),
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # single pattern class
                            pattern=cst.MatchClass(
                                cls=cst.Attribute(cst.Name("a"), cst.Name("b")),
                                patterns=[
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None"))
                                    )
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # single pattern class with trailing comma
                            pattern=cst.MatchClass(
                                cls=cst.Attribute(cst.Name("a"), cst.Name("b")),
                                patterns=[
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                        comma=cst.Comma(),
                                    )
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # single keyword pattern class
                            pattern=cst.MatchClass(
                                cls=cst.Attribute(cst.Name("a"), cst.Name("b")),
                                kwds=[
                                    cst.MatchKeywordElement(
                                        key=cst.Name("foo"),
                                        pattern=cst.MatchSingleton(cst.Name("None")),
                                    )
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # single keyword pattern class with trailing comma
                            pattern=cst.MatchClass(
                                cls=cst.Attribute(cst.Name("a"), cst.Name("b")),
                                kwds=[
                                    cst.MatchKeywordElement(
                                        key=cst.Name("foo"),
                                        pattern=cst.MatchSingleton(cst.Name("None")),
                                        comma=cst.Comma(),
                                    )
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(  # now all at once
                            pattern=cst.MatchClass(
                                cls=cst.Attribute(cst.Name("a"), cst.Name("b")),
                                patterns=[
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                        cst.Comma(),
                                    ),
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                        cst.Comma(),
                                    ),
                                ],
                                kwds=[
                                    cst.MatchKeywordElement(
                                        key=cst.Name("foo"),
                                        pattern=cst.MatchSingleton(cst.Name("None")),
                                        comma=cst.Comma(),
                                    ),
                                    cst.MatchKeywordElement(
                                        key=cst.Name("bar"),
                                        pattern=cst.MatchSingleton(cst.Name("None")),
                                        comma=cst.Comma(),
                                    ),
                                ],
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                    ],
                ),
                "code": (
                    "match x:\n"
                    + "    case a.b(): pass\n"
                    + "    case a.b(None): pass\n"
                    + "    case a.b(None,): pass\n"
                    + "    case a.b(foo=None): pass\n"
                    + "    case a.b(foo=None,): pass\n"
                    + "    case a.b(None,None,foo=None,bar=None,): pass\n"
                ),
                "parser": parser,
            },
            # as pattern
            {
                "node": cst.Match(
                    subject=cst.Name("x"),
                    cases=[
                        cst.MatchCase(
                            pattern=cst.MatchAs(),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(
                            pattern=cst.MatchAs(name=cst.Name("foo")),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(
                            pattern=cst.MatchAs(
                                pattern=cst.MatchSingleton(cst.Name("None")),
                                name=cst.Name("bar"),
                                whitespace_before_as=cst.SimpleWhitespace(" "),
                                whitespace_after_as=cst.SimpleWhitespace(" "),
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                    ],
                ),
                "code": "match x:\n"
                + "    case _: pass\n"
                + "    case foo: pass\n"
                + "    case None as bar: pass\n",
                "parser": parser,
            },
            # or pattern
            {
                "node": cst.Match(
                    subject=cst.Name("x"),
                    cases=[
                        cst.MatchCase(
                            pattern=cst.MatchOr(
                                [
                                    cst.MatchOrElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                        cst.BitOr(),
                                    ),
                                    cst.MatchOrElement(
                                        cst.MatchSingleton(cst.Name("False")),
                                        cst.BitOr(),
                                    ),
                                    cst.MatchOrElement(
                                        cst.MatchSingleton(cst.Name("True"))
                                    ),
                                ]
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        )
                    ],
                ),
                "code": "match x:\n    case None | False | True: pass\n",
                "parser": parser,
            },
            {  # exercise sentinels
                "node": cst.Match(
                    subject=cst.Name("x"),
                    cases=[
                        cst.MatchCase(
                            pattern=cst.MatchList(
                                [cst.MatchStar(), cst.MatchStar()],
                                lbracket=None,
                                rbracket=None,
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(
                            pattern=cst.MatchTuple(
                                [
                                    cst.MatchSequenceElement(
                                        cst.MatchSingleton(cst.Name("None"))
                                    )
                                ]
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(
                            pattern=cst.MatchAs(
                                pattern=cst.MatchTuple(
                                    [
                                        cst.MatchSequenceElement(
                                            cst.MatchSingleton(cst.Name("None"))
                                        )
                                    ]
                                ),
                                name=cst.Name("bar"),
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                        cst.MatchCase(
                            pattern=cst.MatchOr(
                                [
                                    cst.MatchOrElement(
                                        cst.MatchSingleton(cst.Name("None")),
                                    ),
                                    cst.MatchOrElement(
                                        cst.MatchSingleton(cst.Name("False")),
                                    ),
                                    cst.MatchOrElement(
                                        cst.MatchSingleton(cst.Name("True"))
                                    ),
                                ]
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                        ),
                    ],
                ),
                "code": "match x:\n"
                + "    case *_, *_: pass\n"
                + "    case (None,): pass\n"
                + "    case (None,) as bar: pass\n"
                + "    case None | False | True: pass\n",
                "parser": None,
            },
            # Match without whitespace between keyword and the expr
            {
                "node": cst.Match(
                    subject=cst.Name(
                        "x", lpar=[cst.LeftParen()], rpar=[cst.RightParen()]
                    ),
                    cases=[
                        cst.MatchCase(
                            pattern=cst.MatchSingleton(
                                cst.Name(
                                    "None",
                                    lpar=[cst.LeftParen()],
                                    rpar=[cst.RightParen()],
                                )
                            ),
                            body=cst.SimpleStatementSuite((cst.Pass(),)),
                            whitespace_after_case=cst.SimpleWhitespace(
                                value="",
                            ),
                        ),
                    ],
                    whitespace_after_match=cst.SimpleWhitespace(
                        value="",
                    ),
                ),
                "code": "match(x):\n    case(None): pass\n",
                "parser": parser,
            },
        )
    )
    def test_valid(self, **kwargs: Any) -> None:
        self.validate_node(**kwargs)