From a80846e35dd733f094f8ced9daeacba58eeb4316 Mon Sep 17 00:00:00 2001 From: micbou Date: Tue, 12 Jan 2016 21:24:23 +0100 Subject: [PATCH] Check Python interpreter pathname Rename CheckPythonVersion to IsPythonVersionCorrect. In embedders, sys.executable may contain a Vim path instead of a Python one. To avoid starting a Vim instance in this case, we check that given path ends with a Python 2.6 or 2.7 name using a regex. Add tests for this regex. --- python/ycm/paths.py | 18 +++++++++++--- python/ycm/tests/paths_test.py | 45 ++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 python/ycm/tests/paths_test.py diff --git a/python/ycm/paths.py b/python/ycm/paths.py index fcd78572..15f82e81 100644 --- a/python/ycm/paths.py +++ b/python/ycm/paths.py @@ -21,11 +21,13 @@ import os import sys import vim import functools +import re from ycmd import utils DIR_OF_CURRENT_SCRIPT = os.path.dirname( os.path.abspath( __file__ ) ) WIN_PYTHON_PATH = os.path.join( sys.exec_prefix, 'python.exe' ) +PYTHON_BINARY_REGEX = re.compile( r'python(2(\.[67])?)?(.exe)?$' ) def Memoize( obj ): @@ -45,7 +47,7 @@ def PathToPythonInterpreter(): python_interpreter = vim.eval( 'g:ycm_path_to_python_interpreter' ) if python_interpreter: - if not CheckPythonVersion( python_interpreter ): + if not IsPythonVersionCorrect( python_interpreter ): raise RuntimeError( "Path in 'g:ycm_path_to_python_interpreter' option " "does not point to a valid Python 2.6 or 2.7." ) @@ -58,7 +60,7 @@ def PathToPythonInterpreter(): python_interpreter = ( WIN_PYTHON_PATH if utils.OnWindows() else sys.executable ) - if not CheckPythonVersion( python_interpreter ): + if not IsPythonVersionCorrect( python_interpreter ): raise RuntimeError( "Cannot find Python 2.6 or 2.7. You can set its path " "using the 'g:ycm_path_to_python_interpreter' " "option." ) @@ -66,9 +68,17 @@ def PathToPythonInterpreter(): return python_interpreter -def CheckPythonVersion( python_interpreter ): +def EndsWithPython( path ): + """Check if given path ends with a python 2.6 or 2.7 name.""" + return PYTHON_BINARY_REGEX.search( path ) is not None + + +def IsPythonVersionCorrect( path ): """Check if given path is the Python interpreter version 2.6 or 2.7.""" - command = [ python_interpreter, + if not EndsWithPython( path ): + return False + + command = [ path, '-c', "import sys;" "major, minor = sys.version_info[ :2 ];" diff --git a/python/ycm/tests/paths_test.py b/python/ycm/tests/paths_test.py new file mode 100644 index 00000000..b7a43702 --- /dev/null +++ b/python/ycm/tests/paths_test.py @@ -0,0 +1,45 @@ +# +# 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 . + +from ycm.test_utils import MockVimModule +MockVimModule() + +from nose.tools import ok_ +from ycm.paths import EndsWithPython + + +def EndsWithPython_PythonPaths_test(): + python_paths = [ + 'python', + '/usr/bin/python2.6', + '/home/user/.pyenv/shims/python2.7', + r'C:\aPython26\python.exe' + ] + + for path in python_paths: + ok_( EndsWithPython( path ) ) + + +def EndsWithPython_NotPythonPaths_test(): + not_python_paths = [ + '/opt/local/bin/vim', + r'C:\Program Files\Vim\vim74\gvim.exe' + ] + + for path in not_python_paths: + ok_( not EndsWithPython( path ) )