def check_statement_information(stmt, search_name): try: commands = stmt.get_commands() # this might be removed if we analyze and, etc assert len(commands) == 1 call = commands[0] assert type(call) == pr.Call and str(call.name) == 'isinstance' assert bool(call.execution) # isinstance check isinst = call.execution.values assert len(isinst) == 2 # has two params obj, classes = [statement.get_commands() for statement in isinst] assert len(obj) == 1 assert len(classes) == 1 assert isinstance(obj[0], pr.Call) # names fit? assert str(obj[0].name) == search_name assert isinstance(classes[0], pr.Call) # can be type or tuple except AssertionError: return [] result = [] for c in evaluate.follow_call(classes[0]): if isinstance(c, er.Array): result += c.get_index_types() else: result.append(c) for i, c in enumerate(result): result[i] = er.Instance(c) return result
def follow_call_path(path, scope, position): """Follows a path generated by `pr.Call.generate_call_path()`""" current = next(path) if isinstance(current, pr.Array): result = [er.Array(current)] else: if isinstance(current, pr.NamePart): # This is the first global lookup. scopes = find_name(scope, current, position=position, search_global=True) else: if current.type in (pr.Call.STRING, pr.Call.NUMBER): t = type(current.name).__name__ scopes = find_name(builtin.Builtin.scope, t) else: debug.warning('unknown type:', current.type, current) scopes = [] # Make instances of those number/string objects. scopes = [er.Instance(s, (current.name, )) for s in scopes] result = imports.strip_imports(scopes) return follow_paths(path, result, scope, position=position)
def follow_call_path(path, scope, position): """Follows a path generated by `pr.StatementElement.generate_call_path()`""" current = next(path) if isinstance(current, pr.Array): result = [er.Array(current)] else: if isinstance(current, pr.NamePart): # This is the first global lookup. scopes = find_name(scope, current, position=position, search_global=True) else: # for pr.Literal scopes = find_name(builtin.Builtin.scope, current.type_as_string()) # Make instances of those number/string objects. scopes = [er.Instance(s, (current.value,)) for s in scopes] result = imports.strip_imports(scopes) return follow_paths(path, result, scope, position=position)
def process(name): """ Returns the parent of a name, which means the element which stands behind a name. """ result = [] no_break_scope = False par = name.parent exc = pr.Class, pr.Function until = lambda: par.parent.parent.get_parent_until(exc) is_array_assignment = False if par is None: pass elif par.isinstance(pr.Flow): if par.command == 'for': result += handle_for_loops(par) else: debug.warning('Flow: Why are you here? %s' % par.command) elif par.isinstance(pr.Param) \ and par.parent is not None \ and isinstance(until(), pr.Class) \ and par.position_nr == 0: # This is where self gets added - this happens at another # place, if the var_args are clear. But sometimes the class is # not known. Therefore add a new instance for self. Otherwise # take the existing. if isinstance(scope, er.InstanceElement): inst = scope.instance else: inst = er.Instance(er.Class(until())) inst.is_generated = True result.append(inst) elif par.isinstance(pr.Statement): def is_execution(calls): for c in calls: if isinstance(c, (unicode, str)): continue if c.isinstance(pr.Array): if is_execution(c): return True elif c.isinstance(pr.Call): # Compare start_pos, because names may be different # because of executions. if c.name.start_pos == name.start_pos \ and c.execution: return True return False is_exe = False for assignee, op in par.assignment_details: is_exe |= is_execution(assignee) if is_exe: # filter array[3] = ... # TODO check executions for dict contents is_array_assignment = True else: details = par.assignment_details if details and details[0][1] != '=': no_break_scope = True # TODO this makes self variables non-breakable. wanted? if isinstance(name, er.InstanceElement) \ and not name.is_class_var: no_break_scope = True result.append(par) else: # TODO multi-level import non-breakable if isinstance(par, pr.Import) and len(par.namespace) > 1: no_break_scope = True result.append(par) return result, no_break_scope, is_array_assignment
def remove_statements(result): """ This is the part where statements are being stripped. Due to lazy evaluation, statements like a = func; b = a; b() have to be evaluated. """ res_new = [] for r in result: add = [] if r.isinstance(pr.Statement): check_instance = None if isinstance(r, er.InstanceElement) and r.is_class_var: check_instance = r.instance r = r.var # Global variables handling. if r.is_global(): for token_name in r.token_list[1:]: if isinstance(token_name, pr.Name): add = find_name(r.parent, str(token_name)) else: # generated objects are used within executions, but these # objects are in functions, and we have to dynamically # execute first. if isinstance(r, pr.Param): func = r.parent # Instances are typically faked, if the instance is not # called from outside. Here we check it for __init__ # functions and return. if isinstance(func, er.InstanceElement) \ and func.instance.is_generated \ and hasattr(func, 'name') \ and str(func.name) == '__init__' \ and r.position_nr > 0: # 0 would be self r = func.var.params[r.position_nr] # add docstring knowledge doc_params = docstrings.follow_param(r) if doc_params: res_new += doc_params continue if not r.is_generated: res_new += dynamic.search_params(r) if not res_new: c = r.get_commands()[0] if c in ('*', '**'): t = 'tuple' if c == '*' else 'dict' res_new = [er.Instance( find_name(builtin.Builtin.scope, t)[0]) ] if not r.assignment_details: # this means that there are no default params, # so just ignore it. continue # Remove the statement docstr stuff for now, that has to be # implemented with the evaluator class. #if r.docstr: #res_new.append(r) scopes = follow_statement(r, seek_name=name_str) add += remove_statements(scopes) if check_instance is not None: # class renames add = [er.InstanceElement(check_instance, a, True) if isinstance(a, (er.Function, pr.Function)) else a for a in add] res_new += add else: if isinstance(r, pr.Class): r = er.Class(r) elif isinstance(r, pr.Function): r = er.Function(r) if r.isinstance(er.Function) and resolve_decorator: r = r.get_decorated_func() res_new.append(r) debug.dbg('sfn remove, new: %s, old: %s' % (res_new, result)) return res_new