From 4ca918e830eaa4e6df7a263b496f65c36d160a65 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Thu, 30 Jul 2020 13:21:50 +0200 Subject: [PATCH 01/22] Use the new API instead of the deprecated one --- pythonx/jedi_vim.py | 75 +++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/pythonx/jedi_vim.py b/pythonx/jedi_vim.py index 918dba5..af2463c 100644 --- a/pythonx/jedi_vim.py +++ b/pythonx/jedi_vim.py @@ -255,7 +255,7 @@ def get_known_environments(): @catch_and_print_exceptions -def get_script(source=None, column=None): +def get_script(source=None): jedi.settings.additional_dynamic_modules = [ b.name for b in vim.buffers if ( b.name is not None and @@ -263,16 +263,16 @@ def get_script(source=None, column=None): b.options['buflisted'])] if source is None: source = '\n'.join(vim.current.buffer) + buf_path = vim.current.buffer.name + + return jedi.Script(source, path=buf_path, environment=get_environment()) + + +def get_pos(column=None): row = vim.current.window.cursor[0] if column is None: column = vim.current.window.cursor[1] - buf_path = vim.current.buffer.name - - return jedi.Script( - source, row, column, buf_path, - encoding=vim_eval('&encoding') or 'latin1', - environment=get_environment(), - ) + return row, column @_check_jedi_availability(show_error=False) @@ -303,9 +303,9 @@ def completions(): # here again hacks, because jedi has a different interface than vim column += len(base) try: - script = get_script(source=source, column=column) - completions = script.completions() - signatures = script.call_signatures() + script = get_script(source=source) + completions = script.complete(*get_pos(column)) + signatures = script.get_signatures(*get_pos(column)) add_info = "preview" in vim.eval("&completeopt").split(",") out = [] @@ -358,14 +358,15 @@ def goto(mode="goto"): :rtype: list """ script = get_script() + pos = get_pos() if mode == "goto": - definitions = script.goto_assignments(follow_imports=True) + definitions = script.goto(*pos, follow_imports=True) elif mode == "definition": - definitions = script.goto_definitions() + definitions = script.infer(*pos) elif mode == "assignment": - definitions = script.goto_assignments() + definitions = script.goto(*pos) elif mode == "stubs": - definitions = script.goto_assignments(follow_imports=True, only_stubs=True) + definitions = script.goto(*pos, follow_imports=True, only_stubs=True) if not definitions: echo_highlight("Couldn't find any definitions for this.") @@ -376,19 +377,20 @@ def goto(mode="goto"): echo_highlight("Cannot get the definition of Python keywords.") else: echo_highlight("Builtin modules cannot be displayed (%s)." - % d.desc_with_module) + % (d.full_name or d.name)) else: using_tagstack = int(vim_eval('g:jedi#use_tag_stack')) == 1 - if (d.module_path or '') != vim.current.buffer.name: - result = new_buffer(d.module_path, + module_path = str(d.module_path) + if (module_path or '') != vim.current.buffer.name: + result = new_buffer(module_path, using_tagstack=using_tagstack) if not result: return [] - if (using_tagstack and d.module_path and - os.path.exists(d.module_path)): + if (using_tagstack and module_path and + os.path.exists(module_path)): tagname = d.name with tempfile('{0}\t{1}\t{2}'.format( - tagname, d.module_path, 'call cursor({0}, {1})'.format( + tagname, module_path, 'call cursor({0}, {1})'.format( d.line, d.column + 1))) as f: old_tags = vim.eval('&tags') old_wildignore = vim.eval('&wildignore') @@ -445,7 +447,7 @@ def show_goto_multi_results(definitions, mode): lst.append(dict(text=PythonToVimStr(d.description))) else: text = annotate_description(d) - lst.append(dict(filename=PythonToVimStr(relpath(d.module_path)), + lst.append(dict(filename=PythonToVimStr(relpath(str(d.module_path))), lnum=d.line, col=d.column + 1, text=PythonToVimStr(text))) @@ -497,7 +499,7 @@ def _same_definitions(a, b): @catch_and_print_exceptions def usages(visuals=True): script = get_script() - definitions = script.usages() + definitions = script.get_references(*get_pos()) if not definitions: echo_highlight("No usages found here.") return definitions @@ -590,7 +592,7 @@ def highlight_usages(): defs_per_buf = {} for definition in definitions: try: - buf = bufs[definition.module_path] + buf = bufs[str(definition.module_path)] except KeyError: continue defs_per_buf.setdefault(buf, []).append(definition) @@ -693,7 +695,7 @@ def highlight_usages_for_vim_win(): if definitions: buffer_path = vim.current.buffer.name for definition in definitions: - if (definition.module_path or '') == buffer_path: + if (str(definition.module_path) or '') == buffer_path: positions = [ [definition.line, definition.column + 1, @@ -719,7 +721,7 @@ def highlight_usages_for_vim_win(): def show_documentation(): script = get_script() try: - definitions = script.goto_definitions() + definitions = script.help(*get_pos()) except Exception: # print to stdout, will be in :messages definitions = [] @@ -735,7 +737,7 @@ def show_documentation(): for d in definitions: doc = d.docstring() if doc: - title = 'Docstring for %s' % d.desc_with_module + title = 'Docstring for %s' % (d.full_name or d.name) underline = '=' * len(title) docs.append('%s\n%s\n%s' % (title, underline, doc)) else: @@ -783,7 +785,7 @@ def show_call_signatures(signatures=()): # buffer. clear_call_signatures() if signatures == (): - signatures = get_script().call_signatures() + signatures = get_script().get_signatures(*get_pos()) if not signatures: return @@ -1006,18 +1008,19 @@ def do_rename(replace, orig=None): # Sort the whole thing reverse (positions at the end of the line # must be first, because they move the stuff before the position). temp_rename = sorted(temp_rename, reverse=True, - key=lambda x: (x.module_path, x.line, x.column)) + key=lambda x: (str(x.module_path), x.line, x.column)) buffers = set() for r in temp_rename: if r.in_builtin_module(): continue - if os.path.abspath(vim.current.buffer.name) != r.module_path: - assert r.module_path is not None - result = new_buffer(r.module_path) + module_path = r.module_path + if os.path.abspath(vim.current.buffer.name) != str(module_path): + assert module_path is not None + result = new_buffer(module_path) if not result: echo_highlight('Failed to create buffer window for %s!' % ( - r.module_path)) + module_path)) continue buffers.add(vim.current.buffer.name) @@ -1055,7 +1058,7 @@ def py_import(): echo_highlight('%s is a builtin module.' % import_path) else: cmd_args = ' '.join([a.replace(' ', '\\ ') for a in args]) - new_buffer(completion.module_path, cmd_args) + new_buffer(str(completion.module_path), cmd_args) @catch_and_print_exceptions @@ -1068,8 +1071,8 @@ def py_import_completions(): comps = [] else: text = 'import %s' % argl - script = jedi.Script(text, 1, len(text), '', environment=get_environment()) - comps = ['%s%s' % (argl, c.complete) for c in script.completions()] + script = jedi.Script(text, path='', environment=get_environment()) + comps = ['%s%s' % (argl, c.complete) for c in script.complete(1, len(text))] vim.command("return '%s'" % '\n'.join(comps)) From 3a2774777348b8bc12c2f837b3779bda4525b484 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Thu, 30 Jul 2020 14:00:16 +0200 Subject: [PATCH 02/22] Use the project.search function --- pythonx/jedi_vim.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/pythonx/jedi_vim.py b/pythonx/jedi_vim.py index af2463c..851f7dd 100644 --- a/pythonx/jedi_vim.py +++ b/pythonx/jedi_vim.py @@ -92,6 +92,11 @@ def vim_eval(string): return _catch_exception(string, is_eval=True) +def get_project(): + # TODO remove get_environment() in favor of this. + return jedi.get_default_project() + + def no_jedi_warning(error=None): vim.command('echohl WarningMsg') vim.command('echom "Please install Jedi if you want to use jedi-vim."') @@ -1047,32 +1052,26 @@ def py_import(): # args are the same as for the :edit command args = shsplit(vim.eval('a:args')) import_path = args.pop() - text = 'import %s' % import_path - scr = jedi.Script(text, 1, len(text), '', environment=get_environment()) - try: - completion = scr.goto_assignments()[0] - except IndexError: + name = next(get_project().search(import_path), None) + if name is None: echo_highlight('Cannot find %s in sys.path!' % import_path) else: - if completion.column is None: # Python modules always have a line number. + if name.column is None: # Python modules always have a line number. echo_highlight('%s is a builtin module.' % import_path) else: cmd_args = ' '.join([a.replace(' ', '\\ ') for a in args]) - new_buffer(str(completion.module_path), cmd_args) + new_buffer(str(name.module_path), cmd_args) @catch_and_print_exceptions def py_import_completions(): argl = vim.eval('a:argl') - try: - import jedi - except ImportError: + if jedi is None: print('Pyimport completion requires jedi module: https://github.com/davidhalter/jedi') comps = [] else: - text = 'import %s' % argl - script = jedi.Script(text, path='', environment=get_environment()) - comps = ['%s%s' % (argl, c.complete) for c in script.complete(1, len(text))] + names = get_project().complete_search(argl) + comps = [argl + n for n in set(c.complete for c in names)] vim.command("return '%s'" % '\n'.join(comps)) From 1e9bdc863a1c286741a14e6d3cc40fb399ff08e5 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Thu, 30 Jul 2020 14:16:37 +0200 Subject: [PATCH 03/22] definition -> name, because Jedi calls it name now --- pythonx/jedi_vim.py | 204 ++++++++++++++++++++++---------------------- 1 file changed, 100 insertions(+), 104 deletions(-) diff --git a/pythonx/jedi_vim.py b/pythonx/jedi_vim.py index 851f7dd..7a15732 100644 --- a/pythonx/jedi_vim.py +++ b/pythonx/jedi_vim.py @@ -359,33 +359,32 @@ def tempfile(content): def goto(mode="goto"): """ :param str mode: "definition", "assignment", "goto" - :return: list of definitions/assignments - :rtype: list + :rtype: list of jedi.api.classes.Name """ script = get_script() pos = get_pos() if mode == "goto": - definitions = script.goto(*pos, follow_imports=True) + names = script.goto(*pos, follow_imports=True) elif mode == "definition": - definitions = script.infer(*pos) + names = script.infer(*pos) elif mode == "assignment": - definitions = script.goto(*pos) + names = script.goto(*pos) elif mode == "stubs": - definitions = script.goto(*pos, follow_imports=True, only_stubs=True) + names = script.goto(*pos, follow_imports=True, only_stubs=True) - if not definitions: + if not names: echo_highlight("Couldn't find any definitions for this.") - elif len(definitions) == 1 and mode != "related_name": - d = list(definitions)[0] - if d.column is None: - if d.is_keyword: + elif len(names) == 1 and mode != "related_name": + n = list(names)[0] + if n.column is None: + if n.is_keyword: echo_highlight("Cannot get the definition of Python keywords.") else: echo_highlight("Builtin modules cannot be displayed (%s)." - % (d.full_name or d.name)) + % (n.full_name or n.name)) else: using_tagstack = int(vim_eval('g:jedi#use_tag_stack')) == 1 - module_path = str(d.module_path) + module_path = str(n.module_path) if (module_path or '') != vim.current.buffer.name: result = new_buffer(module_path, using_tagstack=using_tagstack) @@ -393,10 +392,10 @@ def goto(mode="goto"): return [] if (using_tagstack and module_path and os.path.exists(module_path)): - tagname = d.name + tagname = n.name with tempfile('{0}\t{1}\t{2}'.format( tagname, module_path, 'call cursor({0}, {1})'.format( - d.line, d.column + 1))) as f: + n.line, n.column + 1))) as f: old_tags = vim.eval('&tags') old_wildignore = vim.eval('&wildignore') try: @@ -410,10 +409,10 @@ def goto(mode="goto"): repr(PythonToVimStr(old_tags))) vim.command('let &wildignore = %s' % repr(PythonToVimStr(old_wildignore))) - vim.current.window.cursor = d.line, d.column + vim.current.window.cursor = n.line, n.column else: - show_goto_multi_results(definitions, mode) - return definitions + show_goto_multi_results(names, mode) + return names def relpath(path): @@ -424,45 +423,45 @@ def relpath(path): return path -def annotate_description(d): - code = d.get_line_code().strip() - if d.type == 'statement': +def annotate_description(n): + code = n.get_line_code().strip() + if n.type == 'statement': return code - if d.type == 'function': + if n.type == 'function': if code.startswith('def'): return code typ = 'def' else: - typ = d.type + typ = n.type return '[%s] %s' % (typ, code) -def show_goto_multi_results(definitions, mode): - """Create (or reuse) a quickfix list for multiple definitions.""" - global _current_definitions +def show_goto_multi_results(names, mode): + """Create (or reuse) a quickfix list for multiple names.""" + global _current_names lst = [] (row, col) = vim.current.window.cursor current_idx = None current_def = None - for d in definitions: - if d.column is None: + for n in names: + if n.column is None: # Typically a namespace, in the future maybe other things as # well. - lst.append(dict(text=PythonToVimStr(d.description))) + lst.append(dict(text=PythonToVimStr(n.description))) else: - text = annotate_description(d) - lst.append(dict(filename=PythonToVimStr(relpath(str(d.module_path))), - lnum=d.line, col=d.column + 1, + text = annotate_description(n) + lst.append(dict(filename=PythonToVimStr(relpath(str(n.module_path))), + lnum=n.line, col=n.column + 1, text=PythonToVimStr(text))) # Select current/nearest entry via :cc later. - if d.line == row and d.column <= col: + if n.line == row and n.column <= col: if (current_idx is None or (abs(lst[current_idx]["col"] - col) - > abs(d.column - col))): + > abs(n.column - col))): current_idx = len(lst) - current_def = d + current_def = n # Build qflist title. qf_title = mode @@ -475,8 +474,8 @@ def show_goto_multi_results(definitions, mode): else: select_entry = 0 - qf_context = id(definitions) - if (_current_definitions + qf_context = id(names) + if (_current_names and VimCompat.can_update_current_qflist_for_context(qf_context)): # Same list, only adjust title/selected entry. VimCompat.setqflist_title(qf_title) @@ -488,7 +487,7 @@ def show_goto_multi_results(definitions, mode): vim_command('%d' % select_entry) -def _same_definitions(a, b): +def _same_names(a, b): """Compare without _inference_state. Ref: https://github.com/davidhalter/jedi-vim/issues/952) @@ -504,35 +503,35 @@ def _same_definitions(a, b): @catch_and_print_exceptions def usages(visuals=True): script = get_script() - definitions = script.get_references(*get_pos()) - if not definitions: + names = script.get_references(*get_pos()) + if not names: echo_highlight("No usages found here.") - return definitions + return names if visuals: - global _current_definitions + global _current_names - if _current_definitions: - if _same_definitions(_current_definitions, definitions): - definitions = _current_definitions + if _current_names: + if _same_names(_current_names, names): + names = _current_names else: clear_usages() - assert not _current_definitions + assert not _current_names - show_goto_multi_results(definitions, "usages") - if not _current_definitions: - _current_definitions = definitions + show_goto_multi_results(names, "usages") + if not _current_names: + _current_names = names highlight_usages() else: - assert definitions is _current_definitions # updated above - return definitions + assert names is _current_names # updated above + return names -_current_definitions = None +_current_names = None """Current definitions to use for highlighting.""" -_pending_definitions = {} +_pending_names = {} """Pending definitions for unloaded buffers.""" -_placed_definitions_in_buffers = set() +_placed_names_in_buffers = set() """Set of buffers for faster cleanup.""" @@ -551,19 +550,19 @@ else: def clear_usages(): """Clear existing highlights.""" - global _current_definitions - if _current_definitions is None: + global _current_names + if _current_names is None: return - _current_definitions = None + _current_names = None if IS_NVIM: - for buf in _placed_definitions_in_buffers: + for buf in _placed_names_in_buffers: src_ids = buf.vars.get('_jedi_usages_src_ids') if src_ids is not None: for src_id in src_ids: buf.clear_highlight(src_id) elif vim_prop_add: - for buf in _placed_definitions_in_buffers: + for buf in _placed_names_in_buffers: vim_prop_remove({ 'type': 'jediUsage', 'all': 1, @@ -571,14 +570,14 @@ def clear_usages(): }) else: # Unset current window only. - assert _current_definitions is None + assert _current_names is None highlight_usages_for_vim_win() - _placed_definitions_in_buffers.clear() + _placed_names_in_buffers.clear() def highlight_usages(): - """Set definitions to be highlighted. + """Set usage names to be highlighted. With Neovim it will use the nvim_buf_add_highlight API to highlight all buffers already. @@ -587,41 +586,41 @@ def highlight_usages(): highlighted via matchaddpos, and autocommands are setup to highlight other windows on demand. Otherwise Vim's text-properties are used. """ - global _current_definitions, _pending_definitions + global _current_names, _pending_names - definitions = _current_definitions - _pending_definitions = {} + names = _current_names + _pending_names = {} if IS_NVIM or vim_prop_add: bufs = {x.name: x for x in vim.buffers} defs_per_buf = {} - for definition in definitions: + for name in names: try: - buf = bufs[str(definition.module_path)] + buf = bufs[str(name.module_path)] except KeyError: continue - defs_per_buf.setdefault(buf, []).append(definition) + defs_per_buf.setdefault(buf, []).append(name) if IS_NVIM: # We need to remember highlight ids with Neovim's API. buf_src_ids = {} - for buf, definitions in defs_per_buf.items(): + for buf, names in defs_per_buf.items(): buf_src_ids[buf] = [] - for definition in definitions: - src_id = _add_highlight_definition(buf, definition) + for name in names: + src_id = _add_highlighted_name(buf, name) buf_src_ids[buf].append(src_id) for buf, src_ids in buf_src_ids.items(): buf.vars['_jedi_usages_src_ids'] = src_ids else: - for buf, definitions in defs_per_buf.items(): + for buf, names in defs_per_buf.items(): try: - for definition in definitions: - _add_highlight_definition(buf, definition) + for name in names: + _add_highlighted_name(buf, name) except vim.error as exc: if exc.args[0].startswith('Vim:E275:'): # "Cannot add text property to unloaded buffer" - _pending_definitions.setdefault(buf.name, []).extend( - definitions) + _pending_names.setdefault(buf.name, []).extend( + names) else: highlight_usages_for_vim_win() @@ -631,29 +630,29 @@ def _handle_pending_usages_for_buf(): buf = vim.current.buffer bufname = buf.name try: - buf_defs = _pending_definitions[bufname] + buf_names = _pending_names[bufname] except KeyError: return - for definition in buf_defs: - _add_highlight_definition(buf, definition) - del _pending_definitions[bufname] + for name in buf_names: + _add_highlighted_name(buf, name) + del _pending_names[bufname] -def _add_highlight_definition(buf, definition): - lnum = definition.line - start_col = definition.column +def _add_highlighted_name(buf, name): + lnum = name.line + start_col = name.column # Skip highlighting of module definitions that point to the start # of the file. - if definition.type == 'module' and lnum == 1 and start_col == 0: + if name.type == 'module' and lnum == 1 and start_col == 0: return - _placed_definitions_in_buffers.add(buf) + _placed_names_in_buffers.add(buf) - # TODO: validate that definition.name is at this position? + # TODO: validate that name.name is at this position? # Would skip the module definitions from above already. - length = len(definition.name) + length = len(name.name) if vim_prop_add: # XXX: needs jediUsage highlight (via after/syntax/python.vim). global vim_prop_type_added @@ -668,7 +667,7 @@ def _add_highlight_definition(buf, definition): return assert IS_NVIM - end_col = definition.column + length + end_col = name.column + length src_id = buf.add_highlight('jediUsage', lnum-1, start_col, end_col, src_id=0) return src_id @@ -681,9 +680,6 @@ def highlight_usages_for_vim_win(): (matchaddpos() only works for the current window.) """ - global _current_definitions - definitions = _current_definitions - win = vim.current.window cur_matchids = win.vars.get('_jedi_usages_vim_matchids') @@ -697,14 +693,14 @@ def highlight_usages_for_vim_win(): vim.eval(expr) matchids = [] - if definitions: + if _current_names: buffer_path = vim.current.buffer.name - for definition in definitions: - if (str(definition.module_path) or '') == buffer_path: + for name in _current_names: + if (str(name.module_path) or '') == buffer_path: positions = [ - [definition.line, - definition.column + 1, - len(definition.name)] + [name.line, + name.column + 1, + len(name.name)] ] expr = "matchaddpos('jediUsage', %s)" % repr(positions) matchids.append(int(vim_eval(expr))) @@ -726,27 +722,27 @@ def highlight_usages_for_vim_win(): def show_documentation(): script = get_script() try: - definitions = script.help(*get_pos()) + names = script.help(*get_pos()) except Exception: # print to stdout, will be in :messages - definitions = [] + names = [] print("Exception, this shouldn't happen.") print(traceback.format_exc()) - if not definitions: + if not names: echo_highlight('No documentation found for that.') vim.command('return') return docs = [] - for d in definitions: - doc = d.docstring() + for n in names: + doc = n.docstring() if doc: - title = 'Docstring for %s' % (d.full_name or d.name) + title = 'Docstring for %s' % (n.full_name or n.name) underline = '=' * len(title) docs.append('%s\n%s\n%s' % (title, underline, doc)) else: - docs.append('|No Docstring for %s|' % d) + docs.append('|No Docstring for %s|' % n) text = ('\n' + '-' * 79 + '\n').join(docs) vim.command('let l:doc = %s' % repr(PythonToVimStr(text))) vim.command('let l:doc_lines = %s' % len(text.split('\n'))) From 5858a999def64628bfb974ab35f2fdb5a9f04d1c Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Thu, 30 Jul 2020 14:36:40 +0200 Subject: [PATCH 04/22] Unify Pyimport and goto --- pythonx/jedi_vim.py | 82 ++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/pythonx/jedi_vim.py b/pythonx/jedi_vim.py index 7a15732..46b1b05 100644 --- a/pythonx/jedi_vim.py +++ b/pythonx/jedi_vim.py @@ -376,45 +376,49 @@ def goto(mode="goto"): echo_highlight("Couldn't find any definitions for this.") elif len(names) == 1 and mode != "related_name": n = list(names)[0] - if n.column is None: - if n.is_keyword: - echo_highlight("Cannot get the definition of Python keywords.") - else: - echo_highlight("Builtin modules cannot be displayed (%s)." - % (n.full_name or n.name)) - else: - using_tagstack = int(vim_eval('g:jedi#use_tag_stack')) == 1 - module_path = str(n.module_path) - if (module_path or '') != vim.current.buffer.name: - result = new_buffer(module_path, - using_tagstack=using_tagstack) - if not result: - return [] - if (using_tagstack and module_path and - os.path.exists(module_path)): - tagname = n.name - with tempfile('{0}\t{1}\t{2}'.format( - tagname, module_path, 'call cursor({0}, {1})'.format( - n.line, n.column + 1))) as f: - old_tags = vim.eval('&tags') - old_wildignore = vim.eval('&wildignore') - try: - # Clear wildignore to ensure tag file isn't ignored - vim.command('set wildignore=') - vim.command('let &tags = %s' % - repr(PythonToVimStr(f.name))) - vim.command('tjump %s' % tagname) - finally: - vim.command('let &tags = %s' % - repr(PythonToVimStr(old_tags))) - vim.command('let &wildignore = %s' % - repr(PythonToVimStr(old_wildignore))) - vim.current.window.cursor = n.line, n.column + _goto_specific_name(n) else: show_goto_multi_results(names, mode) return names +def _goto_specific_name(n, options=''): + if n.column is None: + if n.is_keyword: + echo_highlight("Cannot get the definition of Python keywords.") + else: + echo_highlight("Builtin modules cannot be displayed (%s)." + % (n.full_name or n.name)) + else: + using_tagstack = int(vim_eval('g:jedi#use_tag_stack')) == 1 + module_path = str(n.module_path) + if (module_path or '') != vim.current.buffer.name: + result = new_buffer(module_path, options=options, + using_tagstack=using_tagstack) + if not result: + return [] + if (using_tagstack and module_path and + os.path.exists(module_path)): + tagname = n.name + with tempfile('{0}\t{1}\t{2}'.format( + tagname, module_path, 'call cursor({0}, {1})'.format( + n.line, n.column + 1))) as f: + old_tags = vim.eval('&tags') + old_wildignore = vim.eval('&wildignore') + try: + # Clear wildignore to ensure tag file isn't ignored + vim.command('set wildignore=') + vim.command('let &tags = %s' % + repr(PythonToVimStr(f.name))) + vim.command('tjump %s' % tagname) + finally: + vim.command('let &tags = %s' % + repr(PythonToVimStr(old_tags))) + vim.command('let &wildignore = %s' % + repr(PythonToVimStr(old_wildignore))) + vim.current.window.cursor = n.line, n.column + + def relpath(path): """Make path relative to cwd if it is below.""" abspath = os.path.abspath(path) @@ -1045,18 +1049,14 @@ def do_rename(replace, orig=None): @_check_jedi_availability(show_error=True) @catch_and_print_exceptions def py_import(): - # args are the same as for the :edit command args = shsplit(vim.eval('a:args')) import_path = args.pop() name = next(get_project().search(import_path), None) if name is None: - echo_highlight('Cannot find %s in sys.path!' % import_path) + echo_highlight('Cannot find %s in your project or on sys.path!' % import_path) else: - if name.column is None: # Python modules always have a line number. - echo_highlight('%s is a builtin module.' % import_path) - else: - cmd_args = ' '.join([a.replace(' ', '\\ ') for a in args]) - new_buffer(str(name.module_path), cmd_args) + cmd_args = ' '.join([a.replace(' ', '\\ ') for a in args]) + _goto_specific_name(name, options=cmd_args) @catch_and_print_exceptions From c4fc2cde8c1998d9fe90777d77e7ced90c63afee Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Thu, 30 Jul 2020 15:45:12 +0200 Subject: [PATCH 05/22] Use projects instead of environments --- pythonx/jedi_vim.py | 60 +++++++++++++++++---------------------- pythonx/jedi_vim_debug.py | 3 +- 2 files changed, 28 insertions(+), 35 deletions(-) diff --git a/pythonx/jedi_vim.py b/pythonx/jedi_vim.py index 46b1b05..ba0e6c5 100644 --- a/pythonx/jedi_vim.py +++ b/pythonx/jedi_vim.py @@ -92,11 +92,6 @@ def vim_eval(string): return _catch_exception(string, is_eval=True) -def get_project(): - # TODO remove get_environment() in favor of this. - return jedi.get_default_project() - - def no_jedi_warning(error=None): vim.command('echohl WarningMsg') vim.command('echom "Please install Jedi if you want to use jedi-vim."') @@ -216,40 +211,37 @@ def _check_jedi_availability(show_error=False): return func_receiver -current_environment = (None, None) +_current_project_cache = None, None -def get_environment(use_cache=True): - global current_environment +def _create_project_cache_key(project_path, environment_path): + return dict(project_path=project_path, environment_path=environment_path) - vim_force_python_version = vim_eval("g:jedi#force_py_version") - if use_cache and vim_force_python_version == current_environment[0]: - return current_environment[1] - environment = None - if vim_force_python_version == "auto": - environment = jedi.api.environment.get_cached_default_environment() +def get_project(): + global _current_project_cache + + vim_environment_path = vim_eval("g:jedi#environment_path") + vim_project_path = vim_eval("g:jedi#project_path") + cache_key = _create_project_cache_key(vim_project_path, vim_environment_path) + + if cache_key == _current_project_cache[0]: + return _current_project_cache[1] + + if vim_environment_path in ("auto", "", None): + environment_path = None else: - force_python_version = vim_force_python_version - if '0000' in force_python_version or '9999' in force_python_version: - # It's probably a float that wasn't shortened. - try: - force_python_version = "{:.1f}".format(float(force_python_version)) - except ValueError: - pass - elif isinstance(force_python_version, float): - force_python_version = "{:.1f}".format(force_python_version) + environment_path = vim_environment_path - try: - environment = jedi.get_system_environment(force_python_version) - except jedi.InvalidPythonEnvironment as exc: - environment = jedi.api.environment.get_cached_default_environment() - echo_highlight( - "force_python_version=%s is not supported: %s - using %s." % ( - vim_force_python_version, str(exc), str(environment))) + if vim_project_path == ("auto", "", None): + project_path = jedi.get_default_project().path + else: + project_path = vim_project_path - current_environment = (vim_force_python_version, environment) - return environment + project = jedi.Project(project_path, environment_path=environment_path) + + _current_project_cache = cache_key, project + return project def get_known_environments(): @@ -270,7 +262,7 @@ def get_script(source=None): source = '\n'.join(vim.current.buffer) buf_path = vim.current.buffer.name - return jedi.Script(source, path=buf_path, environment=get_environment()) + return jedi.Script(source, path=buf_path, project=get_project()) def get_pos(column=None): @@ -1067,7 +1059,7 @@ def py_import_completions(): comps = [] else: names = get_project().complete_search(argl) - comps = [argl + n for n in set(c.complete for c in names)] + comps = [argl + n for n in sorted(set(c.complete for c in names))] vim.command("return '%s'" % '\n'.join(comps)) diff --git a/pythonx/jedi_vim_debug.py b/pythonx/jedi_vim_debug.py index 69c59b6..8b052da 100644 --- a/pythonx/jedi_vim_debug.py +++ b/pythonx/jedi_vim_debug.py @@ -58,7 +58,8 @@ def display_debug_info(): echo(' - version: {0}'.format(jedi_vim.jedi.__version__)) try: - environment = jedi_vim.get_environment(use_cache=False) + project = jedi_vim.get_project() + environment = project.get_environment() except AttributeError: script_evaluator = jedi_vim.jedi.Script('')._evaluator try: From 2949389be4936da934afbe401c98f8641596a7c9 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Thu, 30 Jul 2020 18:16:35 +0200 Subject: [PATCH 06/22] Describe the environment_path option properly --- README.rst | 5 +++++ doc/jedi-vim.txt | 12 ++++++++++++ pythonx/jedi_vim.py | 7 ++----- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index 1da847a..bca0be7 100644 --- a/README.rst +++ b/README.rst @@ -208,6 +208,11 @@ get more information. If you set them to ``""``, they are not assigned. let g:jedi#completions_command = "" let g:jedi#rename_command = "r" +A few examples of setting up your project: + +.. code-block:: vim + + let g:jedi#environment_path = "d" Finally, if you don't want completion, but all the other features, use: diff --git a/doc/jedi-vim.txt b/doc/jedi-vim.txt index 32012d5..2a53532 100644 --- a/doc/jedi-vim.txt +++ b/doc/jedi-vim.txt @@ -44,6 +44,7 @@ Contents *jedi-vim-contents* 6.12. force_py_version |g:jedi#force_py_version| 6.13. smart_auto_mappings |g:jedi#smart_auto_mappings| 6.14. use_tag_stack |g:jedi#use_tag_stack| + 6.15. environment_path |g:jedi#environment_path| 7. Testing |jedi-vim-testing| 8. Contributing |jedi-vim-contributing| 9. License |jedi-vim-license| @@ -506,6 +507,17 @@ definition with arbitrary changes to the |jumplist|. Options: 0 or 1 Default: 1 (enabled by default) +------------------------------------------------------------------------------ +6.15. `g:jedi#environment_path` *g:jedi#environment_path* + +To use a specific virtualenv or a specific Python version it is possible to +set an interpreter. + +Both setting the directory and setting a project is working. + +Examples: "/usr/bin/python3.9", "venv", "../venv", "../venv/bin/python" +Default: "auto" + ============================================================================== 7. Testing *jedi-vim-testing* diff --git a/pythonx/jedi_vim.py b/pythonx/jedi_vim.py index ba0e6c5..056ab97 100644 --- a/pythonx/jedi_vim.py +++ b/pythonx/jedi_vim.py @@ -211,19 +211,16 @@ def _check_jedi_availability(show_error=False): return func_receiver +# Tuple of cache key / project _current_project_cache = None, None -def _create_project_cache_key(project_path, environment_path): - return dict(project_path=project_path, environment_path=environment_path) - - def get_project(): global _current_project_cache vim_environment_path = vim_eval("g:jedi#environment_path") vim_project_path = vim_eval("g:jedi#project_path") - cache_key = _create_project_cache_key(vim_project_path, vim_environment_path) + cache_key = dict(project_path=vim_project_path, environment_path=vim_environment_path) if cache_key == _current_project_cache[0]: return _current_project_cache[1] From 104d817f0ced91ba7356ca9fefcea7e7831a8094 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Thu, 30 Jul 2020 18:37:27 +0200 Subject: [PATCH 07/22] environment_path needs to be defined properly --- autoload/jedi.vim | 2 ++ pythonx/jedi_vim.py | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/autoload/jedi.vim b/autoload/jedi.vim index d21afec..9275d59 100644 --- a/autoload/jedi.vim +++ b/autoload/jedi.vim @@ -35,6 +35,8 @@ let s:default_settings = { \ 'popup_select_first': 1, \ 'quickfix_window_height': 10, \ 'force_py_version': "'auto'", + \ 'environment_path': "'auto'", + \ 'project_path': "'auto'", \ 'smart_auto_mappings': 0, \ 'use_tag_stack': 1 \ } diff --git a/pythonx/jedi_vim.py b/pythonx/jedi_vim.py index 056ab97..2d39f1d 100644 --- a/pythonx/jedi_vim.py +++ b/pythonx/jedi_vim.py @@ -216,12 +216,11 @@ _current_project_cache = None, None def get_project(): - global _current_project_cache - vim_environment_path = vim_eval("g:jedi#environment_path") vim_project_path = vim_eval("g:jedi#project_path") - cache_key = dict(project_path=vim_project_path, environment_path=vim_environment_path) + global _current_project_cache + cache_key = dict(project_path=vim_project_path, environment_path=vim_environment_path) if cache_key == _current_project_cache[0]: return _current_project_cache[1] From e23687462b17c038bd8bfa1d1b50460803c4f645 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 31 Jul 2020 15:06:09 +0200 Subject: [PATCH 08/22] Implement :JediChooseEnvironment --- autoload/jedi.vim | 4 ++++ plugin/jedi.vim | 3 +++ pythonx/jedi_vim.py | 24 +++++++++++++++++++----- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/autoload/jedi.vim b/autoload/jedi.vim index 9275d59..2786e2e 100644 --- a/autoload/jedi.vim +++ b/autoload/jedi.vim @@ -424,6 +424,10 @@ function! jedi#py_import(args) abort PythonJedi jedi_vim.py_import() endfun +function! jedi#choose_environment(args) abort + PythonJedi jedi_vim.choose_environment() +endfun + function! jedi#py_import_completions(argl, cmdl, pos) abort PythonJedi jedi_vim.py_import_completions() endfun diff --git a/plugin/jedi.vim b/plugin/jedi.vim index f8fe4b2..245548a 100644 --- a/plugin/jedi.vim +++ b/plugin/jedi.vim @@ -53,6 +53,9 @@ endif " Pyimport command command! -nargs=1 -complete=custom,jedi#py_import_completions Pyimport :call jedi#py_import() +command! -nargs=? -complete=file JediChooseEnvironment :call jedi#choose_environment() + + function! s:jedi_debug_info() " Ensure the autoload file has been loaded (and ignore any errors, which " will be displayed with the debug info). diff --git a/pythonx/jedi_vim.py b/pythonx/jedi_vim.py index 2d39f1d..1fd0fa6 100644 --- a/pythonx/jedi_vim.py +++ b/pythonx/jedi_vim.py @@ -240,11 +240,25 @@ def get_project(): return project -def get_known_environments(): - """Get known Jedi environments.""" - envs = list(jedi.api.environment.find_virtualenvs()) - envs.extend(jedi.api.environment.find_system_environments()) - return envs +def choose_environment(): + args = shsplit(vim.eval('a:args')) + + envs = list(jedi.find_system_environments()) + envs.extend(jedi.find_virtualenvs(paths=args or None)) + + env_paths = [env.executable for env in envs] + + vim_command('belowright new') + vim.current.buffer[:] = env_paths + vim.current.buffer.name = "Hit Enter to Choose an Environment" + vim_command('setlocal buftype=nofile bufhidden=hide noswapfile readonly nomodifiable') + vim_command('noremap :bd') + vim_command('noremap :PythonJedi jedi_vim.choose_environment_hit_enter()') + + +def choose_environment_hit_enter(): + vim.vars['jedi#environment_path'] = vim.current.line + vim_command('bd') @catch_and_print_exceptions From 6edda9063a63312191a26478207f56f138b4cb52 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 31 Jul 2020 20:25:12 +0200 Subject: [PATCH 09/22] Make choose environment buffer disappear if it's not visible anymore --- pythonx/jedi_vim.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pythonx/jedi_vim.py b/pythonx/jedi_vim.py index 1fd0fa6..ea6f033 100644 --- a/pythonx/jedi_vim.py +++ b/pythonx/jedi_vim.py @@ -251,8 +251,8 @@ def choose_environment(): vim_command('belowright new') vim.current.buffer[:] = env_paths vim.current.buffer.name = "Hit Enter to Choose an Environment" - vim_command('setlocal buftype=nofile bufhidden=hide noswapfile readonly nomodifiable') - vim_command('noremap :bd') + vim_command('setlocal buftype=nofile bufhidden=wipe noswapfile nobuflisted readonly nomodifiable') + vim_command('noremap :bw') vim_command('noremap :PythonJedi jedi_vim.choose_environment_hit_enter()') From 2c157e323e2c4f0a57809837a52774559d10818e Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sat, 1 Aug 2020 00:12:24 +0200 Subject: [PATCH 10/22] Fix documentation tests --- pythonx/jedi_vim.py | 5 +++-- test/vspec/documentation.vim | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pythonx/jedi_vim.py b/pythonx/jedi_vim.py index ea6f033..8606d2b 100644 --- a/pythonx/jedi_vim.py +++ b/pythonx/jedi_vim.py @@ -251,7 +251,8 @@ def choose_environment(): vim_command('belowright new') vim.current.buffer[:] = env_paths vim.current.buffer.name = "Hit Enter to Choose an Environment" - vim_command('setlocal buftype=nofile bufhidden=wipe noswapfile nobuflisted readonly nomodifiable') + vim_command( + 'setlocal buftype=nofile bufhidden=wipe noswapfile nobuflisted readonly nomodifiable') vim_command('noremap :bw') vim_command('noremap :PythonJedi jedi_vim.choose_environment_hit_enter()') @@ -744,7 +745,7 @@ def show_documentation(): for n in names: doc = n.docstring() if doc: - title = 'Docstring for %s' % (n.full_name or n.name) + title = 'Docstring for %s %s' % (n.type, n.full_name or n.name) underline = '=' * len(title) docs.append('%s\n%s\n%s' % (title, underline, doc)) else: diff --git a/test/vspec/documentation.vim b/test/vspec/documentation.vim index 074e608..948d12d 100644 --- a/test/vspec/documentation.vim +++ b/test/vspec/documentation.vim @@ -18,10 +18,10 @@ describe 'documentation docstrings' let header = getline(1, 2) PythonJedi vim.vars["is_py2"] = sys.version_info[0] == 2 if g:is_py2 - Expect header[0] == "Docstring for __builtin__:class ImportError" + Expect header[0] == "Docstring for class __builtin__.ImportError" Expect header[1] == "===========================================" else - Expect header[0] == "Docstring for builtins:class ImportError" + Expect header[0] == "Docstring for class builtins.ImportError" Expect header[1] == "========================================" endif let content = join(getline(3, '$'), "\n") From 01e6e6bcf7f8c0d2a2d977141b928b43b402c9c6 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sat, 1 Aug 2020 00:15:46 +0200 Subject: [PATCH 11/22] Fix debug info --- pythonx/jedi_vim_debug.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pythonx/jedi_vim_debug.py b/pythonx/jedi_vim_debug.py index 8b052da..2c67322 100644 --- a/pythonx/jedi_vim_debug.py +++ b/pythonx/jedi_vim_debug.py @@ -2,7 +2,7 @@ import sys import vim -from jedi_vim import PythonToVimStr +from jedi_vim import PythonToVimStr, jedi def echo(msg): @@ -32,6 +32,13 @@ def format_exc_info(exc_info=None, tb_indent=2): return '{0}'.format(('\n' + indent).join(lines)) +def get_known_environments(): + """Get known Jedi environments.""" + envs = list(jedi.find_virtualenvs()) + envs.extend(jedi.find_system_environments()) + return envs + + def display_debug_info(): echo(' - global sys.executable: `{0}`'.format(sys.executable)) echo(' - global sys.version: `{0}`'.format( @@ -82,7 +89,7 @@ def display_debug_info(): if environment: echo('\n##### Known environments\n\n') - for environment in jedi_vim.get_known_environments(): + for environment in get_known_environments(): echo(' - {0} ({1})\n'.format( environment, environment.executable, From 87abaf0781ebbda1b13c439e12f2202b9dca3f12 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sat, 1 Aug 2020 00:30:54 +0200 Subject: [PATCH 12/22] Fix goto issues --- pythonx/jedi_vim.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pythonx/jedi_vim.py b/pythonx/jedi_vim.py index 8606d2b..42d3828 100644 --- a/pythonx/jedi_vim.py +++ b/pythonx/jedi_vim.py @@ -394,8 +394,8 @@ def _goto_specific_name(n, options=''): % (n.full_name or n.name)) else: using_tagstack = int(vim_eval('g:jedi#use_tag_stack')) == 1 - module_path = str(n.module_path) - if (module_path or '') != vim.current.buffer.name: + module_path = str(n.module_path or '') + if module_path != vim.current.buffer.name: result = new_buffer(module_path, options=options, using_tagstack=using_tagstack) if not result: From 862fbbc8a9eec2d1340fcd2b5ba0dfbe24087ec8 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sat, 1 Aug 2020 11:16:57 +0200 Subject: [PATCH 13/22] Add a choose-venv test --- test/vspec/choose-venv.vim | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 test/vspec/choose-venv.vim diff --git a/test/vspec/choose-venv.vim b/test/vspec/choose-venv.vim new file mode 100644 index 0000000..3c2c6ac --- /dev/null +++ b/test/vspec/choose-venv.vim @@ -0,0 +1,29 @@ +source plugin/jedi.vim +source test/_utils.vim + +describe 'simple:' + before + new + normal! ifoo + end + + after + bd! + end + + it 'choose' + Expect g:jedi#environment_path == 'auto' + Expect bufname() == '' + + JediChooseEnvironment + " A Python executable needs to be a few letters + Expect len(getline('.')) > 5 + Expect bufname() == 'Hit Enter to Choose an Environment' + + execute "normal \" + Expect g:jedi#environment_path != 'auto' + bd " TODO why is this necessary? There seems to be a random buffer. + Expect bufname() == '' + Expect getline('.') == 'foo' + end +end From 6efd966481c9ede5e69810cf59e275a631af158c Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sat, 1 Aug 2020 12:01:54 +0200 Subject: [PATCH 14/22] Remove multi definition tests that are not really working anymore because of changes in Jedi --- test/vspec/goto.vim | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/test/vspec/goto.vim b/test/vspec/goto.vim index 002f793..c5306f6 100644 --- a/test/vspec/goto.vim +++ b/test/vspec/goto.vim @@ -73,27 +73,6 @@ describe 'goto with tabs:' Expect tabpagenr('$') == 1 Expect bufname('%') == '' end - - " it 'multi definitions' - " " This used to behave differently. Now we don't have any real multi - " " definitions. - " - " " put = ['import tokenize'] - " " normal G$\d - " " Expect CurrentBufferIsModule('tokenize') == 1 - " " Expect CurrentBufferIsModule('token') == 0 - " " execute "normal \" - " " Expect tabpagenr('$') == 2 - " " Expect winnr('$') == 1 - " " Expect CurrentBufferIsModule('token') == 1 - " - " " bd - " " normal G$\d - " " execute "normal j\" - " " Expect tabpagenr('$') == 2 - " " Expect winnr('$') == 1 - " " Expect CurrentBufferIsModule('tokenize') == 1 - " end end @@ -124,25 +103,6 @@ describe 'goto with buffers' Expect line('.') == 1 Expect col('.') == 1 end - - " it 'multi definitions' - " " set hidden - " " put = ['import tokenize'] - " " normal G$\d - " " Expect CurrentBufferIsModule('tokenize') == 0 - " " Expect CurrentBufferIsModule('token') == 0 - " " execute "normal \" - " " Expect tabpagenr('$') == 1 - " " Expect winnr('$') == 1 - " " Expect CurrentBufferIsModule('token') == 1 - " - " " bd - " " normal G$\d - " " execute "normal j\" - " " Expect tabpagenr('$') == 1 - " " Expect winnr('$') == 1 - " " Expect CurrentBufferIsModule('tokenize') == 1 - " end end From 74fd73d017f237dcbae7be94012ba7c26d1886ff Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sat, 1 Aug 2020 13:32:48 +0200 Subject: [PATCH 15/22] Added an undocumented JediLoadProject for now --- autoload/jedi.vim | 4 ++++ plugin/jedi.vim | 1 + pythonx/jedi_vim.py | 25 +++++++++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/autoload/jedi.vim b/autoload/jedi.vim index 2786e2e..82184b6 100644 --- a/autoload/jedi.vim +++ b/autoload/jedi.vim @@ -428,6 +428,10 @@ function! jedi#choose_environment(args) abort PythonJedi jedi_vim.choose_environment() endfun +function! jedi#load_project(args) abort + PythonJedi jedi_vim.load_project() +endfun + function! jedi#py_import_completions(argl, cmdl, pos) abort PythonJedi jedi_vim.py_import_completions() endfun diff --git a/plugin/jedi.vim b/plugin/jedi.vim index 245548a..d409240 100644 --- a/plugin/jedi.vim +++ b/plugin/jedi.vim @@ -54,6 +54,7 @@ endif command! -nargs=1 -complete=custom,jedi#py_import_completions Pyimport :call jedi#py_import() command! -nargs=? -complete=file JediChooseEnvironment :call jedi#choose_environment() +command! -nargs=? -complete=file JediLoadProject :call jedi#load_project() function! s:jedi_debug_info() diff --git a/pythonx/jedi_vim.py b/pythonx/jedi_vim.py index 42d3828..b215f8a 100644 --- a/pythonx/jedi_vim.py +++ b/pythonx/jedi_vim.py @@ -240,6 +240,7 @@ def get_project(): return project +@catch_and_print_exceptions def choose_environment(): args = shsplit(vim.eval('a:args')) @@ -257,11 +258,35 @@ def choose_environment(): vim_command('noremap :PythonJedi jedi_vim.choose_environment_hit_enter()') +@catch_and_print_exceptions def choose_environment_hit_enter(): vim.vars['jedi#environment_path'] = vim.current.line vim_command('bd') +@catch_and_print_exceptions +def load_project(): + path = vim.eval('a:args') + vim.vars['jedi#project_path'] = path + env_path = vim_eval("g:jedi#environment_path") + if env_path == 'auto': + env_path = None + if path: + try: + project = jedi.Project.load(path) + except FileNotFoundError: + project = jedi.Project(path, environment_path=env_path) + project.save() + else: + project = jedi.get_default_project() + path = project.path + project.save() + + global _current_project_cache + cache_key = dict(project_path=path, environment_path=env_path) + _current_project_cache = cache_key, project + + @catch_and_print_exceptions def get_script(source=None): jedi.settings.additional_dynamic_modules = [ From 48b3e5c0e7cae713fe2dd85e3219e0be9cfcd7bc Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Tue, 4 Aug 2020 15:07:39 +0200 Subject: [PATCH 16/22] In older versions of VIM bufname needs an argument --- test/vspec/choose-venv.vim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/vspec/choose-venv.vim b/test/vspec/choose-venv.vim index 3c2c6ac..d93ea07 100644 --- a/test/vspec/choose-venv.vim +++ b/test/vspec/choose-venv.vim @@ -13,17 +13,17 @@ describe 'simple:' it 'choose' Expect g:jedi#environment_path == 'auto' - Expect bufname() == '' + Expect bufname('%') == '' JediChooseEnvironment " A Python executable needs to be a few letters Expect len(getline('.')) > 5 - Expect bufname() == 'Hit Enter to Choose an Environment' + Expect bufname('%') == 'Hit Enter to Choose an Environment' execute "normal \" Expect g:jedi#environment_path != 'auto' bd " TODO why is this necessary? There seems to be a random buffer. - Expect bufname() == '' + Expect bufname('%') == '' Expect getline('.') == 'foo' end end From acbb71290634a749554825d7f9087b9b79472b65 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Tue, 4 Aug 2020 15:09:01 +0200 Subject: [PATCH 17/22] Try and update the CI from Ubuntu 16.04 to 18.04 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ffcf8df..9cbb318 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ -dist: xenial +dist: bionic language: python -python: 3.7 +python: 3.8 env: matrix: - ENV=test From 6193c9fd954c241d99db08f194c9112e28a982d5 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Tue, 4 Aug 2020 15:22:38 +0200 Subject: [PATCH 18/22] Remove the Python 2 support It should mostly still work (except for :Pyimport), but it won't pass all the tests anymore. Since I'm dropping Python 2 in Jedi anyways, it makes sense to also remove it here. --- .travis.yml | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9cbb318..7c2db15 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,16 +2,9 @@ dist: bionic language: python python: 3.8 env: - matrix: - - ENV=test - - ENV=check - - ENV=test_coverage -matrix: - include: - - env: ENV=test_coverage - python: 2.7 - - env: ENV=test_coverage - python: 3.8 + - ENV=test + - ENV=check + - ENV=test_coverage install: - | if [ "$ENV" = "test" ]; then From a76965238a8cac55caeb1a41aa745e3cb9cf3143 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 23 Oct 2020 17:45:40 +0200 Subject: [PATCH 19/22] Fix the project choice --- pythonx/jedi_vim.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pythonx/jedi_vim.py b/pythonx/jedi_vim.py index b215f8a..2904927 100644 --- a/pythonx/jedi_vim.py +++ b/pythonx/jedi_vim.py @@ -229,7 +229,7 @@ def get_project(): else: environment_path = vim_environment_path - if vim_project_path == ("auto", "", None): + if vim_project_path in ("auto", "", None): project_path = jedi.get_default_project().path else: project_path = vim_project_path From dc0fdc55cb1696341344a6398c692584aa400e0f Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 25 Dec 2020 12:45:23 +0100 Subject: [PATCH 20/22] Updated jedi and parso --- pythonx/jedi | 2 +- pythonx/parso | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pythonx/jedi b/pythonx/jedi index 3b7106a..4b5b2e7 160000 --- a/pythonx/jedi +++ b/pythonx/jedi @@ -1 +1 @@ -Subproject commit 3b7106ae71cb7bd3431101d169a0110ee0c179aa +Subproject commit 4b5b2e791b66f3a99542bc2a0e1d5730dc1491df diff --git a/pythonx/parso b/pythonx/parso index c864ca6..ef90bba 160000 --- a/pythonx/parso +++ b/pythonx/parso @@ -1 +1 @@ -Subproject commit c864ca60d1a2f36524a4f79013a7de223e65e19d +Subproject commit ef90bba3b3d4310c345885a1368dbfc8937765a3 From 04ba9a2430df874dcd581e5c792531a3dca59e06 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 25 Dec 2020 17:44:22 +0100 Subject: [PATCH 21/22] A small fix --- pythonx/jedi_vim.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pythonx/jedi_vim.py b/pythonx/jedi_vim.py index 2904927..3685c9c 100644 --- a/pythonx/jedi_vim.py +++ b/pythonx/jedi_vim.py @@ -297,6 +297,9 @@ def get_script(source=None): if source is None: source = '\n'.join(vim.current.buffer) buf_path = vim.current.buffer.name + if not buf_path: + # If a buffer has no name its name is an empty string. + buf_path = None return jedi.Script(source, path=buf_path, project=get_project()) From ea52ca53051f83fab4e3a683ff0f2fe19966a35a Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sat, 26 Dec 2020 23:07:58 +0100 Subject: [PATCH 22/22] Try to use GitHub Actions --- .github/workflows/ci.yml | 63 ++++++++++++++++++++++++++++++++++++++++ test/vspec/pyimport.vim | 2 ++ 2 files changed, 65 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..d238101 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,63 @@ +name: ci +on: push + +jobs: + tests: + runs-on: ubuntu-20.04 + steps: + - name: Checkout code + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Setup + run: | + sudo pip install pytest + vim --version + + #- name: Setup tmate session + # uses: mxschmitt/action-tmate@v3 + + - name: Run tests + run: 'make test' + + code-quality: + runs-on: ubuntu-20.04 + steps: + - name: Checkout code + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Run tests + run: | + vim --version + make check + + coverage: + runs-on: ubuntu-20.04 + + steps: + - name: Checkout code + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Install dependencies + run: | + sudo add-apt-repository ppa:neovim-ppa/stable -y + sudo apt-get update -q + sudo apt-get install neovim -y + + sudo pip install pynvim pytest-cov + sudo pip list + nvim --version + + - name: Run tests + run: | + make --keep-going test_coverage BUILD_VIRTUAL_ENV=$VIRTUAL_ENV + + - name: Upload coverage data + run: | + coverage xml + bash <(curl -s https://codecov.io/bash) -X fix -f coverage.xml -F py${TRAVIS_PYTHON_VERSION//./} diff --git a/test/vspec/pyimport.vim b/test/vspec/pyimport.vim index ed54db1..fb4bc52 100644 --- a/test/vspec/pyimport.vim +++ b/test/vspec/pyimport.vim @@ -4,10 +4,12 @@ source test/_utils.vim describe 'pyimport' before let g:jedi#use_tabs_not_buffers = 1 + let g:jedi#project_path = 'autoload' end after try | %bwipeout! | catch | endtry + unlet g:jedi#project_path end it 'open_tab'