From 3cf6fa86f5a75a2b25a31408cde97af90b7a4b9e Mon Sep 17 00:00:00 2001 From: micbou Date: Mon, 12 Oct 2015 21:19:37 +0200 Subject: [PATCH] Rewrite SetUpPython function Do not create YouCompleteMe object if setup failed. Use a try/except block to prevent backtraces in Vim. --- autoload/youcompleteme.vim | 50 +++++++++++++++++++------------------- python/ycm/paths.py | 13 ++++++---- python/ycm/setup.py | 48 ++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 30 deletions(-) create mode 100644 python/ycm/setup.py diff --git a/autoload/youcompleteme.vim b/autoload/youcompleteme.vim index 1b15530a..5c511fdf 100644 --- a/autoload/youcompleteme.vim +++ b/autoload/youcompleteme.vim @@ -131,38 +131,38 @@ endfunction function! s:SetUpPython() abort python << EOF -import sys -import vim import os -import subprocess +import sys +import traceback +import vim +# Add python sources folder to the system path. script_folder = vim.eval( 's:script_folder_path' ) -sys.path.insert( 0, os.path.join( script_folder, '../python' ) ) -sys.path.insert( 0, os.path.join( script_folder, '../third_party/ycmd' ) ) -from ycmd import server_utils -server_utils.AddNearestThirdPartyFoldersToSysPath( script_folder ) +sys.path.insert( 0, os.path.join( script_folder, '..', 'python' ) ) -# We need to import ycmd's third_party folders as well since we import and -# use ycmd code in the client. -server_utils.AddNearestThirdPartyFoldersToSysPath( server_utils.__file__ ) -from ycmd import utils -from ycm import base -base.LoadJsonDefaultsIntoVim() -from ycmd import user_options_store -user_options_store.SetAll( base.BuildServerConf() ) -from ycm import paths, vimsupport +from ycm.setup import SetUpSystemPaths, SetUpYCM -popen_args = [ paths.PathToPythonInterpreter(), - paths.PathToCheckCoreVersion() ] +# We enclose this code in a try/except block to avoid backtraces in Vim. +try: + SetUpSystemPaths() -if utils.SafePopen( popen_args ).wait() == 2: - vimsupport.PostVimMessage( - 'YouCompleteMe unavailable: YCM support libs too old, PLEASE RECOMPILE' ) + # Import the modules used in this file. + from ycm import base, vimsupport + + ycm_state = SetUpYCM() +except Exception as error: + # We don't use PostVimMessage or EchoText from the vimsupport module because + # importing this module may fail. + vim.command( 'redraw | echohl WarningMsg' ) + for line in traceback.format_exc().splitlines(): + vim.command( "echom '{0}'".format( line.replace( "'", "''" ) ) ) + + vim.command( "echo 'YouCompleteMe unavailable: {0}'" + .format( str( error ).replace( "'", "''" ) ) ) + vim.command( 'echohl None' ) vim.command( 'return 0' ) - -from ycm.youcompleteme import YouCompleteMe -ycm_state = YouCompleteMe( user_options_store.GetAll() ) -vim.command( 'return 1' ) +else: + vim.command( 'return 1' ) EOF endfunction diff --git a/python/ycm/paths.py b/python/ycm/paths.py index 3a8c716c..9ba85320 100644 --- a/python/ycm/paths.py +++ b/python/ycm/paths.py @@ -20,9 +20,10 @@ import sys import vim import functools import re -from ycmd import utils DIR_OF_CURRENT_SCRIPT = os.path.dirname( os.path.abspath( __file__ ) ) +DIR_OF_YCMD = os.path.join( DIR_OF_CURRENT_SCRIPT, '..', '..', 'third_party', + 'ycmd' ) WIN_PYTHON_PATH = os.path.join( sys.exec_prefix, 'python.exe' ) PYTHON_BINARY_REGEX = re.compile( r'python(2(\.[67])?)?(.exe)?$' ) @@ -42,6 +43,8 @@ def Memoize( obj ): @Memoize def PathToPythonInterpreter(): + from ycmd import utils + python_interpreter = vim.eval( 'g:ycm_path_to_python_interpreter' ) if python_interpreter: @@ -82,6 +85,8 @@ def EndsWithPython( path ): def IsPythonVersionCorrect( path ): """Check if given path is the Python interpreter version 2.6 or 2.7.""" + from ycmd import utils + if not EndsWithPython( path ): return False @@ -95,10 +100,8 @@ def IsPythonVersionCorrect( path ): def PathToServerScript(): - return os.path.join( DIR_OF_CURRENT_SCRIPT, '..', '..', 'third_party', - 'ycmd', 'ycmd' ) + return os.path.join( DIR_OF_YCMD, 'ycmd' ) def PathToCheckCoreVersion(): - return os.path.join( DIR_OF_CURRENT_SCRIPT, '..', '..', 'third_party', - 'ycmd', 'check_core_version.py' ) + return os.path.join( DIR_OF_YCMD, 'check_core_version.py' ) diff --git a/python/ycm/setup.py b/python/ycm/setup.py new file mode 100644 index 00000000..8fadccfd --- /dev/null +++ b/python/ycm/setup.py @@ -0,0 +1,48 @@ +# Copyright (C) 2016 YouCompleteMe contributors +# +# This file is part of YouCompleteMe. +# +# YouCompleteMe is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# YouCompleteMe is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with YouCompleteMe. If not, see . + +import sys +import os +import paths + + +def SetUpSystemPaths(): + sys.path.insert( 0, os.path.join( paths.DIR_OF_YCMD ) ) + + from ycmd import server_utils as su + su.AddNearestThirdPartyFoldersToSysPath( paths.DIR_OF_CURRENT_SCRIPT ) + # We need to import ycmd's third_party folders as well since we import and + # use ycmd code in the client. + su.AddNearestThirdPartyFoldersToSysPath( su.__file__ ) + + +def SetUpYCM(): + import base + from ycmd import user_options_store, utils + from youcompleteme import YouCompleteMe + + base.LoadJsonDefaultsIntoVim() + + user_options_store.SetAll( base.BuildServerConf() ) + + popen_args = [ paths.PathToPythonInterpreter(), + paths.PathToCheckCoreVersion() ] + + if utils.SafePopen( popen_args ).wait() == 2: + raise RuntimeError( 'YCM support libs too old, PLEASE RECOMPILE.' ) + + return YouCompleteMe( user_options_store.GetAll() )