Example #1
0
def convert_while_stmt(config: ParserConfig, children: Sequence[Any]) -> Any:
    while_token, test, while_colon_token, while_suite, *else_block = children

    if len(else_block) > 0:
        (else_token, else_colon_token, else_suite) = else_block
        orelse = Else(
            leading_lines=parse_empty_lines(config, else_token.whitespace_before),
            whitespace_before_colon=parse_simple_whitespace(
                config, else_colon_token.whitespace_before
            ),
            body=else_suite,
        )
    else:
        orelse = None

    return While(
        leading_lines=parse_empty_lines(config, while_token.whitespace_before),
        whitespace_after_while=parse_simple_whitespace(
            config, while_token.whitespace_after
        ),
        test=test.value,
        whitespace_before_colon=parse_simple_whitespace(
            config, while_colon_token.whitespace_before
        ),
        body=while_suite,
        orelse=orelse,
    )
Example #2
0
def convert_try_stmt(config: ParserConfig, children: Sequence[Any]) -> Any:
    trytoken, try_colon_token, try_suite, *rest = children
    handlers: List[ExceptHandler] = []
    orelse: Optional[Else] = None
    finalbody: Optional[Finally] = None

    for clause, colon_token, suite in grouper(rest, 3):
        if isinstance(clause, Token):
            if clause.string == "else":
                if orelse is not None:
                    raise Exception("Logic error!")
                orelse = Else(
                    leading_lines=parse_empty_lines(config, clause.whitespace_before),
                    whitespace_before_colon=parse_simple_whitespace(
                        config, colon_token.whitespace_before
                    ),
                    body=suite,
                )
            elif clause.string == "finally":
                if finalbody is not None:
                    raise Exception("Logic error!")
                finalbody = Finally(
                    leading_lines=parse_empty_lines(config, clause.whitespace_before),
                    whitespace_before_colon=parse_simple_whitespace(
                        config, colon_token.whitespace_before
                    ),
                    body=suite,
                )
            else:
                raise Exception("Logic error!")
        elif isinstance(clause, ExceptClausePartial):
            handlers.append(
                ExceptHandler(
                    body=suite,
                    type=clause.type,
                    name=clause.name,
                    leading_lines=clause.leading_lines,
                    whitespace_after_except=clause.whitespace_after_except,
                    whitespace_before_colon=parse_simple_whitespace(
                        config, colon_token.whitespace_before
                    ),
                )
            )
        else:
            raise Exception("Logic error!")

    return Try(
        leading_lines=parse_empty_lines(config, trytoken.whitespace_before),
        whitespace_before_colon=parse_simple_whitespace(
            config, try_colon_token.whitespace_before
        ),
        body=try_suite,
        handlers=tuple(handlers),
        orelse=orelse,
        finalbody=finalbody,
    )
Example #3
0
def convert_except_clause(config: ParserConfig, children: Sequence[Any]) -> Any:
    if len(children) == 1:
        (except_token,) = children
        whitespace_after_except = SimpleWhitespace("")
        test = None
        name = None
    elif len(children) == 2:
        (except_token, test_node) = children
        whitespace_after_except = parse_simple_whitespace(
            config, except_token.whitespace_after
        )
        test = test_node.value
        name = None
    else:
        (except_token, test_node, as_token, name_token) = children
        whitespace_after_except = parse_simple_whitespace(
            config, except_token.whitespace_after
        )
        test = test_node.value
        name = AsName(
            whitespace_before_as=parse_simple_whitespace(
                config, as_token.whitespace_before
            ),
            whitespace_after_as=parse_simple_whitespace(
                config, as_token.whitespace_after
            ),
            name=Name(name_token.string),
        )

    return ExceptClausePartial(
        leading_lines=parse_empty_lines(config, except_token.whitespace_before),
        whitespace_after_except=whitespace_after_except,
        type=test,
        name=name,
    )
Example #4
0
def convert_indented_suite(config: ParserConfig, children: Sequence[Any]) -> Any:
    newline, indent, *stmts, dedent = children
    return IndentedBlock(
        header=newline,
        indent=(
            None
            if indent.relative_indent == config.default_indent
            else indent.relative_indent
        ),
        body=stmts,
        # We want to be able to only keep comments in the footer that are actually for
        # this IndentedBlock. We do so by assuming that lines which are indented to the
        # same level as the block itself are comments that go at the footer of the
        # block. Comments that are indented to less than this indent are assumed to
        # belong to the next line of code. We override the indent here because the
        # dedent node's absolute indent is the resulting indentation after the dedent
        # is performed. Its this way because the whitespace state for both the dedent's
        # whitespace_after and the next BaseCompoundStatement's whitespace_before is
        # shared. This allows us to partially parse here and parse the rest of the
        # whitespace and comments on the next line, effectively making sure that
        # comments are attached to the correct node.
        footer=parse_empty_lines(
            config,
            dedent.whitespace_after,
            override_absolute_indent=indent.whitespace_before.absolute_indent,
        ),
    )
Example #5
0
def convert_decorator(config: ParserConfig, children: Sequence[Any]) -> Any:
    atsign, name, *arglist, newline = children
    if not arglist:
        # This is either a name or an attribute node, so just extract it.
        decoratornode = name
    else:
        # This needs to be converted into a call node, and we have the
        # arglist partial.
        lpar, *args, rpar = arglist
        args = args[0].args if args else []

        # If the trailing argument doesn't have a comma, then it owns the
        # trailing whitespace before the rpar. Otherwise, the comma owns
        # it.
        if len(args) > 0 and args[-1].comma == MaybeSentinel.DEFAULT:
            args[-1] = args[-1].with_changes(
                whitespace_after_arg=parse_parenthesizable_whitespace(
                    config, rpar.whitespace_before))

        decoratornode = Call(
            func=name,
            whitespace_after_func=parse_simple_whitespace(
                config, lpar.whitespace_before),
            whitespace_before_args=parse_parenthesizable_whitespace(
                config, lpar.whitespace_after),
            args=tuple(args),
        )

    return Decorator(
        leading_lines=parse_empty_lines(config, atsign.whitespace_before),
        whitespace_after_at=parse_simple_whitespace(config,
                                                    atsign.whitespace_after),
        decorator=decoratornode,
        trailing_whitespace=newline,
    )
Example #6
0
def convert_classdef(config: ParserConfig, children: Sequence[Any]) -> Any:
    classdef, name, *arglist, colon, suite = children

    # First, parse out the comments and empty lines before the statement.
    leading_lines = parse_empty_lines(config, classdef.whitespace_before)

    # Compute common whitespace and nodes
    whitespace_after_class = parse_simple_whitespace(config,
                                                     classdef.whitespace_after)
    namenode = Name(name.string)
    whitespace_after_name = parse_simple_whitespace(config,
                                                    name.whitespace_after)

    # Now, construct the classdef node itself
    if not arglist:
        # No arglist, so no arguments to this class
        return ClassDef(
            leading_lines=leading_lines,
            lines_after_decorators=(),
            whitespace_after_class=whitespace_after_class,
            name=namenode,
            whitespace_after_name=whitespace_after_name,
            body=suite,
        )
    else:
        # Unwrap arglist partial, because its valid to not have any
        lpar, *args, rpar = arglist
        args = args[0].args if args else []

        bases: List[Arg] = []
        keywords: List[Arg] = []

        current_arg = bases
        for arg in args:
            if arg.star == "**" or arg.keyword is not None:
                current_arg = keywords
            # Some quick validation
            if current_arg is keywords and (arg.star == "*" or
                                            (arg.star == ""
                                             and arg.keyword is None)):
                raise PartialParserSyntaxError(
                    "Positional argument follows keyword argument.")
            current_arg.append(arg)

        return ClassDef(
            leading_lines=leading_lines,
            lines_after_decorators=(),
            whitespace_after_class=whitespace_after_class,
            name=namenode,
            whitespace_after_name=whitespace_after_name,
            lpar=LeftParen(whitespace_after=parse_parenthesizable_whitespace(
                config, lpar.whitespace_after)),
            bases=bases,
            keywords=keywords,
            rpar=RightParen(whitespace_before=parse_parenthesizable_whitespace(
                config, rpar.whitespace_before)),
            whitespace_before_colon=parse_simple_whitespace(
                config, colon.whitespace_before),
            body=suite,
        )
Example #7
0
def convert_if_stmt_else(config: ParserConfig, children: Sequence[Any]) -> Any:
    else_tok, colon_tok, suite = children
    return Else(
        leading_lines=parse_empty_lines(config, else_tok.whitespace_before),
        whitespace_before_colon=parse_simple_whitespace(
            config, colon_tok.whitespace_before),
        body=suite,
    )
Example #8
0
def convert_ENDMARKER(config: ParserConfig, token: Token) -> Any:
    # Parse any and all empty lines with an indent similar to the header. That is,
    # indent of nothing and including all indents. In some cases, like when the
    # footer parser follows an indented suite, the state's indent can be wrong
    # due to the fact that it is shared with the _DEDENT node. We know that if
    # we're parsing the end of a file, we will have no indent.
    return parse_empty_lines(config,
                             token.whitespace_before,
                             override_absolute_indent="")
Example #9
0
def convert_simple_stmt_line(config: ParserConfig, children: Sequence[Any]) -> Any:
    """
    This function is similar to convert_simple_stmt_suite, but yields a different type
    """
    (partial,) = children
    return SimpleStatementLine(
        partial.body,
        leading_lines=parse_empty_lines(config, partial.whitespace_before),
        trailing_whitespace=partial.trailing_whitespace,
    )
Example #10
0
def _extract_async(
    config: ParserConfig, children: Sequence[Any]
) -> Tuple[List[EmptyLine], Optional[Asynchronous], Any]:
    if len(children) == 1:
        (stmt, ) = children

        whitespace_before = stmt.whitespace_before
        asyncnode = None
    else:
        asynctoken, stmt = children

        whitespace_before = asynctoken.whitespace_before
        asyncnode = Asynchronous(whitespace_after=parse_simple_whitespace(
            config, asynctoken.whitespace_after))

    return (parse_empty_lines(config,
                              whitespace_before), asyncnode, stmt.value)
Example #11
0
def convert_if_stmt(config: ParserConfig, children: Sequence[Any]) -> Any:
    if_tok, test, colon_tok, suite, *tail = children

    if len(tail) > 0:
        (orelse,) = tail
    else:
        orelse = None

    return If(
        leading_lines=parse_empty_lines(config, if_tok.whitespace_before),
        whitespace_before_test=parse_simple_whitespace(config, if_tok.whitespace_after),
        test=test.value,
        whitespace_after_test=parse_simple_whitespace(
            config, colon_tok.whitespace_before
        ),
        body=suite,
        orelse=orelse,
    )
Example #12
0
def convert_for_stmt(config: ParserConfig, children: Sequence[Any]) -> Any:
    (
        for_token,
        expr,
        in_token,
        test,
        for_colon_token,
        for_suite,
        *else_block,
    ) = children

    if len(else_block) > 0:
        (else_token, else_colon_token, else_suite) = else_block
        orelse = Else(
            leading_lines=parse_empty_lines(config, else_token.whitespace_before),
            whitespace_before_colon=parse_simple_whitespace(
                config, else_colon_token.whitespace_before
            ),
            body=else_suite,
        )
    else:
        orelse = None

    return WithLeadingWhitespace(
        For(
            whitespace_after_for=parse_simple_whitespace(
                config, for_token.whitespace_after
            ),
            target=expr.value,
            whitespace_before_in=parse_simple_whitespace(
                config, in_token.whitespace_before
            ),
            whitespace_after_in=parse_simple_whitespace(
                config, in_token.whitespace_after
            ),
            iter=test.value,
            whitespace_before_colon=parse_simple_whitespace(
                config, for_colon_token.whitespace_before
            ),
            body=for_suite,
            orelse=orelse,
        ),
        for_token.whitespace_before,
    )