Пример #1
0
    def _visit_block_stmt(self, node):
        # output coment (prefix)
        self.accessor.emit_prefix_and_consuming(self.m, node)

        # main process
        children = node.children
        blocks = []  # (name, expr, body)
        st = 0
        for i, snode in enumerate(children):
            typ = type_repr(snode.type)
            if typ == "suite":
                assert children[i - 1].value == ":"
                blocks.append((children[st], children[st + 1:i - 1], children[i]))
                st = i + 1

        for (name, expr, body) in blocks:
            if expr:
                args = " ".join([str(x).strip() for x in expr]).lstrip()
                self.m.stmt("with m.{}_({!r}):", name.value.lstrip(), args)
            elif hasattr(name, "value"):  # Leaf
                self.m.stmt("with m.{}_():", name.value.lstrip())
            else:
                typ = type_repr(name.type)
                if typ == "except_clause":
                    self.m.stmt(
                        "with m.{}_({!r}):",
                        name.children[0].value,
                        " ".join([str(x).strip() for x in name.children[1:]]).lstrip(),
                    )
                else:
                    raise ValueError("unexpected blocks: {!r}, {!r}".format(name, expr))
            self.visit_suite(body)
Пример #2
0
    def visit_import_name(self, node: Node) -> t.Optional[t.Any]:
        # import [ <Leaf> | <dotted_as_name> | <dotted_name> ]
        assert len(node.children) == 2, node.children

        if type_repr(node.children[1].type) == "dotted_as_name":
            sym = parse_dotted_as_name(node.children[1])
            sym = dataclasses.replace(sym,
                                      id=id(node),
                                      from_=type_repr(node.type))
            self.symbols[sym.name] = sym
        elif type_repr(node.children[1].type) == "dotted_name":
            # <Leaf> { . <Leaf> }+
            module = parse_dotted_name(node.children[1])
            sym = Symbol(name=module, fullname=module)
            sym = dataclasses.replace(sym,
                                      id=id(node),
                                      from_=type_repr(node.type))
            self.symbols[module] = sym
        else:
            module = node.children[1].value.strip()
            sym = Symbol(name=module, fullname=module)
            sym = dataclasses.replace(sym,
                                      id=id(node),
                                      from_=type_repr(node.type))
            self.symbols[module] = sym
        return True  # stop
Пример #3
0
 def visit_decorated(self, node):
     for snode in node.children[:-1]:
         assert type_repr(snode.type) == "decorator"
         self.m.stmt(
             "m.stmt({!r})", " ".join([str(x)
                                       for x in snode.children]).strip().replace("@ ", "@")
         )
     return self.visit(node.children[-1])
Пример #4
0
def parse_dotted_as_name(node: Node) -> Symbol:
    # <Leaf> as <Leaf>
    assert len(node.children) == 3, str(node.children)

    if type_repr(node.children[0].type) == "dotted_name":
        module = parse_dotted_name(node.children[0])
        assert node.children[1].value == "as"
        name = node.children[2].value.strip()
        return Symbol(fullname=module, name=name)
    else:
        module = node.children[0].value.strip()
        assert node.children[1].value == "as"
        name = node.children[2].value.strip()
        return Symbol(fullname=module, name=name)
Пример #5
0
def parse_import_as_names(node: Node, *, module: str) -> t.List[Symbol]:
    # <Leaf> { , <Leaf> }+
    syms = []
    for i in range(0, len(node.children), 2):
        x = node.children[i]

        if type_repr(x.type) == "import_as_name":
            sym = parse_import_as_name(x)
            sym = Symbol(name=sym.name, fullname=f"{module}.{sym.fullname}")
        else:
            name = x.value.strip()
            sym = Symbol(name=name, fullname=f"{module}.{name}")

        syms.append(sym)
        if i - 1 > 0:
            assert node.children[i - 1].value == ","
    return syms
Пример #6
0
    def visit_import_from(self, node: Node) -> t.Optional[t.Any]:
        assert node.children[0].value == "from"

        module_path = []
        for i, x in enumerate(node.children[1:], 1):
            if type_repr(x.type) == "dotted_name":
                name = parse_dotted_name(x)
            else:
                name = x.value.strip()
                if name == "import":
                    break
            module_path.append(name)
            if name != ".":
                module_path.append(".")
        module_path.pop()
        module = "".join(module_path)

        sym_list = []
        for x in node.children[i + 1:]:
            if type_repr(x.type) == "import_as_name":
                sym = parse_import_as_name(x)
                sym = dataclasses.replace(
                    sym,
                    fullname=f"{module}.{sym.name}",
                    id=id(node),
                    from_=type_repr(node.type),
                )
                sym_list.append(sym)
            elif type_repr(x.type) == "import_as_names":
                syms = parse_import_as_names(x, module=module)
                syms = [
                    dataclasses.replace(sym,
                                        id=id(node),
                                        from_=type_repr(node.type))
                    for sym in syms
                ]
                sym_list.extend(syms)
            elif x.value.strip() == "(":
                continue
            elif x.value.strip() == ")":
                continue
            else:
                name = x.value.strip()
                sym = Symbol(name=name, fullname=f"{module}.{name}")
                sym = dataclasses.replace(sym,
                                          id=id(node),
                                          from_=type_repr(node.type))
                sym_list.append(sym)

        # todo: relative
        for sym in sym_list:
            self.symbols[sym.name] = sym
        return True  # stop
Пример #7
0
    def visit_suite(self, node):
        prefixes = []
        if node.prefix:
            prefixes.append(node)

        # main process
        itr = iter(node.children)

        found_indent = False
        for snode in itr:
            if snode.prefix:
                prefixes.append(snode)

            typ = type_repr(snode.type)
            if typ == token.INDENT:
                found_indent = True
                break

        if not found_indent:
            with self.m.scope():
                self.m.stmt("m.stmt({!r})", str(node).strip())
                return

        suffixes = []
        with self.m.scope():
            # output coment (prefix)
            comments = []
            for has_prefix_node in prefixes:
                comments.append(has_prefix_node.prefix)
                has_prefix_node.prefix = ""
            self.accessor.emit_comment(self.m, "\n".join(comments))

            for snode in itr:
                if snode.type == token.DEDENT:
                    suffixes.append(snode.prefix)
                    snode.prefix = ""
                self.visit(snode)

        # comment (suffix DEDENT)
        if suffixes:
            assert len(suffixes) == 1
            self.accessor.emit_comment(self.m, suffixes[0])
Пример #8
0
    def to_arguments(self, node):
        typ = type_repr(node.type)
        if typ == "parameters":
            # '(', <typedargslist>, ')'
            children = node.children

            if len(children) == 2:
                return LParams(kwargs=LKwargs())

            assert len(children) == 3
            assert children[0].value == "("
            node = children[1]
            assert children[2].value == ")"
            typ = type_repr(node.type)

        if typ == "typedargslist":
            argslist = node.children
        elif hasattr(node, "value"):  # leaf
            argslist = [node]
        else:
            raise ValueError("invalid type {}".format(typ))

        params = LParams(kwargs=LKwargs())
        itr = iter(argslist)
        while True:
            arg_name = None
            arg_type = None
            prefix = ""
            try:
                snode = next(itr)
                if snode.type == token.DOUBLESTAR:
                    prefix = "**"
                    snode = next(itr)
                elif snode.type == token.STAR:
                    prefix = "*"
                    snode = next(itr)

                    if snode.type == token.COMMA:
                        params.append("*")
                        continue

                if type_repr(snode.type) == "tname":  # with type
                    len(snode.children) == "3"
                    arg_name = snode.children[0].value
                    assert snode.children[1].type == token.COLON
                    arg_type = str(snode.children[2]).strip()
                else:
                    arg_name = snode.value

                arg_default = None
                snode = next(itr)  # or EOF
                if snode.type == token.COMMA:
                    pass
                elif snode.type == token.EQUAL:
                    snode = next(itr)
                    arg_default = str(snode)
                    snode = next(itr)  # , or EOF
                    assert snode.type == token.COMMA
                else:
                    raise ValueError("invalid arglist {!r}".format(argslist))
            except StopIteration:
                break
            finally:
                if arg_name is not None:
                    if prefix:  # *args or **kwargs
                        params.append_tail(prefix + arg_name, type=arg_type)
                    elif arg_default is None:
                        params.append(arg_name, type=arg_type)
                    else:
                        params.set(arg_name, arg_default, type=arg_type)
        return params
Пример #9
0
    def visit_simple_stmt(self, node):
        # output coment (prefix)
        self.accessor.emit_prefix_and_consuming(self.m, node)

        # main process
        children = node.children
        typ = type_repr(children[0].type)
        # docstring
        if hasattr(children[0], "value") and children[0].value.startswith(("'''", '"""')):
            docstring = "".join([snode.value for snode in children]).strip()
            if "\n" not in docstring:
                self.m.stmt("m.docstring({!r})", docstring.strip("\"'"))
            else:
                self.m.g.import_("textwrap")
                self.m.stmt('m.docstring(textwrap.dedent(')
                for line in docstring.split("\n"):
                    self.m.stmt(line)
                self.m.stmt("))")
            return

        # from x import (y, z) ?
        elif typ == "import_name":
            # 'import' <dotted_as_names>
            nodes = children[0].children

            assert nodes[0].value == "import"
            self.accessor.import_contextually(self.m, node, str(nodes[1]).strip())
            rest = nodes[2:]

        # import_name | import_from
        elif typ == "import_from":
            # 'from' <module> 'import' ('*' | '(' <import_asnames> ')' | <import_asnames>)
            nodes = children[0].children

            assert nodes[0].value == "from"
            module = str(nodes[1]).strip()
            assert nodes[2].value == "import"
            names = []
            for snode in nodes[2:]:
                typ = type_repr(snode.type)
                if typ == "import_as_names":
                    for ssnode in snode.children:
                        if type_repr(ssnode.type) == token.COMMA:
                            continue
                        names.append(str(ssnode).strip())
                elif typ == "import_as_name":
                    assert len(snode.children) == 3
                    names.append(str(snode).strip())
                elif typ == token.COMMA:
                    continue
                elif typ == token.LPAR:
                    continue
                elif typ == token.RPAR:
                    continue
                elif snode.value == "import":
                    continue
                else:
                    names.append(snode.value)
            self.accessor.from_contextually(self.m, node, module, names)
            rest = children[1:]
        else:
            rest = node.children

        if rest:
            self.accessor.emit_stmt_multiline(self.m, "".join([str(x) for x in rest]))
Пример #10
0
 def is_toplevel(self, node):
     return type_repr(node.parent.type) == "file_input"
Пример #11
0
 def is_def(self, node, _candidates=("funcdef", "classdef")):
     typ = type_repr(node.type)
     return typ in _candidates
Пример #12
0
def main():
    code = inspect.getsource(hello)
    code = inspect.getsource(sys.modules[__name__])

    t = parse_string(code)
    print("# before\n", t, sep="")
    v = Visitor()
    v.visit(t)

    for kind, node in changes:
        if kind == "args":
            assert node.children[0].type == token.LPAR
            assert node.children[-1].type == token.RPAR
            node.children.insert(1, fixer_util.Name("m"))
        elif kind == "stmt":
            # TODO: support ";"

            # <stmt>
            # ↓
            # m.stmt(<stmt>)
            node.prefix = f"{node.prefix}m.stmt("
            assert node.children[-1].value == "\n"
            node.children[-1].prefix = f"){node.children[-1].prefix}"

        elif kind == "let":
            if type_repr(node.children[0].type) == "power":
                # TODO: foo.bar.boo  = v =>  setattr(getattr(foo, "bar"), "boo", v)

                # <recv>.<attr> = <val>
                # ↓
                # m.setattr(<recv>, "<attr>", <val>)
                # todo: recursive
                assert type_repr(node.children[0].type) == "power"
                power = node.children[0]
                name = power.children[0].value
                assert type_repr(power.children[1].type) == "trailer"
                trailer = power.children[1]
                assert trailer.children[0].type == token.DOT
                trailer.children[0] = fixer_util.Comma()
                attr = trailer.children[1]

                node.prefix = f"{node.prefix}m.setattr("
                attr.prefix = f'{attr.prefix} "'

                assert node.children[1].type == token.EQUAL
                eq_node = node.children[1]
                node.children[1] = fixer_util.Comma()
                node.children[1].prefix = f'"{eq_node.prefix}'
                node.parent.children[-1].prefix = f"){node.parent.children[-1].prefix}"
                # attr_next.prefix = f'"){attr_next.prefix}'
                continue

            # <var> = <val>
            # ↓
            # <var> = m.let("<var>", <val>)
            name = node.children[0].value
            assert node.children[1].value == "="
            node.children[2].prefix = f"{node.children[2].prefix}m.let({name!r}, "
            next_sibling = node.next_sibling
            assert next_sibling is not None
            next_sibling.prefix = f"){next_sibling}"

    print("")
    print("# after\n", t, sep="")
Пример #13
0
    def visit_simple_stmt(self, node: Node):
        if type_repr(node.children[0].type) == "expr_stmt":
            return False

        changes.append(("stmt", node))
        return True  # stop