我们从Python开源项目中,提取了以下50个代码示例,用于说明如何使用ast.FunctionDef()。
def get_contracts_and_defs_and_globals(code): _contracts = {} _events = [] _globals = {} _defs = [] _getters = [] for item in code: # Contract references if isinstance(item, ast.ClassDef): if _events or _globals or _defs: raise StructureException("External contract declarations must come before event declarations, global declarations, and function definitions", item) _contracts[item.name] = add_contract(item.body) # Statements of the form: # variable_name: type elif isinstance(item, ast.AnnAssign): _contracts, _events, _globals, _getters = add_globals_and_events(_contracts, _defs, _events, _getters, _globals, item) # Function definitions elif isinstance(item, ast.FunctionDef): _defs.append(item) else: raise StructureException("Invalid top-level statement", item) return _contracts, _events, _defs + _getters, _globals # Header code
def visit_Call(self, node): _id = get_call_names_as_string(node.func) self.function_return_stack.append(_id) logging.debug(_id) ast_node = None local_definitions = self.module_definitions_stack[-1] definition = local_definitions.get_definition(_id) if definition: if isinstance(definition.node, ast.ClassDef): init = local_definitions.get_definition(_id + '.__init__') self.add_builtin(node) elif isinstance(definition.node, ast.FunctionDef): self.undecided = False return self.add_function(node, definition) else: raise Exception('Definition was neither FunctionDef or ClassDef, cannot add the function ') return self.add_builtin(node)
def createNameMap(a, d=None): if d == None: d = { } if not isinstance(a, ast.AST): return d if type(a) == ast.Module: # Need to go through the functions backwards to make this right for i in range(len(a.body) - 1, -1, -1): createNameMap(a.body[i], d) return d if type(a) in [ast.FunctionDef, ast.ClassDef]: if hasattr(a, "originalId") and a.name not in d: d[a.name] = a.originalId elif type(a) == ast.arg: if hasattr(a, "originalId") and a.arg not in d: d[a.arg] = a.originalId return d elif type(a) == ast.Name: if hasattr(a, "originalId") and a.id not in d: d[a.id] = a.originalId return d for child in ast.iter_child_nodes(a): createNameMap(child, d) return d
def occursIn(sub, super): """Does the first AST occur as a subtree of the second?""" superStatementTypes = [ ast.Module, ast.Interactive, ast.Suite, ast.FunctionDef, ast.ClassDef, ast.For, ast.While, ast.If, ast.With, ast.Try, ast.ExceptHandler ] if (not isinstance(super, ast.AST)): return False if type(sub) == type(super) and compareASTs(sub, super, checkEquality=True) == 0: return True # we know that a statement can never occur in an expression # (or in a non-statement-holding statement), so cut the search off now to save time. if isStatement(sub) and type(super) not in superStatementTypes: return False for child in ast.iter_child_nodes(super): if occursIn(sub, child): return True return False
def getAllGlobalNames(a): # Finds all names that can be accessed at the global level in the AST if type(a) != ast.Module: return [] names = [] for obj in a.body: if type(obj) in [ast.FunctionDef, ast.ClassDef]: names.append(obj.name) elif type(obj) in [ast.Assign, ast.AugAssign]: targets = obj.targets if type(obj) == ast.Assign else [obj.target] for target in obj.targets: if type(target) == ast.Name: names.append(target.id) elif type(target) in [ast.Tuple, ast.List]: for elt in target.elts: if type(elt) == ast.Name: names.append(elt.id) elif type(obj) in [ast.Import, ast.ImportFrom]: for module in obj.names: names.append(module.asname if module.asname != None else module.name) return names
def isDefault(a): """Our programs have a default setting of return 42, so we should detect that""" if type(a) == ast.Module and len(a.body) == 1: a = a.body[0] else: return False if type(a) != ast.FunctionDef: return False if len(a.body) == 0: return True elif len(a.body) == 1: if type(a.body[0]) == ast.Return: if a.body[0].value == None or \ type(a.body[0].value) == ast.Num and a.body[0].value.n == 42: return True return False
def varse(node): vv = VarsVisitor() if isinstance(node.ast_node, ast.FunctionDef) or\ isinstance(node.ast_node, ast.ClassDef): return list() elif isinstance(node.ast_node, ast.While)\ or isinstance(node.ast_node, ast.If): vv.visit(node.ast_node.test) else: try: vv.visit(node.ast_node) except AttributeError: return list() if isinstance(node, AssignmentNode): result = list() for var in vv.result: if var not in node.left_hand_side: result.append(var) return result else: return vv.result
def visit_Compare(self, node): """ :type node: _ast.FunctionDef """ is_lambda_def = len(node.ops) == 1\ and type(node.ops[0]) is _ast.Gt \ and (type(node.left) is _ast.Tuple or type(node.left) is _ast.Name) \ and all(map(lambda t: type(t) == _ast.Name, getattr(node.left, 'elts', []))) if not is_lambda_def: return node arguments = _transform_function_arguments(node.left) function_body = node.comparators[0] lambda_ast_transform = ast.Lambda(args=arguments, body=function_body, lineno=node.lineno, col_offset=node.col_offset) return lambda_ast_transform
def match_type(self, typ, node): if typ == 'class': return isinstance(node, ast.ClassDef) if typ == 'def': return isinstance(node, ast.FunctionDef) if typ == 'import': return isinstance(node, (ast.Import, ast.ImportFrom)) if typ == 'assign': return isinstance(node, ast.Assign) if typ == 'attr': return isinstance(node, ast.Attribute) if typ == 'call': if isinstance(node, ast.Call): return True # Python 2.x compatibility return hasattr(ast, 'Print') and isinstance(node, ast.Print)
def _get_module_commands(module): # type: (ast.Module) -> typing.Generator[_EntryPoint, None, None] """Yield all Command objects represented by the python module. Module commands consist of a docopt-style module docstring and a callable Command class. Args: module: An ast.Module object used to retrieve docopt-style commands. Yields: Command objects that represent entry points to append to setup.py. """ cls = next((n for n in module.body if isinstance(n, ast.ClassDef) and n.name == 'Command'), None) if not cls: return methods = (n.name for n in cls.body if isinstance(n, ast.FunctionDef)) if '__call__' not in methods: return docstring = ast.get_docstring(module) for commands, _ in usage.parse_commands(docstring): yield _EntryPoint(commands[0], next(iter(commands[1:]), None), None)
def _get_class_commands(module): # type: (ast.Module) -> typing.Generator[_EntryPoint, None, None] """Yield all Command objects represented by python classes in the module. Class commands are detected by inspecting all callable classes in the module for docopt-style docstrings. Args: module: An ast.Module object used to retrieve docopt-style commands. Yields: Command objects that represent entry points to append to setup.py. """ nodes = (n for n in module.body if isinstance(n, ast.ClassDef)) for cls in nodes: methods = (n.name for n in cls.body if isinstance(n, ast.FunctionDef)) if '__call__' in methods: docstring = ast.get_docstring(cls) for commands, _ in usage.parse_commands(docstring): yield _EntryPoint(commands[0], next(iter(commands[1:]), None), cls.name)
def _get_function_commands(module): # type: (ast.Module) -> typing.Generator[_EntryPoint, None, None] """Yield all Command objects represented by python functions in the module. Function commands consist of all top-level functions that contain docopt-style docstrings. Args: module: An ast.Module object used to retrieve docopt-style commands. Yields: Command objects that represent entry points to append to setup.py. """ nodes = (n for n in module.body if isinstance(n, ast.FunctionDef)) for func in nodes: docstring = ast.get_docstring(func) for commands, _ in usage.parse_commands(docstring): yield _EntryPoint(commands[0], next(iter(commands[1:]), None), func.name)
def run(self): tree = self.tree if self.filename == 'stdin': lines = stdin_utils.stdin_get_value() tree = ast.parse(lines) for statement in ast.walk(tree): for child in ast.iter_child_nodes(statement): child.__flake8_builtins_parent = statement for statement in ast.walk(tree): value = None if isinstance(statement, ast.Assign): value = self.check_assignment(statement) elif isinstance(statement, ast.FunctionDef): value = self.check_function_definition(statement) if value: for line, offset, msg, rtype in value: yield line, offset, msg, rtype
def _fine_property_definition(self, property_name): """Find the lines in the source code that contain this property's name and definition. This function can find both attribute assignments as well as methods/functions. Args: property_name (str): the name of the property to look up in the template definition Returns: tuple: line numbers for the start and end of the attribute definition """ for node in ast.walk(ast.parse(self._source)): if isinstance(node, ast.Assign) and node.targets[0].id == property_name: return node.targets[0].lineno - 1, self._get_node_line_end(node) elif isinstance(node, ast.FunctionDef) and node.name == property_name: return node.lineno - 1, self._get_node_line_end(node) raise ValueError('The requested node could not be found.')
def _is_chalice_view(self, node): # type: (ast.FunctionDef) -> bool # We can certainly improve on this, but this check is more # of a heuristic for the time being. The ideal way to do this # is to infer the Chalice type and ensure the function is # decorated with the Chalice type's route() method. decorator_list = node.decorator_list if not decorator_list: return False for decorator in decorator_list: if isinstance(decorator, ast.Call) and \ isinstance(decorator.func, ast.Attribute): if decorator.func.attr == 'route' and \ decorator.args: return True # For lambda_function and schedule decorator.args # not present. if decorator.func.attr in ('lambda_function', 'schedule'): return True return False
def get_function_return_type(self, function_name, args_type=[]): function = self.functions[function_name] if is_system_function(function_name): return SystemFunction.get_function(function_name).return_type if function is not None: if function.is_args_type_match(args_type): return function.return_type else: raise ParamTypeMismatchError("Function '%s' parameter type is not match", function_name) else: for node in self.module_node.body: if isinstance(node, ast.FunctionDef) and node.name == function_name: generator, return_type = self.analysis_function(node, args_type) self.functions.append(Function(function_name, args_type, return_type, generator)) return return_type return Type.STRING # when function is not exist: string
def visit_FunctionDef(self, node, phase): '''Visitor for AST FunctionDef nodes add relevant information about the node to the context for use in tests which inspect function definitions. Add the function name to the current namespace for all descendants. :param node: The node that is being inspected :return: - ''' self.context['function'] = node qualname = self.namespace + '.' + b_utils.get_func_name(node) name = qualname.split('.')[-1] self.context['qualname'] = qualname self.context['name'] = name # For all child nodes and any tests run, add this function name to # current namespace self.namespace = b_utils.namespace_path_join(self.namespace, name) self.update_scores(self.tester.run_tests(self.context, 'FunctionDef', phase=phase))
def method_could_be_class(node, context, search_classes): if isinstance(node, ast.Call): call_node = node parent = get_top_parent_node(call_node) klass_found = next( (klass for klass in iter_method_classes(parent, call_node, context) if klass in search_classes), None ) return klass_found is not None elif isinstance(node, ast.FunctionDef): klass_node = node.parent if not isinstance(klass_node, ast.ClassDef): # not sure what happened here return False for base_klass in klass_node.bases: base_klass = base_klass.id if base_klass in search_classes: return True if name_is_imported(base_klass, context, search_classes): return True else: raise ValueError('node must be either an ast.Call or ast.FunctionDef instance')
def CONTINUE(self, node): # Walk the tree up until we see a loop (OK), a function or class # definition (not OK), for 'continue', a finally block (not OK), or # the top module scope (not OK) n = node while hasattr(n, 'parent'): n, n_child = n.parent, n if isinstance(n, LOOP_TYPES): # Doesn't apply unless it's in the loop itself if n_child not in n.orelse: return if isinstance(n, (ast.FunctionDef, ast.ClassDef)): break # Handle Try/TryFinally difference in Python < and >= 3.3 if hasattr(n, 'finalbody') and isinstance(node, ast.Continue): if n_child in n.finalbody: self.report(messages.ContinueInFinally, node) return if isinstance(node, ast.Continue): self.report(messages.ContinueOutsideLoop, node) else: # ast.Break self.report(messages.BreakOutsideLoop, node)
def parse_bzl(self, bzl_file): """Extracts documentation for all public macros from the given .bzl file. Args: bzl_file: The .bzl file to extract macro documentation from. """ try: tree = ast.parse(open(bzl_file).read(), bzl_file) self._add_file_docs(tree) for stmt in tree.body: if isinstance(stmt, ast.FunctionDef) and not stmt.name.startswith("_"): self._add_macro_doc(stmt) except IOError as e: # Ignore missing extension print("Failed to parse {0}: {1}".format(bzl_file, e.strerror)) pass
def get_compound_bodies(node): """Returns a list of bodies of a compound statement node. Args: node: AST node. Returns: A list of bodies of the node. If the given node does not represent a compound statement, an empty list is returned. """ if isinstance(node, (ast.Module, ast.FunctionDef, ast.ClassDef, ast.With)): return [node.body] elif isinstance(node, (ast.If, ast.While, ast.For)): return [node.body, node.orelse] elif PY2 and isinstance(node, ast.TryFinally): return [node.body, node.finalbody] elif PY2 and isinstance(node, ast.TryExcept): return [node.body, node.orelse] + [h.body for h in node.handlers] elif PY3 and isinstance(node, ast.Try): return ([node.body, node.orelse, node.finalbody] + [h.body for h in node.handlers]) end return []
def check_methods_per_class(self, **kwargs): """ Inspect the code for too many methods per class. """ try: methods_per_class = kwargs['methods_per_class'] except KeyError: return klass = self.parsed_code.body[0] if not isinstance(klass, ast.ClassDef): return methods = [(node, node.lineno) for node in ast.walk(klass) if isinstance(node, ast.FunctionDef)] try: # Get the last method of the class # and its line number: line_number = methods[-1][1] self.issues[line_number].add( self.code_errors.too_many_methods_per_class( len(methods), methods_per_class ) ) except IndexError: return
def check_arity(self, **kwargs): """ Inspect the code for too many arguments per function/method. """ try: max_arity = kwargs['max_arity'] except KeyError: return node = self.parsed_code.body[0] if not isinstance(node, ast.FunctionDef): return arity = len(node.args.args) if arity > max_arity: line_number = node.lineno self.issues[line_number].add( self.code_errors.too_many_arguments(arity, max_arity) )
def check_lines_per_function(self, **kwargs): """ Inspect the code for too many lines per function/method. """ try: max_lines = kwargs['max_lines_per_function'] except KeyError: return function_definition = self.parsed_code.body[0] if not isinstance(function_definition, ast.FunctionDef): return code_lines = self.code.splitlines()[1:] # Filter out the lines, which do # not consist only of whitespaces: logic_lines = len(list(filter(lambda line: line != re.search('\s+', line).group(), code_lines))) if logic_lines > max_lines: line_number = function_definition.lineno self.issues[line_number].add( self.code_errors.too_many_lines( logic_lines, max_lines) )
def run_call(args, node, process, get_func, **kwargs): # Get function expression if isinstance(node, ast.FunctionDef): # function name func_expr = ast.Name(id=node.name, ctx=ast.Load()) elif isinstance(node, ast.Lambda): # lambda body expr func_expr = node else: raise TypeError("Only function definition or lambda may be called") # args is a call string or argument list/dict if isinstance(args, str): parsed = ast.parse(args).body[0].value parsed.func = func_expr ast.fix_missing_locations(parsed) return get_func(process = process, tree = parsed, **kwargs) else: # e.g. list -> {args: [...], kwargs: {}} fmt_args = fix_format(args) ast.fix_missing_locations(func_expr) return get_func(process = process, tree=func_expr, call = fmt_args, **kwargs)
def get_all_filters(): """Return all the available filters""" return ( # TODO: Add ast.Module to the docstring search. DocString('d', 'doc', (ast.FunctionDef, ast.ClassDef, ast.Module), help="Match class and function docstrings."), NameFilter('c', 'class', (ast.ClassDef, ), help="Match class names."), DefFilter('f', 'def', (ast.FunctionDef, ), (ast.AST, ), help="Match all defs."), DefFilter('F', 'function', (ast.FunctionDef, ), (ast.Module, ), help="Match function names at the module level."), DefFilter('m', 'method', (ast.FunctionDef, ), (ast.ClassDef, ), help="Match class method names."), DefFilter('j', 'closure', (ast.FunctionDef, ), (ast.FunctionDef, ), help="Match closure def names."), ImportFilter('i', 'import', (ast.Import, ast.ImportFrom, ), help="Match imported package names."), CallFilter('C', 'call', (ast.Call, ), help="Match call statements."), AttrFilter('a', 'attr', (ast.Attribute, ), help="Match attributes on objects"), )
def _generate_nodes(parent, level=0, breadcrumb=''): nodes = [] for child in parent.body: if isinstance(child, ast.ClassDef): style = OutlineNodeItem.Style.cls elif isinstance(child, ast.FunctionDef): style = OutlineNodeItem.Style.fn else: style = None if style: node = OutlineNodeItem(style, child.name, child.lineno, child.col_offset, level, breadcrumb) nodes.append(node) if breadcrumb: bc = '{} • {}'.format(breadcrumb, child.name) else: bc = child.name child_nodes = OutlineDataSource._generate_nodes(child, level + 1, bc) if child_nodes: nodes.extend(child_nodes) return nodes
def get_coverable_nodes(cls): return { ast.Assert, ast.Assign, ast.AugAssign, ast.Break, ast.Continue, ast.Delete, ast.Expr, ast.Global, ast.Import, ast.ImportFrom, ast.Nonlocal, ast.Pass, ast.Raise, ast.Return, ast.FunctionDef, ast.ClassDef, ast.TryExcept, ast.TryFinally, ast.ExceptHandler, ast.If, ast.For, ast.While, }
def get_coverable_nodes(cls): return { ast.Assert, ast.Assign, ast.AugAssign, ast.Break, ast.Continue, ast.Delete, ast.Expr, ast.Global, ast.Import, ast.ImportFrom, ast.Nonlocal, ast.Pass, ast.Raise, ast.Return, ast.ClassDef, ast.FunctionDef, ast.Try, ast.ExceptHandler, ast.If, ast.For, ast.While, }
def visit_FunctionDef(self, node): """ Called when a FunctionDef node is visited. If decorators are found, record them in self.decorators. Parameters ---------- node : node The node being visited """ self.decorators[node.name] = [] for n in node.decorator_list: name = '' if isinstance(n, ast.Call): name = n.func.attr if isinstance(n.func, ast.Attribute) else n.func.id else: name = n.attr if isinstance(n, ast.Attribute) else n.id self.decorators[node.name].append(name)
def pythoneval(self, args, debug=False): refs = [ast.Name("x{0}".format(i), ast.Load()) for i in xrange(len(args))] if sys.version_info[0] <= 2: params = ast.arguments([ast.Name("x{0}".format(i), ast.Param()) for i in xrange(len(args))], None, None, []) fcn = ast.FunctionDef("tmp", params, [ast.Return(self.pythonast(refs))], []) else: params = ast.arguments([ast.arg("x{0}".format(i), None) for i in xrange(len(args))], None, [], [], None, []) fcn = ast.FunctionDef("tmp", params, [ast.Return(self.pythonast(refs))], [], None) moduleast = ast.Module([fcn]) fakeLineNumbers(moduleast) if debug: print(astToSource(fcn)) modulecomp = compile(moduleast, "Femtocode", "exec") out = {"$importlib": importlib, "$math": math} exec(modulecomp, out) return out["tmp"](*args)
def _pos_in_src(self): """Return the position in source of the generated node.""" py_node = self.node.py_node if py_node: offset = getattr(py_node, 'col_offset', 0) # multi-line comments have an offset of -1 if offset < 0: offset = 0 # special handling of nodes that are decorable. Those nodes expose # a 'lineno' that starts with the first decorator. for now, take # the last decorator lineno and add one if isinstance(py_node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)) and py_node.decorator_list: result = (py_node.decorator_list[-1].lineno + 1, offset) else: result = (getattr(py_node, 'lineno', None), offset) else: result = (None, None) return result
def precheck(self, runner, script, info): # create models dict if nonexistent if getattr(script, 'functionDefs', None) is None: script.functionDefs = {} # create function argument stack if nonexistent if getattr(script, 'functionArgs', None) is None: script.functionArgs = [] # add new function definitions if isinstance(info, ast.FunctionDef): script.functionDefs[info.name] = info script.functionArgs.append(info.args) # update function def dictionary with assignments elif isinstance(info, ast.Assign): if isinstance(info.value, ast.Name): if info.value.id in script.functionDefs: for target in info.targets: if isinstance(target, ast.Name): script.functionDefs[target.id] = script.functionDefs[info.value.id] else: for target in info.targets: if isinstance(target, ast.Name): if target.id in script.functionDefs: del script.functionDefs[target.id]
def run_in_context(code, context, defs={}): ast_ = ast.parse(code, '<code>', 'exec') last_expr = None last_def_name = None for field_ in ast.iter_fields(ast_): if 'body' != field_[0]: continue if len(field_[1]) > 0: le = field_[1][-1] if isinstance(le, ast.Expr): last_expr = ast.Expression() last_expr.body = field_[1].pop().value elif isinstance(le, (ast.FunctionDef, ast.ClassDef)): last_def_name = le.name exec(compile(ast_, '<hbi-code>', 'exec'), context, defs) if last_expr is not None: return eval(compile(last_expr, '<hbi-code>', 'eval'), context, defs) elif last_def_name is not None: return defs[last_def_name] return None
def eval_function_def(function_def, globals_=None, flags=None): """ Evaluates an AST of a function definition with an optional dictionary of globals. Returns a callable function (a ``types.FunctionType`` object). """ assert type(function_def) == ast.FunctionDef # Making a copy before mutating module = ast.Module(body=[copy.deepcopy(function_def)]) ast.fix_missing_locations(module) if flags is not None: kwds = dict(dont_inherit=True, flags=flags) else: kwds = {} code_object = compile(module, '<nofile>', 'exec', **kwds) locals_ = {} eval(code_object, globals_, locals_) return locals_[function_def.name]
def filter_function_def(function_def, bound_argnames): """ Filters a node containing a function definition (an ``ast.FunctionDef`` object) to exclude all arguments with the names present in ``bound_arguments``. Returns the new ``ast.arguments`` node. """ assert type(function_def) == ast.FunctionDef new_args = filter_arguments(function_def.args, bound_argnames) params = dict( name=function_def.name, args=new_args, body=function_def.body, decorator_list=function_def.decorator_list, returns=function_def.returns) return ast.FunctionDef(**params)
def function_from_source(source, globals_=None): """ A helper function to construct a Function object from a source with custom __future__ imports. """ module = ast.parse(unindent(source)) ast.fix_missing_locations(module) for stmt in module.body: if type(stmt) == ast.FunctionDef: tree = stmt name = stmt.name break else: raise ValueError("No function definitions found in the provided source") code_object = compile(module, '<nofile>', 'exec', dont_inherit=True) locals_ = {} eval(code_object, globals_, locals_) function_obj = locals_[name] function_obj._peval_source = astunparse.unparse(tree) return Function.from_object(function_obj)
def translate_FunctionDef(self, ctx, tree): argument_translation = ast.arguments( args=[ ast.Name(id=arg.uniq_id) for arg in tree.args.args ], vararg=None, kwarg=None, defaults=[]) body_block = tree.body_block body_block_translation = body_block.translate_return(ctx) return ast.FunctionDef( name=tree.uniq_id, args=argument_translation, body=body_block_translation, decorator_list=[])
def check_for_b901(self, node): xs = list(node.body) has_yield = False return_node = None while xs: x = xs.pop() if isinstance(x, (ast.AsyncFunctionDef, ast.FunctionDef)): continue elif isinstance(x, (ast.Yield, ast.YieldFrom)): has_yield = True elif isinstance(x, ast.Return) and x.value is not None: return_node = x if has_yield and return_node is not None: self.errors.append( B901(return_node.lineno, return_node.col_offset) ) break xs.extend(ast.iter_child_nodes(x))
def get_object_name(obj): """ Return the name of a given object """ name_dispatch = { ast.Name: "id", ast.Attribute: "attr", ast.Call: "func", ast.FunctionDef: "name", ast.ClassDef: "name", ast.Subscript: "value", } # This is a new ast type in Python 3 if hasattr(ast, "arg"): name_dispatch[ast.arg] = "arg" while not isinstance(obj, str): assert type(obj) in name_dispatch obj = getattr(obj, name_dispatch[type(obj)]) return obj
def add_contract(code): _defs = [] for item in code: # Function definitions if isinstance(item, ast.FunctionDef): _defs.append(item) else: raise StructureException("Invalid contract reference", item) return _defs
def get_func_nodes(self): """Get all nodes from a function.""" return [definition for definition in project_definitions.values() if isinstance(definition.node, ast.FunctionDef)]
def method_to_ast(method: types.MethodType, file: str = None) -> ast.FunctionDef: """ Return node object for method. """ if method and not isinstance(method, types.MethodType): raise TypeError('Unexpected type: {}'.format(str(type(method)))) result = None if method and hasattr(method, '__code__'): result = code_to_ast(method.__code__, file) return result
def ast_to_func(node: ast.AST, old_func: types.FunctionType, file: str = None) -> types.FunctionType: """ Compile node object to function. """ if node and not isinstance(node, (ast.Module, ast.FunctionDef)): raise TypeError('Unexpected type for node: {}'.format(str(type(node)))) if old_func and not isinstance(old_func, types.FunctionType): raise TypeError('Unexpected type for old_func: {}'.format(str(type(old_func)))) result = old_func if node and old_func: old_code = getattr(old_func, '__code__', None) if not isinstance(node, ast.Module): mod_node = ast.copy_location(ast.Module(body = [node]), node) fun_node = node else: mod_node = node fun_node = node.body[0] module = ast_to_code(mod_node, old_code, file=file) for code in module.co_consts: if not isinstance(code, types.CodeType): continue if code.co_name == fun_node.name and code.co_firstlineno == fun_node.lineno: result.__code__ = code break else: raise ValueError('Not specified value') return result
def contains_function(a, problem_name): for line in a.body: if type(line) == ast.FunctionDef and line.name == problem_name: return True return False
def updateVariableNames(a, varMap, scopeName, randomCounter, imports): if not isinstance(a, ast.AST): return if type(a) in [ast.FunctionDef, ast.ClassDef]: if a.name in varMap: if not hasattr(a, "originalId"): a.originalId = a.name a.name = varMap[a.name] anonymizeStatementNames(a, varMap, "_" + a.name, imports) elif type(a) == ast.arg: if a.arg not in varMap and not (builtInName(a.arg) or importedName(a.arg, imports)): log("Can't assign to arg?", "bug") if a.arg in varMap: if not hasattr(a, "originalId"): a.originalId = a.arg if varMap[a.arg][0] == "r": a.randomVar = True # so we know it can crash if a.arg == varMap[a.arg]: # Check whether this is a given name if not isAnonVariable(varMap[a.arg]): a.dontChangeName = True a.arg = varMap[a.arg] elif type(a) == ast.Name: if a.id not in varMap and not (builtInName(a.id) or importedName(a.id, imports)): varMap[a.id] = "r" + str(randomCounter[0]) + scopeName randomCounter[0] += 1 if a.id in varMap: if not hasattr(a, "originalId"): a.originalId = a.id if varMap[a.id][0] == "r": a.randomVar = True # so we know it can crash if a.id == varMap[a.id]: # Check whether this is a given name if not isAnonVariable(varMap[a.id]): a.dontChangeName = True a.id = varMap[a.id] else: for child in ast.iter_child_nodes(a): updateVariableNames(child, varMap, scopeName, randomCounter, imports)
def anonymizeStatementNames(a, globalMap, scopeName, imports, goBackwards=False): """Gather the local variables, then update variable names in each line""" localMap = gatherLocalScope(a, globalMap, scopeName, imports, goBackwards=goBackwards) varMap = { } varMap.update(globalMap) varMap.update(localMap) randomCounter = [0] functionsSeen = [] if type(a) == ast.FunctionDef: for arg in a.args.args: updateVariableNames(arg, varMap, scopeName, randomCounter, imports) for line in a.body: updateVariableNames(line, varMap, scopeName, randomCounter, imports)
def staticVars(l, vars): """Determines whether the given lines change the given variables""" # First, if one of the variables can be modified, there might be a problem mutableVars = [] for var in vars: if (not (hasattr(var, "type") and (var.type in [int, float, str, bool]))): mutableVars.append(var) for i in range(len(l)): if type(l[i]) == ast.Assign: for var in vars: if var.id in allVariableNamesUsed(l[i].targets[0]): return False elif type(l[i]) == ast.AugAssign: for var in vars: if var.id in allVariableNamesUsed(l[i].target): return False elif type(l[i]) in [ast.If, ast.While]: if not (staticVars(l[i].body, vars) and staticVars(l[i].orelse, vars)): return False elif type(l[i]) == ast.For: for var in vars: if var.id in allVariableNamesUsed(l[i].target): return False if not (staticVars(l[i].body, vars) and staticVars(l[i].orelse, vars)): return False elif type(l[i]) in [ast.FunctionDef, ast.ClassDef, ast.Try, ast.With]: log("transformations\tstaticVars\tMissing type: " + str(type(l[i])), "bug") # If a mutable variable is used, we can't trust it for var in mutableVars: if var.id in allVariableNamesUsed(l[i]): return False return True
def isStatement(a): """Determine whether the given node is a statement (vs an expression)""" return type(a) in [ ast.Module, ast.Interactive, ast.Expression, ast.Suite, ast.FunctionDef, ast.ClassDef, ast.Return, ast.Delete, ast.Assign, ast.AugAssign, ast.For, ast.While, ast.If, ast.With, ast.Raise, ast.Try, ast.Assert, ast.Import, ast.ImportFrom, ast.Global, ast.Expr, ast.Pass, ast.Break, ast.Continue ]