mirror of
https://github.com/davidhalter/jedi-vim.git
synced 2025-12-07 03:04:30 +08:00
init: improve handling of import errors (#840)
* jedi_vim.jedi_import_error: add location This is useful for debugging. It contains e.g. the path to parso, if importing failed from there. Example: > Error: jedi-vim failed to initialize Python: jedi#setup_python_imports: could not import jedi: cannot import name 'PythonTokenTypes' (in /…/jedi-vim/pythonx/jedi/jedi/api/completion.py:1). (in function jedi#init_python[3]..<SNR>44_init_python[27]..jedi#setup_python_imports, line 37) * init: handle jedi_vim.jedi_import_error in Vim plugin Using `set shortmess+=F` would suppress the `:echom` used in `jedi_vim.no_jedi_warning` [1]. This patch makes `jedi#setup_python_imports` handle the error instead. 1: https://github.com/neovim/neovim/issues/8675 * Revisit error handling with loading jedi_vim * jedi#debug_info: display parso submodule separately * Fix jedi#reinit_python * fixup! Revisit error handling with loading jedi_vim * display_debug_info: handle exceptions with environment.get_sys_path * fixup! Revisit error handling with loading jedi_vim [ci skip]
This commit is contained in:
committed by
Dave Halter
parent
0361d6c633
commit
d3d9a91ae6
@@ -91,7 +91,7 @@ endfunction
|
|||||||
|
|
||||||
|
|
||||||
function! jedi#reinit_python() abort
|
function! jedi#reinit_python() abort
|
||||||
unlet! s:_init_python
|
let s:_init_python = -1
|
||||||
call jedi#init_python()
|
call jedi#init_python()
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@@ -99,13 +99,29 @@ endfunction
|
|||||||
let s:_init_python = -1
|
let s:_init_python = -1
|
||||||
function! jedi#init_python() abort
|
function! jedi#init_python() abort
|
||||||
if s:_init_python == -1
|
if s:_init_python == -1
|
||||||
|
let s:_init_python = 0
|
||||||
try
|
try
|
||||||
let s:_init_python = s:init_python()
|
let s:_init_python = s:init_python()
|
||||||
catch
|
let s:_init_python = 1
|
||||||
let s:_init_python = 0
|
catch /^jedi/
|
||||||
|
" Only catch errors from jedi-vim itself here, so that for
|
||||||
|
" unexpected Python exceptions the traceback will be shown
|
||||||
|
" (e.g. with NameError in jedi#setup_python_imports's code).
|
||||||
if !exists('g:jedi#squelch_py_warning')
|
if !exists('g:jedi#squelch_py_warning')
|
||||||
echoerr 'Error: jedi-vim failed to initialize Python: '
|
let error_lines = split(v:exception, '\n')
|
||||||
\ .v:exception.' (in '.v:throwpoint.')'
|
let msg = 'Error: jedi-vim failed to initialize Python: '
|
||||||
|
\ .error_lines[0].' (in '.v:throwpoint.')'
|
||||||
|
if len(error_lines) > 1
|
||||||
|
echohl ErrorMsg
|
||||||
|
echom 'jedi-vim error: '.error_lines[0]
|
||||||
|
for line in error_lines[1:]
|
||||||
|
echom line
|
||||||
|
endfor
|
||||||
|
echohl None
|
||||||
|
let msg .= '. See :messages for more information.'
|
||||||
|
endif
|
||||||
|
redraw " Redraw to only have the main message by default.
|
||||||
|
echoerr msg
|
||||||
endif
|
endif
|
||||||
endtry
|
endtry
|
||||||
endif
|
endif
|
||||||
@@ -127,42 +143,27 @@ function! jedi#setup_python_imports(py_version) abort
|
|||||||
|
|
||||||
execute 'command! -nargs=1 PythonJedi '.cmd_exec.' <args>'
|
execute 'command! -nargs=1 PythonJedi '.cmd_exec.' <args>'
|
||||||
|
|
||||||
let s:init_outcome = 0
|
let g:_jedi_init_error = 0
|
||||||
let init_lines = [
|
let init_lines = [
|
||||||
\ 'import vim',
|
\ 'import vim',
|
||||||
\ 'try:',
|
\ 'try:',
|
||||||
\ ' import jedi_vim',
|
\ ' import jedi_vim',
|
||||||
|
\ ' if hasattr(jedi_vim, "jedi_import_error"):',
|
||||||
|
\ ' from jedi_vim_debug import format_exc_info',
|
||||||
|
\ ' vim.vars["_jedi_init_error"] = format_exc_info(jedi_vim.jedi_import_error)',
|
||||||
\ 'except Exception as exc:',
|
\ 'except Exception as exc:',
|
||||||
\ ' if isinstance(exc, SyntaxError):',
|
\ ' from jedi_vim_debug import format_exc_info',
|
||||||
\ ' exc_msg = repr(exc)',
|
\ ' vim.vars["_jedi_init_error"] = format_exc_info()',
|
||||||
\ ' else:',
|
\ ]
|
||||||
\ ' exc_msg = "%s: %s" % (exc.__class__.__name__, exc)',
|
|
||||||
\ ' vim.command(''let s:init_outcome = "could not import jedi_vim: {0}"''.format(exc_msg))',
|
|
||||||
\ 'else:',
|
|
||||||
\ ' vim.command(''let s:init_outcome = 1'')']
|
|
||||||
try
|
|
||||||
exe 'PythonJedi exec('''.escape(join(init_lines, '\n'), "'").''')'
|
exe 'PythonJedi exec('''.escape(join(init_lines, '\n'), "'").''')'
|
||||||
catch
|
if g:_jedi_init_error isnot 0
|
||||||
throw printf('jedi#setup_python_imports: failed to run Python for initialization: %s.', v:exception)
|
throw printf('jedi#setup_python_imports: %s', g:_jedi_init_error)
|
||||||
endtry
|
|
||||||
if s:init_outcome is 0
|
|
||||||
throw 'jedi#setup_python_imports: failed to run Python for initialization.'
|
|
||||||
elseif s:init_outcome isnot 1
|
|
||||||
throw printf('jedi#setup_python_imports: %s.', s:init_outcome)
|
|
||||||
endif
|
endif
|
||||||
return 1
|
return 1
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! jedi#debug_info() abort
|
function! jedi#debug_info() abort
|
||||||
if s:python_version ==# 'null'
|
|
||||||
try
|
|
||||||
call s:init_python()
|
|
||||||
catch
|
|
||||||
echohl WarningMsg | echom v:exception | echohl None
|
|
||||||
return
|
|
||||||
endtry
|
|
||||||
endif
|
|
||||||
if &verbose
|
if &verbose
|
||||||
if &filetype !=# 'python'
|
if &filetype !=# 'python'
|
||||||
echohl WarningMsg | echo 'You should run this in a buffer with filetype "python".' | echohl None
|
echohl WarningMsg | echo 'You should run this in a buffer with filetype "python".' | echohl None
|
||||||
@@ -187,7 +188,9 @@ function! jedi#debug_info() abort
|
|||||||
echo ' - jedi-vim git version: '
|
echo ' - jedi-vim git version: '
|
||||||
echon substitute(system('git -C '.s:script_path.' describe --tags --always --dirty'), '\v\n$', '', '')
|
echon substitute(system('git -C '.s:script_path.' describe --tags --always --dirty'), '\v\n$', '', '')
|
||||||
echo ' - jedi git submodule status: '
|
echo ' - jedi git submodule status: '
|
||||||
echon substitute(system('git -C '.s:script_path.' submodule status'), '\v\n$', '', '')
|
echon substitute(system('git -C '.s:script_path.' submodule status pythonx/jedi'), '\v\n$', '', '')
|
||||||
|
echo ' - parso git submodule status: '
|
||||||
|
echon substitute(system('git -C '.s:script_path.' submodule status pythonx/parso'), '\v\n$', '', '')
|
||||||
echo "\n"
|
echo "\n"
|
||||||
echo '##### Settings'
|
echo '##### Settings'
|
||||||
echo '```'
|
echo '```'
|
||||||
|
|||||||
@@ -48,7 +48,21 @@ endif
|
|||||||
" Pyimport command
|
" Pyimport command
|
||||||
command! -nargs=1 -complete=custom,jedi#py_import_completions Pyimport :call jedi#py_import(<q-args>)
|
command! -nargs=1 -complete=custom,jedi#py_import_completions Pyimport :call jedi#py_import(<q-args>)
|
||||||
|
|
||||||
command! -nargs=0 -bar JediDebugInfo call jedi#debug_info()
|
function! s:jedi_debug_info()
|
||||||
|
" Ensure the autoload file has been loaded (and ignore any errors, which
|
||||||
|
" will be displayed with the debug info).
|
||||||
|
let unset = {}
|
||||||
|
let saved_squelch_py_warning = get(g:, 'jedi#squelch_py_warning', unset)
|
||||||
|
let g:jedi#squelch_py_warning = 1
|
||||||
|
call jedi#init_python()
|
||||||
|
if saved_squelch_py_warning is unset
|
||||||
|
unlet g:jedi#squelch_py_warning
|
||||||
|
else
|
||||||
|
let g:jedi#squelch_py_warning = saved_squelch_py_warning
|
||||||
|
endif
|
||||||
|
call jedi#debug_info()
|
||||||
|
endfunction
|
||||||
|
command! -nargs=0 -bar JediDebugInfo call s:jedi_debug_info()
|
||||||
command! -nargs=0 -bang JediClearCache call jedi#clear_cache(<bang>0)
|
command! -nargs=0 -bang JediClearCache call jedi#clear_cache(<bang>0)
|
||||||
|
|
||||||
" vim: set et ts=4:
|
" vim: set et ts=4:
|
||||||
|
|||||||
@@ -110,10 +110,9 @@ sys.path.insert(0, parso_path)
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
import jedi
|
import jedi
|
||||||
except ImportError as e:
|
except ImportError:
|
||||||
no_jedi_warning(str(e))
|
|
||||||
jedi = None
|
jedi = None
|
||||||
jedi_import_error = str(e)
|
jedi_import_error = sys.exc_info()
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
version = jedi.__version__
|
version = jedi.__version__
|
||||||
|
|||||||
@@ -1,35 +1,60 @@
|
|||||||
"""Used in jedi-vim's jedi#debug_info()"""
|
"""Used in jedi-vim's jedi#debug_info()"""
|
||||||
|
import sys
|
||||||
|
|
||||||
import vim
|
import vim
|
||||||
|
from jedi_vim import PythonToVimStr
|
||||||
|
|
||||||
|
|
||||||
def echo(msg):
|
def echo(msg):
|
||||||
vim.command('echo {0}'.format(msg))
|
vim.command('echo %r' % PythonToVimStr(msg))
|
||||||
|
|
||||||
|
|
||||||
|
def echo_error(msg):
|
||||||
|
vim.command('echohl ErrorMsg')
|
||||||
|
echo(msg)
|
||||||
|
vim.command('echohl None')
|
||||||
|
|
||||||
|
|
||||||
|
def format_exc_info(exc_info=None, tb_indent=2):
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
if exc_info is None:
|
||||||
|
exc_info = sys.exc_info()
|
||||||
|
|
||||||
|
exc_msg = traceback.format_exception_only(exc_info[0], exc_info[1])
|
||||||
|
lines = ''.join(exc_msg).rstrip('\n').split('\n')
|
||||||
|
|
||||||
|
lines.append('Traceback (most recent call last):')
|
||||||
|
tb = traceback.format_tb(exc_info[2])
|
||||||
|
lines.extend(''.join(tb).rstrip('\n').split('\n'))
|
||||||
|
|
||||||
|
indent = ' ' * tb_indent
|
||||||
|
return '{0}'.format(('\n' + indent).join(lines))
|
||||||
|
|
||||||
|
|
||||||
def display_debug_info():
|
def display_debug_info():
|
||||||
echo("printf(' - global sys.version: `%s`', {0!r})".format(
|
echo(' - global sys.version: `{0}`'.format(
|
||||||
', '.join([x.strip()
|
', '.join([x.strip()
|
||||||
for x in __import__('sys').version.split('\n')])))
|
for x in sys.version.split('\n')])))
|
||||||
echo("printf(' - global site module: `%s`', {0!r})".format(
|
echo(' - global site module: `{0}`'.format(__import__('site').__file__))
|
||||||
__import__('site').__file__))
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import jedi_vim
|
import jedi_vim
|
||||||
except Exception as e:
|
except Exception:
|
||||||
echo("printf('ERROR: jedi_vim is not available: %s: %s', "
|
echo_error('ERROR: could not import jedi_vim: {0}'.format(
|
||||||
"{0!r}, {1!r})".format(e.__class__.__name__, str(e)))
|
format_exc_info()))
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
|
||||||
if jedi_vim.jedi is None:
|
if jedi_vim.jedi is None:
|
||||||
echo("'ERROR: could not import the \"jedi\" Python module.'")
|
if hasattr(jedi_vim, 'jedi_import_error'):
|
||||||
echo("printf(' The error was: %s', {0!r})".format(
|
error_msg = format_exc_info(jedi_vim.jedi_import_error)
|
||||||
getattr(jedi_vim, "jedi_import_error", "UNKNOWN")))
|
|
||||||
else:
|
else:
|
||||||
echo("printf('Jedi path: `%s`', {0!r})".format(
|
error_msg = 'unknown error'
|
||||||
jedi_vim.jedi.__file__))
|
echo_error('ERROR: could not import the "jedi" Python module: {0}'.format(
|
||||||
echo("printf(' - version: %s', {0!r})".format(
|
error_msg))
|
||||||
jedi_vim.jedi.__version__))
|
else:
|
||||||
|
echo('Jedi path: `{0}`'.format(jedi_vim.jedi.__file__))
|
||||||
|
echo(' - version: {0}'.format(jedi_vim.jedi.__version__))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
environment = jedi_vim.get_environment(use_cache=False)
|
environment = jedi_vim.get_environment(use_cache=False)
|
||||||
@@ -40,18 +65,14 @@ def display_debug_info():
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
sys_path = script_evaluator.sys_path
|
sys_path = script_evaluator.sys_path
|
||||||
else:
|
else:
|
||||||
echo("printf(' - environment: %s', {0!r})".format(
|
echo(' - environment: `{0}`'.format(environment))
|
||||||
str(environment)))
|
try:
|
||||||
sys_path = environment.get_sys_path()
|
sys_path = environment.get_sys_path()
|
||||||
|
except Exception:
|
||||||
|
echo_error('ERROR: failed to get sys path from environment: {0}'.format(
|
||||||
|
format_exc_info()))
|
||||||
|
return
|
||||||
|
|
||||||
echo("' - sys_path:'")
|
echo(' - sys_path:')
|
||||||
for p in sys_path:
|
for p in sys_path:
|
||||||
echo("printf(' - `%s`', {0!r})".format(p))
|
echo(' - `{0}`'.format(p))
|
||||||
except Exception as 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')
|
|
||||||
|
|||||||
Reference in New Issue
Block a user