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
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]
def get_jedi_completions(self, info, env=None): '''Get Python completions''' # https://github.com/davidhalter/jedi/blob/master/jedi/utils.py text = info['code'][:info['end']] env = env or {} interpreter = Interpreter(text, [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]
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]
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]
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._evaluator.wrap(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 = tuple(str(n) for n in names if n.end_pos < self._pos) i = imports.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 set([keywords.keyword('import').name]) if isinstance(user_stmt, tree.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, tree.Import): if not path and not dot: # add keywords completion_names += keywords.completion_names( self._evaluator, user_stmt, self._pos, module) # 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, (tree.Function, tree.Class)): # TODO I think this is a hack. It should be an # er.Function/er.Class before that. c = self._evaluator.wrap(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()))
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._definition.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._definition.get_name(), p)) 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.names[-1]) 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): 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()))
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._evaluator.wrap(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 = tuple( str(n) for n in names if n.end_pos < self._pos) i = imports.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 set([keywords.keyword('import').name]) if isinstance(user_stmt, tree.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, tree.Import): if not path and not dot: # add keywords completion_names += keywords.completion_names( self._evaluator, user_stmt, self._pos, module) # 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, (tree.Function, tree.Class)): # TODO I think this is a hack. It should be an # er.Function/er.Class before that. c = self._evaluator.wrap(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()))
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) debug.speed('completions start') path = self._user_context.get_path_until_cursor() if re.search('^\.|\.\.$', 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._definition.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. completions.append((p._definition.get_name(), p)) 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.names[-1]) 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): 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()))
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()))