示例#1
0
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
示例#2
0
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)
示例#3
0
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)
示例#4
0
        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
示例#5
0
    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