Auto merge of #1994 - micbou:set-up-python, r=vheon

[READY] Rewrite SetUpPython function

This PR fixes issue #1726 by moving most of SetUpPython logic to its own module and using a try-catch-else block at the end of the function. It also prevents Python backtraces in Vim (which are really annoying) for common exceptions (`RuntimeError` and `ImportError`).

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.svg" height="40" alt="Review on Reviewable"/>](https://reviewable.io/reviews/valloric/youcompleteme/1994)
<!-- Reviewable:end -->
This commit is contained in:
Homu 2016-02-25 06:12:17 +09:00
commit 35f6090b76
3 changed files with 81 additions and 30 deletions

View File

@ -131,38 +131,38 @@ endfunction
function! s:SetUpPython() abort function! s:SetUpPython() abort
python << EOF python << EOF
import sys
import vim
import os 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' ) 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, '..', 'python' ) )
sys.path.insert( 0, os.path.join( script_folder, '../third_party/ycmd' ) )
from ycmd import server_utils
server_utils.AddNearestThirdPartyFoldersToSysPath( script_folder )
# We need to import ycmd's third_party folders as well since we import and from ycm.setup import SetUpSystemPaths, SetUpYCM
# 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
popen_args = [ paths.PathToPythonInterpreter(), # We enclose this code in a try/except block to avoid backtraces in Vim.
paths.PathToCheckCoreVersion() ] try:
SetUpSystemPaths()
if utils.SafePopen( popen_args ).wait() == 2: # Import the modules used in this file.
vimsupport.PostVimMessage( from ycm import base, vimsupport
'YouCompleteMe unavailable: YCM support libs too old, PLEASE RECOMPILE' )
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' ) vim.command( 'return 0' )
else:
from ycm.youcompleteme import YouCompleteMe vim.command( 'return 1' )
ycm_state = YouCompleteMe( user_options_store.GetAll() )
vim.command( 'return 1' )
EOF EOF
endfunction endfunction

View File

@ -20,9 +20,10 @@ import sys
import vim import vim
import functools import functools
import re import re
from ycmd import utils
DIR_OF_CURRENT_SCRIPT = os.path.dirname( os.path.abspath( __file__ ) ) 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' ) WIN_PYTHON_PATH = os.path.join( sys.exec_prefix, 'python.exe' )
PYTHON_BINARY_REGEX = re.compile( r'python(2(\.[67])?)?(.exe)?$' ) PYTHON_BINARY_REGEX = re.compile( r'python(2(\.[67])?)?(.exe)?$' )
@ -42,6 +43,8 @@ def Memoize( obj ):
@Memoize @Memoize
def PathToPythonInterpreter(): def PathToPythonInterpreter():
from ycmd import utils
python_interpreter = vim.eval( 'g:ycm_path_to_python_interpreter' ) python_interpreter = vim.eval( 'g:ycm_path_to_python_interpreter' )
if python_interpreter: if python_interpreter:
@ -82,6 +85,8 @@ def EndsWithPython( path ):
def IsPythonVersionCorrect( path ): def IsPythonVersionCorrect( path ):
"""Check if given path is the Python interpreter version 2.6 or 2.7.""" """Check if given path is the Python interpreter version 2.6 or 2.7."""
from ycmd import utils
if not EndsWithPython( path ): if not EndsWithPython( path ):
return False return False
@ -95,10 +100,8 @@ def IsPythonVersionCorrect( path ):
def PathToServerScript(): def PathToServerScript():
return os.path.join( DIR_OF_CURRENT_SCRIPT, '..', '..', 'third_party', return os.path.join( DIR_OF_YCMD, 'ycmd' )
'ycmd', 'ycmd' )
def PathToCheckCoreVersion(): def PathToCheckCoreVersion():
return os.path.join( DIR_OF_CURRENT_SCRIPT, '..', '..', 'third_party', return os.path.join( DIR_OF_YCMD, 'check_core_version.py' )
'ycmd', 'check_core_version.py' )

48
python/ycm/setup.py Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
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() )