Skip to content

Commit

Permalink
Merge pull request #365 from micbou/windows-more-py3
Browse files Browse the repository at this point in the history
[READY] Fix Python 2 support and add Python 3 support on Windows
  • Loading branch information
Valloric committed Feb 15, 2016
2 parents 0fd4acc + ef8fc8f commit db76597
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 35 deletions.
13 changes: 9 additions & 4 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,23 @@ branches:
environment:
USE_CLANG_COMPLETER: true
matrix:
- msvc: 11
arch: 32
# We only test MSVC 11 and 12 with Python 3.5 on 64 bits.
- msvc: 11
arch: 64
- msvc: 12
arch: 32
python: 35
- msvc: 12
arch: 64
python: 35
- msvc: 14
arch: 32
python: 35
# We only test Python 2.7 with MSVC 14 on 64 bits.
- msvc: 14
arch: 64
python: 27
- msvc: 14
arch: 64
python: 35
install:
- ci\appveyor\appveyor_install.bat
build_script:
Expand Down
10 changes: 8 additions & 2 deletions build.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#!/usr/bin/env python

from __future__ import unicode_literals
# Passing an environment variable containing unicode literals to a subprocess
# on Windows and Python2 raises a TypeError. Since there is no unicode
# string in this script, we don't import unicode_literals to avoid the issue.
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import os
import subprocess
import os.path as p
Expand Down Expand Up @@ -281,7 +284,10 @@ def RunYcmdTests( build_dir ):
new_env = os.environ.copy()

if OnWindows():
new_env[ 'PATH' ] = DIR_OF_THIS_SCRIPT
# We prepend the folder of the ycm_core_tests executable to the PATH
# instead of overwriting it so that the executable is able to find the
# python35.dll library.
new_env[ 'PATH' ] = DIR_OF_THIS_SCRIPT + ';' + new_env[ 'PATH' ]
else:
new_env[ 'LD_LIBRARY_PATH' ] = DIR_OF_THIS_SCRIPT

Expand Down
17 changes: 13 additions & 4 deletions ci/appveyor/appveyor_install.bat
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,26 @@ if exist racerd_target (
::

if %arch% == 32 (
set python=C:\Python27
set python_path=C:\Python%python%
) else (
set python=C:\Python27-x64
set python_path=C:\Python%python%-x64
)

set PATH=%python%;%python%\Scripts;%PATH%
set PATH=%python_path%;%python_path%\Scripts;%PATH%
python --version
:: Manually setting PYTHONHOME for python 2.7.11 fix the following error when
:: running core tests: "ImportError: No module named site"
:: TODO: check if this is still needed when python 2.7.12 is released.
set PYTHONHOME=%python%
if %python% == 27 (
set PYTHONHOME=%python_path%
)

:: When using Python 3 on AppVeyor, CMake will always pick the 64 bits
:: libraries. We specifically tell CMake the right path to the libraries
:: according to the architecture.
if %python% == 35 (
set EXTRA_CMAKE_ARGS="-DPYTHON_LIBRARY=%python_path%\libs\python%python%.lib"
)

appveyor DownloadFile https://bootstrap.pypa.io/get-pip.py
python get-pip.py
Expand Down
6 changes: 4 additions & 2 deletions run_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,11 @@ def FixupCompleters( parsed_args ):

def BuildYcmdLibs( args ):
if not args.skip_build:
extra_cmake_args = [ '-DUSE_DEV_FLAGS=ON' ]
if 'EXTRA_CMAKE_ARGS' in os.environ:
os.environ[ 'EXTRA_CMAKE_ARGS' ] += ' -DUSE_DEV_FLAGS=ON'
else:
os.environ[ 'EXTRA_CMAKE_ARGS' ] = '-DUSE_DEV_FLAGS=ON'

os.environ[ 'EXTRA_CMAKE_ARGS' ] = ' '.join(extra_cmake_args)
os.environ[ 'YCM_TESTRUN' ] = '1'

build_cmd = [
Expand Down
2 changes: 1 addition & 1 deletion third_party/requests
Submodule requests updated 41 files
+4 −1 AUTHORS.rst
+57 −0 CONTRIBUTING.md
+51 −3 HISTORY.rst
+20 −2 docs/user/advanced.rst
+10 −3 docs/user/quickstart.rst
+9 −3 requests/__init__.py
+17 −3 requests/adapters.py
+6 −8 requests/api.py
+1 −1 requests/auth.py
+12 −7 requests/cookies.py
+15 −0 requests/exceptions.py
+6 −3 requests/models.py
+27 −5 requests/packages/urllib3/__init__.py
+4 −3 requests/packages/urllib3/_collections.py
+25 −14 requests/packages/urllib3/connection.py
+18 −16 requests/packages/urllib3/connectionpool.py
+12 −11 requests/packages/urllib3/contrib/appengine.py
+1 −0 requests/packages/urllib3/contrib/ntlmpool.py
+18 −17 requests/packages/urllib3/contrib/pyopenssl.py
+11 −3 requests/packages/urllib3/exceptions.py
+1 −0 requests/packages/urllib3/fields.py
+1 −0 requests/packages/urllib3/filepost.py
+1 −0 requests/packages/urllib3/packages/__init__.py
+1 −0 requests/packages/urllib3/packages/ssl_match_hostname/.gitignore
+2 −1 requests/packages/urllib3/poolmanager.py
+3 −1 requests/packages/urllib3/request.py
+41 −12 requests/packages/urllib3/response.py
+20 −0 requests/packages/urllib3/util/__init__.py
+1 −0 requests/packages/urllib3/util/connection.py
+1 −0 requests/packages/urllib3/util/request.py
+2 −1 requests/packages/urllib3/util/response.py
+4 −3 requests/packages/urllib3/util/retry.py
+35 −4 requests/packages/urllib3/util/ssl_.py
+5 −3 requests/packages/urllib3/util/timeout.py
+4 −1 requests/packages/urllib3/util/url.py
+6 −6 requests/sessions.py
+1 −0 requests/status_codes.py
+36 −11 requests/utils.py
+2 −0 requirements.txt
+3 −3 setup.py
+158 −137 test_requests.py
4 changes: 2 additions & 2 deletions ycmd/completers/rust/rust_completer.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from future import standard_library
standard_library.install_aliases()

from ycmd.utils import ToBytes, ProcessIsRunning
from ycmd.utils import ToBytes, SetEnviron, ProcessIsRunning
from ycmd.completers.completer import Completer
from ycmd import responses, utils, hmac_utils

Expand Down Expand Up @@ -261,7 +261,7 @@ def _StartServer( self ):

# Enable logging of crashes
env = os.environ.copy()
env[ 'RUST_BACKTRACE' ] = '1'
SetEnviron( env, 'RUST_BACKTRACE', '1' )

if self._rust_source_path:
args.extend( [ '--rust-src-path', self._rust_source_path ] )
Expand Down
2 changes: 1 addition & 1 deletion ycmd/completers/typescript/typescript_completer.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def __init__( self, user_options ):
# source code it seems like this is the way:
# https://github.com/Microsoft/TypeScript/blob/8a93b489454fdcbdf544edef05f73a913449be1d/src/server/server.ts#L136
self._environ = os.environ.copy()
self._environ[ 'TSS_LOG' ] = tsserver_log
utils.SetEnviron( self._environ, 'TSS_LOG', tsserver_log )

# Each request sent to tsserver must have a sequence id.
# Responses contain the id sent in the corresponding request.
Expand Down
8 changes: 6 additions & 2 deletions ycmd/tests/cs/cs_handlers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@
from future import standard_library
standard_library.install_aliases()
from builtins import * # noqa
from future.utils import PY2

from ..handlers_test import Handlers_test
from ycmd.utils import OnTravis
from ycmd.utils import OnTravis, OnWindows
import time
from contextlib import contextmanager

Expand All @@ -33,7 +34,10 @@
# Omnisharp instances between individual test cases. Non caching (false) is
# much faster, but test cases are not totally isolated from each other.
# For test case isolation, set to true.
INSTANCE_PER_TEST = False
# Reusing Omnisharp instances this way on Windows and Python 3 will randomly
# raise the error "OSError: [WinError 6] The handle is invalid" in tests so
# we set it to true in this case.
INSTANCE_PER_TEST = True if OnWindows() and not PY2 else False


class Cs_Handlers_test( Handlers_test ):
Expand Down
29 changes: 12 additions & 17 deletions ycmd/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from future import standard_library
standard_library.install_aliases()
from builtins import * # noqa
from future.utils import PY2, native

import tempfile
import os
Expand All @@ -31,8 +32,6 @@
import stat
import subprocess

from future.utils import PY2, iteritems, native

# Creation flag to disable creating a console window on Windows. See
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863.aspx
CREATE_NO_WINDOW = 0x08000000
Expand Down Expand Up @@ -270,14 +269,6 @@ def ForceSemanticCompletion( request_data ):

# A wrapper for subprocess.Popen that fixes quirks on Windows.
def SafePopen( args, **kwargs ):
def ToNativeStringDict( dict_obj ):
new_dict = dict()
for k, v in iteritems( dict_obj ):
if PY2:
new_dict[ native( ToBytes( k ) ) ] = native( ToBytes( v ) )
else:
new_dict[ ToUnicode( k ) ] = ToUnicode( v )
return new_dict

if OnWindows():
# We need this to start the server otherwise bad things happen.
Expand All @@ -291,17 +282,22 @@ def ToNativeStringDict( dict_obj ):
# http://bugs.python.org/issue1759845.
# Since paths are likely to contains such characters, we convert them to
# short ones to obtain paths with only ascii characters.
args = ConvertArgsToShortPath( args )

if 'env' in kwargs:
# Popen requires that on Windows, the environment has only native strings
# on py2 and py3.
kwargs[ 'env' ] = ToNativeStringDict( kwargs[ 'env' ] )
if PY2:
args = ConvertArgsToShortPath( args )

kwargs.pop( 'stdin_windows', None )
return subprocess.Popen( args, **kwargs )


# We need to convert environment variables to native strings on Windows and
# Python 2 to prevent a TypeError when passing them to a subprocess.
def SetEnviron( environ, variable, value ):
if OnWindows() and PY2:
environ[ native( ToBytes( variable ) ) ] = native( ToBytes( value ) )
else:
environ[ variable ] = value


# Convert paths in arguments command to short path ones
def ConvertArgsToShortPath( args ):
def ConvertIfPath( arg ):
Expand All @@ -317,7 +313,6 @@ def ConvertIfPath( arg ):
# Get the Windows short path name.
# Based on http://stackoverflow.com/a/23598461/200291
def GetShortPathName( path ):
path = native( ToBytes( path ) )
from ctypes import windll, wintypes, create_unicode_buffer

# Set the GetShortPathNameW prototype
Expand Down

0 comments on commit db76597

Please sign in to comment.