diff --git a/autoload/jedi.vim b/autoload/jedi.vim index 699243c..e5593b4 100644 --- a/autoload/jedi.vim +++ b/autoload/jedi.vim @@ -91,7 +91,7 @@ endfunction function! jedi#reinit_python() abort - unlet! s:_init_python + let s:_init_python = -1 call jedi#init_python() endfunction @@ -99,13 +99,29 @@ endfunction let s:_init_python = -1 function! jedi#init_python() abort if s:_init_python == -1 + let s:_init_python = 0 try let s:_init_python = s:init_python() - catch - let s:_init_python = 0 + let s:_init_python = 1 + 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') - echoerr 'Error: jedi-vim failed to initialize Python: ' - \ .v:exception.' (in '.v:throwpoint.')' + let error_lines = split(v:exception, '\n') + 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 endtry endif @@ -127,42 +143,27 @@ function! jedi#setup_python_imports(py_version) abort execute 'command! -nargs=1 PythonJedi '.cmd_exec.' ' - let s:init_outcome = 0 + let g:_jedi_init_error = 0 let init_lines = [ \ 'import vim', \ 'try:', \ ' 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:', - \ ' if isinstance(exc, SyntaxError):', - \ ' exc_msg = repr(exc)', - \ ' 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'), "'").''')' - catch - 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_python_imports: failed to run Python for initialization.' - elseif s:init_outcome isnot 1 - throw printf('jedi#setup_python_imports: %s.', s:init_outcome) + \ ' from jedi_vim_debug import format_exc_info', + \ ' vim.vars["_jedi_init_error"] = format_exc_info()', + \ ] + exe 'PythonJedi exec('''.escape(join(init_lines, '\n'), "'").''')' + if g:_jedi_init_error isnot 0 + throw printf('jedi#setup_python_imports: %s', g:_jedi_init_error) endif return 1 endfunction 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 &filetype !=# 'python' 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: ' echon substitute(system('git -C '.s:script_path.' describe --tags --always --dirty'), '\v\n$', '', '') 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 '##### Settings' echo '```' diff --git a/plugin/jedi.vim b/plugin/jedi.vim index 485cdb7..9245bba 100644 --- a/plugin/jedi.vim +++ b/plugin/jedi.vim @@ -48,7 +48,21 @@ endif " Pyimport command command! -nargs=1 -complete=custom,jedi#py_import_completions Pyimport :call jedi#py_import() -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(0) " vim: set et ts=4: diff --git a/pythonx/jedi_vim.py b/pythonx/jedi_vim.py index 4dd89f0..067a444 100644 --- a/pythonx/jedi_vim.py +++ b/pythonx/jedi_vim.py @@ -110,10 +110,9 @@ sys.path.insert(0, parso_path) try: import jedi -except ImportError as e: - no_jedi_warning(str(e)) +except ImportError: jedi = None - jedi_import_error = str(e) + jedi_import_error = sys.exc_info() else: try: version = jedi.__version__ diff --git a/pythonx/jedi_vim_debug.py b/pythonx/jedi_vim_debug.py index 76de216..b5e6da2 100644 --- a/pythonx/jedi_vim_debug.py +++ b/pythonx/jedi_vim_debug.py @@ -1,57 +1,78 @@ """Used in jedi-vim's jedi#debug_info()""" +import sys + import vim +from jedi_vim import PythonToVimStr 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(): - echo("printf(' - global sys.version: `%s`', {0!r})".format( + echo(' - global sys.version: `{0}`'.format( ', '.join([x.strip() - for x in __import__('sys').version.split('\n')]))) - echo("printf(' - global site module: `%s`', {0!r})".format( - __import__('site').__file__)) + for x in sys.version.split('\n')]))) + echo(' - global site module: `{0}`'.format(__import__('site').__file__)) try: import jedi_vim - except Exception as e: - echo("printf('ERROR: jedi_vim is not available: %s: %s', " - "{0!r}, {1!r})".format(e.__class__.__name__, str(e))) + except Exception: + echo_error('ERROR: could not import jedi_vim: {0}'.format( + format_exc_info())) return - try: - if jedi_vim.jedi is None: - echo("'ERROR: could not import the \"jedi\" Python module.'") - echo("printf(' The error was: %s', {0!r})".format( - getattr(jedi_vim, "jedi_import_error", "UNKNOWN"))) + if jedi_vim.jedi is None: + if hasattr(jedi_vim, 'jedi_import_error'): + error_msg = format_exc_info(jedi_vim.jedi_import_error) else: - echo("printf('Jedi path: `%s`', {0!r})".format( - jedi_vim.jedi.__file__)) - echo("printf(' - version: %s', {0!r})".format( - jedi_vim.jedi.__version__)) + error_msg = 'unknown error' + echo_error('ERROR: could not import the "jedi" Python module: {0}'.format( + error_msg)) + else: + echo('Jedi path: `{0}`'.format(jedi_vim.jedi.__file__)) + echo(' - version: {0}'.format(jedi_vim.jedi.__version__)) + try: + environment = jedi_vim.get_environment(use_cache=False) + except AttributeError: + script_evaluator = jedi_vim.jedi.Script('')._evaluator try: - environment = jedi_vim.get_environment(use_cache=False) + sys_path = script_evaluator.project.sys_path except AttributeError: - 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 = script_evaluator.sys_path + else: + echo(' - environment: `{0}`'.format(environment)) + try: 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:'") - for p in sys_path: - echo("printf(' - `%s`', {0!r})".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') + echo(' - sys_path:') + for p in sys_path: + echo(' - `{0}`'.format(p))