示例#1
0
    def n_mkfunc(self, node):
        """If the function has a docstring (this is found in the code
        constants), pull that out and make it part of the syntax
        tree. When generating the source string that AST node rather
        than the code field is seen and used.
        """

        if self.version >= (3, 7):
            code_index = -3
        else:
            code_index = -2

        code = find_code_node(node, code_index).attr

        mkfunc_pattr = node[-1].pattr
        if isinstance(mkfunc_pattr, tuple):
            assert len(mkfunc_pattr, 4) and isinstance(mkfunc_pattr, int)
            is_closure = node[-1].pattr[3] != 0
        else:
            # FIXME: This is what we had before. It is hoaky and probably wrong.
            is_closure = mkfunc_pattr == "closure"

        if ((not is_closure) and len(code.co_consts) > 0
                and isinstance(code.co_consts[0], str)):
            docstring_node = SyntaxTree(
                "docstring",
                [Token("LOAD_STR", has_arg=True, pattr=code.co_consts[0])])
            docstring_node.transformed_by = "n_mkfunc"
            node = SyntaxTree("mkfunc", node[:-1] + [docstring_node, node[-1]])
            node.transformed_by = "n_mkfunc"

        return node
示例#2
0
    def n_mkfunc(self, node):
        """If the function has a docstring (this is found in the code
        constants), pull that out and make it part of the syntax
        tree. When generating the source string that AST node rather
        than the code field is seen and used.
        """

        if self.version >= 3.7:
            code_index = -3
        else:
            code_index = -2

        code = find_code_node(node, code_index).attr

        if (
            node[-1].pattr != "closure"
            and len(code.co_consts) > 0
            and code.co_consts[0] is not None
        ):
            docstring_node = SyntaxTree(
                "docstring", [Token("LOAD_STR", has_arg=True, pattr=code.co_consts[0])]
            )
            docstring_node.transformed_by = "n_mkfunc"
            node = SyntaxTree("mkfunc", node[:-1] + [docstring_node, node[-1]])
            node.transformed_by = "n_mkfunc"

        return node
示例#3
0
 def n_stmts(self, node):
     if node.first_child() == "SETUP_ANNOTATIONS":
         prev = node[0][0]
         new_stmts = [node[0]]
         for i, sstmt in enumerate(node[1:]):
             ann_assign = sstmt[0][0]
             if (
                 sstmt[0] == "stmt"
                 and ann_assign == "ann_assign"
                 and prev == "assign"
             ):
                 annotate_var = ann_assign[-2]
                 if annotate_var.attr == prev[-1][0].attr:
                     del new_stmts[-1]
                     sstmt[0][0] = SyntaxTree(
                         "ann_assign_init", [ann_assign[0], prev[0], annotate_var]
                     )
                     sstmt[0][0].transformed_by = "n_stmts"
                     pass
                 pass
             new_stmts.append(sstmt)
             prev = ann_assign
             pass
         node.data = new_stmts
     return node
示例#4
0
    def transform(self, ast, code):
        self.maybe_show_tree(ast)
        self.ast = copy(ast)
        self.ast = self.traverse(self.ast, is_lambda=False)

        try:
            # Disambiguate a string (expression) which appears as a "call_stmt" at
            # the beginning of a function versus a docstring. Seems pretty academic,
            # but this is Python.
            call_stmt = ast[0][0]
            if is_not_docstring(call_stmt):
                call_stmt.kind = "string_at_beginning"
                call_stmt.transformed_by = "transform"
                pass
        except:
            pass

        try:
            for i in range(len(self.ast)):
                sstmt = ast[i]
                if len(sstmt) == 1 and sstmt == "sstmt":
                    self.ast[i] = self.ast[i][0]

                if is_docstring(self.ast[i], self.version, code.co_consts):
                    load_const = self.ast[i].first_child()
                    docstring_ast = SyntaxTree(
                        "docstring",
                        [
                            Token(
                                "LOAD_STR",
                                has_arg=True,
                                offset=0,
                                attr=load_const.attr,
                                pattr=load_const.pattr,
                            )
                        ],
                    )
                    docstring_ast.transformed_by = "transform"
                    del self.ast[i]
                    self.ast.insert(0, docstring_ast)
                    break

            if self.ast[-1] == RETURN_NONE:
                self.ast.pop()  # remove last node
                # todo: if empty, add 'pass'
        except:
            pass

        return self.ast
示例#5
0
 def n_import_from37(self, node):
     importlist37 = node[3]
     assert importlist37 == "importlist37"
     if len(importlist37) == 1:
         alias37 = importlist37[0]
         store = alias37[1]
         assert store == "store"
         alias_name = store[0].attr
         import_name_attr = node[2]
         assert import_name_attr == "IMPORT_NAME_ATTR"
         dotted_names = import_name_attr.attr.split(".")
         if len(dotted_names) > 1 and dotted_names[-1] == alias_name:
             # Simulate:
             # Instead of
             # import_from37 ::= LOAD_CONST LOAD_CONST IMPORT_NAME_ATTR importlist37 POP_TOP
             # import_as37   ::= LOAD_CONST LOAD_CONST importlist37 store POP_TOP
             # 'import_as37':     ( '%|import %c as %c\n', 2, -2),
             node = SyntaxTree(
                 "import_as37",
                 [node[0], node[1], import_name_attr, store, node[-1]])
             node.transformed_by = "n_import_from37"
             pass
         pass
     return node
示例#6
0
    def n_ifstmt(self, node):
        """Here we check if we can turn an `ifstmt` or 'iflaststmtl` into
           some kind of `assert` statement"""

        testexpr = node[0]

        if testexpr.kind != "testexpr":
            return node
        if node.kind in ("ifstmt", "ifstmtl"):
            ifstmts_jump = node[1]

            if ifstmts_jump == "_ifstmts_jumpl" and ifstmts_jump[0] == "_ifstmts_jump":
                ifstmts_jump = ifstmts_jump[0]
            elif ifstmts_jump not in ("_ifstmts_jump", "ifstmts_jumpl"):
                return node
            stmts = ifstmts_jump[0]
        else:
            # iflaststmtl works this way
            stmts = node[1]

        if stmts in ("c_stmts",) and len(stmts) == 1:
            stmt = stmts[0]
            raise_stmt = stmt[0]
            if (
                raise_stmt == "raise_stmt1"
                and len(testexpr[0]) == 2
                and raise_stmt.first_child().pattr == "AssertionError"
            ):
                assert_expr = testexpr[0][0]
                assert_expr.kind = "assert_expr"
                jump_cond = testexpr[0][1]
                expr = raise_stmt[0]
                RAISE_VARARGS_1 = raise_stmt[1]
                call = expr[0]
                if call == "call":
                    # ifstmt
                    #     0. testexpr
                    #         testtrue (2)
                    #             0. expr
                    #     1. _ifstmts_jump (2)
                    #         0. c_stmts
                    #             stmt
                    #                 raise_stmt1 (2)
                    #                     0. expr
                    #                         call (3)
                    #                     1. RAISE_VARARGS_1
                    # becomes:
                    # assert2 ::= assert_expr jmp_true LOAD_ASSERT expr RAISE_VARARGS_1 COME_FROM
                    if jump_cond == "jmp_true":
                        kind = "assert2"
                    else:
                        assert jump_cond == "jmp_false"
                        kind = "assert2not"

                    LOAD_ASSERT = call[0].first_child()
                    if LOAD_ASSERT != "LOAD_ASSERT":
                        return node
                    if isinstance(call[1], SyntaxTree):
                        expr = call[1][0]
                        node = SyntaxTree(
                            kind,
                            [assert_expr, jump_cond, LOAD_ASSERT, expr, RAISE_VARARGS_1]
                        )
                        pass
                    pass
                else:
                    # ifstmt
                    #   0. testexpr (2)
                    #      testtrue
                    #       0. expr
                    #   1. _ifstmts_jump (2)
                    #      0. c_stmts
                    #        stmts
                    #           raise_stmt1 (2)
                    #             0. expr
                    #                  LOAD_ASSERT
                    #             1.   RAISE_VARARGS_1
                    # becomes:
                    # assert ::= assert_expr jmp_true LOAD_ASSERT RAISE_VARARGS_1 COME_FROM
                    if jump_cond == "jmp_true":
                        if self.is_pypy:
                            kind = "assert0_pypy"
                        else:
                            kind = "assert"
                    else:
                        assert jump_cond == "jmp_false"
                        kind = "assertnot"

                    LOAD_ASSERT = expr[0]
                    node = SyntaxTree(
                        kind,
                        [assert_expr, jump_cond, LOAD_ASSERT, RAISE_VARARGS_1]
                    )
                node.transformed_by="n_ifstmt",
                pass
            pass
        return node
示例#7
0
    def n_ifstmt(self, node):
        """Here we check if we can turn an `ifstmt` or 'iflaststmtl` into
           some kind of `assert` statement"""

        testexpr = node[0]

        if testexpr.kind != "testexpr":
            return node
        if node.kind == "ifstmt":
            ifstmts_jump = node[1]
            if node[1] != "_ifstmts_jump":
                return node
            stmts = ifstmts_jump[0]
        else:
            # iflaststmtl works this way
            stmts = node[1]

        if stmts in ("c_stmts", ) and len(stmts) == 1:
            stmt = stmts[0]
            raise_stmt = stmt[0]
            if raise_stmt == "raise_stmt1" and len(testexpr[0]) == 2:
                assert_expr = testexpr[0][0]
                assert_expr.kind = "assert_expr"
                jump_cond = testexpr[0][1]
                expr = raise_stmt[0]
                RAISE_VARARGS_1 = raise_stmt[1]
                if expr[0] == "call":
                    # ifstmt
                    #     0. testexpr
                    #         testtrue (2)
                    #             0. expr
                    #     1. _ifstmts_jump (2)
                    #         0. c_stmts
                    #             stmt
                    #                 raise_stmt1 (2)
                    #                     0. expr
                    #                         call (3)
                    #                     1. RAISE_VARARGS_1
                    # becomes:
                    # assert2 ::= assert_expr jmp_true LOAD_ASSERT expr RAISE_VARARGS_1 COME_FROM
                    if jump_cond == "jmp_true":
                        kind = "assert2"
                    else:
                        assert jump_cond == "jmp_false"
                        kind = "assert2not"

                    call = expr[0]
                    LOAD_ASSERT = call[0]
                    expr = call[1][0]
                    node = SyntaxTree(kind, [
                        assert_expr, jump_cond, LOAD_ASSERT, expr,
                        RAISE_VARARGS_1
                    ])
                else:
                    # ifstmt
                    #   0. testexpr (2)
                    #      testtrue
                    #       0. expr
                    #   1. _ifstmts_jump (2)
                    #      0. c_stmts
                    #        stmts
                    #           raise_stmt1 (2)
                    #             0. expr
                    #                  LOAD_ASSERT
                    #             1.   RAISE_VARARGS_1
                    # becomes:
                    # assert ::= assert_expr jmp_true LOAD_ASSERT RAISE_VARARGS_1 COME_FROM
                    if jump_cond == "jmp_true":
                        kind = "assert"
                    else:
                        assert jump_cond == "jmp_false"
                        kind = "assertnot"

                    LOAD_ASSERT = expr[0]
                    node = SyntaxTree(
                        kind,
                        [assert_expr, jump_cond, LOAD_ASSERT, RAISE_VARARGS_1])
                node.transformed_by = "n_ifstmt",
                pass
            pass
        return node
示例#8
0
    def n_ifstmt(self, node):
        """Here we check if we can turn an `ifstmt` or 'iflaststmtl` into
           some kind of `assert` statement"""

        testexpr = node[0]

        if testexpr != "testexpr":
            return node

        if node.kind in ("ifstmt", "ifstmtl"):
            ifstmts_jump = node[1]

            if ifstmts_jump == "_ifstmts_jumpl" and ifstmts_jump[
                    0] == "_ifstmts_jump":
                ifstmts_jump = ifstmts_jump[0]
            elif ifstmts_jump not in ("_ifstmts_jump", "ifstmts_jumpl"):
                return node
            stmts = ifstmts_jump[0]
        else:
            # iflaststmtl works this way
            stmts = node[1]

        if stmts in ("c_stmts", ) and len(stmts) == 1:
            stmt = stmts[0]
            raise_stmt = stmt[0]
            testtrue_or_false = testexpr[0]
            if (raise_stmt == "raise_stmt1"
                    and 1 <= len(testtrue_or_false) <= 2
                    and raise_stmt.first_child().pattr == "AssertionError"):
                if testtrue_or_false == "testtrue":
                    # Skip over the testtrue because because it would
                    # produce a "not" and we don't want that here.
                    assert_expr = testtrue_or_false[0]
                    jump_cond = NoneToken
                else:
                    assert_expr = testtrue_or_false[0]
                    jump_cond = testtrue_or_false[1]
                    assert_expr.kind = "assert_expr"
                expr = raise_stmt[0]
                RAISE_VARARGS_1 = raise_stmt[1]
                call = expr[0]
                if call == "call":
                    # ifstmt
                    #     0. testexpr
                    #         testtrue (2)
                    #             0. expr
                    #     1. _ifstmts_jump (2)
                    #         0. c_stmts
                    #             stmt
                    #                 raise_stmt1 (2)
                    #                     0. expr
                    #                         call (3)
                    #                     1. RAISE_VARARGS_1
                    # becomes:
                    # assert2 ::= assert_expr jmp_true LOAD_ASSERT expr RAISE_VARARGS_1 COME_FROM
                    if jump_cond in ("jmp_true", NoneToken):
                        kind = "assert2"
                    else:
                        if jump_cond == "jmp_false":
                            # FIXME: We don't handle this kind of thing yet.
                            return node
                        kind = "assert2not"

                    LOAD_ASSERT = call[0].first_child()
                    if LOAD_ASSERT != "LOAD_ASSERT":
                        return node
                    if isinstance(call[1], SyntaxTree):
                        expr = call[1][0]
                        node = SyntaxTree(
                            kind,
                            [
                                assert_expr,
                                jump_cond,
                                LOAD_ASSERT,
                                expr,
                                RAISE_VARARGS_1,
                            ],
                        )
                        node.transformed_by = "n_ifstmt"
                        pass
                    pass
                else:
                    # ifstmt
                    #   0. testexpr (2)
                    #      testtrue
                    #       0. expr
                    #   1. _ifstmts_jump (2)
                    #      0. c_stmts
                    #        stmts
                    #           raise_stmt1 (2)
                    #             0. expr
                    #                  LOAD_ASSERT
                    #             1.   RAISE_VARARGS_1
                    # becomes:
                    # assert ::= assert_expr jmp_true LOAD_ASSERT RAISE_VARARGS_1 COME_FROM
                    if jump_cond in ("jmp_true", NoneToken):
                        if self.is_pypy:
                            kind = "assert0_pypy"
                        else:
                            kind = "assert"
                    else:
                        assert jump_cond == "jmp_false"
                        kind = "assertnot"

                    LOAD_ASSERT = expr[0]
                    node = SyntaxTree(
                        kind,
                        [assert_expr, jump_cond, LOAD_ASSERT, RAISE_VARARGS_1])
                node.transformed_by = ("n_ifstmt", )
                pass
            pass
        return node