123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- #!/usr/bin/env python
- #
- # Copyright (C) 2011, 2012 Strahinja Val Markovic <val@markovic.io>
- #
- # 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 tempfile
- import os
- import sys
- import signal
- import functools
- import socket
- import stat
- from distutils.spawn import find_executable
- import subprocess
- WIN_PYTHON27_PATH = 'C:\python27\pythonw.exe'
- WIN_PYTHON26_PATH = 'C:\python26\pythonw.exe'
- def IsIdentifierChar( char ):
- return char.isalnum() or char == '_'
- def SanitizeQuery( query ):
- return query.strip()
- def ToUtf8IfNeeded( value ):
- if isinstance( value, unicode ):
- return value.encode( 'utf8' )
- if isinstance( value, str ):
- return value
- return str( value )
- def PathToTempDir():
- tempdir = os.path.join( tempfile.gettempdir(), 'ycm_temp' )
- if not os.path.exists( tempdir ):
- os.makedirs( tempdir )
- # Needed to support multiple users working on the same machine;
- # see issue 606.
- MakeFolderAccessibleToAll( tempdir )
- return tempdir
- def MakeFolderAccessibleToAll( path_to_folder ):
- current_stat = os.stat( path_to_folder )
- # readable, writable and executable by everyone
- flags = ( current_stat.st_mode | stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH
- | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP )
- os.chmod( path_to_folder, flags )
- def RunningInsideVim():
- try:
- import vim # NOQA
- return True
- except ImportError:
- return False
- def GetUnusedLocalhostPort():
- sock = socket.socket()
- # This tells the OS to give us any free port in the range [1024 - 65535]
- sock.bind( ( '', 0 ) )
- port = sock.getsockname()[ 1 ]
- sock.close()
- return port
- def RemoveIfExists( filename ):
- try:
- os.remove( filename )
- except OSError:
- pass
- def Memoize( obj ):
- cache = obj.cache = {}
- @functools.wraps( obj )
- def memoizer( *args, **kwargs ):
- key = str( args ) + str( kwargs )
- if key not in cache:
- cache[ key ] = obj( *args, **kwargs )
- return cache[ key ]
- return memoizer
- @Memoize
- def PathToPythonInterpreter():
- if not RunningInsideVim():
- return sys.executable
- import vim # NOQA
- user_path_to_python = vim.eval( 'g:ycm_path_to_python_interpreter' )
- if user_path_to_python:
- return user_path_to_python
- # We check for 'python2' before 'python' because some OS's (I'm looking at you
- # Arch Linux) have made the... interesting decision to point /usr/bin/python
- # to python3.
- python_names = [ 'python2', 'python' ]
- if OnWindows():
- # On Windows, 'pythonw' doesn't pop-up a console window like running
- # 'python' does.
- python_names.insert( 0, 'pythonw' )
- path_to_python = PathToFirstExistingExecutable( python_names )
- if path_to_python:
- return path_to_python
- # On Windows, Python may not be on the PATH at all, so we check some common
- # install locations.
- if OnWindows():
- if os.path.exists( WIN_PYTHON27_PATH ):
- return WIN_PYTHON27_PATH
- elif os.path.exists( WIN_PYTHON26_PATH ):
- return WIN_PYTHON26_PATH
- raise RuntimeError( 'Python 2.7/2.6 not installed!' )
- def PathToFirstExistingExecutable( executable_name_list ):
- for executable_name in executable_name_list:
- path = find_executable( executable_name )
- if path:
- return path
- return None
- def OnWindows():
- return sys.platform == 'win32'
- # From here: http://stackoverflow.com/a/8536476/1672783
- def TerminateProcess( pid ):
- if OnWindows():
- import ctypes
- PROCESS_TERMINATE = 1
- handle = ctypes.windll.kernel32.OpenProcess( PROCESS_TERMINATE,
- False,
- pid )
- ctypes.windll.kernel32.TerminateProcess( handle, -1 )
- ctypes.windll.kernel32.CloseHandle( handle )
- else:
- os.kill( pid, signal.SIGTERM )
- def AddThirdPartyFoldersToSysPath():
- path_to_third_party = os.path.join(
- os.path.dirname( os.path.abspath( __file__ ) ),
- '../../third_party' )
- for folder in os.listdir( path_to_third_party ):
- sys.path.insert( 0, os.path.realpath( os.path.join( path_to_third_party,
- folder ) ) )
- def ForceSemanticCompletion( request_data ):
- return ( 'force_semantic' in request_data and
- bool( request_data[ 'force_semantic' ] ) )
- # A wrapper for subprocess.Popen that works around a Popen bug on Windows.
- def SafePopen( *args, **kwargs ):
- if kwargs.get( 'stdin', '' ) is None:
- # We need this on Windows otherwise bad things happen. See issue #637.
- kwargs[ 'stdin' ] = subprocess.PIPE if OnWindows() else None
- return subprocess.Popen( *args, **kwargs )
|