def visit_If(self, node): if self.isompdirective(node.test): self.visit(ast.Expr(node.test)) return self.visit(ast.If(ast.Num(1), node.body, node.orelse)) else: return self.attach_data(node)
four = ast.Num(n=4) # initial assign initial_assign = ast.Assign( targets=[copy(x_lhs)], value=copy(two)) initial_assign.lineno = 1 initial_assign.col_offset = 0 ast.fix_missing_locations(initial_assign) # print statement print_statement = ast.Expr( value=ast.Call( func=ast.Name(id="print", ctx=ast.Load()), args=[use_x], keywords=[] ) ) print_statement.lineno = 2 print_statement.col_offset = 0 ast.fix_missing_locations(print_statement) if_ = ast.If() if_.test = ast.Compare() if_.test.left = copy(use_x) if_.test.ops = [ast.Eq()] if_.test.comparators = [copy(four)]
def visit_Assign(self, node): assert (len(node.targets) == 1) self.generic_visit(node) is_static_assign = isinstance( node.value, ast.Call) and ASTResolver.resolve_to( node.value.func, ti.static, globals()) if is_static_assign: return node if isinstance(node.targets[0], ast.Tuple): targets = node.targets[0].elts # Create stmts = [] holder = self.parse_stmt('__tmp_tuple = ti.expr_init_list(0, ' f'{len(targets)})') holder.value.args[0] = node.value stmts.append(holder) def tuple_indexed(i): indexing = self.parse_stmt('__tmp_tuple[0]') self.set_subscript_index(indexing.value, self.parse_expr("{}".format(i))) return indexing.value for i, target in enumerate(targets): is_local = isinstance(target, ast.Name) if is_local and self.is_creation(target.id): var_name = target.id target.ctx = ast.Store() # Create, no AST resolution needed init = ast.Attribute(value=ast.Name(id='ti', ctx=ast.Load()), attr='expr_init', ctx=ast.Load()) rhs = ast.Call( func=init, args=[tuple_indexed(i)], keywords=[], ) self.create_variable(var_name) stmts.append(ast.Assign(targets=[target], value=rhs)) else: # Assign target.ctx = ast.Load() func = ast.Attribute(value=target, attr='assign', ctx=ast.Load()) call = ast.Call(func=func, args=[tuple_indexed(i)], keywords=[]) stmts.append(ast.Expr(value=call)) for stmt in stmts: ast.copy_location(stmt, node) stmts.append(self.parse_stmt('del __tmp_tuple')) return self.make_single_statement(stmts) else: is_local = isinstance(node.targets[0], ast.Name) if is_local and self.is_creation(node.targets[0].id): var_name = node.targets[0].id # Create, no AST resolution needed init = ast.Attribute(value=ast.Name(id='ti', ctx=ast.Load()), attr='expr_init', ctx=ast.Load()) rhs = ast.Call( func=init, args=[node.value], keywords=[], ) self.create_variable(var_name) return ast.copy_location( ast.Assign(targets=node.targets, value=rhs), node) else: # Assign node.targets[0].ctx = ast.Load() func = ast.Attribute(value=node.targets[0], attr='assign', ctx=ast.Load()) call = ast.Call(func=func, args=[node.value], keywords=[]) return ast.copy_location(ast.Expr(value=call), node)
def gen_empty_line_stmt(self): return ast.Expr(value=ast.Name(id=" "))
def _is_multiwildcard(n): return astcheck.is_ast_like( n, ast.Expr(value=ast.Name(id=MULTIWILDCARD_NAME)))
def p_stmt_expr(self, p): 'stmt : expr' p[0] = ast.Expr(value=p[1], lineno=p.lineno(1), col_offset=p.lexpos(1))
def visit_Call(self, node: ast.Call): body = copy.deepcopy(node) result = ast.If(test=ast.NameConstant(True), body=[ast.Expr(body)], orelse=[]) print(astunparse.unparse(result)) return result
def __ast_transform_blocks(generator, func_tree, fn_src, fn_name, scope, insert_self, filename, func_ln, transform_return=False, pre_locals=None, unroll_for=False, apply_ssa=False): # pre-compute the frames # we have 3 frames back f = inspect.currentframe().f_back.f_back.f_back # will go one above to get the locals as well? if f.f_back is not None: _locals = f.f_back.f_locals.copy() else: _locals = {} _locals.update(f.f_locals) _globals = f.f_globals.copy() if pre_locals is not None: _locals.update(pre_locals) debug = generator.debug fn_body = func_tree.body[0] func_args = fn_body.args.args # add out scope to the arg list to capture all the statements func_args.append(ast.arg(arg="scope", annotation=None)) if transform_return: return_visitor = ReturnNodeVisitor("scope", generator.debug) return_visitor.visit(fn_body) # change to block comment to comment_ transform_block_comment(fn_body) # transform aug assign aug_assign_visitor = AugAssignNodeVisitor() fn_body = aug_assign_visitor.visit(fn_body) # if there is a need to apply ssa if apply_ssa: # only elaborate for for_visitor = StaticElaborationNodeForVisitor(generator, fn_src, scope, True, _locals, _globals, filename, func_ln) fn_body = for_visitor.visit(fn_body) target_nodes = for_visitor.target_node fn_body = transform_always_comb_ssa(fn_body, generator, _locals) else: # static eval for loop and if statement for_visitor = StaticElaborationNodeForVisitor(generator, fn_src, scope, unroll_for, _locals, _globals, filename, func_ln) fn_body = for_visitor.visit(fn_body) if_visitor = StaticElaborationNodeIfVisitor(generator, fn_src, scope, _locals, _globals, filename, func_ln) fn_body = if_visitor.visit(fn_body) target_nodes = compute_target_node(for_visitor.target_node, if_visitor.target_node) # transform assign assign_visitor = AssignNodeVisitor(generator, debug) fn_body = assign_visitor.visit(fn_body) ast.fix_missing_locations(fn_body) if apply_ssa: target_nodes = compute_target_node(target_nodes, assign_visitor.target_node) # transform the assert_ function to get fn_ln assert_visitor = AssertNodeVisitor(generator, debug) fn_body = assert_visitor.visit(fn_body) exception_visitor = ExceptionNodeVisitor(generator, debug) fn_body = exception_visitor.visit(fn_body) # mark the local variables for node, (key, value) in target_nodes.items(): assign_local_visitor = GenVarLocalVisitor(key, value, "scope") assign_local_visitor.visit(node) # add stmt to the scope add_stmt_to_scope(fn_body) # add code to run it if insert_self: args = [ast.Name(id="_self", ctx=ast.Load())] else: args = [] args.append(ast.Name(id="_scope", ctx=ast.Load())) call_node = ast.Call(func=ast.Name(id=fn_name, ctx=ast.Load()), args=args, keywords=[], ctx=ast.Load) func_tree.body.append(ast.Expr(value=call_node)) return _locals, _globals
def to_expr(value): return value if isinstance(value, ast.stmt) else ast.Expr(value=value)
def visit_If(self, node: ast.If): predicate = node.test # if it's a var comparison, we change it to eq functional call predicate = self.__change_if_predicate(predicate) # we only replace stuff if the predicate has something to do with the # verilog variable predicate_src = astor.to_source(predicate) has_var = False try: predicate_value = eval(predicate_src, self.global_, self.local) except (_kratos.exception.InvalidConversionException, _kratos.exception.UserException, _kratos.exception.VarException) as _: has_var = True predicate_value = None # if's a kratos var, we continue if not has_var and not isinstance(predicate_value, _kratos.Var): if not isinstance(predicate_value, bool): print_src(self.fn_src, predicate.lineno) raise SyntaxError("Cannot statically evaluate if predicate") if predicate_value: for i, n in enumerate(node.body): if_exp = StaticElaborationNodeIfVisitor( self.generator, self.fn_src, self.scope, self.local, self.global_, self.filename, self.scope_ln) node.body[i] = if_exp.visit(n) return node.body else: for i, n in enumerate(node.orelse): if_exp = StaticElaborationNodeIfVisitor( self.generator, self.fn_src, self.scope, self.local, self.global_, self.filename, self.scope_ln) node.orelse[i] = if_exp.visit(n) return node.orelse else: # need to convert the logical operators to either reduced function calls, or # expression or if_test = LogicOperatorVisitor(self.local, self.global_, self.filename, self.scope_ln) predicate = if_test.visit(node.test) expression = node.body else_expression = node.orelse if self.generator.debug: keywords_if = [ ast.keyword(arg="f_ln", value=ast.Constant(value=node.lineno)) ] # do our best guess if len(else_expression) > 0: if else_expression[0].lineno != expression[0].lineno: ln = else_expression[0].lineno + 1 else: ln = else_expression[0].lineno keywords_else = [ ast.keyword(arg="f_ln", value=ast.Constant(value=ln)) ] else: keywords_else = [] else: keywords_if = [] keywords_else = [] for key, value in self.key_pair: keywords_if.append(ast.keyword(arg=key, value=ast.Str(s=value))) if_node = ast.Call(func=ast.Attribute(value=ast.Name(id="scope", ctx=ast.Load()), attr="if_", ctx=ast.Load()), args=[predicate] + expression, keywords=keywords_if, ctx=ast.Load) else_node = ast.Call(func=ast.Attribute(attr="else_", value=if_node, ctx=ast.Load()), args=else_expression, keywords=keywords_else) # store the mapping self.target_node[node] = else_node return self.visit(ast.Expr(value=else_node))
def visit_If(self, node: ast.If): # push the mapping into a stack # need to flatten the if statement and add phi function test = self.visit(node.test) body = [] self.phi_scope.append(SSAScope(self.var_ref)) # compute the enable condition self.set_enable_cond(test, False) for stmt in node.body: stmt = self.visit(stmt) self.__add_list(body, stmt) body_scope: SSAScope = self.phi_scope[-1] # pop the last scope self.phi_scope = self.phi_scope[:-1] else_scope: SSAScope = SSAScope({}) if node.orelse: self.phi_scope.append(SSAScope(self.var_ref)) else_scope = self.phi_scope[-1] # compute the enable condition self.set_enable_cond(test, True) for stmt in node.orelse: stmt = self.visit(stmt) self.__add_list(body, stmt) # pop the last scope self.phi_scope = self.phi_scope[:-1] # if there is any variable created, need to create phi functions vars_ = [] for var in body_scope.created_vars: if var not in vars_: vars_.append(var) for var in else_scope.created_vars: if var not in vars_: vars_.append(var) for var in vars_: if var in body_scope.created_vars: true_var = body_scope.created_vars[var] # both? if var in else_scope.created_vars: # create a phi node, in this, just a ternary else_var = else_scope.created_vars[var] else: # need previous scope value else_var = self.__find_var_def(var) assert else_var is not None, "Latch {0} is created!".format( var) else: else_var = else_scope.created_vars[var] # need previous scope value true_var = self.__find_var_def(var) assert true_var is not None, "Latch {0} is created!".format( var) n = ast.Expr(value=ast.Call( func=ast.Name(id="ternary"), args=[test, ast.Name(id=true_var), ast.Name(id=else_var)], ctx=ast.Load(), keywords=[]), lineno=test.lineno) new_name = self.create_new_var(var) n = ast.Assign( targets=[ast.Name(id=new_name, ctx=ast.Store())], value=n, lineno=node.lineno) body.append(n) return body
def visit_For(self, node: ast.For): # making sure that we don't have for/else case if len(node.orelse) > 0: # this is illegal syntax lines = [n.lineno for n in node.orelse] print_src(self.fn_src, lines) raise SyntaxError("Illegal Syntax: you are not allowed to use " "for/else in code block") # get the target iter_ = node.iter iter_src = astor.to_source(iter_) try: iter_obj = eval(iter_src, self.global_, self.local) iter_ = list(iter_obj) except RuntimeError: print_src(self.fn_src, node.iter.lineno) raise SyntaxError("Unable to statically evaluate loop iter") for v in iter_: if not isinstance(v, (int, str)): print_src(self.fn_src, node.iter.lineno) raise SyntaxError("Loop iter has to be either integer or " "string, got " + str(type(v))) target = node.target if not isinstance(target, ast.Name): print_src(self.fn_src, node.iter.lineno) raise SyntaxError("Unable to parse loop " "target " + astor.to_source(target)) # if not in debug mode and we are allowed to do so if not self.generator.debug and not self.unroll_for and isinstance(iter_obj, range) and \ self.__loop_self_var(target, node.body): # return it as a function call _vars = iter_obj.start, iter_obj.stop, iter_obj.step, node.lineno _vars = [ast.Num(n=n) for n in _vars] keywords = [] if self.generator.debug: keywords = [ ast.keyword(arg="f_ln", value=ast.Constant(value=node.lineno)) ] # we redirect the var to one of the scope vars. the index is based # on the line number index_num = node.lineno # create the for statement in the scope for_stmt = _kratos.ForStmt(target.id, iter_obj.start, iter_obj.stop, iter_obj.step) self.scope.for_stmt[index_num] = for_stmt # set the for iter var # redirect the variable to env self.scope.iter_var[index_num] = for_stmt.get_iter_var() index = ast.Subscript(slice=ast.Index(value=ast.Num(n=index_num)), value=ast.Attribute(value=ast.Name( id="scope", ctx=ast.Load()), attr="iter_var", ctx=ast.Load())) for_node = ast.Call(func=ast.Attribute(value=ast.Name( id="scope", ctx=ast.Load()), attr="for_", ctx=ast.Load()), args=[ast.Str(s=target.id)] + _vars, keywords=keywords, ctx=ast.Load()) body_visitor = StaticElaborationNodeForVisitor.NameVisitor( target, index) body = [] for i in range(len(node.body)): n = self.visit(body_visitor.visit(node.body[i])) if isinstance(n, list): for nn in n: body.append(nn) else: body.append(n) body_node = ast.Call(func=ast.Attribute(attr="loop", value=for_node, ctx=ast.Load()), args=body, keywords=[]) # create an entry for the target self.local[str(target.id)] = 0 return self.visit(ast.Expr(body_node)) else: new_node = [] for value in iter_: loop_body = copy.deepcopy(node.body) for n in loop_body: # need to replace all the reference to visitor = StaticElaborationNodeForVisitor.NameVisitor( target, value) n = visitor.visit(n) self.key_pair.append((target.id, value)) n = self.visit(n) self.key_pair.pop(len(self.key_pair) - 1) if isinstance(n, list): for n_ in n: new_node.append(n_) self.target_node[n_] = (target.id, value) else: new_node.append(n) self.target_node[n] = (target.id, value) return new_node
def setUp(self): class_node = ast.ClassDef( name='Class', bases=[], keywords=[], body=[ ast.Expr(value=ast.Str(s='Class docstrings')), ast.FunctionDef( name='__init__', args=ast.arguments( args=[ast.arg(arg='self', annotation=None)], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[ ast.Expr(value=ast.Str(s="Constructor's docstrings")), ast.Pass() ], decorator_list=[], returns=None), ast.FunctionDef(name='_private_func', args=ast.arguments(args=[ ast.arg(arg='self', annotation=None), ast.arg(arg='arg', annotation=None) ], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[ast.Pass()], decorator_list=[], returns=None), ast.FunctionDef( name='func_without_args', args=ast.arguments(args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[ ast.Expr(value=ast.Str(s='Func docstrings')), ast.Pass() ], decorator_list=[ ast.Name(id='staticmethod', ctx=ast.Load()) ], returns=None), ast.FunctionDef(name='func_with_args', args=ast.arguments(args=[ ast.arg(arg='self', annotation=None), ast.arg(arg='a', annotation=None), ast.arg(arg='b', annotation=None), ast.arg(arg='c', annotation=None) ], kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[ast.Pass()], decorator_list=[], returns=None) ], decorator_list=[]) self.class_lister = ClassLister() self.class_lister.visit(class_node)
def visit_If(self, if_node: ast.If): """ Swap out the pattern `If(x): Raise(y)` with a ConditionalExceptionWrapper specialized for the specific exception y. The specialized ConditionalExceptionWrapper module will be added in the RewrittenModule. Only works with builtin Exceptions, as we assume the signature of the init for the Exception is a string. """ raise_node = if_node.body[0] if not isinstance(raise_node, ast.Raise): return if_node # Don't handle orelse for now. # TODO: Move orelse to the body after calling ConditionalExceptionWrapper. if len(if_node.orelse) != 0: return if_node def _reuse_loc(node): return ast.copy_location(node, if_node) # If the exception has a message then we expect the raise's exc to be a # Call w/ a msg. Else if it's a exc Name then there's no msg to use. node_for_exc = raise_node.exc if isinstance(node_for_exc, ast.Name): # E.g. `raise AssertionError`, i.e. without an exc_msg. name_node_of_exc = node_for_exc exc_msg = _reuse_loc(ast.Constant(None)) elif isinstance(node_for_exc, ast.Call): # E.g. `raise AssertionError("error message")` name_node_of_exc = node_for_exc.func if not isinstance(name_node_of_exc, ast.Name): return if_node # Most assertions just take a single string arg, but some may not; skip # handling such assertions for now. if len(node_for_exc.args) != 1: return if_node exc_msg = node_for_exc.args[0] else: return if_node # Convert what we expect is the name of the exception into its # associated python class. name_of_exc = name_node_of_exc.id try: exc_type = eval(name_of_exc) except Exception: return if_node # Check that we actually have a builtin exception. if (not issubclass(exc_type, Exception) or getattr(getattr(exc_type, "__class__", None), "__module__", None) != "builtins"): return if_node # We need a ConditionalExceptionWrapper specialized for every kind of # exception, so add it to exceptions_rewritten to remember for later to # add a specialized attr with it. self.exceptions_rewritten.add(exc_type) # From here we definitely should be able to do the replacement. Create a # Call node to the ConditionalExceptionWrapper module we're replacing # the If with, with args set as the If's condition and the string of the # exception. The call to the self._conditional_exception_wrapper_*Error # module is safe because the RewrittenModule will add it as an attr # based on the returned exceptions_rewritten, and we assume we are # currently modifying the AST of a method from a RewrittenModule. exc_wrapper_node = ast.parse( f"self.{_get_exception_wrapper_attr_name(exc_type)}()", mode="eval") assert isinstance(exc_wrapper_node, ast.Expression) exc_wrapper_call_node = exc_wrapper_node.body assert isinstance(exc_wrapper_call_node, ast.Call) exc_wrapper_call_node.args = [if_node.test, exc_msg] # Ensure that the new node conforms to the Python AST grammar expr_wrapper = _reuse_loc(ast.Expr(_reuse_loc(exc_wrapper_call_node))) # Return the new node to signify that we want to use it as a replacement # for the original `If x: Raise y` pattern. return expr_wrapper
async def meval(code, globs, **kwargs): # Note to self: please don't set globals here as they will be lost. # Don't clutter locals locs = {} # Restore globals later globs = globs.copy() # This code saves __name__ and __package into a kwarg passed to the func. # It is set before the users code runs to make sure relative imports work global_args = "_globs" while global_args in globs.keys(): # Make sure there's no name collision, just keep prepending _s global_args = "_" + global_args kwargs[global_args] = {} for glob in ["__name__", "__package__"]: # Copy data to args we are sending kwargs[global_args][glob] = globs[glob] root = ast.parse(code, "exec") code = root.body ret_name = "_ret" ok = False while True: if ret_name in globs.keys(): ret_name = "_" + ret_name continue for node in ast.walk(root): if isinstance(node, ast.Name) and node.id == ret_name: ret_name = "_" + ret_name break ok = True if ok: break if not code: return None if not any(isinstance(node, ast.Return) for node in code): for i in range(len(code)): if isinstance(code[i], ast.Expr): if ( i == len(code) - 1 or not isinstance(code[i].value, ast.Call) ): code[i] = ast.copy_location( ast.Expr(ast.Call( func=ast.Attribute( value=ast.Name(id=ret_name, ctx=ast.Load()), attr="append", ctx=ast.Load() ), args=[code[i].value], keywords=[] )), code[-1] ) else: for node in code: if isinstance(node, ast.Return): node.value = ast.List(elts=[node.value], ctx=ast.Load()) code.append(ast.copy_location( ast.Return(value=ast.Name(id=ret_name, ctx=ast.Load())), code[-1] )) # globals().update(**<global_args>) glob_copy = ast.Expr( ast.Call( func=ast.Attribute(value=ast.Call( func=ast.Name(id="globals", ctx=ast.Load()), args=[], keywords=[] ), attr="update", ctx=ast.Load()), args=[], keywords=[ast.keyword( arg=None, value=ast.Name(id=global_args, ctx=ast.Load()) )] ) ) ast.fix_missing_locations(glob_copy) code.insert(0, glob_copy) ret_decl = ast.Assign( targets=[ast.Name(id=ret_name, ctx=ast.Store())], value=ast.List(elts=[], ctx=ast.Load()) ) ast.fix_missing_locations(ret_decl) code.insert(1, ret_decl) args = [] for a in list(map(lambda x: ast.arg(x, None), kwargs.keys())): ast.fix_missing_locations(a) args += [a] args = ast.arguments( args=[], vararg=None, kwonlyargs=args, kwarg=None, defaults=[], kw_defaults=[None for i in range(len(args))] ) args.posonlyargs = [] fun = ast.AsyncFunctionDef( name="tmp", args=args, body=code, decorator_list=[], returns=None ) ast.fix_missing_locations(fun) mod = ast.parse("") mod.body = [fun] comp = compile(mod, "<string>", "exec") exec(comp, {}, locs) r = await locs["tmp"](**kwargs) for i in range(len(r)): if hasattr(r[i], "__await__"): r[i] = await r[i] # workaround for 3.5 i = 0 while i < len(r) - 1: if r[i] is None: del r[i] else: i += 1 if len(r) == 1: [r] = r elif not r: r = None return r
def to_node(self): args = [] for arg in self.args: args.append(arg.to_node()) return ast.Expr(value=ast.Call(func=ast.Name(id='print', ctx=ast.Load), args=args, keywords=[]))
async def async_eval(code, **kwargs): # Note to self: please don't set globals here as they will be lost. # Don't clutter locals locs = {} # Restore globals later globs = globals().copy() # This code saves __name__ and __package into a kwarg passed to the function. # It is set before the users code runs to make sure relative imports work global_args = "_globs" while global_args in globs.keys(): # Make sure there's no name collision, just keep prepending _s global_args = "_" + global_args kwargs[global_args] = {} for glob in ["__name__", "__package__"]: # Copy data to args we are sending kwargs[global_args][glob] = globs[glob] root = ast.parse(code, 'exec') code = root.body if isinstance( code[-1], ast.Expr): # If we can use it as a lambda return (but multiline) code[-1] = ast.copy_location(ast.Return( code[-1].value), code[-1]) # Change it to a return statement # globals().update(**<global_args>) glob_copy = ast.Expr( ast.Call( func=ast.Attribute(value=ast.Call(func=ast.Name(id='globals', ctx=ast.Load()), args=[], keywords=[]), attr='update', ctx=ast.Load()), args=[], keywords=[ ast.keyword(arg=None, value=ast.Name(id=global_args, ctx=ast.Load())) ])) glob_copy.lineno = 0 glob_copy.col_offset = 0 ast.fix_missing_locations(glob_copy) code.insert(0, glob_copy) args = [] for a in list(map(lambda x: ast.arg(x, None), kwargs.keys())): a.lineno = 0 a.col_offset = 0 args += [a] fun = ast.AsyncFunctionDef( 'tmp', ast.arguments(args=[], vararg=None, kwonlyargs=args, kwarg=None, defaults=[], kw_defaults=[None for i in range(len(args))]), code, [], None) fun.lineno = 0 fun.col_offset = 0 mod = ast.Module([fun]) comp = compile(mod, '<string>', 'exec') exec(comp, {}, locs) with temp_stdio() as out: result = await locs["tmp"](**kwargs) try: globals().clear() # Inconsistent state finally: globals().update(**globs) return result, out.getvalue()
def test_invalid_sum(self): pos = dict(lineno=2, col_offset=3) m = ast.Module([ast.Expr(ast.expr(**pos), **pos)]) with self.assertRaises(TypeError) as cm: compile(m, "<test>", "exec") self.assertIn("but got <_ast.expr", str(cm.exception))
def visit_Delete(self, node): """ This converter replaces bare deletes with conditional global pops. It is roughly equivalent to transforming: .. code:: python del foobar into: .. code:: python if 'foobar' in globals(): globals().pop('foobar') else: del foobar This thus makes deletions in retain mode work more-or-less as intended. """ return ast.If( test=ast.NameConstant( value=True, # if True; aka unconditional, will be optimized out lineno=node.lineno, col_offset=node.col_offset, ), body=[ ast.If( # if 'x' in globals(): test=ast.Compare( # 'x' left=ast.Str( s=target.id, lineno=node.lineno, col_offset=node.col_offset, ), ops=[ # in ast.In(lineno=node.lineno, col_offset=node.col_offset) ], comparators=[ # globals() self.globals_call(node) ], lineno=node.lineno, col_offset=node.col_offset, ), body=[ ast.Expr( # globals().pop('x') value=ast.Call( # globals().pop func=ast.Attribute( value=self.globals_call(node), attr="pop", ctx=ast.Load(), lineno=node.lineno, col_offset=node.col_offset, ), args=[ # 'x' ast.Str( s=target.id, lineno=node.lineno, col_offset=node.col_offset, ) ], keywords=[], lineno=node.lineno, col_offset=node.col_offset, ), lineno=node.lineno, col_offset=node.col_offset, ) ], # else: orelse=[ # del x ast.Delete( targets=[target], lineno=node.lineno, col_offset=node.col_offset, ) ], lineno=node.lineno, col_offset=node.col_offset, ) if isinstance(target, ast.Name) else ast.Delete( targets=[target], lineno=node.lineno, col_offset=node.col_offset, ) # for each target to be deleted, e.g. `del {x}, {y}, {z}` for target in node.targets ], orelse=[], lineno=node.lineno, col_offset=node.col_offset, )
def test_invalid_identitifer(self): m = ast.Module([ast.Expr(ast.Name(42, ast.Load()))]) ast.fix_missing_locations(m) with self.assertRaises(TypeError) as cm: compile(m, "<test>", "exec") self.assertIn("identifier must be of type str", str(cm.exception))
def visit_Return(self, node): new_node = ast.copy_location(ast.Expr(value=node.value), node) return FunctionBodyTransformer.decorate(new_node, node)
def test_invalid_string(self): m = ast.Module([ast.Expr(ast.Str(42))]) ast.fix_missing_locations(m) with self.assertRaises(TypeError) as cm: compile(m, "<test>", "exec") self.assertIn("string must be of type str", str(cm.exception))
def gen_request_lines(self, req): apiritif_http = ast.Attribute(value=ast.Name(id='apiritif', ctx=ast.Load()), attr='http', ctx=ast.Load()) target = ast.Name(id='target', ctx=ast.Load()) requestor = target if self.__access_method == "target" else apiritif_http method = req.method.lower() think_time = dehumanize_time( req.priority_option('think-time', default=None)) named_args = self._extract_named_args(req) if req.label: label = req.label else: label = req.url lines = [] tran = ast.Attribute(value=ast.Name(id='apiritif', ctx=ast.Load()), attr="transaction", ctx=ast.Load()) transaction = ast.With( context_expr=ast.Call(func=tran, args=[self.gen_expr(label)], keywords=[], starargs=None, kwargs=None), optional_vars=None, body=[ ast.Assign(targets=[ast.Name(id="response", ctx=ast.Store())], value=ast.Call( func=ast.Attribute(value=requestor, attr=method, ctx=ast.Load()), args=[self.gen_expr(req.url)], keywords=[ ast.keyword(arg=name, value=self.gen_expr(value)) for name, value in iteritems(named_args) ], starargs=None, kwargs=None)) ], ) lines.append(transaction) lines.extend(self._gen_assertions(req)) lines.extend(self._gen_jsonpath_assertions(req)) lines.extend(self._gen_xpath_assertions(req)) lines.extend(self._gen_extractors(req)) if think_time: lines.append( ast.Expr( ast.Call(func=ast.Attribute(value=ast.Name(id="time", ctx=ast.Load()), attr="sleep", ctx=ast.Load()), args=[self.gen_expr(think_time)], keywords=[], starargs=None, kwargs=None))) return lines
def expr(self, node, msg=None, *, exc=ValueError): mod = ast.Module([ast.Expr(node)]) self.mod(mod, msg, exc=exc)
def dfs_instrument(node): nonlocal b_index # find body or orelse code blocks using DFS for info in astor.iter_node(node): if info[1] == 'body' or (info[1] == 'orelse' and len(info[0]) != 0): # stmts : new statements list for inserting print statements stmts = [] # for each statements do, for stmt in info[0]: if isinstance(stmt, ast.For) or isinstance(stmt, ast.If) or isinstance(stmt, ast.While): # branch found b_index += 1 # for if and while statements, insert printing a and b if isinstance(stmt, ast.While) or isinstance(stmt, ast.If): # if condition is comparing two values, if isinstance(stmt.test, ast.Compare): # insert values assignment stmts.append( ast.Assign( targets=[ast.Tuple(elts=[ ast.Name(id='TDG_l'), ast.Name(id='TDG_r') ])], value=ast.Tuple(elts=[ stmt.test.left, stmt.test.comparators[0] ]) ) ) # insert values printing stmts.append( ast.Expr( value=ast.Call( func=ast.Name(id='print'), args=[ ast.Str(s='TDG'), ast.Str(s='V'), ast.Str(s=str(b_index)), ast.Name(id='TDG_l'), ast.Name(id='TDG_r') ], keywords=[] ) ) ) # substitute left and right value to assigned value stmt.test.left = ast.Name(id='TDG_l') stmt.test.comparators[0] = ast.Name(id='TDG_r') # for conditional statements, insert branch executed printing for info2 in astor.iter_node(stmt): if info2[1] == 'body': info2[0].insert(0, ast.Expr(value=ast.Call( func=ast.Name(id='print'), args=[ ast.Str(s='TDG'), ast.Str(s='B'), ast.Str(s=str(b_index)), ast.Str('T') ], keywords=[] ))) elif info2[1] == 'orelse' and len(info2[0]) != 0: info2[0].insert(0, ast.Expr(value=ast.Call( func=ast.Name(id='print'), args=[ ast.Str(s='TDG'), ast.Str(s='B'), ast.Str(s=str(b_index)), ast.Str('F') ], keywords=[] ))) # add statement to stmts stmts.append(stmt) # substitute body(orelse) to stmts if info[1] == 'body': node.body = stmts elif info[1] == 'orelse' and len(info[0]) != 0: node.orelse = stmts # recursively DFS for stmt in info[0]: dfs_instrument(stmt)
def test_module(self): m = ast.Interactive([ast.Expr(ast.Name("x", ast.Store()))]) self.mod(m, "must have Load context", "single") m = ast.Expression(ast.Name("x", ast.Store())) self.mod(m, "must have Load context", "eval")
def __pow__(self, power, modulo=None): if isinstance(power, (int, float)): power = Decimal(power) return Decimal(super(Decimal, self).__pow__(power, modulo)) def __rpow__(self, other): if isinstance(other, (int, float)): other = Decimal(other) return Decimal(super(Decimal, other).__pow__(self)) TYPE_STORE = type(ast.Store()) TYPE_LOAD = type(ast.Load()) TYPE_DEL = type(ast.Del()) TYPE_EXPR = type(ast.Expr()) MATH_CONTEXT = { 'acos': math.acos, 'acosh': math.acosh, 'asin': math.asin, 'asinh': math.asinh, 'atan': math.atan, 'atan2': math.atan2, 'atanh': math.atanh, 'ceil': math.ceil, 'copysign': math.copysign, 'cos': math.cos, 'cosh': math.cosh, 'degrees': math.degrees, 'erf': math.erf,
def test_expr(self): e = ast.Expr(ast.Name("x", ast.Store())) self.stmt(e, "must have Load context")
def to_stmt(pynode): if not isinstance(pynode, py.stmt): pynode = py.Expr(pynode, lineno=pynode.lineno, col_offset=pynode.col_offset) return pynode
def test__parent_stmt(): n = ast.FunctionDef(body=[ast.Expr(value=ast.Constant(value=1))]) assert n.body[0].parent is n assert n.body[0].value.parent is n.body[0] assert n.parent is None