11from __future__ import unicode_literals
22
33import contextlib
4- import distutils .spawn
54import os
65import sys
76
87from pre_commit .envcontext import envcontext
98from pre_commit .envcontext import UNSET
109from pre_commit .envcontext import Var
1110from pre_commit .languages import helpers
11+ from pre_commit .parse_shebang import find_executable
1212from pre_commit .util import clean_path_on_failure
1313from pre_commit .xargs import xargs
1414
1515
1616ENVIRONMENT_DIR = 'py_env'
17+ get_default_version = helpers .basic_get_default_version
1718
1819
1920def bin_dir (venv ):
@@ -39,10 +40,53 @@ def in_env(repo_cmd_runner, language_version):
3940 yield
4041
4142
43+ def _get_default_version (): # pragma: no cover (platform dependent)
44+ def _norm (path ):
45+ _ , exe = os .path .split (path .lower ())
46+ exe , _ , _ = exe .partition ('.exe' )
47+ if find_executable (exe ) and exe not in {'python' , 'pythonw' }:
48+ return exe
49+
50+ # First attempt from `sys.executable` (or the realpath)
51+ # On linux, I see these common sys.executables:
52+ #
53+ # system `python`: /usr/bin/python -> python2.7
54+ # system `python2`: /usr/bin/python2 -> python2.7
55+ # virtualenv v: v/bin/python (will not return from this loop)
56+ # virtualenv v -ppython2: v/bin/python -> python2
57+ # virtualenv v -ppython2.7: v/bin/python -> python2.7
58+ # virtualenv v -ppypy: v/bin/python -> v/bin/pypy
59+ for path in {sys .executable , os .path .realpath (sys .executable )}:
60+ exe = _norm (path )
61+ if exe :
62+ return exe
63+
64+ # Next try the `pythonX.X` executable
65+ exe = 'python{}.{}' .format (* sys .version_info )
66+ if find_executable (exe ):
67+ return exe
68+
69+ # Give a best-effort try for windows
70+ if os .path .exists (r'C:\{}\python.exe' .format (exe .replace ('.' , '' ))):
71+ return exe
72+
73+ # We tried!
74+ return 'default'
75+
76+
77+ def get_default_version ():
78+ # TODO: when dropping python2, use `functools.lru_cache(maxsize=1)`
79+ try :
80+ return get_default_version .cached_version
81+ except AttributeError :
82+ get_default_version .cached_version = _get_default_version ()
83+ return get_default_version ()
84+
85+
4286def norm_version (version ):
4387 if os .name == 'nt' : # pragma: no cover (windows)
4488 # Try looking up by name
45- if distutils . spawn . find_executable (version ):
89+ if find_executable (version ) and find_executable ( version ) != version :
4690 return version
4791
4892 # If it is in the form pythonx.x search in the default
@@ -54,11 +98,7 @@ def norm_version(version):
5498 return os .path .expanduser (version )
5599
56100
57- def install_environment (
58- repo_cmd_runner ,
59- version = 'default' ,
60- additional_dependencies = (),
61- ):
101+ def install_environment (repo_cmd_runner , version , additional_dependencies ):
62102 additional_dependencies = tuple (additional_dependencies )
63103 directory = helpers .environment_dir (ENVIRONMENT_DIR , version )
64104
0 commit comments