Auto merge of #2585 - micbou:remove-python-check, r=Valloric
[READY] Remove Python version check Even with the `-S` option (see PR https://github.com/Valloric/YouCompleteMe/pull/2502), starting the Python interpreter to check its version can be slow. For instance, on my machine (in PowerShell): ```ps > Measure-Command -Expression {python -S -c "pass"} ... TotalMilliseconds : 25,4387 ``` It's also not particularly useful because, in the typical case, the Python used to start ycmd will be the one from `PYTHON_USED_DURING_BUILDING` which is necessarily a supported version. In the cases where the `g:ycm_server_python_interpreter` option is specified or a Python is found in the PATH, it's up to the user to provide a supported version. If they don't, the ycmd server will probably fail to start and the following error will be displayed to them: ``` The ycmd server SHUT DOWN (restart with ':YcmRestartServer'). Unexpected exit code 1. Use the ':YcmToggleLogs' command to check the logs. ``` They can then look at the logs to understand what went wrong. Finally, the last case is when the Python is the one used by YCM itself. In that case, if the Python version is not supported, it will fail before doing the check so it doesn't matter. As always, here are the improvements on startup time: <table> <tr> <th rowspan="2">Platform</th> <th colspan="2">First run (ms)</th> <th colspan="2">Subsequent runs (ms)</th> </tr> <tr> <td>Before</td> <td>After</td> <td>Before</td> <td>After</td> </tr> <tr> <td>Ubuntu 16.04 64-bit</td> <td>147</td> <td>134</td> <td>74</td> <td>65</td> </tr> <tr> <td>macOS 10.12</td> <td>189</td> <td>165</td> <td>127</td> <td>107</td> </tr> <tr> <td>Windows 10 64-bit</td> <td>242</td> <td>200</td> <td>147</td> <td>115</td> </tr> </table> *Results obtained by running the `prof.py` script from [this branch](https://github.com/micbou/YouCompleteMe/tree/profiling-startup) on Python 3.6.* <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/valloric/youcompleteme/2585) <!-- Reviewable:end -->
This commit is contained in:
commit
01570aac03
@ -1,4 +1,4 @@
|
|||||||
# Copyright (C) 2015 YouCompleteMe contributors.
|
# Copyright (C) 2015-2017 YouCompleteMe contributors.
|
||||||
#
|
#
|
||||||
# This file is part of YouCompleteMe.
|
# This file is part of YouCompleteMe.
|
||||||
#
|
#
|
||||||
@ -51,19 +51,20 @@ def Memoize( obj ):
|
|||||||
|
|
||||||
@Memoize
|
@Memoize
|
||||||
def PathToPythonInterpreter():
|
def PathToPythonInterpreter():
|
||||||
|
# Not calling the Python interpreter to check its version as it significantly
|
||||||
|
# impacts startup time.
|
||||||
from ycmd import utils
|
from ycmd import utils
|
||||||
|
|
||||||
python_interpreter = vim.eval( 'g:ycm_server_python_interpreter' )
|
python_interpreter = vim.eval( 'g:ycm_server_python_interpreter' )
|
||||||
|
|
||||||
if python_interpreter:
|
if python_interpreter:
|
||||||
if IsPythonVersionCorrect( python_interpreter ):
|
if _EndsWithPython( python_interpreter ):
|
||||||
return python_interpreter
|
return python_interpreter
|
||||||
|
|
||||||
raise RuntimeError( "Path in 'g:ycm_server_python_interpreter' option "
|
raise RuntimeError( "Path in 'g:ycm_server_python_interpreter' option "
|
||||||
"does not point to a valid Python 2.6+ or 3.3+." )
|
"does not point to a valid Python 2.6+ or 3.3+." )
|
||||||
|
|
||||||
python_interpreter = _PathToPythonUsedDuringBuild()
|
python_interpreter = _PathToPythonUsedDuringBuild()
|
||||||
if IsPythonVersionCorrect( python_interpreter ):
|
if _EndsWithPython( python_interpreter ):
|
||||||
return python_interpreter
|
return python_interpreter
|
||||||
|
|
||||||
# On UNIX platforms, we use sys.executable as the Python interpreter path.
|
# On UNIX platforms, we use sys.executable as the Python interpreter path.
|
||||||
@ -72,8 +73,7 @@ def PathToPythonInterpreter():
|
|||||||
# interpreter path.
|
# interpreter path.
|
||||||
python_interpreter = ( WIN_PYTHON_PATH if utils.OnWindows() else
|
python_interpreter = ( WIN_PYTHON_PATH if utils.OnWindows() else
|
||||||
sys.executable )
|
sys.executable )
|
||||||
|
if _EndsWithPython( python_interpreter ):
|
||||||
if IsPythonVersionCorrect( python_interpreter ):
|
|
||||||
return python_interpreter
|
return python_interpreter
|
||||||
|
|
||||||
# As a last resort, we search python in the PATH. We prefer Python 2 over 3
|
# As a last resort, we search python in the PATH. We prefer Python 2 over 3
|
||||||
@ -84,8 +84,7 @@ def PathToPythonInterpreter():
|
|||||||
python_interpreter = utils.PathToFirstExistingExecutable( [ 'python2',
|
python_interpreter = utils.PathToFirstExistingExecutable( [ 'python2',
|
||||||
'python',
|
'python',
|
||||||
'python3' ] )
|
'python3' ] )
|
||||||
|
if python_interpreter:
|
||||||
if IsPythonVersionCorrect( python_interpreter ):
|
|
||||||
return python_interpreter
|
return python_interpreter
|
||||||
|
|
||||||
raise RuntimeError( "Cannot find Python 2.6+ or 3.3+. You can set its path "
|
raise RuntimeError( "Cannot find Python 2.6+ or 3.3+. You can set its path "
|
||||||
@ -104,34 +103,10 @@ def _PathToPythonUsedDuringBuild():
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def EndsWithPython( path ):
|
def _EndsWithPython( path ):
|
||||||
"""Check if given path ends with a python 2.6+ or 3.3+ name."""
|
"""Check if given path ends with a python 2.6+ or 3.3+ name."""
|
||||||
return path and PYTHON_BINARY_REGEX.search( path ) is not None
|
return path and PYTHON_BINARY_REGEX.search( path ) is not None
|
||||||
|
|
||||||
|
|
||||||
def IsPythonVersionCorrect( path ):
|
|
||||||
"""Check if given path is the Python interpreter version 2.6+ or 3.3+."""
|
|
||||||
from ycmd import utils
|
|
||||||
|
|
||||||
if not EndsWithPython( path ):
|
|
||||||
return False
|
|
||||||
|
|
||||||
command = [ path,
|
|
||||||
# Disable site customize. Faster, and less likely to encounter
|
|
||||||
# issues with disconnected mounts (nfs, fuse, etc.)
|
|
||||||
'-S',
|
|
||||||
'-c',
|
|
||||||
"import sys;"
|
|
||||||
"major, minor = sys.version_info[ :2 ];"
|
|
||||||
"good_python = ( major == 2 and minor >= 6 ) "
|
|
||||||
"or ( major == 3 and minor >= 3 ) or major > 3;"
|
|
||||||
# If this looks weird, remember that:
|
|
||||||
# int( True ) == 1
|
|
||||||
# int( False ) == 0
|
|
||||||
"sys.exit( not good_python )" ]
|
|
||||||
|
|
||||||
return utils.SafePopen( command ).wait() == 0
|
|
||||||
|
|
||||||
|
|
||||||
def PathToServerScript():
|
def PathToServerScript():
|
||||||
return os.path.join( DIR_OF_YCMD, 'ycmd' )
|
return os.path.join( DIR_OF_YCMD, 'ycmd' )
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (C) 2016 YouCompleteMe contributors
|
# Copyright (C) 2016-2017 YouCompleteMe contributors
|
||||||
#
|
#
|
||||||
# This file is part of YouCompleteMe.
|
# This file is part of YouCompleteMe.
|
||||||
#
|
#
|
||||||
@ -26,15 +26,15 @@ from ycm.tests.test_utils import MockVimModule
|
|||||||
MockVimModule()
|
MockVimModule()
|
||||||
|
|
||||||
from nose.tools import ok_
|
from nose.tools import ok_
|
||||||
from ycm.paths import EndsWithPython
|
from ycm.paths import _EndsWithPython
|
||||||
|
|
||||||
|
|
||||||
def EndsWithPython_Good( path ):
|
def EndsWithPython_Good( path ):
|
||||||
ok_( EndsWithPython( path ) )
|
ok_( _EndsWithPython( path ) )
|
||||||
|
|
||||||
|
|
||||||
def EndsWithPython_Bad( path ):
|
def EndsWithPython_Bad( path ):
|
||||||
ok_( not EndsWithPython( path ) )
|
ok_( not _EndsWithPython( path ) )
|
||||||
|
|
||||||
|
|
||||||
def EndsWithPython_Python2Paths_test():
|
def EndsWithPython_Python2Paths_test():
|
||||||
@ -50,7 +50,6 @@ def EndsWithPython_Python2Paths_test():
|
|||||||
yield EndsWithPython_Good, path
|
yield EndsWithPython_Good, path
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def EndsWithPython_Python3Paths_test():
|
def EndsWithPython_Python3Paths_test():
|
||||||
python_paths = [
|
python_paths = [
|
||||||
'python3',
|
'python3',
|
||||||
|
Loading…
Reference in New Issue
Block a user