예제 #1
0
    def get_completions(self, info):
        '''Get Python completions'''
        # https://github.com/davidhalter/jedi/blob/master/jedi/utils.py
        if jedi is None:
            return []

        text = info['code']
        position = (info['line_num'], info['column'])
        interpreter = Interpreter(text, [self.env])

        if jedi.__version__ >= LooseVersion('0.12.0'):
            lines = split_lines(text)
            name = get_on_completion_name(interpreter._module_node, lines,
                                          position)
            before = text[:len(text) - len(name)]
        elif jedi.__version__ >= LooseVersion('0.10.0'):
            lines = split_lines(text)
            name = get_on_completion_name(interpreter._get_module_node(),
                                          lines, position)
            before = text[:len(text) - len(name)]
        else:
            path = UserContext(text, position).get_path_until_cursor()
            path, dot, like = completion_parts(path)
            before = text[:len(text) - len(like)]

        completions = interpreter.completions()
        completions = [before + c.name_with_symbols for c in completions]

        self.kernel.log.error(completions)

        return [c[info['start']:] for c in completions]
예제 #2
0
파일: utils.py 프로젝트: songsin/Pyto
        def complete(self, text, state):
            """
            This complete stuff is pretty weird, a generator would make
            a lot more sense, but probably due to backwards compatibility
            this is still the way how it works.

            The only important part is stuff in the ``state == 0`` flow,
            everything else has been copied from the ``rlcompleter`` std.
            library module.
            """
            if state == 0:
                sys.path.insert(0, os.getcwd())
                # Calling python doesn't have a path, so add to sys.path.
                try:
                    interpreter = Interpreter(text, [namespace_module.__dict__])

                    path = UserContext(text, (1, len(text))).get_path_until_cursor()
                    path, dot, like = completion_parts(path)
                    before = text[:len(text) - len(like)]
                    completions = interpreter.completions()
                finally:
                    sys.path.pop(0)

                self.matches = [before + c.name_with_symbols for c in completions]
            try:
                return self.matches[state]
            except IndexError:
                return None
예제 #3
0
    def __init__(self,
                 source=None,
                 line=None,
                 column=None,
                 path=None,
                 encoding='utf-8',
                 source_path=None,
                 source_encoding=None,
                 sys_path=None):
        if source_path is not None:
            warnings.warn("Use path instead of source_path.",
                          DeprecationWarning)
            path = source_path
        if source_encoding is not None:
            warnings.warn("Use encoding instead of source_encoding.",
                          DeprecationWarning)
            encoding = source_encoding

        self._orig_path = path
        self.path = None if path is None else os.path.abspath(path)

        if source is None:
            with open(path) as f:
                source = f.read()

        self.source = common.source_to_unicode(source, encoding)
        lines = common.splitlines(self.source)
        line = max(len(lines), 1) if line is None else line
        if not (0 < line <= len(lines)):
            raise ValueError('`line` parameter is not in a valid range.')

        line_len = len(lines[line - 1])
        column = line_len if column is None else column
        if not (0 <= column <= line_len):
            raise ValueError('`column` parameter is not in a valid range.')
        self._pos = line, column

        cache.clear_time_caches()
        debug.reset_time()
        self._grammar = load_grammar('grammar%s.%s' % sys.version_info[:2])
        self._user_context = UserContext(self.source, self._pos)
        self._parser = UserContextParser(self._grammar, self.source, path,
                                         self._pos, self._user_context,
                                         self._parsed_callback)
        if sys_path is None:
            venv = os.getenv('VIRTUAL_ENV')
            if venv:
                sys_path = list(get_venv_path(venv))
        self._evaluator = Evaluator(self._grammar, sys_path=sys_path)
        debug.speed('init')
예제 #4
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.ImportPath):
                    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([self._parser.user_scope()])
        else:
            # Fetch definition of callee, if there's no path otherwise.
            if not goto_path:
                (call,
                 _) = helpers.func_call_and_param_index(user_stmt, self._pos)
                if call is not None:
                    while call.next is not None:
                        call = call.next
                    # reset cursor position:
                    (row, col) = call.name.end_pos
                    pos = (row, max(col - 1, 0))
                    self._user_context = UserContext(self.source, pos)
                    # then try to find the path again
                    goto_path = self._user_context.get_path_under_cursor()

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

        definitions = resolve_import_paths(definitions)
        d = set([
            classes.Definition(self._evaluator, s) for s in definitions
            if s is not imports.ImportPath.GlobalNamespace
        ])
        return helpers.sorted_definitions(d)
예제 #5
0
    def __init__(self,
                 source=None,
                 line=None,
                 column=None,
                 path=None,
                 encoding='utf-8',
                 source_path=None,
                 source_encoding=None):
        if source_path is not None:
            warnings.warn("Use path instead of source_path.",
                          DeprecationWarning)
            path = source_path
        if source_encoding is not None:
            warnings.warn("Use encoding instead of source_encoding.",
                          DeprecationWarning)
            encoding = source_encoding

        self._orig_path = path
        self.path = None if path is None else os.path.abspath(path)

        if source is None:
            with open(path) as f:
                source = f.read()

        lines = source.splitlines() or ['']
        if source and source[-1] == '\n':
            lines.append('')
        line = max(len(lines), 1) if line is None else line
        if not (0 < line <= len(lines)):
            raise ValueError('`line` parameter is not in a valid range.')

        line_len = len(lines[line - 1])
        column = line_len if column is None else column
        if not (0 <= column <= line_len):
            raise ValueError('`column` parameter is not in a valid range.')
        self._pos = line, column

        cache.clear_caches()
        debug.reset_time()
        self.source = common.source_to_unicode(source, encoding)
        self._user_context = UserContext(self.source, self._pos)
        self._parser = UserContextParser(self.source, path, self._pos,
                                         self._user_context)
        self._evaluator = Evaluator()
        debug.speed('init')
예제 #6
0
    def get_completions(self, info):
        """Get Python completions."""
        # https://github.com/davidhalter/jedi/blob/master/jedi/utils.py
        if jedi is None:
            return []

        text = info['code']
        interpreter = Interpreter(text, [self.env])

        position = (info['line_num'], info['column'])
        path = UserContext(text, position).get_path_until_cursor()
        path, dot, like = completion_parts(path)
        before = text[:len(text) - len(like)]

        completions = interpreter.completions()
        completions = [before + c.name_with_symbols for c in completions]

        return [c[info['start']:] for c in completions]