Ejemplo n.º 1
0
def _break_check(evaluator, stmt, base_scope, element_scope):
    from jedi.evaluate.representation import wrap
    element_scope = wrap(evaluator, element_scope)
    base_scope = wrap(evaluator, base_scope)

    reachable = REACHABLE
    if isinstance(element_scope, pr.IfStmt):
        if element_scope.node_after_else(stmt):
            for check_node in element_scope.check_nodes():
                reachable = _check_if(evaluator, check_node)
                if reachable in (REACHABLE, UNSURE):
                    break
            reachable = reachable.invert()
        else:
            node = element_scope.node_in_which_check_node(stmt)
            reachable = _check_if(evaluator, node)
    elif isinstance(element_scope, (pr.TryStmt, pr.WhileStmt)):
        return UNSURE

    # Only reachable branches need to be examined further.
    if reachable in (UNREACHABLE, UNSURE):
        return reachable

    if base_scope != element_scope and base_scope != element_scope.parent:
        return reachable & _break_check(evaluator, stmt, base_scope, element_scope.parent)
    return reachable
Ejemplo n.º 2
0
def break_check(evaluator, base_scope, element_scope, origin_scope=None):
    from jedi.evaluate.representation import wrap
    base_scope = wrap(evaluator, base_scope)
    element_scope = wrap(evaluator, element_scope)

    # Direct parents get resolved, we filter scopes that are separate branches.
    # This makes sense for autocompletion and static analysis. For actual
    # Python it doesn't matter, because we're talking about potentially
    # unreachable code.
    s = origin_scope
    while s is not None:
        if element_scope == s:
            return REACHABLE
        s = s.parent

    reachable = REACHABLE
    if isinstance(element_scope, Flow):
        if element_scope.command == 'else':
            check_scope = element_scope
            while check_scope.previous is not None:
                check_scope = check_scope.previous
                reachable = _check_flow(evaluator, check_scope)
                if reachable in (REACHABLE, UNSURE):
                    break
            reachable = reachable.invert()
        else:
            reachable = _check_flow(evaluator, element_scope)

    # Only reachable branches need to be examined further.
    if reachable in (UNREACHABLE, UNSURE):
        return reachable

    if base_scope != element_scope and base_scope != element_scope.parent:
        return reachable & break_check(evaluator, base_scope, element_scope.parent)
    return reachable
Ejemplo n.º 3
0
def _break_check(evaluator, stmt, base_scope, element_scope):
    from jedi.evaluate.representation import wrap
    element_scope = wrap(evaluator, element_scope)
    base_scope = wrap(evaluator, base_scope)

    reachable = REACHABLE
    if isinstance(element_scope, pr.IfStmt):
        if element_scope.node_after_else(stmt):
            for check_node in element_scope.check_nodes():
                reachable = _check_if(evaluator, check_node)
                if reachable in (REACHABLE, UNSURE):
                    break
            reachable = reachable.invert()
        else:
            node = element_scope.node_in_which_check_node(stmt)
            reachable = _check_if(evaluator, node)
    elif isinstance(element_scope, (pr.TryStmt, pr.WhileStmt)):
        return UNSURE

    # Only reachable branches need to be examined further.
    if reachable in (UNREACHABLE, UNSURE):
        return reachable

    if base_scope != element_scope and base_scope != element_scope.parent:
        return reachable & _break_check(evaluator, stmt, base_scope,
                                        element_scope.parent)
    return reachable
Ejemplo n.º 4
0
    def _simple_complete(self, path, dot, like):
        if not path and not dot:
            scope = self._parser.user_scope()
            if not scope.is_scope():  # Might be a flow (if/while/etc).
                scope = scope.get_parent_scope()
            names_dicts = global_names_dict_generator(
                self._evaluator, er.wrap(self._evaluator, scope), self._pos)
            completion_names = []
            for names_dict, pos in names_dicts:
                names = list(chain.from_iterable(names_dict.values()))
                if not names:
                    continue
                completion_names += filter_definition_names(
                    names, self._parser.user_stmt(), pos)
        elif self._get_under_cursor_stmt(path) is None:
            return []
        else:
            scopes = list(self._prepare_goto(path, True))
            completion_names = []
            debug.dbg('possible completion scopes: %s', scopes)
            for s in scopes:
                names = []
                for names_dict in s.names_dicts(search_global=False):
                    names += chain.from_iterable(names_dict.values())

                completion_names += filter_definition_names(
                    names, self._parser.user_stmt())
        return completion_names
Ejemplo n.º 5
0
    def eval_statement(self, stmt, seek_name=None):
        """
        The starting point of the completion. A statement always owns a call
        list, which are the calls, that a statement does. In case multiple
        names are defined in the statement, `seek_name` returns the result for
        this name.

        :param stmt: A `pr.ExprStmt`.
        """
        debug.dbg('eval_statement %s (%s)', stmt, seek_name)
        types = self.eval_element(stmt.get_rhs())

        if seek_name:
            types = finder.check_tuple_assignments(types, seek_name)

        first_operation = stmt.first_operation()
        if first_operation not in ('=', None) and not isinstance(stmt, er.InstanceElement):  # TODO don't check for this.
            # `=` is always the last character in aug assignments -> -1
            operator = copy.copy(first_operation)
            operator.value = operator.value[:-1]
            name = str(stmt.get_defined_names()[0])
            parent = er.wrap(self, stmt.get_parent_scope())
            left = self.find_types(parent, name, stmt.start_pos, search_global=True)
            if isinstance(stmt.get_parent_until(pr.ForStmt), pr.ForStmt):
                # Iterate through result and add the values, that's possible
                # only in for loops without clutter, because they are
                # predictable.
                for r in types:
                    left = precedence.calculate(self, left, operator, [r])
                types = left
            else:
                types = precedence.calculate(self, left, operator, types)
        debug.dbg('eval_statement result %s', types)
        return types
Ejemplo n.º 6
0
    def eval_statement(self, stmt, seek_name=None):
        """
        The starting point of the completion. A statement always owns a call
        list, which are the calls, that a statement does. In case multiple
        names are defined in the statement, `seek_name` returns the result for
        this name.

        :param stmt: A `pr.ExprStmt`.
        """
        debug.dbg('eval_statement %s (%s)', stmt, seek_name)
        types = self.eval_element(stmt.get_rhs())

        if seek_name:
            types = finder.check_tuple_assignments(types, seek_name)

        first_operation = stmt.first_operation()
        if first_operation not in ('=', None) and not isinstance(stmt, er.InstanceElement):  # TODO don't check for this.
            # `=` is always the last character in aug assignments -> -1
            operator = copy.copy(first_operation)
            operator.value = operator.value[:-1]
            name = str(stmt.get_defined_names()[0])
            parent = er.wrap(self, stmt.get_parent_scope())
            left = self.find_types(parent, name, stmt.start_pos, search_global=True)
            if isinstance(stmt.get_parent_until(pr.ForStmt), pr.ForStmt):
                # Iterate through result and add the values, that's possible
                # only in for loops without clutter, because they are
                # predictable.
                for r in types:
                    left = precedence.calculate(self, left, operator, [r])
                types = left
            else:
                types = precedence.calculate(self, left, operator, types)
        debug.dbg('eval_statement result %s', types)
        return types
Ejemplo n.º 7
0
    def _simple_complete(self, path, dot, like):
        if not path and not dot:
            scope = self._parser.user_scope()
            if not scope.is_scope():  # Might be a flow (if/while/etc).
                scope = scope.get_parent_scope()
            names_dicts = global_names_dict_generator(
                self._evaluator,
                er.wrap(self._evaluator, scope),
                self._pos
            )
            completion_names = []
            for names_dict, pos in names_dicts:
                names = list(chain.from_iterable(names_dict.values()))
                if not names:
                    continue
                completion_names += filter_definition_names(names, self._parser.user_stmt(), pos)
        elif self._get_under_cursor_stmt(path) is None:
            return []
        else:
            scopes = list(self._prepare_goto(path, True))
            completion_names = []
            debug.dbg('possible completion scopes: %s', scopes)
            for s in scopes:
                names = []
                for names_dict in s.names_dicts(search_global=False):
                    names += chain.from_iterable(names_dict.values())

                completion_names += filter_definition_names(names, self._parser.user_stmt())
        return completion_names
Ejemplo n.º 8
0
    def names_dict_lookup(self, names_dict, position):
        def get_param(scope, el):
            if isinstance(el.get_parent_until(pr.Param), pr.Param):
                return scope.param_by_name(str(el))
            return el

        search_str = str(self.name_str)
        try:
            names = names_dict[search_str]
            if not names:  # We want names, otherwise stop.
                return []
        except KeyError:
            return []

        names = filter_definition_names(names, self.name_str, position)

        name_scope = None
        # Only the names defined in the last position are valid definitions.
        last_names = []
        for name in reversed(sorted(names, key=lambda name: name.start_pos)):
            stmt = name.get_definition()
            name_scope = er.wrap(self._evaluator, stmt.get_parent_scope())

            if isinstance(self.scope, er.Instance) and not isinstance(
                    name_scope, er.Instance):
                # Instances should not be checked for positioning, because we
                # don't know in which order the functions are called.
                last_names.append(name)
                continue

            if isinstance(name_scope, compiled.CompiledObject):
                # Let's test this. TODO need comment. shouldn't this be
                # filtered before?
                last_names.append(name)
                continue

            if isinstance(name, compiled.CompiledName) \
                    or isinstance(name, er.InstanceName) and isinstance(name._origin_name, compiled.CompiledName):
                last_names.append(name)
                continue

            if isinstance(self.name_str, pr.Name):
                origin_scope = self.name_str.get_parent_until(pr.Scope,
                                                              reverse=True)
            else:
                origin_scope = None
            if isinstance(stmt.parent, compiled.CompiledObject):
                # TODO seriously? this is stupid.
                continue
            check = flow_analysis.break_check(self._evaluator, name_scope,
                                              stmt, origin_scope)
            if check is not flow_analysis.UNREACHABLE:
                last_names.append(name)
            if check is flow_analysis.REACHABLE:
                break

        if isinstance(name_scope, er.FunctionExecution):
            # Replace params
            return [get_param(name_scope, n) for n in last_names]
        return last_names
Ejemplo n.º 9
0
Archivo: finder.py Proyecto: Axure/jedi
    def names_dict_lookup(self, names_dict, position):
        def get_param(scope, el):
            if isinstance(el.get_parent_until(pr.Param), pr.Param):
                return scope.param_by_name(str(el))
            return el

        search_str = str(self.name_str)
        try:
            names = names_dict[search_str]
            if not names:  # We want names, otherwise stop.
                return []
        except KeyError:
            return []

        names = filter_definition_names(names, self.name_str, position)

        name_scope = None
        # Only the names defined in the last position are valid definitions.
        last_names = []
        for name in reversed(sorted(names, key=lambda name: name.start_pos)):
            stmt = name.get_definition()
            name_scope = er.wrap(self._evaluator, stmt.get_parent_scope())

            if isinstance(self.scope, er.Instance) and not isinstance(name_scope, er.Instance):
                # Instances should not be checked for positioning, because we
                # don't know in which order the functions are called.
                last_names.append(name)
                continue

            if isinstance(name_scope, compiled.CompiledObject):
                # Let's test this. TODO need comment. shouldn't this be
                # filtered before?
                last_names.append(name)
                continue

            if isinstance(name, compiled.CompiledName) \
                    or isinstance(name, er.InstanceName) and isinstance(name._origin_name, compiled.CompiledName):
                last_names.append(name)
                continue

            if isinstance(self.name_str, pr.Name):
                origin_scope = self.name_str.get_parent_until(pr.Scope, reverse=True)
            else:
                origin_scope = None
            if isinstance(stmt.parent, compiled.CompiledObject):
                # TODO seriously? this is stupid.
                continue
            check = flow_analysis.break_check(self._evaluator, name_scope,
                                              stmt, origin_scope)
            if check is not flow_analysis.UNREACHABLE:
                last_names.append(name)
            if check is flow_analysis.REACHABLE:
                break

        if isinstance(name_scope, er.FunctionExecution):
            # Replace params
            return [get_param(name_scope, n) for n in last_names]
        return last_names
Ejemplo n.º 10
0
 def _clean_names(self, names):
     """
     ``NameFinder.filter_name`` should only output names with correct
     wrapper parents. We don't want to see AST classes out in the
     evaluation, so remove them already here!
     """
     for n in names:
         definition = n.parent
         if isinstance(definition, (pr.Function, pr.Class, pr.Module)):
             yield er.wrap(self._evaluator, definition).name
         else:
             yield n
Ejemplo n.º 11
0
 def _clean_names(self, names):
     """
     ``NameFinder.filter_name`` should only output names with correct
     wrapper parents. We don't want to see AST classes out in the
     evaluation, so remove them already here!
     """
     for n in names:
         definition = n.parent
         if isinstance(definition, (pr.Function, pr.Class, pr.Module)):
             yield er.wrap(self._evaluator, definition).name
         else:
             yield n
Ejemplo n.º 12
0
def break_check(evaluator, base_scope, stmt, origin_scope=None):
    from jedi.evaluate.representation import wrap
    element_scope = wrap(evaluator, stmt.get_parent_scope(include_flows=True))
    # Direct parents get resolved, we filter scopes that are separate branches.
    # This makes sense for autocompletion and static analysis. For actual
    # Python it doesn't matter, because we're talking about potentially
    # unreachable code.
    # e.g. `if 0:` would cause all name lookup within the flow make
    # unaccessible. This is not a "problem" in Python, because the code is
    # never called. In Jedi though, we still want to infer types.
    while origin_scope is not None:
        if element_scope == origin_scope:
            return REACHABLE
        origin_scope = origin_scope.parent
    return _break_check(evaluator, stmt, base_scope, element_scope)
Ejemplo n.º 13
0
def break_check(evaluator, base_scope, stmt, origin_scope=None):
    from jedi.evaluate.representation import wrap
    element_scope = wrap(evaluator, stmt.get_parent_scope(include_flows=True))
    # Direct parents get resolved, we filter scopes that are separate branches.
    # This makes sense for autocompletion and static analysis. For actual
    # Python it doesn't matter, because we're talking about potentially
    # unreachable code.
    # e.g. `if 0:` would cause all name lookup within the flow make
    # unaccessible. This is not a "problem" in Python, because the code is
    # never called. In Jedi though, we still want to infer types.
    while origin_scope is not None:
        if element_scope == origin_scope:
            return REACHABLE
        origin_scope = origin_scope.parent
    return _break_check(evaluator, stmt, base_scope, element_scope)
Ejemplo n.º 14
0
    def goto_definitions(self):
        """
        Return the definitions of a the path under the cursor.  goto function!
        This follows complicated paths and returns the end, not the first
        definition. The big difference between :meth:`goto_assignments` and
        :meth:`goto_definitions` is that :meth:`goto_assignments` doesn't
        follow imports and statements. Multiple objects may be returned,
        because Python itself is a dynamic language, which means depending on
        an option you can have two different versions of a function.

        :rtype: list of :class:`classes.Definition`
        """
        def resolve_import_paths(scopes):
            for s in scopes.copy():
                if isinstance(s, imports.ImportWrapper):
                    scopes.remove(s)
                    scopes.update(resolve_import_paths(set(s.follow())))
            return scopes

        goto_path = self._user_context.get_path_under_cursor()
        context = self._user_context.get_context()
        definitions = set()
        if next(context) in ('class', 'def'):
            definitions = set(
                [er.wrap(self._evaluator, self._parser.user_scope())])
        else:
            # Fetch definition of callee, if there's no path otherwise.
            if not goto_path:
                definitions = set(signature._definition
                                  for signature in self.call_signatures())

        if re.match('\w[\w\d_]*$', goto_path) and not definitions:
            user_stmt = self._parser.user_stmt()
            if user_stmt is not None and user_stmt.type == 'expr_stmt':
                for name in user_stmt.get_defined_names():
                    if name.start_pos <= self._pos <= name.end_pos:
                        # TODO scaning for a name and then using it should be
                        # the default.
                        definitions = set(
                            self._evaluator.goto_definition(name))

        if not definitions and goto_path:
            definitions = set(self._prepare_goto(goto_path))

        definitions = resolve_import_paths(definitions)
        names = [s.name for s in definitions]
        defs = [classes.Definition(self._evaluator, name) for name in names]
        return helpers.sorted_definitions(set(defs))
Ejemplo n.º 15
0
    def __init__(self, evaluator, name):
        self._evaluator = evaluator
        self._name = name
        """
        An instance of :class:`jedi.parser.reprsentation.Name` subclass.
        """
        self._definition = er.wrap(evaluator, self._name.get_definition())
        self.is_keyword = isinstance(self._definition, keywords.Keyword)

        # generate a path to the definition
        self._module = name.get_parent_until()
        if self.in_builtin_module():
            self.module_path = None
        else:
            self.module_path = self._module.path
            """Shows the file path of a module. e.g. ``/usr/lib/python2.7/os.py``"""
Ejemplo n.º 16
0
    def __init__(self, evaluator, name):
        self._evaluator = evaluator
        self._name = name
        """
        An instance of :class:`jedi.parser.reprsentation.Name` subclass.
        """
        self._definition = er.wrap(evaluator, self._name.get_definition())
        self.is_keyword = isinstance(self._definition, keywords.Keyword)

        # generate a path to the definition
        self._module = name.get_parent_until()
        if self.in_builtin_module():
            self.module_path = None
        else:
            self.module_path = self._module.path
            """Shows the file path of a module. e.g. ``/usr/lib/python2.7/os.py``"""
Ejemplo n.º 17
0
    def goto_definitions(self):
        """
        Return the definitions of a the path under the cursor.  goto function!
        This follows complicated paths and returns the end, not the first
        definition. The big difference between :meth:`goto_assignments` and
        :meth:`goto_definitions` is that :meth:`goto_assignments` doesn't
        follow imports and statements. Multiple objects may be returned,
        because Python itself is a dynamic language, which means depending on
        an option you can have two different versions of a function.

        :rtype: list of :class:`classes.Definition`
        """
        def resolve_import_paths(scopes):
            for s in scopes.copy():
                if isinstance(s, imports.ImportWrapper):
                    scopes.remove(s)
                    scopes.update(resolve_import_paths(set(s.follow())))
            return scopes

        goto_path = self._user_context.get_path_under_cursor()
        context = self._user_context.get_context()
        definitions = set()
        if next(context) in ('class', 'def'):
            definitions = set([er.wrap(self._evaluator, self._parser.user_scope())])
        else:
            # Fetch definition of callee, if there's no path otherwise.
            if not goto_path:
                definitions = set(signature._definition
                                  for signature in self.call_signatures())

        if re.match('\w[\w\d_]*$', goto_path) and not definitions:
            user_stmt = self._parser.user_stmt()
            if user_stmt is not None and user_stmt.type == 'expr_stmt':
                for name in user_stmt.get_defined_names():
                    if name.start_pos <= self._pos <= name.end_pos:
                        # TODO scaning for a name and then using it should be
                        # the default.
                        definitions = set(self._evaluator.goto_definition(name))

        if not definitions and goto_path:
            definitions = set(self._prepare_goto(goto_path))

        definitions = resolve_import_paths(definitions)
        names = [s.name for s in definitions]
        defs = [classes.Definition(self._evaluator, name) for name in names]
        return helpers.sorted_definitions(set(defs))
Ejemplo n.º 18
0
def _eval_param(evaluator, param, scope):
    res_new = []
    func = param.get_parent_scope()

    cls = func.parent.get_parent_until((pr.Class, pr.Function))

    from jedi.evaluate.param import ExecutedParam, Arguments
    if isinstance(cls, pr.Class) and param.position_nr == 0 \
            and not isinstance(param, ExecutedParam):
        # This is where we add self - if it has never been
        # instantiated.
        if isinstance(scope, er.InstanceElement):
            res_new.append(scope.instance)
        else:
            inst = er.Instance(evaluator,
                               er.wrap(evaluator, cls),
                               Arguments(evaluator, ()),
                               is_generated=True)
            res_new.append(inst)
        return res_new

    # 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 str(func.name) == '__init__':
        param = func.var.params[param.position_nr]

    # Add docstring knowledge.
    doc_params = docstrings.follow_param(evaluator, param)
    if doc_params:
        return doc_params

    if isinstance(param, ExecutedParam):
        return res_new + param.eval(evaluator)
    else:
        # Param owns no information itself.
        res_new += dynamic.search_params(evaluator, param)
        if not res_new:
            if param.stars:
                t = 'tuple' if param.stars == 1 else 'dict'
                typ = evaluator.find_types(compiled.builtin, t)[0]
                res_new = evaluator.execute(typ)
        if param.default:
            res_new += evaluator.eval_element(param.default)
        return res_new
Ejemplo n.º 19
0
        def get_posibilities(evaluator, module, func_name):
            try:
                names = module.used_names[func_name]
            except KeyError:
                return []

            for name in names:
                stmt = name.get_definition()
                if not isinstance(stmt,
                                  (pr.ExprStmt, pr.CompFor, pr.ReturnStmt)):
                    continue
                parent = name.parent
                if pr.is_node(parent, 'trailer'):
                    parent = parent.parent

                trailer = None
                if pr.is_node(parent, 'power'):
                    for t in parent.children[1:]:
                        if t == '**':
                            break
                        if t.start_pos > name.start_pos and t.children[
                                0] == '(':
                            trailer = t
                            break
                if trailer is not None:
                    types = evaluator.goto_definition(name)

                    # We have to remove decorators, because they are not the
                    # "original" functions, this way we can easily compare.
                    # At the same time we also have to remove InstanceElements.
                    undec = []
                    for escope in types:
                        if escope.isinstance(er.Function, er.Instance) \
                                and escope.decorates is not None:
                            undec.append(escope.decorates)
                        elif isinstance(escope, er.InstanceElement):
                            undec.append(escope.var)
                        else:
                            undec.append(escope)

                    if er.wrap(evaluator, compare) in undec:
                        # Only if we have the correct function we execute
                        # it, otherwise just ignore it.
                        evaluator.eval_trailer(types, trailer)
            return listener.param_possibilities
Ejemplo n.º 20
0
Archivo: finder.py Proyecto: Axure/jedi
def _eval_param(evaluator, param, scope):
    res_new = []
    func = param.get_parent_scope()

    cls = func.parent.get_parent_until((pr.Class, pr.Function))

    from jedi.evaluate.param import ExecutedParam, Arguments
    if isinstance(cls, pr.Class) and param.position_nr == 0 \
            and not isinstance(param, ExecutedParam):
        # This is where we add self - if it has never been
        # instantiated.
        if isinstance(scope, er.InstanceElement):
            res_new.append(scope.instance)
        else:
            inst = er.Instance(evaluator, er.wrap(evaluator, cls),
                               Arguments(evaluator, ()), is_generated=True)
            res_new.append(inst)
        return res_new

    # 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 str(func.name) == '__init__':
        param = func.var.params[param.position_nr]

    # Add docstring knowledge.
    doc_params = docstrings.follow_param(evaluator, param)
    if doc_params:
        return doc_params

    if isinstance(param, ExecutedParam):
        return res_new + param.eval(evaluator)
    else:
        # Param owns no information itself.
        res_new += dynamic.search_params(evaluator, param)
        if not res_new:
            if param.stars:
                t = 'tuple' if param.stars == 1 else 'dict'
                typ = evaluator.find_types(compiled.builtin, t)[0]
                res_new = evaluator.execute(typ)
        if param.default:
            res_new += evaluator.eval_element(param.default)
        return res_new
Ejemplo n.º 21
0
    def goto_definitions(self):
        """
        Return the definitions of a the path under the cursor.  goto function!
        This follows complicated paths and returns the end, not the first
        definition. The big difference between :meth:`goto_assignments` and
        :meth:`goto_definitions` is that :meth:`goto_assignments` doesn't
        follow imports and statements. Multiple objects may be returned,
        because Python itself is a dynamic language, which means depending on
        an option you can have two different versions of a function.

        :rtype: list of :class:`classes.Definition`
        """
        def resolve_import_paths(scopes):
            for s in scopes.copy():
                if isinstance(s, imports.ImportWrapper):
                    scopes.remove(s)
                    scopes.update(resolve_import_paths(set(s.follow())))
            return scopes

        user_stmt = self._parser.user_stmt_with_whitespace()
        goto_path = self._user_context.get_path_under_cursor()
        context = self._user_context.get_context()
        definitions = set()
        if next(context) in ('class', 'def'):
            definitions = set([er.wrap(self._evaluator, self._parser.user_scope())])
        else:
            # Fetch definition of callee, if there's no path otherwise.
            if not goto_path:
                call, _, _ = search_call_signatures(user_stmt, self._pos)
                if call is not None:
                    definitions = set(self._evaluator.eval_call(call))

        if not definitions:
            if goto_path:
                definitions = set(self._prepare_goto(goto_path))

        definitions = resolve_import_paths(definitions)
        names = [s.name for s in definitions
                 if s is not imports.ImportWrapper.GlobalNamespace]
        defs = [classes.Definition(self._evaluator, name) for name in names]
        return helpers.sorted_definitions(set(defs))
Ejemplo n.º 22
0
        def get_posibilities(evaluator, module, func_name):
            try:
                names = module.used_names[func_name]
            except KeyError:
                return []

            for name in names:
                parent = name.parent
                if pr.is_node(parent, 'trailer'):
                    parent = parent.parent

                trailer = None
                if pr.is_node(parent, 'power'):
                    for t in parent.children[1:]:
                        if t == '**':
                            break
                        if t.start_pos > name.start_pos and t.children[0] == '(':
                            trailer = t
                            break
                if trailer is not None:
                    types = evaluator.goto_definition(name)

                    # We have to remove decorators, because they are not the
                    # "original" functions, this way we can easily compare.
                    # At the same time we also have to remove InstanceElements.
                    undec = []
                    for escope in types:
                        if escope.isinstance(er.Function, er.Instance) \
                                and escope.decorates is not None:
                            undec.append(escope.decorates)
                        elif isinstance(escope, er.InstanceElement):
                            undec.append(escope.var)
                        else:
                            undec.append(escope)

                    if er.wrap(evaluator, compare) in undec:
                        # Only if we have the correct function we execute
                        # it, otherwise just ignore it.
                        evaluator.eval_trailer(types, trailer)
            return listener.param_possibilities
Ejemplo n.º 23
0
    def completions(self):
        """
        Return :class:`classes.Completion` objects. Those objects contain
        information about the completions, more than just names.

        :return: Completion objects, sorted by name and __ comes last.
        :rtype: list of :class:`classes.Completion`
        """
        def get_completions(user_stmt, bs):
            if isinstance(user_stmt, pr.Import):
                context = self._user_context.get_context()
                next(context)  # skip the path
                if next(context) == 'from':
                    # completion is just "import" if before stands from ..
                    return ((k, bs) for k in keywords.keyword_names('import'))
            return self._simple_complete(path, like)

        def completion_possible(path):
            """
            The completion logic is kind of complicated, because we strip the
            last word part. To ignore certain strange patterns with dots, just
            use regex.
            """
            if re.match('\d+\.\.$|\.{4}$', path):
                return True  # check Ellipsis and float literal `1.`

            return not re.search(r'^\.|^\d\.$|\.\.$', path)

        debug.speed('completions start')
        path = self._user_context.get_path_until_cursor()
        if not completion_possible(path):
            return []
        path, dot, like = helpers.completion_parts(path)

        user_stmt = self._parser.user_stmt_with_whitespace()
        b = compiled.builtin
        completions = get_completions(user_stmt, b)

        if not dot:
            # add named params
            for call_sig in self.call_signatures():
                # Allow protected access, because it's a public API.
                module = call_sig._name.get_parent_until()
                # Compiled modules typically don't allow keyword arguments.
                if not isinstance(module, compiled.CompiledObject):
                    for p in call_sig.params:
                        # Allow access on _definition here, because it's a
                        # public API and we don't want to make the internal
                        # Name object public.
                        if p._definition.stars == 0:  # no *args/**kwargs
                            completions.append((p._name, p._name))

            if not path and not isinstance(user_stmt, pr.Import):
                # add keywords
                completions += ((k, b) for k in keywords.keyword_names(all=True))

        needs_dot = not dot and path

        comps = []
        comp_dct = {}
        for c, s in set(completions):
            n = str(c)
            if settings.case_insensitive_completion \
                    and n.lower().startswith(like.lower()) \
                    or n.startswith(like):
                if not filter_private_variable(s, user_stmt or self._parser.user_scope(), n):
                    if isinstance(c.parent, (pr.Function, pr.Class)):
                        # TODO I think this is a hack. It should be an
                        #   er.Function/er.Class before that.
                        c = er.wrap(self._evaluator, c.parent).name
                    new = classes.Completion(self._evaluator, c, needs_dot, len(like), s)
                    k = (new.name, new.complete)  # key
                    if k in comp_dct and settings.no_completion_duplicates:
                        comp_dct[k]._same_name_completions.append(new)
                    else:
                        comp_dct[k] = new
                        comps.append(new)

        debug.speed('completions end')

        return sorted(comps, key=lambda x: (x.name.startswith('__'),
                                            x.name.startswith('_'),
                                            x.name.lower()))
Ejemplo n.º 24
0
    def completion_names(self, evaluator, only_modules=False):
        """
        :param only_modules: Indicates wheter it's possible to import a
            definition that is not defined in a module.
        """
        from jedi.evaluate import finder, representation as er
        names = []
        if self.import_path:
            # flask
            if self.str_import_path == ('flask', 'ext'):
                # List Flask extensions like ``flask_foo``
                for mod in self._get_module_names():
                    modname = str(mod)
                    if modname.startswith('flask_'):
                        extname = modname[len('flask_'):]
                        names.append(self._generate_name(extname))
                # Now the old style: ``flaskext.foo``
                for dir in self.sys_path_with_modifications():
                    flaskext = os.path.join(dir, 'flaskext')
                    if os.path.isdir(flaskext):
                        names += self._get_module_names([flaskext])

            for scope in self.follow(evaluator):
                # Non-modules are not completable.
                if not scope.type == 'file_input':  # not a module
                    continue

                # namespace packages
                if isinstance(scope, pr.Module) and scope.path.endswith('__init__.py'):
                    pkg_path = os.path.dirname(scope.path)
                    paths = self.namespace_packages(pkg_path, self.import_path)
                    names += self._get_module_names([pkg_path] + paths)

                if only_modules:
                    # In the case of an import like `from x.` we don't need to
                    # add all the variables.
                    if ('os',) == self.str_import_path and not self.level:
                        # os.path is a hardcoded exception, because it's a
                        # ``sys.modules`` modification.
                        names.append(self._generate_name('path'))

                    continue

                for names_dict in scope.names_dicts(search_global=False):
                    _names = list(chain.from_iterable(names_dict.values()))
                    if not _names:
                        continue
                    _names = finder.filter_definition_names(_names, scope)
                    names += _names
        else:
            # Empty import path=completion after import
            if not self.level:
                names += self._get_module_names()

            if self.file_path is not None:
                path = os.path.abspath(self.file_path)
                for i in range(self.level - 1):
                    path = os.path.dirname(path)
                names += self._get_module_names([path])

                if self.level:
                    rel_path = os.path.join(self.get_relative_path(),
                                            '__init__.py')
                    if os.path.exists(rel_path):
                        module = _load_module(self._evaluator, rel_path)
                        module = er.wrap(self._evaluator, module)
                        for names_dict in module.names_dicts(search_global=False):
                            names += chain.from_iterable(names_dict.values())
        return names
Ejemplo n.º 25
0
    def parent(self):
        """
        Creating fake statements for the interpreter.
        """
        obj = self._value
        parser_path = []
        if inspect.ismodule(obj):
            module = obj
        else:
            names = []
            try:
                o = obj.__objclass__
                names.append(obj.__name__)
                obj = o
            except AttributeError:
                pass

            try:
                module_name = obj.__module__
                names.insert(0, obj.__name__)
            except AttributeError:
                # Unfortunately in some cases like `int` there's no __module__
                module = builtins
            else:
                # TODO this import is wrong. Yields x for x.y.z instead of z
                module = __import__(module_name)
            parser_path = names
        raw_module = get_module(self._value)

        found = []
        try:
            path = module.__file__
        except AttributeError:
            pass
        else:
            path = re.sub('c$', '', path)
            if path.endswith('.py'):
                # cut the `c` from `.pyc`
                with open(path) as f:
                    source = source_to_unicode(f.read())
                mod = FastParser(load_grammar(), source, path[:-1]).module
                if parser_path:
                    assert len(parser_path) == 1
                    found = self._evaluator.find_types(mod, parser_path[0], search_global=True)
                else:
                    found = [er.wrap(self._evaluator, mod)]

                if not found:
                    debug.warning('Possibly an interpreter lookup for Python code failed %s',
                                  parser_path)

        if not found:
            evaluated = compiled.CompiledObject(obj)
            if evaluated == builtins:
                # The builtins module is special and always cached.
                evaluated = compiled.builtin
            found = [evaluated]

        content = iterable.AlreadyEvaluated(found)
        stmt = pt.ExprStmt([self, pt.Operator(pt.zero_position_modifier,
                                              '=', (0, 0), ''), content])
        stmt.parent = self._module
        return stmt
Ejemplo n.º 26
0
    def completions(self):
        """
        Return :class:`classes.Completion` objects. Those objects contain
        information about the completions, more than just names.

        :return: Completion objects, sorted by name and __ comes last.
        :rtype: list of :class:`classes.Completion`
        """
        def get_completions(user_stmt, bs):
            # TODO this closure is ugly. it also doesn't work with
            # simple_complete (used for Interpreter), somehow redo.
            module = self._parser.module()
            names, level, only_modules, unfinished_dotted = \
                helpers.check_error_statements(module, self._pos)
            completion_names = []
            if names is not None:
                imp_names = [n for n in names if n.end_pos < self._pos]
                i = imports.get_importer(self._evaluator, imp_names, module, level)
                completion_names = i.completion_names(self._evaluator, only_modules)

            # TODO this paragraph is necessary, but not sure it works.
            context = self._user_context.get_context()
            if not next(context).startswith('.'):  # skip the path
                if next(context) == 'from':
                    # completion is just "import" if before stands from ..
                    if unfinished_dotted:
                        return completion_names
                    else:
                        return keywords.keyword_names('import')

            if isinstance(user_stmt, pr.Import):
                module = self._parser.module()
                completion_names += imports.completion_names(self._evaluator,
                                                             user_stmt, self._pos)
                return completion_names

            if names is None and not isinstance(user_stmt, pr.Import):
                if not path and not dot:
                    # add keywords
                    completion_names += keywords.keyword_names(all=True)
                    # TODO delete? We should search for valid parser
                    # transformations.
                completion_names += self._simple_complete(path, dot, like)
            return completion_names

        debug.speed('completions start')
        path = self._user_context.get_path_until_cursor()
        # Dots following an int are not the start of a completion but a float
        # literal.
        if re.search(r'^\d\.$', path):
            return []
        path, dot, like = helpers.completion_parts(path)

        user_stmt = self._parser.user_stmt_with_whitespace()

        b = compiled.builtin
        completion_names = get_completions(user_stmt, b)

        if not dot:
            # add named params
            for call_sig in self.call_signatures():
                # Allow protected access, because it's a public API.
                module = call_sig._name.get_parent_until()
                # Compiled modules typically don't allow keyword arguments.
                if not isinstance(module, compiled.CompiledObject):
                    for p in call_sig.params:
                        # Allow access on _definition here, because it's a
                        # public API and we don't want to make the internal
                        # Name object public.
                        if p._definition.stars == 0:  # no *args/**kwargs
                            completion_names.append(p._name)

        needs_dot = not dot and path

        comps = []
        comp_dct = {}
        for c in set(completion_names):
            n = str(c)
            if settings.case_insensitive_completion \
                    and n.lower().startswith(like.lower()) \
                    or n.startswith(like):
                if isinstance(c.parent, (pr.Function, pr.Class)):
                    # TODO I think this is a hack. It should be an
                    #   er.Function/er.Class before that.
                    c = er.wrap(self._evaluator, c.parent).name
                new = classes.Completion(self._evaluator, c, needs_dot, len(like))
                k = (new.name, new.complete)  # key
                if k in comp_dct and settings.no_completion_duplicates:
                    comp_dct[k]._same_name_completions.append(new)
                else:
                    comp_dct[k] = new
                    comps.append(new)

        debug.speed('completions end')

        return sorted(comps, key=lambda x: (x.name.startswith('__'),
                                            x.name.startswith('_'),
                                            x.name.lower()))
Ejemplo n.º 27
0
Archivo: finder.py Proyecto: Axure/jedi
def global_names_dict_generator(evaluator, scope, position):
    """
    For global name lookups. Yields tuples of (names_dict, position). If the
    position is None, the position does not matter anymore in that scope.

    This function is used to include names from outer scopes. For example, when
    the current scope is function:

    >>> from jedi._compatibility import u, no_unicode_pprint
    >>> from jedi.parser import Parser, load_grammar
    >>> parser = Parser(load_grammar(), u('''
    ... x = ['a', 'b', 'c']
    ... def func():
    ...     y = None
    ... '''))
    >>> scope = parser.module.subscopes[0]
    >>> scope
    <Function: func@3-5>

    `global_names_dict_generator` is a generator.  First it yields names from
    most inner scope.

    >>> from jedi.evaluate import Evaluator
    >>> evaluator = Evaluator(load_grammar())
    >>> scope = er.wrap(evaluator, scope)
    >>> pairs = list(global_names_dict_generator(evaluator, scope, (4, 0)))
    >>> no_unicode_pprint(pairs[0])
    ({'func': [], 'y': [<Name: y@4,4>]}, (4, 0))

    Then it yields the names from one level "lower". In this example, this
    is the most outer scope. As you can see, the position in the tuple is now
    None, because typically the whole module is loaded before the function is
    called.

    >>> no_unicode_pprint(pairs[1])
    ({'func': [<Name: func@3,4>], 'x': [<Name: x@2,0>]}, None)

    After that we have a few underscore names that are part of the module.

    >>> sorted(pairs[2][0].keys())
    ['__doc__', '__file__', '__name__', '__package__']
    >>> pairs[3]  # global names -> there are none in our example.
    ({}, None)
    >>> pairs[4]  # package modules -> Also none.
    ({}, None)

    Finally, it yields names from builtin, if `include_builtin` is
    true (default).

    >>> pairs[5][0].values()                              #doctest: +ELLIPSIS
    [[<CompiledName: ...>], ...]
    """
    in_func = False
    while scope is not None:
        if not (scope.type == 'classdef' and in_func):
            # Names in methods cannot be resolved within the class.

            for names_dict in scope.names_dicts(True):
                yield names_dict, position
            if scope.type == 'funcdef':
                # The position should be reset if the current scope is a function.
                in_func = True
                position = None
        scope = er.wrap(evaluator, scope.get_parent_scope())

    # Add builtins to the global scope.
    for names_dict in compiled.builtin.names_dicts(True):
        yield names_dict, None
Ejemplo n.º 28
0
def global_names_dict_generator(evaluator, scope, position):
    """
    For global name lookups. Yields tuples of (names_dict, position). If the
    position is None, the position does not matter anymore in that scope.

    This function is used to include names from outer scopes. For example, when
    the current scope is function:

    >>> from jedi._compatibility import u, no_unicode_pprint
    >>> from jedi.parser import Parser, load_grammar
    >>> parser = Parser(load_grammar(), u('''
    ... x = ['a', 'b', 'c']
    ... def func():
    ...     y = None
    ... '''))
    >>> scope = parser.module.subscopes[0]
    >>> scope
    <Function: func@3-5>

    `global_names_dict_generator` is a generator.  First it yields names from
    most inner scope.

    >>> from jedi.evaluate import Evaluator
    >>> evaluator = Evaluator(load_grammar())
    >>> scope = er.wrap(evaluator, scope)
    >>> pairs = list(global_names_dict_generator(evaluator, scope, (4, 0)))
    >>> no_unicode_pprint(pairs[0])
    ({'func': [], 'y': [<Name: y@4,4>]}, (4, 0))

    Then it yields the names from one level "lower". In this example, this
    is the most outer scope. As you can see, the position in the tuple is now
    None, because typically the whole module is loaded before the function is
    called.

    >>> no_unicode_pprint(pairs[1])
    ({'func': [<Name: func@3,4>], 'x': [<Name: x@2,0>]}, None)

    After that we have a few underscore names that are part of the module.

    >>> sorted(pairs[2][0].keys())
    ['__doc__', '__file__', '__name__', '__package__']
    >>> pairs[3]  # global names -> there are none in our example.
    ({}, None)
    >>> pairs[4]  # package modules -> Also none.
    ({}, None)

    Finally, it yields names from builtin, if `include_builtin` is
    true (default).

    >>> pairs[5][0].values()                              #doctest: +ELLIPSIS
    [[<CompiledName: ...>], ...]
    """
    in_func = False
    while scope is not None:
        if not (scope.type == 'classdef' and in_func):
            # Names in methods cannot be resolved within the class.

            for names_dict in scope.names_dicts(True):
                yield names_dict, position
            if scope.type == 'funcdef':
                # The position should be reset if the current scope is a function.
                in_func = True
                position = None
        scope = er.wrap(evaluator, scope.get_parent_scope())

    # Add builtins to the global scope.
    for names_dict in compiled.builtin.names_dicts(True):
        yield names_dict, None
Ejemplo n.º 29
0
Archivo: finder.py Proyecto: Axure/jedi
 def __init__(self, evaluator, scope, name_str, position=None):
     self._evaluator = evaluator
     # Make sure that it's not just a syntax tree node.
     self.scope = er.wrap(evaluator, scope)
     self.name_str = name_str
     self.position = position
Ejemplo n.º 30
0
    def completions(self):
        """
        Return :class:`classes.Completion` objects. Those objects contain
        information about the completions, more than just names.

        :return: Completion objects, sorted by name and __ comes last.
        :rtype: list of :class:`classes.Completion`
        """
        def get_completions(user_stmt, bs):
            # TODO this closure is ugly. it also doesn't work with
            # simple_complete (used for Interpreter), somehow redo.
            module = self._parser.module()
            names, level, only_modules, unfinished_dotted = \
                helpers.check_error_statements(module, self._pos)
            completion_names = []
            if names is not None:
                imp_names = [n for n in names if n.end_pos < self._pos]
                i = imports.get_importer(self._evaluator, imp_names, module,
                                         level)
                completion_names = i.completion_names(self._evaluator,
                                                      only_modules)

            # TODO this paragraph is necessary, but not sure it works.
            context = self._user_context.get_context()
            if not next(context).startswith('.'):  # skip the path
                if next(context) == 'from':
                    # completion is just "import" if before stands from ..
                    if unfinished_dotted:
                        return completion_names
                    else:
                        return keywords.keyword_names('import')

            if isinstance(user_stmt, pr.Import):
                module = self._parser.module()
                completion_names += imports.completion_names(
                    self._evaluator, user_stmt, self._pos)
                return completion_names

            if names is None and not isinstance(user_stmt, pr.Import):
                if not path and not dot:
                    # add keywords
                    completion_names += keywords.keyword_names(all=True)
                    # TODO delete? We should search for valid parser
                    # transformations.
                completion_names += self._simple_complete(path, dot, like)
            return completion_names

        debug.speed('completions start')
        path = self._user_context.get_path_until_cursor()
        # Dots following an int are not the start of a completion but a float
        # literal.
        if re.search(r'^\d\.$', path):
            return []
        path, dot, like = helpers.completion_parts(path)

        user_stmt = self._parser.user_stmt_with_whitespace()

        b = compiled.builtin
        completion_names = get_completions(user_stmt, b)

        if not dot:
            # add named params
            for call_sig in self.call_signatures():
                # Allow protected access, because it's a public API.
                module = call_sig._name.get_parent_until()
                # Compiled modules typically don't allow keyword arguments.
                if not isinstance(module, compiled.CompiledObject):
                    for p in call_sig.params:
                        # Allow access on _definition here, because it's a
                        # public API and we don't want to make the internal
                        # Name object public.
                        if p._definition.stars == 0:  # no *args/**kwargs
                            completion_names.append(p._name)

        needs_dot = not dot and path

        comps = []
        comp_dct = {}
        for c in set(completion_names):
            n = str(c)
            if settings.case_insensitive_completion \
                    and n.lower().startswith(like.lower()) \
                    or n.startswith(like):
                if isinstance(c.parent, (pr.Function, pr.Class)):
                    # TODO I think this is a hack. It should be an
                    #   er.Function/er.Class before that.
                    c = er.wrap(self._evaluator, c.parent).name
                new = classes.Completion(self._evaluator, c, needs_dot,
                                         len(like))
                k = (new.name, new.complete)  # key
                if k in comp_dct and settings.no_completion_duplicates:
                    comp_dct[k]._same_name_completions.append(new)
                else:
                    comp_dct[k] = new
                    comps.append(new)

        debug.speed('completions end')

        return sorted(
            comps,
            key=lambda x:
            (x.name.startswith('__'), x.name.startswith('_'), x.name.lower()))
Ejemplo n.º 31
0
    def completion_names(self, evaluator, only_modules=False):
        """
        :param only_modules: Indicates wheter it's possible to import a
            definition that is not defined in a module.
        """
        from jedi.evaluate import finder, representation as er
        names = []
        if self.import_path:
            # flask
            if self.str_import_path == ('flask', 'ext'):
                # List Flask extensions like ``flask_foo``
                for mod in self._get_module_names():
                    modname = str(mod)
                    if modname.startswith('flask_'):
                        extname = modname[len('flask_'):]
                        names.append(self._generate_name(extname))
                # Now the old style: ``flaskext.foo``
                for dir in self.sys_path_with_modifications():
                    flaskext = os.path.join(dir, 'flaskext')
                    if os.path.isdir(flaskext):
                        names += self._get_module_names([flaskext])

            for scope in self.follow(evaluator):
                # Non-modules are not completable.
                if not scope.type == 'file_input':  # not a module
                    continue

                # namespace packages
                if isinstance(
                        scope,
                        pr.Module) and scope.path.endswith('__init__.py'):
                    pkg_path = os.path.dirname(scope.path)
                    paths = self.namespace_packages(pkg_path, self.import_path)
                    names += self._get_module_names([pkg_path] + paths)

                if only_modules:
                    # In the case of an import like `from x.` we don't need to
                    # add all the variables.
                    if ('os', ) == self.str_import_path and not self.level:
                        # os.path is a hardcoded exception, because it's a
                        # ``sys.modules`` modification.
                        names.append(self._generate_name('path'))

                    continue

                for names_dict in scope.names_dicts(search_global=False):
                    _names = list(chain.from_iterable(names_dict.values()))
                    if not _names:
                        continue
                    _names = finder.filter_definition_names(_names, scope)
                    names += _names
        else:
            # Empty import path=completion after import
            if not self.level:
                names += self._get_module_names()

            if self.file_path is not None:
                path = os.path.abspath(self.file_path)
                for i in range(self.level - 1):
                    path = os.path.dirname(path)
                names += self._get_module_names([path])

                if self.level:
                    rel_path = os.path.join(self.get_relative_path(),
                                            '__init__.py')
                    if os.path.exists(rel_path):
                        module = _load_module(self._evaluator, rel_path)
                        module = er.wrap(self._evaluator, module)
                        for names_dict in module.names_dicts(
                                search_global=False):
                            names += chain.from_iterable(names_dict.values())
        return names
Ejemplo n.º 32
0
    def parent(self):
        """
        Creating fake statements for the interpreter.
        """
        obj = self._value
        parser_path = []
        if inspect.ismodule(obj):
            module = obj
        else:
            names = []
            try:
                o = obj.__objclass__
                names.append(obj.__name__)
                obj = o
            except AttributeError:
                pass

            try:
                module_name = obj.__module__
                names.insert(0, obj.__name__)
            except AttributeError:
                # Unfortunately in some cases like `int` there's no __module__
                module = builtins
            else:
                # TODO this import is wrong. Yields x for x.y.z instead of z
                module = __import__(module_name)
            parser_path = names
        raw_module = get_module(self._value)

        found = []
        try:
            path = module.__file__
        except AttributeError:
            pass
        else:
            path = re.sub('c$', '', path)
            if path.endswith('.py'):
                # cut the `c` from `.pyc`
                with open(path) as f:
                    source = source_to_unicode(f.read())
                mod = FastParser(load_grammar(), source, path[:-1]).module
                if parser_path:
                    assert len(parser_path) == 1
                    found = self._evaluator.find_types(mod,
                                                       parser_path[0],
                                                       search_global=True)
                else:
                    found = [er.wrap(self._evaluator, mod)]

                if not found:
                    debug.warning(
                        'Possibly an interpreter lookup for Python code failed %s',
                        parser_path)

        if not found:
            evaluated = compiled.CompiledObject(obj)
            if evaluated == builtins:
                # The builtins module is special and always cached.
                evaluated = compiled.builtin
            found = [evaluated]

        content = iterable.AlreadyEvaluated(found)
        stmt = pt.ExprStmt([
            self,
            pt.Operator(pt.zero_position_modifier, '=', (0, 0), ''), content
        ])
        stmt.parent = self._module
        return stmt
Ejemplo n.º 33
0
 def parent(self):
     scope = self._definition.get_parent_scope()
     scope = er.wrap(self._evaluator, scope)
     return Definition(self._evaluator, scope.name)
Ejemplo n.º 34
0
    def filter_name(self, scope_names_generator):
        """
        Filters all variables of a scope (which are defined in the
        `scope_names_generator`), until the name fits.
        """
        # TODO Now this import is really ugly. Try to remove it.
        # It's possibly the only api dependency.
        from jedi.api.interpreter import InterpreterNamespace
        names = []
        self.maybe_descriptor = isinstance(self.scope, er.Class)
        for name_list_scope, name_list in scope_names_generator:
            break_scopes = []
            if not isinstance(name_list_scope, compiled.CompiledObject):
                # Here is the position stuff happening (sorting of variables).
                # Compiled objects don't need that, because there's only one
                # reference.
                name_list = sorted(name_list, key=lambda n: n.start_pos, reverse=True)

            for name in name_list:
                if unicode(self.name_str) != name.get_code():
                    continue

                stmt = name.get_definition()
                scope = stmt.parent
                if scope in break_scopes:
                    continue

                # Exclude `arr[1] =` from the result set.
                if not self._name_is_array_assignment(name, stmt):
                    # TODO we ignore a lot of elements here that should not be
                    #   ignored. But then again flow_analysis also stops when the
                    #   input scope is reached. This is not correct: variables
                    #   might still have conditions if defined outside of the
                    #   current scope.
                    if isinstance(stmt, (pr.Param, pr.Import)) \
                            or isinstance(name_list_scope, (pr.Lambda, pr.ListComprehension, er.Instance, InterpreterNamespace)) \
                            or isinstance(scope, compiled.CompiledObject) \
                            or isinstance(stmt, pr.ExprStmt) and stmt.is_global():
                        # Always reachable.
                        names.append(name)
                    else:
                        check = flow_analysis.break_check(self._evaluator,
                                                          name_list_scope,
                                                          er.wrap(self._evaluator, scope),
                                                          self.scope)
                        if check is not flow_analysis.UNREACHABLE:
                            names.append(name)
                        if check is flow_analysis.REACHABLE:
                            break

                if names and self._is_name_break_scope(stmt):
                    if self._does_scope_break_immediately(scope, name_list_scope):
                        break
                    else:
                        break_scopes.append(scope)
            if names:
                break

            if isinstance(self.scope, er.Instance):
                # After checking the dictionary of an instance (self
                # attributes), an attribute maybe a descriptor.
                self.maybe_descriptor = True

        scope_txt = (self.scope if self.scope == name_list_scope
                     else '%s-%s' % (self.scope, name_list_scope))
        debug.dbg('finder.filter_name "%s" in (%s): %s@%s', self.name_str,
                  scope_txt, u(names), self.position)
        return list(self._clean_names(names))
Ejemplo n.º 35
0
 def __init__(self, evaluator, scope, name_str, position=None):
     self._evaluator = evaluator
     # Make sure that it's not just a syntax tree node.
     self.scope = er.wrap(evaluator, scope)
     self.name_str = name_str
     self.position = position
Ejemplo n.º 36
0
 def parent(self):
     scope = self._definition.get_parent_scope()
     scope = er.wrap(self._evaluator, scope)
     return Definition(self._evaluator, scope.name)