diff --git a/autoload/jedi.vim b/autoload/jedi.vim index 54ac65a7..6621a7c4 100644 --- a/autoload/jedi.vim +++ b/autoload/jedi.vim @@ -58,15 +58,6 @@ endfor let s:script_path = fnameescape(expand(':p:h:h')) function! s:init_python() abort - if g:jedi#force_py_version !=# 'auto' - " Always use the user supplied version. - try - return jedi#setup_py_version(g:jedi#force_py_version) - catch - throw 'Could not setup g:jedi#force_py_version: '.v:exception - endtry - endif - " Handle "auto" version. if has('nvim') || (has('python') && has('python3')) " Neovim usually has both python providers. Skipping the `has` check @@ -88,7 +79,7 @@ function! s:init_python() abort " Make sure that the auto-detected version is available in Vim. if !has('nvim') || has('python'.(s:def_py == 2 ? '' : s:def_py)) - return jedi#setup_py_version(s:def_py) + return jedi#setup_python_imports(s:def_py) endif " Add a warning in case the auto-detected version is not available, @@ -105,9 +96,9 @@ function! s:init_python() abort endif if has('python') - call jedi#setup_py_version(2) + call jedi#setup_python_imports(2) elseif has('python3') - call jedi#setup_py_version(3) + call jedi#setup_python_imports(3) else throw 'jedi-vim requires Vim with support for Python 2 or 3.' endif @@ -139,7 +130,7 @@ endfunction let s:python_version = 'null' -function! jedi#setup_py_version(py_version) abort +function! jedi#setup_python_imports(py_version) abort if a:py_version == 2 let cmd_exec = 'python' let s:python_version = 2 @@ -147,7 +138,7 @@ function! jedi#setup_py_version(py_version) abort let cmd_exec = 'python3' let s:python_version = 3 else - throw 'jedi#setup_py_version: invalid py_version: '.a:py_version + throw 'jedi#setup_python_imports: invalid py_version: '.a:py_version endif execute 'command! -nargs=1 PythonJedi '.cmd_exec.' ' @@ -164,12 +155,12 @@ function! jedi#setup_py_version(py_version) abort try exe 'PythonJedi exec('''.escape(join(init_lines, '\n'), "'").''')' catch - throw printf('jedi#setup_py_version: failed to run Python for initialization: %s.', v:exception) + throw printf('jedi#setup_python_imports: failed to run Python for initialization: %s.', v:exception) endtry if s:init_outcome is 0 - throw 'jedi#setup_py_version: failed to run Python for initialization.' + throw 'jedi#setup_python_imports: failed to run Python for initialization.' elseif s:init_outcome isnot 1 - throw printf('jedi#setup_py_version: %s.', s:init_outcome) + throw printf('jedi#setup_python_imports: %s.', s:init_outcome) endif return 1 endfunction @@ -252,23 +243,6 @@ function! jedi#debug_info() abort endif endfunction -function! jedi#force_py_version(py_version) abort - let g:jedi#force_py_version = a:py_version - return jedi#setup_py_version(a:py_version) -endfunction - - -function! jedi#force_py_version_switch() abort - if g:jedi#force_py_version == 2 - call jedi#force_py_version(3) - elseif g:jedi#force_py_version == 3 - call jedi#force_py_version(2) - else - throw "Don't know how to switch from ".g:jedi#force_py_version.'!' - endif -endfunction - - " Helper function instead of `python vim.eval()`, and `.command()` because " these also return error definitions. function! jedi#_vim_exceptions(str, is_eval) abort diff --git a/doc/jedi-vim.txt b/doc/jedi-vim.txt index 6ad08147..db98cdf5 100644 --- a/doc/jedi-vim.txt +++ b/doc/jedi-vim.txt @@ -480,21 +480,20 @@ small a horizontal split happens. ------------------------------------------------------------------------------ 6.12. `g:jedi#force_py_version` *g:jedi#force_py_version* -If you have installed both python 2 and python 3, you can force which one jedi -should use by setting this variable. It forces the internal Vim command, which -will be used for every jedi call to the respective python interpreter. -The variable can be set in the .vimrc like this to force python 3: +If you have installed multiple Python versions, you can force the Python +version that is going to be used. +You don't have to compile VIM with multiple Python versions. +The variable can be set in the .vimrc like this to force python 2: -let g:jedi#force_py_version = 3 +let g:jedi#force_py_version = 2 -This variable can be switched during runtime using the following function: -Function: `jedi#force_py_version_switch()` +By default jedi loads the latest Python version installed on your system that +can be found. -or set directly using this function, which has the same name as the variable: -Function: `jedi#force_py_version(py_version)` +This variable can be changed during runtime. -Options: 2 or 3 -Default: "auto" (will use sys.version_info from "python" in your $PATH) +Options: 2, 2.7, 3, 3.3, 3.4, ... +Default: "auto" ------------------------------------------------------------------------------ 6.13. `g:jedi#smart_auto_mappings` *g:jedi#smart_auto_mappings* diff --git a/pythonx/jedi_vim.py b/pythonx/jedi_vim.py index adacde33..756f665d 100644 --- a/pythonx/jedi_vim.py +++ b/pythonx/jedi_vim.py @@ -25,6 +25,16 @@ ELLIPSIS = u"…" +try: + # Somehow sys.prefix is set in combination with VIM and virtualenvs. + # However the sys path is not affected. Just reset it to the normal value. + sys.prefix = sys.base_prefix + sys.exec_prefix = sys.base_exec_prefix +except AttributeError: + # If we're not in a virtualenv we don't care. Everything is fine. + pass + + class PythonToVimStr(unicode): """ Vim has a different string implementation of single quotes """ __slots__ = [] @@ -73,11 +83,11 @@ def _catch_exception(string, is_eval): def vim_command(string): - _catch_exception(string, False) + _catch_exception(string, is_eval=False) def vim_eval(string): - return _catch_exception(string, True) + return _catch_exception(string, is_eval=True) def no_jedi_warning(error=None): @@ -148,6 +158,42 @@ def wrapper(*args, **kwargs): return func_receiver +current_environment = (None, None) + + +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]: + return current_environment[1] + + environment = None + if vim_force_python_version == "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) + 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))) + + current_environment = (vim_force_python_version, environment) + return environment + + @catch_and_print_exceptions def get_script(source=None, column=None): jedi.settings.additional_dynamic_modules = [ @@ -161,8 +207,12 @@ def get_script(source=None, column=None): if column is None: column = vim.current.window.cursor[1] buf_path = vim.current.buffer.name - encoding = vim_eval('&encoding') or 'latin1' - return jedi.Script(source, row, column, buf_path, encoding) + + return jedi.Script( + source, row, column, buf_path, + encoding=vim_eval('&encoding') or 'latin1', + environment=get_environment(), + ) @_check_jedi_availability(show_error=False) @@ -627,7 +677,7 @@ def py_import(): args = shsplit(vim.eval('a:args')) import_path = args.pop() text = 'import %s' % import_path - scr = jedi.Script(text, 1, len(text), '') + scr = jedi.Script(text, 1, len(text), '', environment=get_environment()) try: completion = scr.goto_assignments()[0] except IndexError: @@ -650,7 +700,7 @@ def py_import_completions(): comps = [] else: text = 'import %s' % argl - script = jedi.Script(text, 1, len(text), '') + script = jedi.Script(text, 1, len(text), '', environment=get_environment()) comps = ['%s%s' % (argl, c.complete) for c in script.completions()] vim.command("return '%s'" % '\n'.join(comps)) diff --git a/pythonx/jedi_vim_debug.py b/pythonx/jedi_vim_debug.py index 81633e74..76de216c 100644 --- a/pythonx/jedi_vim_debug.py +++ b/pythonx/jedi_vim_debug.py @@ -1,16 +1,16 @@ """Used in jedi-vim's jedi#debug_info()""" +import vim -def display_debug_info(): - import vim +def echo(msg): + vim.command('echo {0}'.format(msg)) - def echo(msg): - vim.command('echo {0}'.format(msg)) - echo("printf(' - sys.version: `%s`', {0!r})".format( +def display_debug_info(): + echo("printf(' - global sys.version: `%s`', {0!r})".format( ', '.join([x.strip() for x in __import__('sys').version.split('\n')]))) - echo("printf(' - site module: `%s`', {0!r})".format( + echo("printf(' - global site module: `%s`', {0!r})".format( __import__('site').__file__)) try: @@ -30,15 +30,28 @@ def echo(msg): jedi_vim.jedi.__file__)) echo("printf(' - version: %s', {0!r})".format( jedi_vim.jedi.__version__)) - echo("' - sys_path:'") - script_evaluator = jedi_vim.jedi.Script('')._evaluator try: - sys_path = script_evaluator.project.sys_path + environment = jedi_vim.get_environment(use_cache=False) except AttributeError: - sys_path = script_evaluator.sys_path + script_evaluator = jedi_vim.jedi.Script('')._evaluator + try: + sys_path = script_evaluator.project.sys_path + except AttributeError: + sys_path = script_evaluator.sys_path + else: + echo("printf(' - environment: %s', {0!r})".format( + str(environment))) + sys_path = environment.get_sys_path() + + echo("' - sys_path:'") for p in sys_path: echo("printf(' - `%s`', {0!r})".format(p)) except Exception as e: - echo("printf('There was an error accessing jedi_vim.jedi: %s', " - "{0!r})".format(e)) + vim.command('echohl ErrorMsg') + echo("printf('There was an error accessing jedi_vim.jedi: %s', {0!r})".format( + str(e))) + import traceback + for l in traceback.format_exc().splitlines(): + echo("printf('%s', {0!r})".format(l)) + vim.command('echohl None')