Ejemplo n.º 1
0
def wrap_code(code: str, args: str = '') -> ast.Module:
    """Compiles Python code into an async function or generator.

    Automatically adds return if the function body is a single evaluation.
    Also adds inline import expression support.
    """

    if sys.version_info >= (3, 7):
        user_code = import_expression.parse(code, mode='exec')
        injected = ''
    else:
        injected = code

    mod = import_expression.parse(CORO_CODE.format(
        args, textwrap.indent(injected, ' ' * 8)),
                                  mode='exec')

    definition = mod.body[-1]  # async def ...:
    assert isinstance(definition, ast.AsyncFunctionDef)

    try_block = definition.body[-1]  # try:
    assert isinstance(try_block, ast.Try)

    if sys.version_info >= (3, 7):
        try_block.body.extend(user_code.body)
    else:
        preclude_offset = CORO_CODE.split('pass')[0].count('\n') + 1
        ast.increment_lineno(
            mod, -preclude_offset)  # bring line numbers back in sync with repl

    ast.fix_missing_locations(mod)

    is_asyncgen = any(
        isinstance(node, ast.Yield) for node in ast.walk(try_block))

    last_expr = try_block.body[-1]

    # if the last part isn't an expression, ignore it
    if not isinstance(last_expr, ast.Expr):
        return mod

    # if the last expression is not a yield
    if not isinstance(last_expr.value, ast.Yield):
        # copy the expression into a return/yield
        if is_asyncgen:
            # copy the value of the expression into a yield
            yield_stmt = ast.Yield(last_expr.value)
            ast.copy_location(yield_stmt, last_expr)
            # place the yield into its own expression
            yield_expr = ast.Expr(yield_stmt)
            ast.copy_location(yield_expr, last_expr)

            # place the yield where the original expression was
            try_block.body[-1] = yield_expr
        else:
            # copy the expression into a return
            return_stmt = ast.Return(last_expr.value)
            ast.copy_location(return_stmt, last_expr)

            # place the return where the original expression was
            try_block.body[-1] = return_stmt

    return mod
Ejemplo n.º 2
0
    def test_operators(self):
        boolop0 = ast.BoolOp()
        boolop1 = ast.BoolOp(ast.And(), 
                          [ ast.Name('True', ast.Load()), ast.Name('False', ast.Load()), ast.Name('a',ast.Load())])
        boolop2 = ast.BoolOp(ast.And(), 
                          [ ast.Name('True', ast.Load()), ast.Name('False', ast.Load()), ast.Name('a',ast.Load())],
                          0, 0)
        binop0 = ast.BinOp()
        binop1 = ast.BinOp(ast.Str('xy'), ast.Mult(), ast.Num(3))
        binop2 = ast.BinOp(ast.Str('xy'), ast.Mult(), ast.Num(3), 0, 0)

        unaryop0 = ast.UnaryOp()
        unaryop1 = ast.UnaryOp(ast.Not(), ast.Name('True',ast.Load())) 
        unaryop2 = ast.UnaryOp(ast.Not(), ast.Name('True',ast.Load()), 0, 0)

        lambda0 = ast.Lambda()
        lambda1 = ast.Lambda(ast.arguments([ast.Name('x', ast.Param())], None, None, []), ast.Name('x', ast.Load()))
        
        ifexp0 = ast.IfExp()
        ifexp1 = ast.IfExp(ast.Name('True',ast.Load()), ast.Num(1), ast.Num(0))
        ifexp2 = ast.IfExp(ast.Name('True',ast.Load()), ast.Num(1), ast.Num(0), 0, 0)

        dict0 = ast.Dict()
        dict1 = ast.Dict([ast.Num(1), ast.Num(2)], [ast.Str('a'), ast.Str('b')])
        dict2 = ast.Dict([ast.Num(1), ast.Num(2)], [ast.Str('a'), ast.Str('b')], 0, 0)

        set0 = ast.Set()
        set1 = ast.Set([ast.Num(1), ast.Num(2)])
        set2 = ast.Set([ast.Num(1), ast.Num(2)], 0, 0)

        lc0 = ast.ListComp()
        lc1 = ast.ListComp( ast.Name('x',ast.Load()), 
                   [ast.comprehension(ast.Name('x', ast.Store()), 
                                      ast.Tuple([ast.Num(1), ast.Num(2)], ast.Load()), [])])
        lc2 = ast.ListComp( ast.Name('x',ast.Load()), 
                   [ast.comprehension(ast.Name('x', ast.Store()), 
                                      ast.Tuple([ast.Num(1), ast.Num(2)], ast.Load()), [])], 0, 0)


        setcomp0 = ast.SetComp()
        setcomp1 = ast.SetComp(ast.Name('x', ast.Load()), 
                   [ast.comprehension(ast.Name('x', ast.Store()), ast.Str('abracadabra'), 
                                      [ast.Compare(ast.Name('x', ast.Load()), [ast.NotIn()], 
                                                   [ast.Str('abc')])])])


        comprehension0 = ast.comprehension()
        comprehension1 = ast.comprehension(ast.Name('x', ast.Store()), 
                                           ast.Tuple([ast.Num(1), ast.Num(2)], ast.Load()), [])


        # "{i : chr(65+i) for i in (1,2)}")
        dictcomp0 = ast.DictComp()
        dictcomp1 = ast.DictComp(ast.Name('i', ast.Load()), 
                                 ast.Call(ast.Name('chr', ast.Load()), 
                                          [ast.BinOp(ast.Num(65), ast.Add(), ast.Name('i', ast.Load()))],
                                          [], None, None), 
                                 [ast.comprehension(ast.Name('i', ast.Store()), 
                                                    ast.Tuple([ast.Num(1), ast.Num(n=2)], ast.Load()), [])])
        dictcomp2 = ast.DictComp(ast.Name('i', ast.Load()), 
                                 ast.Call(ast.Name('chr', ast.Load()), 
                                          [ast.BinOp(ast.Num(65), ast.Add(), ast.Name('i', ast.Load()))],
                                          [], None, None), 
                                 [ast.comprehension(ast.Name('i', ast.Store()), 
                                                    ast.Tuple([ast.Num(1), ast.Num(n=2)], ast.Load()), [])],0,0)

        # (x for x in (1,2))
        genexp0 = ast.GeneratorExp()
        genexp1 = ast.GeneratorExp(ast.Name('x', ast.Load()), 
                                   [ast.comprehension(ast.Name('x', ast.Store()), 
                                                      ast.Tuple([ast.Num(1), ast.Num(2)], ast.Load()), [])])
        genexp2 = ast.GeneratorExp(ast.Name('x', ast.Load()), 
                                   [ast.comprehension(ast.Name('x', ast.Store()), 
                                                      ast.Tuple([ast.Num(1), ast.Num(2)], ast.Load()), [])],0,0)

        # yield 2
        yield0 = ast.Yield()
        yield1 = ast.Yield(ast.Num(2))
        yield2 = ast.Yield(ast.Num(2),0,0)
        yield20 = ast.Yield(lineno=0, col_offset=0)

        # a>0
        compare0 = ast.Compare()
        compare1 = ast.Compare(ast.Name('a', ast.Load()), [ast.Gt()], [ast.Num(0)])
        compare2 = ast.Compare(ast.Name('a', ast.Load()), [ast.Gt()], [ast.Num(0)],0,0)

        # chr(65)
        call0 = ast.Call()
        call1 = ast.Call(ast.Name('chr', ast.Load()), [ast.Num(65)], [], None, None)
        call2 = ast.Call(ast.Name('chr', ast.Load()), [ast.Num(65)], [], None, None, 0, 0)
        call20 = ast.Call(ast.Name('f', ast.Load()), [ast.Num(0)], [])
        call21 = ast.Call(ast.Name('f', ast.Load()), [ast.Num(0)], [], lineno=0, col_offset=0)

        # 0
        num0 = ast.Num()
        num1 = ast.Num(0)
        num2 = ast.Num(0,0,0)

        # "foo"
        str0 = ast.Str()
        str1 = ast.Str("foo")
        str2 = ast.Str("foo",0,0)

        # TODO: come back
        repr0 = ast.Repr()
        repr1 = ast.Repr(ast.Num(0))
        repr2 = ast.Repr(ast.Num(0),0,0)

        # foo.bar
        attr0 = ast.Attribute()
        attr1 = ast.Attribute(ast.Name('foo', ast.Load()), 'bar', ast.Load())
        attr2 = ast.Attribute(ast.Name('foo', ast.Load()), 'bar', ast.Load(), 0,0)

        # a[1:2]
        subscript0 = ast.Subscript()
        subscript1 = ast.Subscript(ast.Name('a', ast.Load()), ast.Slice(ast.Num(1), ast.Num(2)), ast.Load())
        subscript2 = ast.Subscript(ast.Name('a', ast.Load()), ast.ExtSlice([ast.Num(1), ast.Num(2)]), ast.Load(), 0, 0)

        # name
        name0 = ast.Name()
        name1 = ast.Name("name", ast.Load())
        name2 = ast.Name("name", ast.Load(),0,0)

        # [1,2]
        list0 = ast.List()
        list1 = ast.List([ast.Num(1), ast.Num(2)], ast.Load())
        list2 = ast.List([ast.Num(1), ast.Num(2)], ast.Load(),0,0)

        # (1,2)
        tuple0 = ast.Tuple()
        tuple1 = ast.Tuple([ast.Num(1), ast.Num(2)], ast.Load())
        tuple2 = ast.Tuple([ast.Num(1), ast.Num(2)], ast.Load(), 0, 0)
Ejemplo n.º 3
0
 def visit_Return(self, node):
     self.generic_visit(node)
     return ast.Expr(ast.Yield(node.value)) if self.active[-1] else node
Ejemplo n.º 4
0
 def visitYield(self, n, *args):
     return ast.Yield(self.dispatch(n.value, *args) if n.value else None)
 def test_optional_arg(self):
     node = python_ast.Yield()
     setattr(node, "value", None)
     assert python_ast.dump(node) == \
         python_ast.dump(to_python_ast(to_ast(node,
                                              lambda x: [x])))
Ejemplo n.º 6
0
 def test_yield(self):
     self.expr(ast.Yield(ast.Name("x", ast.Store())), "must have Load")
     self.expr(ast.YieldFrom(ast.Name("x", ast.Store())), "must have Load")
Ejemplo n.º 7
0
    def 新节点(
            类型, 主体=None, 忽略类型=None, 值=None, 左=None, 运算符=None, 右=None, 标识=None,
            上下文=None, 函数=None, 参数=None, 关键词=None, 变量=None, 条件=None, 否则=None,
            前项=None, 后项=None, 标注=None, 名称=None, 返回=None, 各基准类=None, 片段=None):
        if 类型 == 语法.模块:
            节点 = ast.Module(body=主体, type_ignores=忽略类型)
        elif 类型 == 语法.表达式:
            节点 = ast.Expr(value=值)
        elif 类型 == 语法.数:
            节点 = ast.Num(n=值)
        elif 类型 == 语法.二元表达式:
            # 通过类名方式简化if语句
            运算符名 = 运算符.__class__.__name__
            if 运算符名 in ('And', 'Or'):
                节点 = ast.BoolOp(op=运算符, values=[前项, 后项])
            elif 运算符名 in ('Add', 'Sub', 'Mult', 'Pow', 'Mod', 'LShift', 'RShift', 'BitAnd', 'BitOr'):
                节点 = ast.BinOp(left=左, op=运算符, right=右)
            else:
                # DONE: 为何比较符和后项在数组中?
                # https://docs.python.org/zh-cn/3/library/ast.html#ast.Compare 函数定义的参数在数组中
                节点 = ast.Compare(前项, [运算符], [后项])
        elif 类型 == 语法.名称:
            节点 = ast.Name(id=标识, ctx=上下文)
        elif 类型 == 语法.调用:
            节点 = ast.Call(func=函数, args=参数, keywords=关键词)
        elif 类型 == 语法.赋值:
            节点 = ast.Assign([变量], 值)
        elif 类型 == 语法.增量赋值:
            节点 = ast.AugAssign(变量, 运算符, 值)
        elif 类型 == 语法.类型赋值:
            节点 = ast.AnnAssign(
                target=变量,
                annotation=标注,
                value=值,
                simple=1,
            )
        elif 类型 == 语法.条件声明:
            节点 = ast.If(test=条件, body=主体, orelse=否则)
        elif 类型 == 语法.每当声明:
            节点 = ast.While(test=条件, body=主体, orelse=[])
        elif 类型 == 语法.终止声明:
            节点 = ast.Break()
        elif 类型 == 语法.跳过声明:
            节点 = ast.Continue()
        elif 类型 == 语法.操作数:
            节点 = ast.arg(arg=参数)
        elif 类型 == 语法.lambda形参 or 类型 == 语法.形参:
            节点 = ast.arg(arg=参数, annotation=标注)
        elif 类型 == 语法.形参列表:
            节点 = ast.arguments(args=参数, kwonlyargs=[], kw_defaults=[], defaults=[], vararg=None, kwarg=None)
        elif 类型 == 语法.函数:
            节点 = ast.FunctionDef(
                name=名称,
                args=参数,
                body=主体,
                decorator_list=[]
            )
            if 返回:
                节点.returns = 返回
        elif 类型 == 语法.生成表达式:
            节点 = ast.Yield(value=值)
        elif 类型 == 语法.返回声明:
            节点 = ast.Return(value=值)
        elif 类型 == 语法.引用声明:
            节点 = ast.Import(names=名称)
        elif 类型 == 语法.lambda表达式:
            节点 = ast.Lambda(args=参数, body=主体)
        elif 类型 == 语法.类型定义:
            节点 = ast.ClassDef(
                name=名称,
                bases=各基准类,
                keywords=[],
                body=主体,
                decorator_list=[]
            )
        elif 类型 == 语法.字符串:
            节点 = ast.Str(值)
        elif 类型 == 语法.外部声明:
            节点 = ast.Global(names=名称)
        elif 类型 == 语法.一元表达式:
            节点 = ast.UnaryOp(op=运算符, operand=值)

        if 片段:
            节点.lineno = 语法树.取行号(片段)
            节点.col_offset = 语法树.取列号(片段)
        return 节点
Ejemplo n.º 8
0
 def p_yield_expr3(self, p):
     ''' yield_expr : YIELD FROM testlist '''
     value = ast_for_testlist(p[2])
     p[0] = ast.Yield(value=value, lineno=p.lineno(1))
Ejemplo n.º 9
0
 def p_yield_expr2(self, p):
     ''' yield_expr : YIELD testlist_star_expr '''
     value = ast_for_testlist(p[2])
     p[0] = ast.Yield(value=value, lineno=p.lineno(1))
Ejemplo n.º 10
0
 def visit_Call(self, node):
     return ast.Yield(value=node)
Ejemplo n.º 11
0
def Yield(draw, expression) -> ast.Yield:
    return ast.Yield(draw(expression))
    def visit_Yield(self, node: Yield, *args, **kwargs) -> C.Yield:
        value = self.visit(node.value, *args, **kwargs)

        return C.Yield(value=value, )
Ejemplo n.º 13
0
def generate_yield(max_depth=None):
    return ast.Expr(ast.Yield(generate_expression(max_depth=max_depth - 1)))
Ejemplo n.º 14
0
def yield_(value):
    return ast.Yield(value=value)
Ejemplo n.º 15
0
 def _yield(self, node):
     return ast.Expr(ast.Yield(node))
Ejemplo n.º 16
0
def p_yield_stmt(p):
    """expression : YIELD expression"""

    p[0] = ast.Yield(p[2])
def make_yield():
    """Yield(expr? value)"""

    return ast.Yield(value=make_expression())
Ejemplo n.º 18
0
    def test_empty_init(self):
        # Jython 2.5.0 did not allow empty constructors for many ast node types
        # but CPython ast nodes do allow this.  For the moment, I don't see a
        # reason to allow construction of the super types (like ast.AST and
        # ast.stmt) as well as the op types that are implemented as enums in
        # Jython (like boolop), but I've left them in but commented out for
        # now.  We may need them in the future since CPython allows this, but
        # it may fall under implementation detail.

        #ast.AST()
        ast.Add()
        ast.And()
        ast.Assert()
        ast.Assign()
        ast.Attribute()
        ast.AugAssign()
        ast.AugLoad()
        ast.AugStore()
        ast.BinOp()
        ast.BitAnd()
        ast.BitOr()
        ast.BitXor()
        ast.BoolOp()
        ast.Break()
        ast.Call()
        ast.ClassDef()
        ast.Compare()
        ast.Continue()
        ast.Del()
        ast.Delete()
        ast.Dict()
        ast.Div()
        ast.Ellipsis()
        ast.Eq()
        ast.Exec()
        ast.Expr()
        ast.Expression()
        ast.ExtSlice()
        ast.FloorDiv()
        ast.For()
        ast.FunctionDef()
        ast.GeneratorExp()
        ast.Global()
        ast.Gt()
        ast.GtE()
        ast.If()
        ast.IfExp()
        ast.Import()
        ast.ImportFrom()
        ast.In()
        ast.Index()
        ast.Interactive()
        ast.Invert()
        ast.Is()
        ast.IsNot()
        ast.LShift()
        ast.Lambda()
        ast.List()
        ast.ListComp()
        ast.Load()
        ast.Lt()
        ast.LtE()
        ast.Mod()
        ast.Module()
        ast.Mult()
        ast.Name()
        ast.Not()
        ast.NotEq()
        ast.NotIn()
        ast.Num()
        ast.Or()
        ast.Param()
        ast.Pass()
        ast.Pow()
        ast.Print()
        ast.RShift()
        ast.Raise()
        ast.Repr()
        ast.Return()
        ast.Slice()
        ast.Store()
        ast.Str()
        ast.Sub()
        ast.Subscript()
        ast.Suite()
        ast.TryExcept()
        ast.TryFinally()
        ast.Tuple()
        ast.UAdd()
        ast.USub()
        ast.UnaryOp()
        ast.While()
        ast.With()
        ast.Yield()
        ast.alias()
        ast.arguments()
        #ast.boolop()
        #ast.cmpop()
        ast.comprehension()
        #ast.excepthandler()
        #ast.expr()
        #ast.expr_context()
        ast.keyword()
Ejemplo n.º 19
0
def ast_yield_true():
    return ast.Yield(value=ast.Name(id='True', ctx=ast.Load))
Ejemplo n.º 20
0
    def _check_for_duplicate_yields(self, node: ast.Yield,
                                    current_statement: ast.stmt) -> None:
        if not isinstance(node.value, ast.Tuple) or len(node.value.elts) < 2:
            return

        duplicate_indices = {}  # index to first index
        seen = {}  # ast.dump result to index
        for i, member in enumerate(node.value.elts):
            # identical AST nodes don't compare equally, so just stringify them for comparison
            code = ast.dump(member)
            if code in seen:
                duplicate_indices[i] = seen[code]
            else:
                seen[code] = i

        if not duplicate_indices:
            return

        new_members = [
            elt for i, elt in enumerate(node.value.elts)
            if i not in duplicate_indices
        ]
        if len(new_members) == 1:
            new_value = new_members[0]
        else:
            new_value = ast.Tuple(elts=new_members)
        new_yield_node = ast.Yield(value=new_value)

        if isinstance(current_statement,
                      ast.Expr) and current_statement.value is node:
            new_nodes = [ast.Expr(value=new_yield_node)]
        elif (isinstance(current_statement, ast.Assign)
              and current_statement.value is node):
            if (len(current_statement.targets) != 1
                    or not isinstance(current_statement.targets[0], ast.Tuple)
                    or len(current_statement.targets[0].elts) != len(
                        node.value.elts)):
                new_nodes = None
            else:
                new_targets = []
                # these are for cases where we do something like
                #   a, b = yield f.asynq(), f.asynq()
                # we turn this into
                #   a = yield f.asynq()
                #   b = a
                extra_nodes = []
                assignment_targets = current_statement.targets[0].elts
                for i, target in enumerate(assignment_targets):
                    if i not in duplicate_indices:
                        new_targets.append(target)
                    elif not (isinstance(target, ast.Name)
                              and target.id == "_"):
                        extra_nodes.append(
                            ast.Assign(
                                targets=[target],
                                value=assignment_targets[duplicate_indices[i]],
                            ))
                if len(new_targets) == 1:
                    new_target = new_targets[0]
                else:
                    new_target = ast.Tuple(elts=new_targets)

                new_assign = ast.Assign(targets=[new_target],
                                        value=new_yield_node)
                new_nodes = [new_assign] + extra_nodes
        else:
            new_nodes = None

        if new_nodes is not None:
            lines_to_delete = self._lines_of_node(node)
            indent = self._indentation_of_node(current_statement)
            new_code = "".join(
                decompile(node, starting_indentation=indent)
                for node in new_nodes)
            new_lines = [line + "\n" for line in new_code.splitlines()]
            replacement = Replacement(lines_to_delete, new_lines)
        else:
            replacement = None

        self.visitor.show_error(node,
                                error_code=ErrorCode.duplicate_yield,
                                replacement=replacement)