def check(self): return (is_ast_like( self.tree, ast.Module( body=[ast.Assign(targets=[ast.Name(id='your_name')])])) and isinstance(self.console.locals.get('your_name'), str))
def visit_Assign(self, node): assert (len(node.targets) == 1) self.generic_visit(node) if isinstance(node.targets[0], ast.Tuple): targets = node.targets[0].elts # Create stmts = [] holder = self.parse_stmt('__tmp_tuple = 0') holder.value = node.value stmts.append(holder) def tuple_indexed(i): indexing = self.parse_stmt('__tmp_tuple[0]') indexing.value.slice.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 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 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 _transform_statement(vars_already_initilized, statement): transformed_statement = None if isinstance(statement, ast.Assign): if isinstance(statement.value, ast.Call): args = [] function_name = ast.Str(s=statement.value.func.id) args.append(function_name) for arg in statement.value.args: vars_already_initilized, transformed_arg = _transform_statement( vars_already_initilized, arg) args.append(transformed_arg) args = ast.List(elts=args, ctx=ast.Load()) transformed_statement = _trace_function_call( statement.targets[0], args) else: for target in statement.targets: #TODO: #Need soemthing to make sure multiple assignemnts #get traced to the right things. Ex. x, y = (1, 2) #if it's already defined - set it to new value. if target.id in vars_already_initilized: vars_already_initilized, rhs = _transform_statement( vars_already_initilized, statement.value) transformed_statement = _trace_set(target, rhs) else: #not defined yet, so trace it to a let. vars_already_initilized, rhs = _transform_statement( vars_already_initilized, statement.value) transformed_statement = _trace_let(target, rhs) vars_already_initilized[target.id] = 1 elif isinstance(statement, ast.FunctionDef): args = [arg.arg for arg in statement.args.args] #insert statements into function body statement.body = _transform_statements(statement.body, {}) #create function body trace and insert in begining of function body. function_trace = _trace_function_body(args) statement.body.insert(0, function_trace) #create assignment for each arg and insert after function body trace call arg_assignments = _trace_args(args) for arg in arg_assignments: statement.body.insert(1, arg) transformed_statement = statement elif isinstance(statement, ast.Return): vars_already_initilized, return_expr = _transform_statement( vars_already_initilized, statement.value) transformed_statement = _trace_break(return_expr) elif isinstance(statement, ast.If): #only supports single conditions for now if isinstance(statement.test, ast.NameConstant): vars_already_initilized, conditional = _transform_statement( vars_already_initilized, statement.test) else: vars_already_initilized, test_lhs = _transform_statement( vars_already_initilized, statement.test.left) op = _convert_operator_to_string(statement.test.ops[0]) vars_already_initilized, test_rhs = _transform_statement( vars_already_initilized, statement.test.comparators[0]) conditional = _exp_binop(op, test_lhs, test_rhs) name = 'test' while name in vars_already_initilized: name = name + '0' vars_already_initilized[name] = 1 transformed_statement = [ ast.Assign(targets=[ast.Name(id=name)], value=conditional) ] statement.body = _transform_statements(statement.body, vars_already_initilized, False) statement.body.insert(0, _trace_if_true(ast.Name(id=name))) if statement.orelse: statement.orelse = _transform_statements(statement.orelse, vars_already_initilized, False) statement.orelse.insert(0, _trace_if_false(ast.Name(id=name))) transformed_statement.append(statement) elif isinstance(statement, ast.BinOp): vars_already_initilized, lhs = _transform_statement( vars_already_initilized, statement.left) op = _convert_operator_to_string(statement.op) vars_already_initilized, rhs = _transform_statement( vars_already_initilized, statement.right) transformed_statement = _exp_binop(op, lhs, rhs) elif isinstance(statement, ast.UnaryOp): op = _convert_operator_to_string(statement.op) vars_already_initilized, rhs = _transform_statement( vars_already_initilized, statement.operand) transformed_statement = _exp_unary_op(op, rhs) elif isinstance(statement, ast.Name): transformed_statement = _exp_identifier(statement) elif isinstance(statement, ast.Num): transformed_statement = _exp_num(statement) elif isinstance(statement, ast.NameConstant) and statement.value is None: transformed_statement = _exp_none() elif isinstance(statement, ast.NameConstant) and statement.value in [True, False]: transformed_statement = _exp_bool(statement) return vars_already_initilized, transformed_statement
def _make_for_loops_while(parent_node, names_in_use): """Converts for loops into while loops. Creates an index variable and a call to the len() function as a test condition for the while loop. All for loop iterators must be indexable. DOES NOT SUPPOT NONINDEXABLE ITERATORS. Parameters: parent_node: ast node Returns: parent node with updates""" # Get every index of for loop objects in the body of parent node. # Could be done cleaner with a numpy .where, but we'd have to import numpy # pretty much just for that. try: indxs_for_loops = [] for indx in range(len(parent_node.body)): current = parent_node.body[indx] if isinstance(current, ast.For): indxs_for_loops.append(indx) if hasattr(current, "body"): is_module = isinstance(current, ast.Module) is_func_def = isinstance(current, ast.FunctionDef) if not is_func_def and not is_module: current, names_in_use = _make_for_loops_while( current, names_in_use) except AttributeError: # node has no body. No for loops in it. return parent_node, names_in_use num_lines_inserted = 0 for for_loop_index in indxs_for_loops: for_loop_index = for_loop_index + num_lines_inserted for_loop = parent_node.body[for_loop_index] # Make loop incrementor variable. name_incrementor_variable = _new_name('loop_index', names_in_use) names_in_use[name_incrementor_variable] = 1 # Make a call to built in len() function with the iterator # provided in the for loop. len_builtin_function = ast.Name(id='len', ctx=ast.Load) len_function_call = ast.Call(func=len_builtin_function, args=[for_loop.iter], keywords=[]) # Test for while loop. left = ast.Name(id=name_incrementor_variable, ctx=ast.Load) compare_op = ast.Compare(left=left, ops=[ast.Lt()], comparators=[len_function_call]) # Assign current value of loop to for loop target. index = ast.Index(ast.Name(id=name_incrementor_variable, ctx=ast.Load)) value = ast.Subscript(for_loop.iter, index) target = [for_loop.target] assign_to_for_loop_target = ast.Assign(target, value) # Increment index variable. name = ast.Name(id=name_incrementor_variable) add_1_to_index_variable = ast.AugAssign(name, ast.Add(), ast.Num(1)) # Construct while loop. while_loop = [assign_to_for_loop_target] + \ for_loop.body + [add_1_to_index_variable] while_loop = ast.While(test=compare_op, body=while_loop, orelse=[]) # Replace for with while loop. parent_node.body[for_loop_index] = while_loop # Insert loop incrementor variable before while loop and set to 0. inc_name = ast.Name(id=name_incrementor_variable, ctx=ast.Store) inc_0 = ast.Assign([inc_name], ast.Num(0)) parent_node.body.insert(for_loop_index, inc_0) # Not the total lines inserted, only the lines inserted into the # parent's body. (so not the lines inside the loop) num_lines_inserted += 1 return parent_node, names_in_use
def assign(self, expr: ast.expr) -> ast.Name: """Give *expr* a name.""" name = self.variable() self.statements.append(ast.Assign([ast.Name(name, ast.Store())], expr)) return ast.Name(name, ast.Load())
def do_with_case(self, ctx_id, ctx_node, node, orelse): if not isinstance(node.context_expr, ast.Name): return node if orelse is not None and node.context_expr.id == "_": raise SyntaxError( "any type identifier _ must be at the end of with-statement list" ) # append the last match when it doesn't exist if orelse is None and node.context_expr.id != "_": orelse = [ ast.Raise(type=ast.Call(func=ast.Name(id="SyntaxError", ctx=ast.Load()), args=[ast.Str("match nothing!")], keywords=[], starargs=None, kwargs=None), inst=None, tback=None) ] body = [] for stmt in node.body: if self.check_match_begin(stmt): body.append(self.visit_With(stmt)) else: body.append(stmt) # convert to if-statement if node.optional_vars is not None: if isinstance(node.optional_vars, ast.Tuple): total = len(node.optional_vars.elts) elif isinstance(node.optional_vars, ast.Name): total = 1 else: raise SyntaxError( "variable capture list must be variable (for only one variable) or tuple (for many variables)" ) assert isinstance(ctx_node, ast.Call) ctx_var = ctx_node.args[0].id import_stmt = ast.ImportFrom(module="pymatch", names=[ast.alias("unpack", None)], level=0) unpack_stmt = ast.Assign(targets=[node.optional_vars], value=ast.Call( func=ast.Name(id="unpack", ctx=ast.Load()), args=[ ast.Name(id=ctx_var, ctx=ast.Load()), ast.Num(total) ], keywords=[], starargs=None, kwargs=None)) body = [import_stmt, unpack_stmt] + body if node.context_expr.id == "_": return body else: return ast.If(test=ast.Call( func=ast.Name(id="issubclass", ctx=ast.Load()), args=[ast.Name(id=ctx_id, ctx=ast.Load()), node.context_expr], keywords=[], starargs=None, kwargs=None), body=body, orelse=deepcopy(orelse))
def gen_store(name, value): return ast.Assign(targets=[ ast.Subscript(value=ast_attr("self.vars"), slice=ast.Str(name)) ], value=value)
def assign(self, val, name=''): """ Assign an element to the variable (variable = val) If the parameter name is provided, then assign to an attribute (variable.name = val) """ return ast.Assign([self.store(name=name)], val)
code = line else: code += "\n" + line variables = [] if code: parsed = ast.parse(code) for i, node in enumerate(parsed.body): # do this auto variable only for pure expressions # which is not a function call if isinstance(node, ast.Expr) and not isinstance( node.value, ast.Call): name = "res%s" % var_counter var_counter += 1 new_node = (ast.Assign( targets=[ast.Name(id=name, ctx=ast.Store())], value=node.value)) parsed.body[i] = ast.fix_missing_locations(new_node) variables.append(name) eval(compile(parsed, "<string>", "exec")) for var in variables: val = locals()[var] from pprint import pprint if "DataFrame" in type(val).__name__ or val is not None: pprint(val) if mpl: flush_figures(request) except Py4JNetworkError: # since it's using local connection, network error # means java process is already dead
def find_if(body, parent, args, reach): try: for field in body._fields: find_if(getattr(body, field), parent, args, reach) except AttributeError: if isinstance(body, list): ind = 0 while ind in range(len(body)): line = body[ind] if isinstance(line, ast.Return): reach = False elif isinstance(line, ast.If) or isinstance(line, ast.While): node = branch_dist(line.test, args) new_branch = branch(parent, line.lineno, reach) # Assign branch distance to temporary variable body.insert( ind, ast.Assign(targets=[ast.Name(id=args.temp_name)], value=node)) # Print branch_id, op_type, branch distance in order body.insert( ind + 1, ast.Expr(value=ast.Call( func=ast.Attribute(value=ast.Name( id=args.file_name), attr='write'), args=[ ast.Call(func=ast.Attribute( value=ast.Str(s='{} {}\n'), attr='format'), args=[ ast.Num(n=new_branch.ind), ast.Name(id=args.temp_name) ], keywords=[], starargs=None, kwargs=None) ], keywords=[], starargs=None, kwargs=None))) line.test = ast.Compare(left=ast.Name(id=args.temp_name), ops=[ast.LtE()], comparators=[ast.Num(n=0)]) if isinstance(line, ast.While): line.body.append(body[ind]) line.body.append(body[ind + 1]) find_if(line.body, new_branch.ind, args, reach) find_if(line.orelse, -new_branch.ind, args, reach) ind += 2 else: find_if(line, parent, args, reach) ind += 1
def init_assign(prop): return ast.Assign( targets=[ast.Attribute(value=ast.Name(id="self"), attr=prop)], value=ast.Name(id=prop))
def parse_annotation_mutable_layers(code, lineno, nas_mode): """Parse the string of mutable layers in annotation. Return a list of AST Expr nodes code: annotation string (excluding '@') nas_mode: the mode of NAS """ module = ast.parse(code) assert type(module) is ast.Module, 'internal error #1' assert len( module.body ) == 1, 'Annotation mutable_layers contains more than one expression' assert type(module.body[0]) is ast.Expr, 'Annotation is not expression' call = module.body[0].value nodes = [] mutable_id = 'mutable_block_' + str(lineno) mutable_layer_cnt = 0 for arg in call.args: fields = { 'layer_choice': False, 'fixed_inputs': False, 'optional_inputs': False, 'optional_input_size': False, 'layer_output': False } for k, value in zip(arg.keys, arg.values): if k.id == 'layer_choice': assert not fields[ 'layer_choice'], 'Duplicated field: layer_choice' assert type( value ) is ast.List, 'Value of layer_choice should be a list' call_funcs_keys = [] call_funcs_values = [] call_kwargs_values = [] for call in value.elts: assert type( call ) is ast.Call, 'Element in layer_choice should be function call' call_name = astor.to_source(call).strip() call_funcs_keys.append(ast_Str(s=call_name)) call_funcs_values.append(call.func) assert not call.args, 'Number of args without keyword should be zero' kw_args = [] kw_values = [] for kw in call.keywords: kw_args.append(ast_Str(s=kw.arg)) kw_values.append(kw.value) call_kwargs_values.append( ast.Dict(keys=kw_args, values=kw_values)) call_funcs = ast.Dict(keys=call_funcs_keys, values=call_funcs_values) call_kwargs = ast.Dict(keys=call_funcs_keys, values=call_kwargs_values) fields['layer_choice'] = True elif k.id == 'fixed_inputs': assert not fields[ 'fixed_inputs'], 'Duplicated field: fixed_inputs' assert type( value ) is ast.List, 'Value of fixed_inputs should be a list' fixed_inputs = value fields['fixed_inputs'] = True elif k.id == 'optional_inputs': assert not fields[ 'optional_inputs'], 'Duplicated field: optional_inputs' assert type( value ) is ast.List, 'Value of optional_inputs should be a list' var_names = [ ast_Str(s=astor.to_source(var).strip()) for var in value.elts ] optional_inputs = ast.Dict(keys=var_names, values=value.elts) fields['optional_inputs'] = True elif k.id == 'optional_input_size': assert not fields[ 'optional_input_size'], 'Duplicated field: optional_input_size' assert type(value) is ast_Num or type(value) is ast.List, \ 'Value of optional_input_size should be a number or list' optional_input_size = value fields['optional_input_size'] = True elif k.id == 'layer_output': assert not fields[ 'layer_output'], 'Duplicated field: layer_output' assert type( value ) is ast.Name, 'Value of layer_output should be ast.Name type' layer_output = value fields['layer_output'] = True else: raise AssertionError('Unexpected field in mutable layer') # make call for this mutable layer assert fields['layer_choice'], 'layer_choice must exist' assert fields['layer_output'], 'layer_output must exist' mutable_layer_id = 'mutable_layer_' + str(mutable_layer_cnt) mutable_layer_cnt += 1 target_call_attr = ast.Attribute(value=ast.Name(id='nni', ctx=ast.Load()), attr='mutable_layer', ctx=ast.Load()) target_call_args = [ ast_Str(s=mutable_id), ast_Str(s=mutable_layer_id), call_funcs, call_kwargs ] if fields['fixed_inputs']: target_call_args.append(fixed_inputs) else: target_call_args.append(ast.List(elts=[])) if fields['optional_inputs']: target_call_args.append(optional_inputs) assert fields[ 'optional_input_size'], 'optional_input_size must exist when optional_inputs exists' target_call_args.append(optional_input_size) else: target_call_args.append(ast.Dict(keys=[], values=[])) target_call_args.append(ast_Num(n=0)) target_call_args.append(ast_Str(s=nas_mode)) if nas_mode in ['enas_mode', 'oneshot_mode', 'darts_mode']: target_call_args.append(ast.Name(id='tensorflow')) target_call = ast.Call(func=target_call_attr, args=target_call_args, keywords=[]) node = ast.Assign(targets=[layer_output], value=target_call) nodes.append(node) return nodes
def execute_code_block(compiler, block, example_globals, script_vars, gallery_conf): """Executes the code block of the example file""" if example_globals is None: # testing shortcut example_globals = script_vars['fake_main'].__dict__ blabel, bcontent, lineno = block # If example is not suitable to run, skip executing its blocks if not script_vars['execute_script'] or blabel == 'text': return '' cwd = os.getcwd() # Redirect output to stdout and orig_stdout, orig_stderr = sys.stdout, sys.stderr src_file = script_vars['src_file'] # First cd in the original example dir, so that any file # created by the example get created in this directory captured_std = StringIO() os.chdir(os.path.dirname(src_file)) sys_path = copy.deepcopy(sys.path) sys.path.append(os.getcwd()) sys.stdout = sys.stderr = LoggingTee(captured_std, logger, src_file) try: dont_inherit = 1 if sys.version_info >= (3, 8): ast_Module = partial(ast.Module, type_ignores=[]) else: ast_Module = ast.Module code_ast = ast_Module([bcontent]) code_ast = compile(bcontent, src_file, 'exec', ast.PyCF_ONLY_AST | compiler.flags, dont_inherit) ast.increment_lineno(code_ast, lineno - 1) # capture output if last line is expression is_last_expr = False if len(code_ast.body) and isinstance(code_ast.body[-1], ast.Expr): is_last_expr = True last_val = code_ast.body.pop().value # exec body minus last expression _, mem_body = _memory_usage( _exec_once( compiler(code_ast, src_file, 'exec'), script_vars['fake_main']), gallery_conf) # exec last expression, made into assignment body = [ast.Assign( targets=[ast.Name(id='___', ctx=ast.Store())], value=last_val)] last_val_ast = ast_Module(body=body) ast.fix_missing_locations(last_val_ast) _, mem_last = _memory_usage( _exec_once( compiler(last_val_ast, src_file, 'exec'), script_vars['fake_main']), gallery_conf) # capture the assigned variable ___ = example_globals['___'] mem_max = max(mem_body, mem_last) else: _, mem_max = _memory_usage( _exec_once( compiler(code_ast, src_file, 'exec'), script_vars['fake_main']), gallery_conf) script_vars['memory_delta'].append(mem_max) except Exception: sys.stdout.flush() sys.stderr.flush() sys.stdout, sys.stderr = orig_stdout, orig_stderr except_rst = handle_exception(sys.exc_info(), src_file, script_vars, gallery_conf) code_output = u"\n{0}\n\n\n\n".format(except_rst) # still call this even though we won't use the images so that # figures are closed save_figures(block, script_vars, gallery_conf) else: sys.stdout.flush() sys.stderr.flush() sys.stdout, orig_stderr = orig_stdout, orig_stderr sys.path = sys_path os.chdir(cwd) last_repr = None repr_meth = None if is_last_expr: if gallery_conf['ignore_repr_types']: ignore_repr = re.search( gallery_conf['ignore_repr_types'], str(type(___)) ) else: ignore_repr = False if gallery_conf['capture_repr'] != () and not ignore_repr: for meth in gallery_conf['capture_repr']: try: last_repr = getattr(___, meth)() # for case when last statement is print() if last_repr is None or last_repr == 'None': repr_meth = None else: repr_meth = meth except Exception: pass else: if isinstance(last_repr, str): break captured_std = captured_std.getvalue().expandtabs() # normal string output if repr_meth in ['__repr__', '__str__'] and last_repr: captured_std = u"{0}\n{1}".format(captured_std, last_repr) if captured_std and not captured_std.isspace(): captured_std = CODE_OUTPUT.format(indent(captured_std, u' ' * 4)) else: captured_std = '' images_rst = save_figures(block, script_vars, gallery_conf) # give html output its own header if repr_meth == '_repr_html_': captured_html = html_header.format(indent(last_repr, u' ' * 8)) else: captured_html = '' code_output = u"\n{0}\n\n{1}\n{2}\n\n".format( images_rst, captured_std, captured_html) finally: os.chdir(cwd) sys.path = sys_path sys.stdout, sys.stderr = orig_stdout, orig_stderr return code_output
def visit_With(self, node): node = self.generic_visit(node) # Build equivalent code with try catch finally. # PEP-0343 provides the equivalent code for us. statements = [] # mgr = node.expr mgr_id = self.id_factory("mgr") s = mk_assign(mgr_id, node.context_expr) statements.append(s) # exit = type(msg).__exit__ exit_id = self.id_factory("exit") s = mk_assign(exit_id, mk_attr(mk_call('type', [mk_name(mgr_id)]), "__exit__")) statements.append(s) # value = type(msg).__enter__(mgr) value_id = self.id_factory("value") s = mk_assign( value_id, mk_call_expr( mk_attr(mk_call('type', [mk_name(mgr_id)]), "__enter__"), [mk_name(mgr_id)])) statements.append(s) # exc = True exc_id = self.id_factory("exc") s = mk_assign(exc_id, mk_name("True")) statements.append(s) # try: tryfinally_body = [] tryfinally_finalbody = [] s = ast.TryFinally(body=tryfinally_body, finalbody=tryfinally_finalbody) statements.append(s) # try: tryexcept_body = [] tryexcept_except = [] expt_handler = ast.ExceptHandler(type=None, name=None, body=tryexcept_except) s = ast.TryExcept(body=tryexcept_body, handlers=[expt_handler], orelse=[]) tryfinally_body.append(s) # node.optional_vars = value if node.optional_vars: s = ast.Assign(targets=[node.optional_vars], value=mk_name(value_id)) tryexcept_body.append(s) # body tryexcept_body.extend(node.body) # except: # exc = False s = mk_assign(exc_id, mk_name("False")) tryexcept_except.append(s) # sys.exc_info() sys_exc_info = mk_call_expr(mk_attr(mk_name('sys'), "exc_info"), []) # exit(mgr, *sys.exc_info()) exit_call = mk_call(exit_id, [mk_name(mgr_id)], vararg=sys_exc_info) # not exit(mgr, *sys.exc_info()) test = ast.UnaryOp(op=ast.Not(), operand=exit_call) # if not exit(mgr, *sys.exc_info()): # raise s = ast.If(test=test, body=[ast.Raise(type=None, inst=None, tback=None)], orelse=[]) tryexcept_except.append(s) # finally: # if exc: # exit(mgr, None, None, None) exit_call = mk_call(exit_id, [ mk_name(mgr_id), mk_name("None"), mk_name("None"), mk_name("None") ]) s = ast.If(test=mk_name(exc_id), body=[ast.Expr(value=exit_call)], orelse=[]) tryfinally_finalbody.append(s) return statements
def visit_For(self, node): # CASE: for x in xs: ... # TODO: this is c/p from while, maybe try to abstract the common # parts. if node.orelse: raise MyiaSyntaxError("For loops may not have an else: clause.") assert self.dest wsym = self.global_gen(self.dest, WTEST) wbsym = self.global_gen(self.dest, WLOOP) augm_body = node.body + [ast.Assign()] # We visit the body once to get the free variables testp = self.sub_parser(dry=True) testp.return_error = 'Cannot return in while loops.' testp.body_wrapper(node.body) in_vars = testp.free_variables in_vars.update(testp.local_assignments) # type: ignore in_vars = list(in_vars) # type: ignore out_vars = list(testp.local_assignments) # We visit once more, this time adding the free vars as parameters p = self.sub_parser(dest=wbsym) in_iter = p.new_variable('~it~') in_list = p.new_variable('~li~') loopvar = p.new_variable(node.target) in_syms = [in_iter, in_list] + [p.new_variable(v) for v in in_vars] # Have to execute this before the body in order to get the right # symbols, otherwise they will be shadowed. If I recall correctly, # that's why we need to revisit instead of just using testp. initial_values = [p.vtrack[v] for v in out_vars] test = Apply(inst_builtin.less, in_iter, Apply(inst_builtin.len, in_list)) body = p.body_wrapper(node.body) loop_args = in_syms loop_body = body( Apply(wsym, Apply(inst_builtin.add, in_iter, Value(1)), in_list, *[p.vtrack[v] for v in in_vars])) loop_ass = Apply(inst_builtin.index, in_list, in_iter) loop_body = Let(((loopvar, loop_ass), ), loop_body) with About(loop_body.find_location(), 'parse'): loop_fn = self.reg_lambda(wbsym, loop_args, loop_body) outer_body = Apply( Apply( inst_builtin.switch, test, Closure(loop_fn, in_syms), # Closure on identity is a trick to create a thunk # that returns a pre-defined value (we need this # parameter to be a function with no arguments in # order to match the signature of the other branch). Closure(inst_builtin.identity, (Tuple(initial_values), )))) self.reg_lambda(wsym, in_syms, outer_body) # We immediately apply our shiny new function to start # the loop rolling. listvar = self.gen('~li~') val = Apply(wsym, Value(0), listvar, *[self.visit_variable(v) for v in in_vars]) # We get back the variables the while loop sets. listass = _Assign(listvar, self.visit(node.iter)) return Begin([listass, self.multi_assign(out_vars, val)])
def _bind_arguments(self, f_ast, call_expr, new_stmts): args_def = f_ast.args # Scope a variable name as unique to the function, and update any references # to it in the function def unique_and_rename(name): unique_name = f'{name}{SEP}{f_ast.name}' renamer = Rename(name, unique_name) for stmt in f_ast.body: renamer.visit(stmt) return unique_name args = call_expr.args[:] # Rename all variables declared in the function that aren't arguments assgn_finder = FindAssignments() assgn_finder.visit(f_ast) arg_names = set([arg.arg for arg in args_def.args]) for name in assgn_finder.names: if name not in arg_names: unique_and_rename(name) # If function is called with f(*args) if len(call_expr.args) > 0 and \ isinstance(call_expr.args[-1], ast.Starred): star_arg = call_expr.args.pop().value # Get the length of the star_arg runtime list star_arg_obj = eval(a2s(star_arg), self.globls, self.globls) # Generate an indexing expression for each element of the list call_star_args = [ ast.Subscript(value=star_arg, slice=ast.Index(value=ast.Num(i))) for i in range(len(star_arg_obj)) ] else: star_arg = None # If function is called with f(**kwargs) star_kwarg = [arg for arg in call_expr.keywords if arg.arg is None] star_kwarg = star_kwarg[0].value if len(star_kwarg) > 0 else None if star_kwarg is not None: star_kwarg_dict = eval(a2s(star_kwarg), self.globls, self.globls) call_star_kwarg = { key: ast.Subscript(value=star_kwarg, slice=ast.Index(value=ast.Str(key))) for key in star_kwarg_dict.keys() } # Function's anonymous arguments, e.g. f(1, 2) becomes [1, 2] call_anon_args = call_expr.args[:] # Function's keyword arguments, e.g. f(x=1, y=2) becomes {'x': 1, 'y': 2} call_kwargs = { arg.arg: arg.value for arg in call_expr.keywords if arg.arg is not None } # Match up defaults with variable names. # # Python convention is that if function has N arguments and K < N defaults, then # the defaults correspond to arguments N - K .. N. nodefault = len(args_def.args) - len(args_def.defaults) anon_defaults = { arg.arg: default for arg, default in zip(args_def.args[nodefault:], args_def.defaults) } # All keyword-only arguments must have defaults. # # kwonlyargs occur if a function definition has args AFTER a *args, e.g. # the var "y" in `def foo(x, *args, y=1)` kw_defaults = { arg.arg: default for arg, default in zip(args_def.kwonlyargs, args_def.kw_defaults) } # For each non-keyword-only argument, match it up with the corresponding # syntax from the call expression for arg in args_def.args: k = arg.arg # First, match with anonymous arguments if len(call_anon_args) > 0: v = call_anon_args.pop(0) # Then use *args if it exists elif star_arg is not None and len(call_star_args) > 0: v = call_star_args.pop(0) # Then use keyword arguments elif k in call_kwargs: v = call_kwargs.pop(k) # Then use **kwargs if it exists elif star_kwarg is not None and k in call_star_kwarg: v = call_star_kwarg.pop(k) # Otherwise use the default value else: v = anon_defaults.pop(k) # Add a binding from function argument to call argument uniq_k = unique_and_rename(k) stmt = ast.Assign(targets=[make_name(uniq_k)], value=v) new_stmts.append(stmt) # Perform equivalent procedure as above, but for keyword-only arguments for arg in args_def.kwonlyargs: k = arg.arg if k in call_kwargs: v = call_kwargs.pop(k) elif star_kwarg is not None and k in call_star_kwarg: v = call_star_kwarg.pop(k) else: v = kw_defaults.pop(k) uniq_k = unique_and_rename(k) stmt = ast.Assign(targets=[make_name(uniq_k)], value=v) new_stmts.append(stmt) # If function definition uses *args, then assign it to the remaining anonymous # arguments from the call_expr if args_def.vararg is not None: k = unique_and_rename(args_def.vararg.arg) v = call_anon_args[:] if star_arg is not None: v += call_star_args new_stmts.append( ast.Assign(targets=[make_name(k)], value=ast.List(elts=v))) # Similarly for **kwargs in the function definition if args_def.kwarg is not None: k = unique_and_rename(args_def.kwarg.arg) items = call_kwargs.items() if star_kwarg is not None: items = itertools.chain(items, call_star_kwarg.items()) kwkeys, kwvalues = unzip(items) new_stmts.append( ast.Assign(targets=[make_name(k)], value=ast.Dict([ast.Str(s) for s in kwkeys], kwvalues)))
def new_assignment(name, value): name = ast.Name(id=name) value = new_constant(value) return ast.Assign(targets=[name], value=value)
def assgn(value): return ast.Assign(targets=[make_name(ret_var)], value=value)
def build(self) -> typing.Optional[ast.ClassDef]: base_class: typing.Union[ast.Attribute, ast.Name] # Create the base class if not self.resource.base or self.resource.base.name == "object": base_class = ast.Attribute(value=ast.Name(id="marshmallow"), attr="Schema") else: if self.resource.base.name in FIELD_TYPES: return None base_class = ast.Name(id=self.resource.base.name + "Schema") if self.resource.package_name != self.resource.base.package_name: self.generator.import_resource( self.resource.package_name, self.resource.base.package_name, self.resource.base.name + "Schema", ) # Define the base class class_node = ast.ClassDef( name=self.resource.name + "Schema", bases=[base_class], keywords=[], decorator_list=[], body=[], ) doc_string = ( f"Marshmallow schema for :class:`commercetools.types.{self.resource.name}`." ) class_node.body.append( ast.Expr(value=ast.Str(s=doc_string, kind=None))) # Add the field definitions for prop in self.resource.properties: node = self._create_schema_property(prop) if node: class_node.body.append(node) # Add the Meta class class_node.body.append( ast.ClassDef( name="Meta", bases=[], keywords=[], body=[ ast.Assign( targets=[ast.Name(id="unknown")], value=ast.Name(id="marshmallow.EXCLUDE"), ) ], decorator_list=[], )) # Create the post_load() method post_load_node = self._create_marshmallow_hook("post_load") if self.contains_regex_field: post_load_node.body.append( self._create_regex_call("_regex", "postprocess")) post_load_node.body.append( ast.Return(value=ast.Call( func=ast.Name(id=f"types.{self.resource.name}"), args=[], keywords=[ast.keyword(arg=None, value=ast.Name(id="data"))], ))) class_node.body.append(post_load_node) # Create the pre_load() method if self.contains_regex_field: node = self._create_marshmallow_hook("pre_load") node.body.append(self._create_regex_call("_regex", "preprocess")) node.body.append(ast.Return(value=ast.Name(id="data"))) class_node.body.append(node) node = self._create_marshmallow_hook("pre_dump") node.body.append(self._create_regex_call("_regex", "preprocess")) node.body.append(ast.Return(value=ast.Name(id="data"))) class_node.body.append(node) node = self._create_marshmallow_hook("post_dump") node.body.append(self._create_regex_call("_regex", "postprocess")) node.body.append(ast.Return(value=ast.Name(id="data"))) class_node.body.append(node) d_field = self.resource.get_discriminator_field() if d_field: post_load_node.body.insert( 0, ast.Delete(targets=[ ast.Subscript( value=ast.Name(id="data"), slice=ast.Index(value=ast.Str(s=d_field.attribute_name, kind=None)), ) ]), ) return class_node
def compile_to_logpdf(graph: GraphicalModel, namespace: Dict) -> Artifact: """Compile a graphical model into a log-probability density function. Example ------- Let us consider a simple linear regression example: >>> @mcx.model ... def linear_regression(x, lmbda=1.): ... scale <~ Exponential(lmbda) ... coeff <~ Normal(0, 1) ... y = np.dot(x, coeff) ... predictions <~ Normal(y, scale) ... return predictions MCX parses this definition into a graphical model. This function compiles the graph in a python function that returns the values of the log-probability density function: >>> def linear_regression_logpdf(x, scale, coeffs, predictions, lmbda=1.): ... logpdf = 0 ... logpdf += Exponential(lmbda).logpdf(scale) ... logpdf += Normal(0, 1).logpdf(coeff) ... y = np.dot(x, coeff) ... logpdf += Normal(y, coeff).logpdf(predictions) ... return logpdf The logpdf is then partially applied on the dataset {(x, prediction)} for inference. Of course it would impact the core Parameters ---------- model: A probabilistic graphical model. namespace: The names contained in the model definition's global scope. Returns ------- logpdf: A function that returns the log probability of a model at one point the parameter space. var_names: The name of the random variables arguments of the logpdf function, in the order in which they appear. logpdf_source: A string containing the source code of the logpdf. Useful for inspection by the user. """ fn_name = graph.name + "_logpdf" # # ARGUMENTS # kwarg_nodes = [ node[1]["content"] for node in graph.nodes(data=True) if isinstance(node[1]["content"], Argument) and node[1]["content"].default_value is not None ] # The (keyword) arguments of the model definition and random variables # are passed as arguments to the logpdf. model_kwargs = [kwarg.to_logpdf_iadd() for kwarg in kwarg_nodes] model_arguments = [ node[1]["content"].to_logpdf_iadd() for node in graph.nodes(data=True) if isinstance(node[1]["content"], Argument) and node[1]["content"].default_value is None ] random_variables = [ ast.arg(arg=node[1]["content"].name, annotation=None) for node in graph.nodes(data=True) if isinstance(node[1]["content"], RandVar) ] logpdf_arguments = random_variables + model_arguments + model_kwargs # We propagate the kwargs' default values defaults = [kwarg.default_value for kwarg in kwarg_nodes] # # FUNCTION BODY # To write the function body, we traverse the graph in topological order # while incrementing the value of the logpdf. # body: List[Union[ast.Assign, ast.Constant, ast.Num, ast.Return]] = [] body.append( ast.Assign( targets=[ast.Name(id="logpdf", ctx=ast.Store())], value=ast.Constant(value=0), )) ordered_nodes = [ graph.nodes[node]["content"] for node in nx.topological_sort(graph) if not isinstance(graph.nodes[node]["content"], Argument) ] for node in ordered_nodes: body.append(node.to_logpdf_iadd()) returned = ast.Return(value=ast.Name(id="logpdf", ctx=ast.Load())) body.append(returned) logpdf_ast = ast.Module( body=[ ast.FunctionDef( name=fn_name, args=ast.arguments( args=logpdf_arguments, vararg=None, kwarg=None, posonlyargs=[], kwonlyargs=[], defaults=defaults, kw_defaults=[], ), body=body, decorator_list=[], ) ], type_ignores=[], ) logpdf_ast = ast.fix_missing_locations(logpdf_ast) logpdf = compile(logpdf_ast, filename="<ast>", mode="exec") exec(logpdf, namespace) fn = namespace[fn_name] argument_names = [arg.arg for arg in logpdf_arguments] return Artifact(fn, argument_names, fn_name, astor.code_gen.to_source(logpdf_ast))
def gen_unpack_wrapper(self, node, target, ctx='store'): """Helper function to protect tuple unpacks. node: used to copy the locations for the new nodes. target: is the tuple which must be protected. ctx: Defines the context of the returned temporary node. It returns a tuple with two element. Element 1: Is a temporary name node which must be used to replace the target. The context (store, param) is defined by the 'ctx' parameter.. Element 2: Is a try .. finally where the body performs the protected tuple unpack of the temporary variable into the original target. """ # Generate a tmp name to replace the tuple with. tmp_name = self.gen_tmp_name() # Generates an expressions which protects the unpack. # converter looks like 'wrapper(tmp_name)'. # 'wrapper' takes care to protect sequence unpacking with _getiter_. converter = self.protect_unpack_sequence( target, ast.Name(tmp_name, ast.Load())) # Assign the expression to the original names. # Cleanup the temporary variable. # Generates: # try: # # converter is 'wrapper(tmp_name)' # arg = converter # finally: # del tmp_arg try_body = [ast.Assign(targets=[target], value=converter)] finalbody = [self.gen_del_stmt(tmp_name)] if IS_PY2: cleanup = ast.TryFinally(body=try_body, finalbody=finalbody) else: cleanup = ast.Try(body=try_body, finalbody=finalbody, handlers=[], orelse=[]) if ctx == 'store': ctx = ast.Store() elif ctx == 'param': ctx = ast.Param() else: # pragma: no cover # Only store and param are defined ctx. raise NotImplementedError( 'Unsupported context type: "{name}".'.format(name=type(ctx)), ) # This node is used to catch the tuple in a tmp variable. tmp_target = ast.Name(tmp_name, ctx) copy_locations(tmp_target, node) copy_locations(cleanup, node) return (tmp_target, cleanup)
def find_pyparams_assignments_nodes( node: ast.Module, assigment_op_name: str = PyParam.__name__ ) -> List[Union[ast.AnnAssign, ast.Assign]]: """Scans the AST Module i.e. an AST representation of the python file and return all AnnAssign nodes. Note that AnnAssign appears when pyparam is defined with typing annotation e.g. variable_a: int = PyParam(value=512) # is a AnnAssign node variable_a = PyParam(value=512) # is a Assign node Args: node: a root node of the AST tree, this node should be a AST representation of the python file assigment_op_name: a name of the assignment function e.g. PyParam.__name__ Returns: nodes: a list of AnnAssign or Assign found in the Module """ supported_nodes = [ast.AnnAssign, ast.Assign] pyparams_nodes = [] for element in node.body: if element.__dict__.get("body", None) is not None: pyparams_nodes += find_pyparams_assignments_nodes( element, assigment_op_name=assigment_op_name) # dealing with function definition arguments if isinstance(element, ast.FunctionDef): defaults = element.args.defaults num_defaults = len(defaults) args = element.args.args[-num_defaults:] arg_nodes = [] for arg, default in zip(args, defaults): arg_nodes.append( ast.Assign(targets=[ast.Name(arg.arg, None)], value=default)) body_element = ast.Module(arg_nodes) pyparams_nodes += find_pyparams_assignments_nodes( body_element, assigment_op_name=assigment_op_name) # must be AnnAssign if any([isinstance(element, sn) for sn in supported_nodes]): # value must be Call if isinstance(element.value, ast.Call): # func must be named if isinstance(element.value.func, ast.Name): func_id = element.value.func.id # the name of the function must be e.g. "PyParam" if func_id == assigment_op_name: pyparams_nodes += [element] else: # loop over the arguments of some Func(**kwargs) declaration # note only named keywords are supported kwarg_nodes = [] for keyword in element.value.keywords: kwarg_nodes.append( ast.Assign( targets=[ast.Name(keyword.arg, None)], value=keyword.value)) body_element = ast.Module(kwarg_nodes) pyparams_nodes += find_pyparams_assignments_nodes( body_element, assigment_op_name=assigment_op_name) return pyparams_nodes
def t_add_dead_code(the_ast, uid=1, all_sites=False): """ Statement of the form if False:\n <HOLE> = 1 is added to the target program. all_sites=False: The insertion location (either beginning, or end) is chosen at random. all_sites=True: The statement is inserted at all possible locations. """ def insert_holes(the_ast, hole_id, site_map): if 'body' not in the_ast.__dict__ or len(the_ast.body) == 0: return False, the_ast, hole_id, site_map new_body = [] for node in the_ast.body: site_map["if false : @R_{}@ = 1".format(hole_id)] = [ "", 'transforms.AddDeadCode' ] new_body += [ ast.If(test=ast.Name(id="False", ctx=ast.Load()), body=[ ast.Assign(targets=[ ast.Name(id="REPLACEME" + str(hole_id), ctx=ast.Store()) ], value=ast.Num(n=1)) ], orelse=[]), node ] hole_id += 1 site_map["if false : @R_{}@ = 1".format(hole_id)] = [ "", 'transforms.AddDeadCode' ] new_body.append( ast.If(test=ast.Name(id="False", ctx=ast.Load()), body=[ ast.Assign(targets=[ ast.Name(id="REPLACEME" + str(hole_id), ctx=ast.Store()) ], value=ast.Num(n=1)) ], orelse=[])) hole_id += 1 the_ast.body = new_body for i in range(len(the_ast.body[1:])): if i % 2 == 0: node = the_ast.body[i + 1] _, _, hole_id, site_map = insert_holes(node, hole_id, site_map) return True, the_ast, hole_id, site_map if len(the_ast.body) == 0 or not isinstance(the_ast.body[0], ast.FunctionDef): return False, the_ast, uid - 1, {} if all_sites: changed, the_ast_body, hole_id, site_map = insert_holes( the_ast.body[0], uid, {}) the_ast.body[0] = the_ast_body return changed, the_ast, hole_id - 1, site_map else: site_map = {} if bool(random.getrandbits(1)): the_ast.body[0].body.insert( 0, ast.If(test=ast.Name(id="False", ctx=ast.Load()), body=[ ast.Assign(targets=[ ast.Name(id="REPLACEME" + str(uid), ctx=ast.Store()) ], value=ast.Num(n=1)) ], orelse=[])) site_map['@R_{}@'.format(uid)] = ["", 'transforms.AddDeadCode'] else: the_ast.body[0].body.append( ast.If(test=ast.Name(id="False", ctx=ast.Load()), body=[ ast.Assign(targets=[ ast.Name(id="REPLACEME" + str(uid), ctx=ast.Store()) ], value=ast.Num(n=1)) ], orelse=[])) site_map['@R_{}@'.format(uid)] = ["", 'transforms.AddDeadCode'] return True, the_ast, uid, site_map
def _compile_directive_call_assets(self, el, options): """ This special 't-call' tag can be used in order to aggregate/minify javascript and css assets""" if len(el): raise SyntaxError("t-call-assets cannot contain children nodes") # nodes = self._get_asset(xmlid, options, css=css, js=js, debug=values.get('debug'), async=async, values=values) # # for index, (tagName, t_attrs, content) in enumerate(nodes): # if index: # append('\n ') # append('<') # append(tagName) # # self._post_processing_att(tagName, t_attrs, options) # for name, value in t_attrs.items(): # if value or isinstance(value, string_types)): # append(u' ') # append(name) # append(u'="') # append(escape(pycompat.to_text((value))) # append(u'"') # # if not content and tagName in self._void_elements: # append('/>') # else: # append('>') # if content: # append(content) # append('</') # append(tagName) # append('>') # space = el.getprevious() is not None and el.getprevious( ).tail or el.getparent().text sep = u'\n' + space.rsplit('\n').pop() return [ ast.Assign( targets=[ast.Name(id='nodes', ctx=ast.Store())], value=ast.Call( func=ast.Attribute(value=ast.Name(id='self', ctx=ast.Load()), attr='_get_asset_nodes', ctx=ast.Load()), args=[ ast.Str(el.get('t-call-assets')), ast.Name(id='options', ctx=ast.Load()), ], keywords=[ ast.keyword('css', self._get_attr_bool(el.get('t-css', True))), ast.keyword('js', self._get_attr_bool(el.get('t-js', True))), ast.keyword( 'debug', ast.Call(func=ast.Attribute(value=ast.Name( id='values', ctx=ast.Load()), attr='get', ctx=ast.Load()), args=[ast.Str('debug')], keywords=[], starargs=None, kwargs=None)), ast.keyword( 'async', self._get_attr_bool(el.get('async', False))), ast.keyword('values', ast.Name(id='values', ctx=ast.Load())), ], starargs=None, kwargs=None)), ast.For( target=ast.Tuple(elts=[ ast.Name(id='index', ctx=ast.Store()), ast.Tuple(elts=[ ast.Name(id='tagName', ctx=ast.Store()), ast.Name(id='t_attrs', ctx=ast.Store()), ast.Name(id='content', ctx=ast.Store()) ], ctx=ast.Store()) ], ctx=ast.Store()), iter=ast.Call(func=ast.Name(id='enumerate', ctx=ast.Load()), args=[ast.Name(id='nodes', ctx=ast.Load())], keywords=[], starargs=None, kwargs=None), body=[ ast.If(test=ast.Name(id='index', ctx=ast.Load()), body=[self._append(ast.Str(sep))], orelse=[]), self._append(ast.Str(u'<')), self._append(ast.Name(id='tagName', ctx=ast.Load())), ] + self._append_attributes() + [ ast.If(test=ast.BoolOp( op=ast.And(), values=[ ast.UnaryOp(ast.Not(), ast.Name(id='content', ctx=ast.Load()), lineno=0, col_offset=0), ast.Compare( left=ast.Name(id='tagName', ctx=ast.Load()), ops=[ast.In()], comparators=[ ast.Attribute(value=ast.Name( id='self', ctx=ast.Load()), attr='_void_elements', ctx=ast.Load()) ]), ]), body=[self._append(ast.Str(u'/>'))], orelse=[ self._append(ast.Str(u'>')), ast.If(test=ast.Name(id='content', ctx=ast.Load()), body=[ self._append( ast.Name(id='content', ctx=ast.Load())) ], orelse=[]), self._append(ast.Str(u'</')), self._append( ast.Name(id='tagName', ctx=ast.Load())), self._append(ast.Str(u'>')), ]) ], orelse=[]) ]
def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: """Return the AST statements to replace the ast.Assert instance. This rewrites the test of an assertion to provide intermediate values and replace it with an if statement which raises an assertion error with a detailed explanation in case the expression is false. """ if isinstance(assert_.test, ast.Tuple) and len(assert_.test.elts) >= 1: from _pytest.warning_types import PytestAssertRewriteWarning import warnings # TODO: This assert should not be needed. assert self.module_path is not None warnings.warn_explicit( PytestAssertRewriteWarning( "assertion is always true, perhaps remove parentheses?" ), category=None, filename=os.fspath(self.module_path), lineno=assert_.lineno, ) self.statements = [] # type: List[ast.stmt] self.variables = [] # type: List[str] self.variable_counter = itertools.count() if self.enable_assertion_pass_hook: self.format_variables = [] # type: List[str] self.stack = [] # type: List[Dict[str, ast.expr]] self.expl_stmts = [] # type: List[ast.stmt] self.push_format_context() # Rewrite assert into a bunch of statements. top_condition, explanation = self.visit(assert_.test) negation = ast.UnaryOp(ast.Not(), top_condition) if self.enable_assertion_pass_hook: # Experimental pytest_assertion_pass hook msg = self.pop_format_context(ast.Str(explanation)) # Failed if assert_.msg: assertmsg = self.helper("_format_assertmsg", assert_.msg) gluestr = "\n>assert " else: assertmsg = ast.Str("") gluestr = "assert " err_explanation = ast.BinOp(ast.Str(gluestr), ast.Add(), msg) err_msg = ast.BinOp(assertmsg, ast.Add(), err_explanation) err_name = ast.Name("AssertionError", ast.Load()) fmt = self.helper("_format_explanation", err_msg) exc = ast.Call(err_name, [fmt], []) raise_ = ast.Raise(exc, None) statements_fail = [] statements_fail.extend(self.expl_stmts) statements_fail.append(raise_) # Passed fmt_pass = self.helper("_format_explanation", msg) orig = self._assert_expr_to_lineno()[assert_.lineno] hook_call_pass = ast.Expr( self.helper( "_call_assertion_pass", ast.Num(assert_.lineno), ast.Str(orig), fmt_pass, ) ) # If any hooks implement assert_pass hook hook_impl_test = ast.If( self.helper("_check_if_assertion_pass_impl"), self.expl_stmts + [hook_call_pass], [], ) statements_pass = [hook_impl_test] # Test for assertion condition main_test = ast.If(negation, statements_fail, statements_pass) self.statements.append(main_test) if self.format_variables: variables = [ ast.Name(name, ast.Store()) for name in self.format_variables ] clear_format = ast.Assign(variables, ast.NameConstant(None)) self.statements.append(clear_format) else: # Original assertion rewriting # Create failure message. body = self.expl_stmts self.statements.append(ast.If(negation, body, [])) if assert_.msg: assertmsg = self.helper("_format_assertmsg", assert_.msg) explanation = "\n>assert " + explanation else: assertmsg = ast.Str("") explanation = "assert " + explanation template = ast.BinOp(assertmsg, ast.Add(), ast.Str(explanation)) msg = self.pop_format_context(template) fmt = self.helper("_format_explanation", msg) err_name = ast.Name("AssertionError", ast.Load()) exc = ast.Call(err_name, [fmt], []) raise_ = ast.Raise(exc, None) body.append(raise_) # Clear temporary variables by setting them to None. if self.variables: variables = [ast.Name(name, ast.Store()) for name in self.variables] clear = ast.Assign(variables, ast.NameConstant(None)) self.statements.append(clear) # Fix line numbers. for stmt in self.statements: set_location(stmt, assert_.lineno, assert_.col_offset) return self.statements
def eval_annassign(env, node): if node.value is None: return val_ = ast.Assign(targets=[node.target], value=node.value) return eval_assign(env, val_)
def visit_Assign(self, node): """Look for 'LOG = logging.getLogger' This handles the simple case: name = [logging_module].getLogger(...) - or - name = [i18n_name](...) And some much more comple ones: name = [i18n_name](...) % X - or - self.name = [i18n_name](...) % X """ attr_node_types = (ast.Name, ast.Attribute) if (len(node.targets) != 1 or not isinstance(node.targets[0], attr_node_types)): # say no to: "x, y = ..." return super(CheckForLoggingIssues, self).generic_visit(node) target_name = self._find_name(node.targets[0]) if (isinstance(node.value, ast.BinOp) and isinstance(node.value.op, ast.Mod)): if (isinstance(node.value.left, ast.Call) and isinstance(node.value.left.func, ast.Name) and node.value.left.func.id in self.i18n_names): # NOTE(dstanek): this is done to match cases like: # `msg = _('something %s') % x` node = ast.Assign(value=node.value.left) if not isinstance(node.value, ast.Call): # node.value must be a call to getLogger self.assignments.pop(target_name, None) return super(CheckForLoggingIssues, self).generic_visit(node) # is this a call to an i18n function? if (isinstance(node.value.func, ast.Name) and node.value.func.id in self.i18n_names): self.assignments[target_name] = node.value.func.id return super(CheckForLoggingIssues, self).generic_visit(node) if (not isinstance(node.value.func, ast.Attribute) or not isinstance(node.value.func.value, attr_node_types)): # function must be an attribute on an object like # logging.getLogger return super(CheckForLoggingIssues, self).generic_visit(node) object_name = self._find_name(node.value.func.value) func_name = node.value.func.attr if (object_name in self.logger_module_names and func_name == 'getLogger'): self.logger_names.append(target_name) return super(CheckForLoggingIssues, self).generic_visit(node)
def visit_Assign(self, node): assert (len(node.targets) == 1) self.generic_visit(node) decorated = isinstance(node.value, ast.Call) and isinstance( node.value.func, ast.Attribute) and isinstance(node.value.func.value, ast.Name) \ and node.value.func.value.id == 'ti' is_static_assign = False if decorated: attr = node.value.func if attr.attr == 'static': is_static_assign = True else: pass # eg. x = ti.cast(xx) will reach here, but they're not decorators, so no raising errors here 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]') indexing.value.slice.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 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 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 makeRegressor(model: Xgboost, useSigmoids: bool = False, useNumPy: bool = False) -> ast.Module: """Converts a regression XGBoost decision tree model into a python module of if-else trees""" #code:typing.List[ast.stmt]=[] code = [] numpyModuleName = "numpy" if useSigmoids: code.extend( generateFermiSplitFunction( sigmoidSplitFuncName, tanhModuleName=(numpyModuleName if useNumPy else "math"))) if useNumPy: code.append( ast.ImportFrom(module=numpyModuleName, names=[ast.alias(name=numpySumName, asname=None)], level=0)) features = int(model.param.num_feature) trees = int(model.gbm_.param.num_trees) groups = int(model.gbm_.param.num_output_group) if groups == 0: groups = 1 treesInAGroup = trees // groups groupFunctions = [] groupFunctionsNames = [] elts = [] for j in range(groups): group = [] for i in range(treesInAGroup): t = model.gbm_.trees[j * treesInAGroup + i] name = "g" + str(j) + "_t" + str(i) code.extend(treesToFuncs(t, name, useSigmoids)) group.append(ast.Name(id=name)) elts.append(ast.Tuple(elts=group)) groupFuncName = "g" + str(j) groupFunctionsNames.append(ast.Name(groupFuncName)) groupFunctions.append( makeGroup(groupFuncName, model.param.base_score, useNumPy=useNumPy)) code.extend(groupFunctions) code.append( ast.Assign(targets=[treesAccumulator], value=ast.Dict(keys=groupFunctionsNames, values=elts))) code.append( wrapWithFunc([ ast.Expr(value=astStr(s=genModelSummary(model))), ast.Assert(test=ast.Compare(left=ast.Call( func=lenFunc, args=[vector], keywords=[]), ops=[ast.Eq()], comparators=[astNum(n=features)]), msg=ast.BinOp(left=ast.BinOp( left=astStr(s="This model requires exactly " + str(features) + " feature, but "), op=ast.Add(), right=ast.Call(func=strFunc, args=[ ast.Call(func=lenFunc, args=[vector], keywords=[]) ], keywords=[])), op=ast.Add(), right=astStr(s=" were given"))), ast.Assign( targets=[res], value=ast.ListComp( elt=ast.Call(func=groupTemp, args=[vector], keywords=[]), generators=[ ast.comprehension( target=groupTemp, iter=treesAccumulator, ifs=[]) ])), ast.Return(value=res) ], regressorFunctionName)) return ast.Module(body=code)
def from_phpast(node): if node is None: return py.Pass(**pos(node)) if isinstance(node, str): return py.Str(node, **pos(node)) if isinstance(node, (int, float)): return py.Num(node, **pos(node)) if isinstance(node, php.Array): if node.nodes: if node.nodes[0].key is not None: keys = [] values = [] for elem in node.nodes: keys.append(from_phpast(elem.key)) values.append(from_phpast(elem.value)) return py.Dict(keys, values, **pos(node)) else: return py.List([from_phpast(x.value) for x in node.nodes], py.Load(**pos(node)), **pos(node)) else: return py.List([], py.Load(**pos(node)), **pos(node)) if isinstance(node, php.InlineHTML): args = [py.Str(node.data, **pos(node))] return py.Call( py.Name('inline_html', py.Load(**pos(node)), **pos(node)), args, [], None, None, **pos(node)) if isinstance(node, php.Echo): return py.Call(py.Name('echo', py.Load(**pos(node)), **pos(node)), list(map(from_phpast, node.nodes)), [], None, None, **pos(node)) if isinstance(node, php.Print): return py.Print(None, [from_phpast(node.node)], True, **pos(node)) if isinstance(node, php.Exit): args = [] if node.expr is not None: args.append(from_phpast(node.expr)) return py.Raise( py.Call(py.Name('Exit', py.Load(**pos(node)), **pos(node)), args, [], None, None, **pos(node)), None, None, **pos(node)) if isinstance(node, php.Return): if node.node is None: return py.Return(None, **pos(node)) else: return py.Return(from_phpast(node.node), **pos(node)) if isinstance(node, php.Break): assert node.node is None, 'level on break not supported' return py.Break(**pos(node)) if isinstance(node, php.Continue): assert node.node is None, 'level on continue not supported' return py.Continue(**pos(node)) if isinstance(node, php.Silence): return from_phpast(node.expr) if isinstance(node, php.Block): return from_phpast(php.If(1, node, [], None, lineno=node.lineno)) if isinstance(node, php.Unset): return py.Delete(list(map(from_phpast, node.nodes)), **pos(node)) if isinstance(node, php.IsSet) and len(node.nodes) == 1: if isinstance(node.nodes[0], php.ArrayOffset): return py.Compare(from_phpast(node.nodes[0].expr), [py.In(**pos(node))], [from_phpast(node.nodes[0].node)], **pos(node)) if isinstance(node.nodes[0], php.ObjectProperty): return py.Call( py.Name('hasattr', py.Load(**pos(node)), **pos(node)), [ from_phpast(node.nodes[0].node), from_phpast(node.nodes[0].name) ], [], None, None, **pos(node)) if isinstance(node.nodes[0], php.Variable): return py.Compare(py.Str( node.nodes[0].name[1:], **pos(node)), [py.In(**pos(node))], [ py.Call(py.Name('vars', py.Load(**pos(node)), **pos(node)), [], [], None, None, **pos(node)) ], **pos(node)) return py.Compare(from_phpast(node.nodes[0]), [py.IsNot(**pos(node))], [py.Name('None', py.Load(**pos(node)), **pos(node))], **pos(node)) if isinstance(node, php.Empty): return from_phpast( php.UnaryOp('!', php.BinaryOp('&&', php.IsSet([node.expr], lineno=node.lineno), node.expr, lineno=node.lineno), lineno=node.lineno)) if isinstance(node, php.Assignment): if (isinstance(node.node, php.ArrayOffset) and node.node.expr is None): return py.Call( py.Attribute(from_phpast(node.node.node), 'append', py.Load(**pos(node)), **pos(node)), [from_phpast(node.expr)], [], None, None, **pos(node)) if (isinstance(node.node, php.ObjectProperty) and isinstance(node.node.name, php.BinaryOp)): return to_stmt( py.Call(py.Name('setattr', py.Load(**pos(node)), **pos(node)), [ from_phpast(node.node.node), from_phpast(node.node.name), from_phpast(node.expr) ], [], None, None, **pos(node))) return py.Assign([store(from_phpast(node.node))], from_phpast(node.expr), **pos(node)) if isinstance(node, php.ListAssignment): return py.Assign([ py.Tuple(list(map(store, list(map(from_phpast, node.nodes)))), py.Store(**pos(node)), **pos(node)) ], from_phpast(node.expr), **pos(node)) if isinstance(node, php.AssignOp): return from_phpast( php.Assignment(node.left, php.BinaryOp(node.op[:-1], node.left, node.right, lineno=node.lineno), False, lineno=node.lineno)) if isinstance(node, (php.PreIncDecOp, php.PostIncDecOp)): return from_phpast( php.Assignment(node.expr, php.BinaryOp(node.op[0], node.expr, 1, lineno=node.lineno), False, lineno=node.lineno)) if isinstance(node, php.ArrayOffset): return py.Subscript(from_phpast(node.node), py.Index(from_phpast(node.expr), **pos(node)), py.Load(**pos(node)), **pos(node)) if isinstance(node, php.ObjectProperty): if isinstance(node.name, (php.Variable, php.BinaryOp)): return py.Call( py.Name('getattr', py.Load(**pos(node)), **pos(node)), [from_phpast(node.node), from_phpast(node.name)], [], None, None, **pos(node)) return py.Attribute(from_phpast(node.node), node.name, py.Load(**pos(node)), **pos(node)) if isinstance(node, php.Constant): name = node.name if name.lower() == 'true': name = 'True' if name.lower() == 'false': name = 'False' if name.lower() == 'null': name = 'None' return py.Name(name, py.Load(**pos(node)), **pos(node)) if isinstance(node, php.Variable): name = node.name[1:] if name == 'this': name = 'self' return py.Name(name, py.Load(**pos(node)), **pos(node)) if isinstance(node, php.Global): return py.Global([var.name[1:] for var in node.nodes], **pos(node)) if isinstance(node, php.Include): once = py.Name('True' if node.once else 'False', py.Load(**pos(node)), **pos(node)) return py.Call(py.Name('include', py.Load(**pos(node)), **pos(node)), [from_phpast(node.expr), once], [], None, None, **pos(node)) if isinstance(node, php.Require): once = py.Name('True' if node.once else 'False', py.Load(**pos(node)), **pos(node)) return py.Call(py.Name('require', py.Load(**pos(node)), **pos(node)), [from_phpast(node.expr), once], [], None, None, **pos(node)) if isinstance(node, php.UnaryOp): op = unary_ops.get(node.op) assert op is not None, "unknown unary operator: '%s'" % node.op op = op(**pos(node)) return py.UnaryOp(op, from_phpast(node.expr), **pos(node)) if isinstance(node, php.BinaryOp): if node.op == '.': pattern, pieces = build_format(node.left, node.right) if pieces: return py.BinOp( py.Str(pattern, **pos(node)), py.Mod(**pos(node)), py.Tuple(list(map(from_phpast, pieces)), py.Load(**pos(node)), **pos(node)), **pos(node)) else: return py.Str(pattern % (), **pos(node)) if node.op in bool_ops: op = bool_ops[node.op](**pos(node)) return py.BoolOp(op, [from_phpast(node.left), from_phpast(node.right)], **pos(node)) if node.op in cmp_ops: op = cmp_ops[node.op](**pos(node)) return py.Compare(from_phpast(node.left), [op], [from_phpast(node.right)], **pos(node)) op = binary_ops.get(node.op) if node.op == 'instanceof': return py.Call( func=py.Name(id='isinstance', ctx=py.Load(**pos(node))), args=[from_phpast(node.left), from_phpast(node.right)], keywords=[], starargs=None, kwargs=None) assert op is not None, "unknown binary operator: '%s'" % node.op op = op(**pos(node)) return py.BinOp(from_phpast(node.left), op, from_phpast(node.right), **pos(node)) if isinstance(node, php.TernaryOp): return py.IfExp(from_phpast(node.expr), from_phpast(node.iftrue), from_phpast(node.iffalse), **pos(node)) if isinstance(node, php.Cast): return py.Call( py.Name(casts.get(node.type, node.type), py.Load(**pos(node)), **pos(node)), [from_phpast(node.expr)], [], None, None, **pos(node)) if isinstance(node, php.If): orelse = [] if node.else_: for else_ in map(from_phpast, deblock(node.else_.node)): orelse.append(to_stmt(else_)) for elseif in reversed(node.elseifs): orelse = [ py.If( from_phpast(elseif.expr), list( map(to_stmt, list(map(from_phpast, deblock(elseif.node))))), orelse, **pos(node)) ] return py.If( from_phpast(node.expr), list(map(to_stmt, list(map(from_phpast, deblock(node.node))))), orelse, **pos(node)) if isinstance(node, php.For): assert node.test is None or len(node.test) == 1, \ 'only a single test is supported in for-loops' return from_phpast( php.Block((node.start or []) + [ php.While(node.test[0] if node.test else 1, php.Block(deblock(node.node) + (node.count or []), lineno=node.lineno), lineno=node.lineno) ], lineno=node.lineno)) if isinstance(node, php.Foreach): if node.keyvar is None: target = py.Name(node.valvar.name[1:], py.Store(**pos(node)), **pos(node)) else: target = py.Tuple([ py.Name(node.keyvar.name[1:], py.Store(**pos(node))), py.Name(node.valvar.name[1:], py.Store(**pos(node))) ], py.Store(**pos(node)), **pos(node)) return py.For( target, from_phpast(node.expr), list(map(to_stmt, list(map(from_phpast, deblock(node.node))))), [], **pos(node)) if isinstance(node, php.While): return py.While( from_phpast(node.expr), list(map(to_stmt, list(map(from_phpast, deblock(node.node))))), [], **pos(node)) if isinstance(node, php.DoWhile): condition = php.If(php.UnaryOp('!', node.expr, lineno=node.lineno), php.Break(None, lineno=node.lineno), [], None, lineno=node.lineno) return from_phpast( php.While(1, php.Block(deblock(node.node) + [condition], lineno=node.lineno), lineno=node.lineno)) if isinstance(node, php.Try): return py.TryExcept( list(map(to_stmt, list(map(from_phpast, node.nodes)))), [ py.ExceptHandler( py.Name(catch.class_, py.Load(**pos(node)), **pos(node)), store(from_phpast(catch.var)), list(map(to_stmt, list(map(from_phpast, catch.nodes)))), **pos(node)) for catch in node.catches ], [], **pos(node)) if isinstance(node, php.Throw): return py.Raise(from_phpast(node.node), None, None, **pos(node)) if isinstance(node, php.Function): args = [] defaults = [] for param in node.params: args.append( py.Name(param.name[1:], py.Param(**pos(node)), **pos(node))) if param.default is not None: defaults.append(from_phpast(param.default)) body = list(map(to_stmt, list(map(from_phpast, node.nodes)))) if not body: body = [py.Pass(**pos(node))] return py.FunctionDef(node.name, py.arguments(args, None, None, defaults), body, [], **pos(node)) if isinstance(node, php.Method): args = [] defaults = [] decorator_list = [] if 'static' in node.modifiers: decorator_list.append( py.Name('classmethod', py.Load(**pos(node)), **pos(node))) args.append(py.Name('cls', py.Param(**pos(node)), **pos(node))) else: args.append(py.Name('self', py.Param(**pos(node)), **pos(node))) for param in node.params: args.append( py.Name(param.name[1:], py.Param(**pos(node)), **pos(node))) if param.default is not None: defaults.append(from_phpast(param.default)) body = list(map(to_stmt, list(map(from_phpast, node.nodes)))) if not body: body = [py.Pass(**pos(node))] return py.FunctionDef(node.name, py.arguments(args, None, None, defaults), body, decorator_list, **pos(node)) if isinstance(node, php.Class): name = node.name bases = [] extends = node.extends or 'object' bases.append(py.Name(extends, py.Load(**pos(node)), **pos(node))) body = list(map(to_stmt, list(map(from_phpast, node.nodes)))) for stmt in body: if (isinstance(stmt, py.FunctionDef) and stmt.name in (name, '__construct')): stmt.name = '__init__' if not body: body = [py.Pass(**pos(node))] return py.ClassDef(name, bases, body, [], **pos(node)) if isinstance(node, (php.ClassConstants, php.ClassVariables)): assert len(node.nodes) == 1, \ 'only one class-level assignment supported per line' if isinstance(node.nodes[0], php.ClassConstant): name = php.Constant(node.nodes[0].name, lineno=node.lineno) else: name = php.Variable(node.nodes[0].name, lineno=node.lineno) initial = node.nodes[0].initial if initial is None: initial = php.Constant('None', lineno=node.lineno) return py.Assign([store(from_phpast(name))], from_phpast(initial), **pos(node)) if isinstance(node, (php.FunctionCall, php.New)): if isinstance(node.name, str): name = py.Name(node.name, py.Load(**pos(node)), **pos(node)) else: name = py.Subscript( py.Call(py.Name('vars', py.Load(**pos(node)), **pos(node)), [], [], None, None, **pos(node)), py.Index(from_phpast(node.name), **pos(node)), py.Load(**pos(node)), **pos(node)) args, kwargs = build_args(node.params) return py.Call(name, args, kwargs, None, None, **pos(node)) if isinstance(node, php.MethodCall): args, kwargs = build_args(node.params) return py.Call( py.Attribute(from_phpast(node.node), node.name, py.Load(**pos(node)), **pos(node)), args, kwargs, None, None, **pos(node)) if isinstance(node, php.StaticMethodCall): class_ = node.class_ if class_ == 'self': class_ = 'cls' args, kwargs = build_args(node.params) return py.Call( py.Attribute(py.Name(class_, py.Load(**pos(node)), **pos(node)), node.name, py.Load(**pos(node)), **pos(node)), args, kwargs, None, None, **pos(node)) if isinstance(node, php.StaticProperty): class_ = node.node name = node.name if isinstance(name, php.Variable): name = name.name[1:] return py.Attribute(py.Name(class_, py.Load(**pos(node)), **pos(node)), name, py.Load(**pos(node)), **pos(node)) return py.Call(py.Name('XXX', py.Load(**pos(node)), **pos(node)), [py.Str(str(node), **pos(node))], [], None, None, **pos(node))