Skip to content

Commit d876661

Browse files
committed
Use a more intelligent default language version
1 parent 853cbec commit d876661

File tree

15 files changed

+109
-54
lines changed

15 files changed

+109
-54
lines changed

pre_commit/languages/all.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,18 @@
1010
from pre_commit.languages import swift
1111
from pre_commit.languages import system
1212

13-
# A language implements the following constant and two functions in its module:
13+
# A language implements the following constant and functions in its module:
1414
#
1515
# # Use None for no environment
1616
# ENVIRONMENT_DIR = 'foo_env'
1717
#
18-
# def install_environment(
19-
# repo_cmd_runner,
20-
# version='default',
21-
# additional_dependencies=(),
22-
# ):
18+
# def get_default_version():
19+
# """Return a value to replace the 'default' value for language_version.
20+
#
21+
# return 'default' if there is no better option.
22+
# """
23+
#
24+
# def install_environment(repo_cmd_runner, version, additional_dependencies):
2325
# """Installs a repository in the given repository. Note that the current
2426
# working directory will already be inside the repository.
2527
#

pre_commit/languages/docker.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
ENVIRONMENT_DIR = 'docker'
1616
PRE_COMMIT_LABEL = 'PRE_COMMIT'
17+
get_default_version = helpers.basic_get_default_version
1718

1819

1920
def md5(s): # pragma: windows no cover
@@ -55,9 +56,7 @@ def build_docker_image(repo_cmd_runner, **kwargs): # pragma: windows no cover
5556

5657

5758
def install_environment(
58-
repo_cmd_runner,
59-
version='default',
60-
additional_dependencies=(),
59+
repo_cmd_runner, version, additional_dependencies,
6160
): # pragma: windows no cover
6261
assert repo_cmd_runner.exists('Dockerfile'), (
6362
'No Dockerfile was found in the hook repository'

pre_commit/languages/golang.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515

1616
ENVIRONMENT_DIR = 'golangenv'
17+
get_default_version = helpers.basic_get_default_version
1718

1819

1920
def get_env_patch(venv):
@@ -44,11 +45,7 @@ def guess_go_dir(remote_url):
4445
return 'unknown_src_dir'
4546

4647

47-
def install_environment(
48-
repo_cmd_runner,
49-
version='default',
50-
additional_dependencies=(),
51-
):
48+
def install_environment(repo_cmd_runner, version, additional_dependencies):
5249
helpers.assert_version_default('golang', version)
5350
directory = repo_cmd_runner.path(
5451
helpers.environment_dir(ENVIRONMENT_DIR, 'default'),

pre_commit/languages/helpers.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,7 @@ def assert_no_additional_deps(lang, additional_deps):
3333
'For now, pre-commit does not support '
3434
'additional_dependencies for {}'.format(lang),
3535
)
36+
37+
38+
def basic_get_default_version():
39+
return 'default'

pre_commit/languages/node.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313

1414
ENVIRONMENT_DIR = 'node_env'
15+
get_default_version = helpers.basic_get_default_version
1516

1617

1718
def get_env_patch(venv): # pragma: windows no cover
@@ -34,9 +35,7 @@ def in_env(repo_cmd_runner, language_version): # pragma: windows no cover
3435

3536

3637
def install_environment(
37-
repo_cmd_runner,
38-
version='default',
39-
additional_dependencies=(),
38+
repo_cmd_runner, version, additional_dependencies,
4039
): # pragma: windows no cover
4140
additional_dependencies = tuple(additional_dependencies)
4241
assert repo_cmd_runner.exists('package.json')

pre_commit/languages/pcre.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,16 @@
22

33
import sys
44

5+
from pre_commit.languages import helpers
56
from pre_commit.xargs import xargs
67

78

89
ENVIRONMENT_DIR = None
910
GREP = 'ggrep' if sys.platform == 'darwin' else 'grep'
11+
get_default_version = helpers.basic_get_default_version
1012

1113

12-
def install_environment(
13-
repo_cmd_runner,
14-
version='default',
15-
additional_dependencies=(),
16-
):
14+
def install_environment(repo_cmd_runner, version, additional_dependencies):
1715
"""Installation for pcre type is a noop."""
1816
raise AssertionError('Cannot install pcre repo.')
1917

pre_commit/languages/python.py

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
from __future__ import unicode_literals
22

33
import contextlib
4-
import distutils.spawn
54
import os
65
import sys
76

87
from pre_commit.envcontext import envcontext
98
from pre_commit.envcontext import UNSET
109
from pre_commit.envcontext import Var
1110
from pre_commit.languages import helpers
11+
from pre_commit.parse_shebang import find_executable
1212
from pre_commit.util import clean_path_on_failure
1313
from pre_commit.xargs import xargs
1414

1515

1616
ENVIRONMENT_DIR = 'py_env'
17+
get_default_version = helpers.basic_get_default_version
1718

1819

1920
def 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+
4286
def 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

pre_commit/languages/ruby.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717

1818
ENVIRONMENT_DIR = 'rbenv'
19+
get_default_version = helpers.basic_get_default_version
1920

2021

2122
def get_env_patch(venv, language_version): # pragma: windows no cover
@@ -97,9 +98,7 @@ def _install_ruby(runner, version): # pragma: windows no cover
9798

9899

99100
def install_environment(
100-
repo_cmd_runner,
101-
version='default',
102-
additional_dependencies=(),
101+
repo_cmd_runner, version, additional_dependencies,
103102
): # pragma: windows no cover
104103
additional_dependencies = tuple(additional_dependencies)
105104
directory = helpers.environment_dir(ENVIRONMENT_DIR, version)

pre_commit/languages/script.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,10 @@
55

66

77
ENVIRONMENT_DIR = None
8+
get_default_version = helpers.basic_get_default_version
89

910

10-
def install_environment(
11-
repo_cmd_runner,
12-
version='default',
13-
additional_dependencies=(),
14-
):
11+
def install_environment(repo_cmd_runner, version, additional_dependencies):
1512
"""Installation for script type is a noop."""
1613
raise AssertionError('Cannot install script repo.')
1714

pre_commit/languages/swift.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from pre_commit.xargs import xargs
1111

1212
ENVIRONMENT_DIR = 'swift_env'
13+
get_default_version = helpers.basic_get_default_version
1314
BUILD_DIR = '.build'
1415
BUILD_CONFIG = 'release'
1516

@@ -29,9 +30,7 @@ def in_env(repo_cmd_runner): # pragma: windows no cover
2930

3031

3132
def install_environment(
32-
repo_cmd_runner,
33-
version='default',
34-
additional_dependencies=(),
33+
repo_cmd_runner, version, additional_dependencies,
3534
): # pragma: windows no cover
3635
helpers.assert_version_default('swift', version)
3736
helpers.assert_no_additional_deps('swift', additional_dependencies)

0 commit comments

Comments
 (0)