예제 #1
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,
        )
예제 #2
0
def convert_atom_parens(
    config: ParserConfig, children: typing.Sequence[typing.Any]
) -> typing.Any:
    lpar_tok, *atoms, rpar_tok = children

    lpar = LeftParen(
        whitespace_after=parse_parenthesizable_whitespace(
            config, lpar_tok.whitespace_after
        )
    )

    rpar = RightParen(
        whitespace_before=parse_parenthesizable_whitespace(
            config, rpar_tok.whitespace_before
        )
    )

    if len(atoms) == 1:
        # inner_atom is a _BaseParenthesizedNode
        inner_atom = atoms[0].value
        return WithLeadingWhitespace(
            inner_atom.with_changes(
                lpar=(lpar, *inner_atom.lpar), rpar=(*inner_atom.rpar, rpar)
            ),
            lpar_tok.whitespace_before,
        )
    else:
        return WithLeadingWhitespace(
            Tuple((), lpar=(lpar,), rpar=(rpar,)), lpar_tok.whitespace_before
        )
예제 #3
0
def convert_parameters(config: ParserConfig, children: Sequence[Any]) -> Any:
    lpar, *paramlist, rpar = children
    return FuncdefPartial(
        lpar=LeftParen(whitespace_after=parse_parenthesizable_whitespace(
            config, lpar.whitespace_after)),
        params=Parameters() if not paramlist else paramlist[0],
        rpar=RightParen(whitespace_before=parse_parenthesizable_whitespace(
            config, rpar.whitespace_before)),
    )
예제 #4
0
def convert_import_from(config: ParserConfig, children: Sequence[Any]) -> Any:
    fromtoken, import_relative, importtoken, *importlist = children

    if len(importlist) == 1:
        (possible_star, ) = importlist
        if isinstance(possible_star, Token):
            # Its a "*" import, so we must construct this node.
            names = ImportStar()
        else:
            # Its an import as names partial, grab the names from that.
            names = possible_star.names
        lpar = None
        rpar = None
    else:
        # Its an import as names partial with parens
        lpartoken, namespartial, rpartoken = importlist
        lpar = LeftParen(whitespace_after=parse_parenthesizable_whitespace(
            config, lpartoken.whitespace_after))
        names = namespartial.names
        rpar = RightParen(whitespace_before=parse_parenthesizable_whitespace(
            config, rpartoken.whitespace_before))

    # If we have a relative-only import, then we need to relocate the space
    # after the final dot to be owned by the import token.
    if len(import_relative.relative) > 0 and import_relative.module is None:
        whitespace_before_import = import_relative.relative[
            -1].whitespace_after
        relative = (
            *import_relative.relative[:-1],
            import_relative.relative[-1].with_changes(
                whitespace_after=SimpleWhitespace("")),
        )
    else:
        whitespace_before_import = parse_simple_whitespace(
            config, importtoken.whitespace_before)
        relative = import_relative.relative

    return WithLeadingWhitespace(
        ImportFrom(
            whitespace_after_from=parse_simple_whitespace(
                config, fromtoken.whitespace_after),
            relative=relative,
            module=import_relative.module,
            whitespace_before_import=whitespace_before_import,
            whitespace_after_import=parse_simple_whitespace(
                config, importtoken.whitespace_after),
            lpar=lpar,
            names=names,
            rpar=rpar,
        ),
        fromtoken.whitespace_before,
    )
예제 #5
0
def convert_trailer_arglist(
        config: ParserConfig,
        children: typing.Sequence[typing.Any]) -> typing.Any:
    lpar, *arglist, rpar = children
    return CallPartial(
        lpar=WithLeadingWhitespace(
            LeftParen(whitespace_after=parse_parenthesizable_whitespace(
                config, lpar.whitespace_after)),
            lpar.whitespace_before,
        ),
        args=() if not arglist else arglist[0].args,
        rpar=RightParen(whitespace_before=parse_parenthesizable_whitespace(
            config, rpar.whitespace_before)),
    )