From 54f30f6e509a711fc800abd8561022db0a9f4f67 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sat, 23 Jun 2018 11:37:19 +0200 Subject: [PATCH] WIP: improve selection of environments --- autoload/jedi.vim | 17 +++++++++++ plugin/jedi.vim | 16 ++++++++++ pythonx/jedi_vim.py | 71 +++++++++++++++++++++++++++++++++------------ 3 files changed, 86 insertions(+), 18 deletions(-) diff --git a/autoload/jedi.vim b/autoload/jedi.vim index e106b47e..a3228678 100644 --- a/autoload/jedi.vim +++ b/autoload/jedi.vim @@ -36,6 +36,8 @@ let s:default_settings = { \ 'quickfix_window_height': 10, \ 'force_py_version': "'auto'", \ 'smart_auto_mappings': 0, + \ 'use_environment': "'auto'", + \ 'environment_paths': '[]', \ 'use_tag_stack': 1 \ } @@ -289,6 +291,14 @@ call jedi#init_python() " Might throw an error. " ------------------------------------------------------------------------ " functions that call python code " ------------------------------------------------------------------------ +function! jedi#use_environment(...) abort + PythonJedi jedi_vim.set_environment(*vim.eval('a:000')) +endfunction + +function! jedi#use_environment_for_buffer(env) abort + PythonJedi jedi_vim.set_environment(*vim.eval('[env, bufnr("%")]')) +endfunction + function! jedi#goto() abort PythonJedi jedi_vim.goto(mode="goto") endfunction @@ -753,6 +763,13 @@ function! jedi#setup_completion() abort endif endfunction +" TODO: fallback to completing files (i.e. return known envs first, then +" files?!). +function! jedi#complete_environments(argl, cmdl, pos) abort + PythonJedi jedi_vim.complete_environments() +EOF +endfunction + "PythonJedi jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout, speed=True, warnings=False, notices=False) "PythonJedi jedi_vim.jedi.set_debug_function(jedi_vim.print_to_stdout) diff --git a/plugin/jedi.vim b/plugin/jedi.vim index f8fe4b21..58a58a19 100644 --- a/plugin/jedi.vim +++ b/plugin/jedi.vim @@ -68,6 +68,22 @@ function! s:jedi_debug_info() call jedi#debug_info() endfunction command! -nargs=0 -bar JediDebugInfo call s:jedi_debug_info() + +" Transfer bang into current buffer number. +" TODO: use window instead!? +function! s:use_environment(bang, env) abort + let bufnr = a:bang ? +bufnr('%') : 0 + if a:env ==# 'auto' + let env = '' + elseif a:env[-4:] ==# ' (*)' + let env = a:env[:-5] + else + let env = a:env + endif + return jedi#use_environment(env, bufnr) +endfunction +command! -bang -nargs=? -complete=custom,jedi#complete_environments JediUseEnvironment :call s:use_environment(0, ) + command! -nargs=0 -bang JediClearCache call jedi#clear_cache(0) " vim: set et ts=4: diff --git a/pythonx/jedi_vim.py b/pythonx/jedi_vim.py index 666970ff..46621583 100644 --- a/pythonx/jedi_vim.py +++ b/pythonx/jedi_vim.py @@ -211,49 +211,84 @@ def wrapper(*args, **kwargs): return func_receiver +# XXX: might use lru cache, given that you can configure it per buffer?! current_environment = (None, None) +def set_environment(executable=None, bufnr=None): + global current_environment + + # print(repr(executable), repr(bufnr)) + + if not executable: # "unset" + executable = 'auto' + environment = None + else: + try: + # XXX: create_environment is not deterministic + # (https://github.com/davidhalter/jedi/issues/1155) + # jedi.create_environment(executable, safe=False) + environment = jedi.api.environment.Environment(executable) + except jedi.InvalidPythonEnvironment as exc: + echo_highlight('executable=%s is not supported: %s.' % ( + executable, str(exc))) + return + bufnr = int(bufnr) + if bufnr: + vim_command("call setbufvar(%d, 'jedi_use_environment', %r)" % ( + bufnr, executable)) + else: + vim_command("let g:jedi#use_environment = %r" % executable) + current_environment = (executable, environment) + + def get_environment(use_cache=True): global current_environment - vim_force_python_version = vim_eval("g:jedi#force_py_version") - if use_cache and vim_force_python_version == current_environment[0]: + use_environment = vim_eval( + "get(b:, 'jedi_use_environment', get(g:, 'jedi#use_environment', ''))") + if use_cache and use_environment == current_environment[0]: return current_environment[1] environment = None - if vim_force_python_version == "auto": + if use_environment == "auto": environment = jedi.api.environment.get_cached_default_environment() 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) - try: - environment = jedi.get_system_environment(force_python_version) + # XXX: create_environment is not deterministic + # (https://github.com/davidhalter/jedi/issues/1155) + # jedi.create_environment(executable, safe=False) + environment = jedi.api.environment.Environment(use_environment) 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))) + 'use_environment=%s is not supported: %s - using %s.' % ( + use_environment, str(exc), str(environment))) - current_environment = (vim_force_python_version, environment) + current_environment = (use_environment, environment) return environment def get_known_environments(): """Get known Jedi environments.""" - envs = list(jedi.api.environment.find_virtualenvs()) + paths = vim_eval("g:jedi#environment_paths") + envs = list(jedi.api.environment.find_virtualenvs(paths=paths, safe=False)) envs.extend(jedi.api.environment.find_system_environments()) return envs +def complete_environments(): + envs = get_known_environments() + try: + current_executable = current_environment[1].executable + except AttributeError: + current_executable = None + vim.command("return '%s'" % '\n'.join( + ('%s (*)' if env.executable == current_executable else '%s') % ( + env.executable + ) for env in envs)) + + @catch_and_print_exceptions def get_script(source=None, column=None): jedi.settings.additional_dynamic_modules = [