Beispiel #1
0
    def _simple_complete(self, path, like):
        try:
            scopes = list(self._prepare_goto(path, True))
        except NotFoundError:
            scopes = []
            scope_generator = evaluate.get_names_of_scope(
                self._parser.user_scope, self._pos)
            completions = []
            for scope, name_list in scope_generator:
                for c in name_list:
                    completions.append((c, scope))
        else:
            completions = []
            debug.dbg('possible scopes', scopes)
            for s in scopes:
                if s.isinstance(er.Function):
                    names = s.get_magic_method_names()
                else:
                    if isinstance(s, imports.ImportPath):
                        under = like + self._module.get_path_after_cursor()
                        if under == 'import':
                            current_line = self._module.get_position_line()
                            if not current_line.endswith('import import'):
                                continue
                        a = s.import_stmt.alias
                        if a and a.start_pos <= self._pos <= a.end_pos:
                            continue
                        names = s.get_defined_names(on_import_stmt=True)
                    else:
                        names = s.get_defined_names()

                for c in names:
                    completions.append((c, s))
        return completions
Beispiel #2
0
    def _simple_complete(self, path, like):
        try:
            scopes = list(self._prepare_goto(path, True))
        except NotFoundError:
            scopes = []
            scope_generator = evaluate.get_names_of_scope(
                self._parser.user_scope, self._pos)
            completions = []
            for scope, name_list in scope_generator:
                for c in name_list:
                    completions.append((c, scope))
        else:
            completions = []
            debug.dbg('possible scopes', scopes)
            for s in scopes:
                if s.isinstance(er.Function):
                    names = s.get_magic_method_names()
                else:
                    if isinstance(s, imports.ImportPath):
                        under = like + self._module.get_path_after_cursor()
                        if under == 'import':
                            current_line = self._module.get_position_line()
                            if not current_line.endswith('import import'):
                                continue
                        a = s.import_stmt.alias
                        if a and a.start_pos <= self._pos <= a.end_pos:
                            continue
                        names = s.get_defined_names(on_import_stmt=True)
                    else:
                        names = s.get_defined_names()

                for c in names:
                    completions.append((c, s))
        return completions
Beispiel #3
0
def _defined_names(scope):
    """
    List sub-definitions (e.g., methods in class).

    :type scope: Scope
    :rtype: list of Definition
    """
    pair = next(evaluate.get_names_of_scope(scope, star_search=False, include_builtin=False), None)
    names = pair[1] if pair else []
    return [Definition(d) for d in sorted(names, key=lambda s: s.start_pos)]
Beispiel #4
0
def _defined_names(scope):
    """
    List sub-definitions (e.g., methods in class).

    :type scope: Scope
    :rtype: list of Definition
    """
    pair = next(
        evaluate.get_names_of_scope(scope,
                                    star_search=False,
                                    include_builtin=False), None)
    names = pair[1] if pair else []
    return [Definition(d) for d in sorted(names, key=lambda s: s.start_pos)]
Beispiel #5
0
    def get_defined_names(self, on_import_stmt=False):
        names = []
        for scope in self.follow():
            if scope is ImportPath.GlobalNamespace:
                if self._is_relative_import() == 0:
                    names += self._get_module_names()

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

                    if self._is_relative_import():
                        rel_path = self._get_relative_path() + '/__init__.py'
                        with common.ignored(IOError):
                            m = modules.Module(rel_path)
                            names += m.parser.module.get_defined_names()
            else:
                if on_import_stmt and 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 self.is_just_from:
                    # In the case of an import like `from x.` we don't need to
                    # add all the variables.
                    if [
                            'os'
                    ] == self.import_path and not self._is_relative_import():
                        # os.path is a hardcoded exception, because it's a
                        # ``sys.modules`` modification.
                        p = (0, 0)
                        names.append(
                            pr.Name(self.GlobalNamespace, [('path', p)], p, p,
                                    self.import_stmt))
                    continue
                for s, scope_names in evaluate.get_names_of_scope(
                        scope, include_builtin=False):
                    for n in scope_names:
                        if self.import_stmt.from_ns is None \
                                or self.is_partial_import:
                            # from_ns must be defined to access module
                            # values plus a partial import means that there
                            # is something after the import, which
                            # automatically implies that there must not be
                            # any non-module scope.
                            continue
                        names.append(n)
        return names
Beispiel #6
0
    def get_defined_names(self, on_import_stmt=False):
        names = []
        for scope in self.follow():
            if scope is ImportPath.GlobalNamespace:
                if self._is_relative_import() == 0:
                    names += self._get_module_names()

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

                    if self._is_relative_import():
                        rel_path = self._get_relative_path() + '/__init__.py'
                        with common.ignored(IOError):
                            m = modules.Module(rel_path)
                            names += m.parser.module.get_defined_names()
            else:
                if on_import_stmt and 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 self.is_just_from:
                    # In the case of an import like `from x.` we don't need to
                    # add all the variables.
                    if ['os'] == self.import_path and not self._is_relative_import():
                        # os.path is a hardcoded exception, because it's a
                        # ``sys.modules`` modification.
                        p = (0, 0)
                        names.append(pr.Name(self.GlobalNamespace, [('path', p)],
                                       p, p, self.import_stmt))
                    continue
                for s, scope_names in evaluate.get_names_of_scope(scope,
                                                                  include_builtin=False):
                    for n in scope_names:
                        if self.import_stmt.from_ns is None \
                                or self.is_partial_import:
                                # from_ns must be defined to access module
                                # values plus a partial import means that there
                                # is something after the import, which
                                # automatically implies that there must not be
                                # any non-module scope.
                                continue
                        names.append(n)
        return names
Beispiel #7
0
    def get_defined_names(self, on_import_stmt=False):
        names = []
        for scope in self.follow():
            if scope is ImportPath.GlobalNamespace:
                if self.import_stmt.relative_count == 0:
                    names += self.get_module_names()

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

                    if self.import_stmt.relative_count:
                        rel_path = self.get_relative_path() + '/__init__.py'
                        try:
                            m = modules.Module(rel_path)
                            names += m.parser.module.get_defined_names()
                        except IOError:
                            pass
            else:
                if on_import_stmt and isinstance(scope, pr.Module) \
                                        and scope.path.endswith('__init__.py'):
                    pkg_path = os.path.dirname(scope.path)
                    names += self.get_module_names([pkg_path])
                for s, scope_names in evaluate.get_names_of_scope(scope,
                                                    include_builtin=False):
                    for n in scope_names:
                        if self.import_stmt.from_ns is None \
                                            or self.is_partial_import:
                                # from_ns must be defined to access module
                                # values plus a partial import means that there
                                # is something after the import, which
                                # automatically implies that there must not be
                                # any non-module scope.
                                continue
                        names.append(n)
        return names
Beispiel #8
0
    def get_defined_names(self, on_import_stmt=False):
        names = []
        for scope in self.follow():
            if scope is ImportPath.GlobalNamespace:
                if self.import_stmt.relative_count == 0:
                    names += self.get_module_names()

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

                    if self.import_stmt.relative_count:
                        rel_path = self.get_relative_path() + '/__init__.py'
                        with common.ignored(IOError):
                            m = modules.Module(rel_path)
                            names += m.parser.module.get_defined_names()
            else:
                if on_import_stmt and isinstance(scope, pr.Module) \
                                        and scope.path.endswith('__init__.py'):
                    pkg_path = os.path.dirname(scope.path)
                    names += self.get_module_names([pkg_path])
                for s, scope_names in evaluate.get_names_of_scope(
                        scope, include_builtin=False):
                    for n in scope_names:
                        if self.import_stmt.from_ns is None \
                                            or self.is_partial_import:
                            # from_ns must be defined to access module
                            # values plus a partial import means that there
                            # is something after the import, which
                            # automatically implies that there must not be
                            # any non-module scope.
                            continue
                        names.append(n)
        return names
Beispiel #9
0
    def completions(self):
        """
        Return :class:`api_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:`api_classes.Completion`
        """
        debug.speed('completions start')
        path = self._module.get_path_until_cursor()
        if re.search('^\.|\.\.$', path):
            return []
        path, dot, like = self._get_completion_parts(path)
        completion_line = self._module.get_line(self.pos[0])[:self.pos[1]]

        try:
            scopes = list(self._prepare_goto(path, True))
        except NotFoundError:
            scopes = []
            scope_generator = evaluate.get_names_of_scope(
                                            self._parser.user_scope, self.pos)
            completions = []
            for scope, name_list in scope_generator:
                for c in name_list:
                    completions.append((c, scope))
        else:
            completions = []
            debug.dbg('possible scopes', scopes)
            for s in scopes:
                if s.isinstance(er.Function):
                    names = s.get_magic_method_names()
                else:
                    if isinstance(s, imports.ImportPath):
                        if like == 'import':
                            if not completion_line.endswith('import import'):
                                continue
                        a = s.import_stmt.alias
                        if a and a.start_pos <= self.pos <= a.end_pos:
                            continue
                        names = s.get_defined_names(on_import_stmt=True)
                    else:
                        names = s.get_defined_names()

                for c in names:
                    completions.append((c, s))

        if not dot:  # named params have no dots
            for call_def in self.call_signatures():
                if not call_def.module.is_builtin():
                    for p in call_def.params:
                        completions.append((p.get_name(), p))

            # Do the completion if there is no path before and no import stmt.
            u = self._parser.user_stmt
            bs = builtin.Builtin.scope
            if isinstance(u, pr.Import):
                if (u.relative_count > 0 or u.from_ns) and not re.search(
                            r'(,|from)\s*$|import\s+$', completion_line):
                    completions += ((k, bs) for k
                                            in keywords.get_keywords('import'))

            if not path and not isinstance(u, pr.Import):
                # add keywords
                completions += ((k, bs) for k in keywords.get_keywords(
                                                                    all=True))

        needs_dot = not dot and path

        comps = []
        comp_dct = {}
        for c, s in set(completions):
            n = c.names[-1]
            if settings.case_insensitive_completion \
                    and n.lower().startswith(like.lower()) \
                    or n.startswith(like):
                if not evaluate.filter_private_variable(s,
                                                    self._parser.user_stmt, n):
                    new = api_classes.Completion(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()))
Beispiel #10
0
    def completions(self):
        """
        Return :class:`api_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:`api_classes.Completion`
        """
        debug.speed('completions start')
        path = self._module.get_path_until_cursor()
        if re.search('^\.|\.\.$', path):
            return []
        path, dot, like = self._get_completion_parts(path)
        completion_line = self._module.get_line(self.pos[0])[:self.pos[1]]

        try:
            scopes = list(self._prepare_goto(path, True))
        except NotFoundError:
            scopes = []
            scope_generator = evaluate.get_names_of_scope(
                self._parser.user_scope, self.pos)
            completions = []
            for scope, name_list in scope_generator:
                for c in name_list:
                    completions.append((c, scope))
        else:
            completions = []
            debug.dbg('possible scopes', scopes)
            for s in scopes:
                if s.isinstance(er.Function):
                    names = s.get_magic_method_names()
                else:
                    if isinstance(s, imports.ImportPath):
                        if like == 'import':
                            if not completion_line.endswith('import import'):
                                continue
                        a = s.import_stmt.alias
                        if a and a.start_pos <= self.pos <= a.end_pos:
                            continue
                        names = s.get_defined_names(on_import_stmt=True)
                    else:
                        names = s.get_defined_names()

                for c in names:
                    completions.append((c, s))

        if not dot:  # named params have no dots
            for call_def in self.call_signatures():
                if not call_def.module.is_builtin():
                    for p in call_def.params:
                        completions.append((p.get_name(), p))

            # Do the completion if there is no path before and no import stmt.
            u = self._parser.user_stmt
            bs = builtin.Builtin.scope
            if isinstance(u, pr.Import):
                if (u.relative_count > 0 or u.from_ns) and not re.search(
                        r'(,|from)\s*$|import\s+$', completion_line):
                    completions += ((k, bs)
                                    for k in keywords.get_keywords('import'))

            if not path and not isinstance(u, pr.Import):
                # add keywords
                completions += ((k, bs)
                                for k in keywords.get_keywords(all=True))

        needs_dot = not dot and path

        comps = []
        comp_dct = {}
        for c, s in set(completions):
            n = c.names[-1]
            if settings.case_insensitive_completion \
                    and n.lower().startswith(like.lower()) \
                    or n.startswith(like):
                if not evaluate.filter_private_variable(
                        s, self._parser.user_stmt, n):
                    new = api_classes.Completion(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()))