mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-02-17 08:14:42 +04:00
Use a more intelligent default language version
This commit is contained in:
parent
853cbecd4e
commit
d876661345
15 changed files with 109 additions and 54 deletions
|
|
@ -10,16 +10,18 @@ from pre_commit.languages import script
|
||||||
from pre_commit.languages import swift
|
from pre_commit.languages import swift
|
||||||
from pre_commit.languages import system
|
from pre_commit.languages import system
|
||||||
|
|
||||||
# A language implements the following constant and two functions in its module:
|
# A language implements the following constant and functions in its module:
|
||||||
#
|
#
|
||||||
# # Use None for no environment
|
# # Use None for no environment
|
||||||
# ENVIRONMENT_DIR = 'foo_env'
|
# ENVIRONMENT_DIR = 'foo_env'
|
||||||
#
|
#
|
||||||
# def install_environment(
|
# def get_default_version():
|
||||||
# repo_cmd_runner,
|
# """Return a value to replace the 'default' value for language_version.
|
||||||
# version='default',
|
#
|
||||||
# additional_dependencies=(),
|
# return 'default' if there is no better option.
|
||||||
# ):
|
# """
|
||||||
|
#
|
||||||
|
# def install_environment(repo_cmd_runner, version, additional_dependencies):
|
||||||
# """Installs a repository in the given repository. Note that the current
|
# """Installs a repository in the given repository. Note that the current
|
||||||
# working directory will already be inside the repository.
|
# working directory will already be inside the repository.
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ from pre_commit.xargs import xargs
|
||||||
|
|
||||||
ENVIRONMENT_DIR = 'docker'
|
ENVIRONMENT_DIR = 'docker'
|
||||||
PRE_COMMIT_LABEL = 'PRE_COMMIT'
|
PRE_COMMIT_LABEL = 'PRE_COMMIT'
|
||||||
|
get_default_version = helpers.basic_get_default_version
|
||||||
|
|
||||||
|
|
||||||
def md5(s): # pragma: windows no cover
|
def md5(s): # pragma: windows no cover
|
||||||
|
|
@ -55,9 +56,7 @@ def build_docker_image(repo_cmd_runner, **kwargs): # pragma: windows no cover
|
||||||
|
|
||||||
|
|
||||||
def install_environment(
|
def install_environment(
|
||||||
repo_cmd_runner,
|
repo_cmd_runner, version, additional_dependencies,
|
||||||
version='default',
|
|
||||||
additional_dependencies=(),
|
|
||||||
): # pragma: windows no cover
|
): # pragma: windows no cover
|
||||||
assert repo_cmd_runner.exists('Dockerfile'), (
|
assert repo_cmd_runner.exists('Dockerfile'), (
|
||||||
'No Dockerfile was found in the hook repository'
|
'No Dockerfile was found in the hook repository'
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ from pre_commit.xargs import xargs
|
||||||
|
|
||||||
|
|
||||||
ENVIRONMENT_DIR = 'golangenv'
|
ENVIRONMENT_DIR = 'golangenv'
|
||||||
|
get_default_version = helpers.basic_get_default_version
|
||||||
|
|
||||||
|
|
||||||
def get_env_patch(venv):
|
def get_env_patch(venv):
|
||||||
|
|
@ -44,11 +45,7 @@ def guess_go_dir(remote_url):
|
||||||
return 'unknown_src_dir'
|
return 'unknown_src_dir'
|
||||||
|
|
||||||
|
|
||||||
def install_environment(
|
def install_environment(repo_cmd_runner, version, additional_dependencies):
|
||||||
repo_cmd_runner,
|
|
||||||
version='default',
|
|
||||||
additional_dependencies=(),
|
|
||||||
):
|
|
||||||
helpers.assert_version_default('golang', version)
|
helpers.assert_version_default('golang', version)
|
||||||
directory = repo_cmd_runner.path(
|
directory = repo_cmd_runner.path(
|
||||||
helpers.environment_dir(ENVIRONMENT_DIR, 'default'),
|
helpers.environment_dir(ENVIRONMENT_DIR, 'default'),
|
||||||
|
|
|
||||||
|
|
@ -33,3 +33,7 @@ def assert_no_additional_deps(lang, additional_deps):
|
||||||
'For now, pre-commit does not support '
|
'For now, pre-commit does not support '
|
||||||
'additional_dependencies for {}'.format(lang),
|
'additional_dependencies for {}'.format(lang),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def basic_get_default_version():
|
||||||
|
return 'default'
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ from pre_commit.xargs import xargs
|
||||||
|
|
||||||
|
|
||||||
ENVIRONMENT_DIR = 'node_env'
|
ENVIRONMENT_DIR = 'node_env'
|
||||||
|
get_default_version = helpers.basic_get_default_version
|
||||||
|
|
||||||
|
|
||||||
def get_env_patch(venv): # pragma: windows no cover
|
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
|
||||||
|
|
||||||
|
|
||||||
def install_environment(
|
def install_environment(
|
||||||
repo_cmd_runner,
|
repo_cmd_runner, version, additional_dependencies,
|
||||||
version='default',
|
|
||||||
additional_dependencies=(),
|
|
||||||
): # pragma: windows no cover
|
): # pragma: windows no cover
|
||||||
additional_dependencies = tuple(additional_dependencies)
|
additional_dependencies = tuple(additional_dependencies)
|
||||||
assert repo_cmd_runner.exists('package.json')
|
assert repo_cmd_runner.exists('package.json')
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,16 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from pre_commit.languages import helpers
|
||||||
from pre_commit.xargs import xargs
|
from pre_commit.xargs import xargs
|
||||||
|
|
||||||
|
|
||||||
ENVIRONMENT_DIR = None
|
ENVIRONMENT_DIR = None
|
||||||
GREP = 'ggrep' if sys.platform == 'darwin' else 'grep'
|
GREP = 'ggrep' if sys.platform == 'darwin' else 'grep'
|
||||||
|
get_default_version = helpers.basic_get_default_version
|
||||||
|
|
||||||
|
|
||||||
def install_environment(
|
def install_environment(repo_cmd_runner, version, additional_dependencies):
|
||||||
repo_cmd_runner,
|
|
||||||
version='default',
|
|
||||||
additional_dependencies=(),
|
|
||||||
):
|
|
||||||
"""Installation for pcre type is a noop."""
|
"""Installation for pcre type is a noop."""
|
||||||
raise AssertionError('Cannot install pcre repo.')
|
raise AssertionError('Cannot install pcre repo.')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
import distutils.spawn
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
@ -9,11 +8,13 @@ from pre_commit.envcontext import envcontext
|
||||||
from pre_commit.envcontext import UNSET
|
from pre_commit.envcontext import UNSET
|
||||||
from pre_commit.envcontext import Var
|
from pre_commit.envcontext import Var
|
||||||
from pre_commit.languages import helpers
|
from pre_commit.languages import helpers
|
||||||
|
from pre_commit.parse_shebang import find_executable
|
||||||
from pre_commit.util import clean_path_on_failure
|
from pre_commit.util import clean_path_on_failure
|
||||||
from pre_commit.xargs import xargs
|
from pre_commit.xargs import xargs
|
||||||
|
|
||||||
|
|
||||||
ENVIRONMENT_DIR = 'py_env'
|
ENVIRONMENT_DIR = 'py_env'
|
||||||
|
get_default_version = helpers.basic_get_default_version
|
||||||
|
|
||||||
|
|
||||||
def bin_dir(venv):
|
def bin_dir(venv):
|
||||||
|
|
@ -39,10 +40,53 @@ def in_env(repo_cmd_runner, language_version):
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
def _get_default_version(): # pragma: no cover (platform dependent)
|
||||||
|
def _norm(path):
|
||||||
|
_, exe = os.path.split(path.lower())
|
||||||
|
exe, _, _ = exe.partition('.exe')
|
||||||
|
if find_executable(exe) and exe not in {'python', 'pythonw'}:
|
||||||
|
return exe
|
||||||
|
|
||||||
|
# First attempt from `sys.executable` (or the realpath)
|
||||||
|
# On linux, I see these common sys.executables:
|
||||||
|
#
|
||||||
|
# system `python`: /usr/bin/python -> python2.7
|
||||||
|
# system `python2`: /usr/bin/python2 -> python2.7
|
||||||
|
# virtualenv v: v/bin/python (will not return from this loop)
|
||||||
|
# virtualenv v -ppython2: v/bin/python -> python2
|
||||||
|
# virtualenv v -ppython2.7: v/bin/python -> python2.7
|
||||||
|
# virtualenv v -ppypy: v/bin/python -> v/bin/pypy
|
||||||
|
for path in {sys.executable, os.path.realpath(sys.executable)}:
|
||||||
|
exe = _norm(path)
|
||||||
|
if exe:
|
||||||
|
return exe
|
||||||
|
|
||||||
|
# Next try the `pythonX.X` executable
|
||||||
|
exe = 'python{}.{}'.format(*sys.version_info)
|
||||||
|
if find_executable(exe):
|
||||||
|
return exe
|
||||||
|
|
||||||
|
# Give a best-effort try for windows
|
||||||
|
if os.path.exists(r'C:\{}\python.exe'.format(exe.replace('.', ''))):
|
||||||
|
return exe
|
||||||
|
|
||||||
|
# We tried!
|
||||||
|
return 'default'
|
||||||
|
|
||||||
|
|
||||||
|
def get_default_version():
|
||||||
|
# TODO: when dropping python2, use `functools.lru_cache(maxsize=1)`
|
||||||
|
try:
|
||||||
|
return get_default_version.cached_version
|
||||||
|
except AttributeError:
|
||||||
|
get_default_version.cached_version = _get_default_version()
|
||||||
|
return get_default_version()
|
||||||
|
|
||||||
|
|
||||||
def norm_version(version):
|
def norm_version(version):
|
||||||
if os.name == 'nt': # pragma: no cover (windows)
|
if os.name == 'nt': # pragma: no cover (windows)
|
||||||
# Try looking up by name
|
# Try looking up by name
|
||||||
if distutils.spawn.find_executable(version):
|
if find_executable(version) and find_executable(version) != version:
|
||||||
return version
|
return version
|
||||||
|
|
||||||
# If it is in the form pythonx.x search in the default
|
# If it is in the form pythonx.x search in the default
|
||||||
|
|
@ -54,11 +98,7 @@ def norm_version(version):
|
||||||
return os.path.expanduser(version)
|
return os.path.expanduser(version)
|
||||||
|
|
||||||
|
|
||||||
def install_environment(
|
def install_environment(repo_cmd_runner, version, additional_dependencies):
|
||||||
repo_cmd_runner,
|
|
||||||
version='default',
|
|
||||||
additional_dependencies=(),
|
|
||||||
):
|
|
||||||
additional_dependencies = tuple(additional_dependencies)
|
additional_dependencies = tuple(additional_dependencies)
|
||||||
directory = helpers.environment_dir(ENVIRONMENT_DIR, version)
|
directory = helpers.environment_dir(ENVIRONMENT_DIR, version)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ from pre_commit.xargs import xargs
|
||||||
|
|
||||||
|
|
||||||
ENVIRONMENT_DIR = 'rbenv'
|
ENVIRONMENT_DIR = 'rbenv'
|
||||||
|
get_default_version = helpers.basic_get_default_version
|
||||||
|
|
||||||
|
|
||||||
def get_env_patch(venv, language_version): # pragma: windows no cover
|
def get_env_patch(venv, language_version): # pragma: windows no cover
|
||||||
|
|
@ -97,9 +98,7 @@ def _install_ruby(runner, version): # pragma: windows no cover
|
||||||
|
|
||||||
|
|
||||||
def install_environment(
|
def install_environment(
|
||||||
repo_cmd_runner,
|
repo_cmd_runner, version, additional_dependencies,
|
||||||
version='default',
|
|
||||||
additional_dependencies=(),
|
|
||||||
): # pragma: windows no cover
|
): # pragma: windows no cover
|
||||||
additional_dependencies = tuple(additional_dependencies)
|
additional_dependencies = tuple(additional_dependencies)
|
||||||
directory = helpers.environment_dir(ENVIRONMENT_DIR, version)
|
directory = helpers.environment_dir(ENVIRONMENT_DIR, version)
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,10 @@ from pre_commit.xargs import xargs
|
||||||
|
|
||||||
|
|
||||||
ENVIRONMENT_DIR = None
|
ENVIRONMENT_DIR = None
|
||||||
|
get_default_version = helpers.basic_get_default_version
|
||||||
|
|
||||||
|
|
||||||
def install_environment(
|
def install_environment(repo_cmd_runner, version, additional_dependencies):
|
||||||
repo_cmd_runner,
|
|
||||||
version='default',
|
|
||||||
additional_dependencies=(),
|
|
||||||
):
|
|
||||||
"""Installation for script type is a noop."""
|
"""Installation for script type is a noop."""
|
||||||
raise AssertionError('Cannot install script repo.')
|
raise AssertionError('Cannot install script repo.')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ from pre_commit.util import clean_path_on_failure
|
||||||
from pre_commit.xargs import xargs
|
from pre_commit.xargs import xargs
|
||||||
|
|
||||||
ENVIRONMENT_DIR = 'swift_env'
|
ENVIRONMENT_DIR = 'swift_env'
|
||||||
|
get_default_version = helpers.basic_get_default_version
|
||||||
BUILD_DIR = '.build'
|
BUILD_DIR = '.build'
|
||||||
BUILD_CONFIG = 'release'
|
BUILD_CONFIG = 'release'
|
||||||
|
|
||||||
|
|
@ -29,9 +30,7 @@ def in_env(repo_cmd_runner): # pragma: windows no cover
|
||||||
|
|
||||||
|
|
||||||
def install_environment(
|
def install_environment(
|
||||||
repo_cmd_runner,
|
repo_cmd_runner, version, additional_dependencies,
|
||||||
version='default',
|
|
||||||
additional_dependencies=(),
|
|
||||||
): # pragma: windows no cover
|
): # pragma: windows no cover
|
||||||
helpers.assert_version_default('swift', version)
|
helpers.assert_version_default('swift', version)
|
||||||
helpers.assert_no_additional_deps('swift', additional_dependencies)
|
helpers.assert_no_additional_deps('swift', additional_dependencies)
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,10 @@ from pre_commit.xargs import xargs
|
||||||
|
|
||||||
|
|
||||||
ENVIRONMENT_DIR = None
|
ENVIRONMENT_DIR = None
|
||||||
|
get_default_version = helpers.basic_get_default_version
|
||||||
|
|
||||||
|
|
||||||
def install_environment(
|
def install_environment(repo_cmd_runner, version, additional_dependencies):
|
||||||
repo_cmd_runner,
|
|
||||||
version='default',
|
|
||||||
additional_dependencies=(),
|
|
||||||
):
|
|
||||||
"""Installation for system type is a noop."""
|
"""Installation for system type is a noop."""
|
||||||
raise AssertionError('Cannot install system repo.')
|
raise AssertionError('Cannot install system repo.')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ from cached_property import cached_property
|
||||||
|
|
||||||
import pre_commit.constants as C
|
import pre_commit.constants as C
|
||||||
from pre_commit.clientlib import load_manifest
|
from pre_commit.clientlib import load_manifest
|
||||||
|
from pre_commit.languages.all import languages
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger('pre_commit')
|
logger = logging.getLogger('pre_commit')
|
||||||
|
|
@ -38,4 +39,10 @@ class Manifest(object):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def hooks(self):
|
def hooks(self):
|
||||||
return {hook['id']: hook for hook in self.manifest_contents}
|
ret = {}
|
||||||
|
for hook in self.manifest_contents:
|
||||||
|
if hook['language_version'] == 'default':
|
||||||
|
language = languages[hook['language']]
|
||||||
|
hook['language_version'] = language.get_default_version()
|
||||||
|
ret[hook['id']] = hook
|
||||||
|
return ret
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,7 @@ from pre_commit.languages.all import languages
|
||||||
def test_install_environment_argspec(language):
|
def test_install_environment_argspec(language):
|
||||||
expected_argspec = inspect.ArgSpec(
|
expected_argspec = inspect.ArgSpec(
|
||||||
args=['repo_cmd_runner', 'version', 'additional_dependencies'],
|
args=['repo_cmd_runner', 'version', 'additional_dependencies'],
|
||||||
varargs=None,
|
varargs=None, keywords=None, defaults=None,
|
||||||
keywords=None,
|
|
||||||
defaults=('default', ()),
|
|
||||||
)
|
)
|
||||||
argspec = inspect.getargspec(languages[language].install_environment)
|
argspec = inspect.getargspec(languages[language].install_environment)
|
||||||
assert argspec == expected_argspec
|
assert argspec == expected_argspec
|
||||||
|
|
@ -33,3 +31,12 @@ def test_run_hook_argpsec(language):
|
||||||
)
|
)
|
||||||
argspec = inspect.getargspec(languages[language].run_hook)
|
argspec = inspect.getargspec(languages[language].run_hook)
|
||||||
assert argspec == expected_argspec
|
assert argspec == expected_argspec
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('language', all_languages)
|
||||||
|
def test_get_default_version_argspec(language):
|
||||||
|
expected_argspec = inspect.ArgSpec(
|
||||||
|
args=[], varargs=None, keywords=None, defaults=None,
|
||||||
|
)
|
||||||
|
argspec = inspect.getargspec(languages[language].get_default_version)
|
||||||
|
assert argspec == expected_argspec
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,7 @@ from testing.util import get_head_sha
|
||||||
@pytest.yield_fixture
|
@pytest.yield_fixture
|
||||||
def manifest(store, tempdir_factory):
|
def manifest(store, tempdir_factory):
|
||||||
path = make_repo(tempdir_factory, 'script_hooks_repo')
|
path = make_repo(tempdir_factory, 'script_hooks_repo')
|
||||||
head_sha = get_head_sha(path)
|
repo_path = store.clone(path, get_head_sha(path))
|
||||||
repo_path = store.clone(path, head_sha)
|
|
||||||
yield Manifest(repo_path, path)
|
yield Manifest(repo_path, path)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -76,3 +75,13 @@ def test_legacy_manifest_warn(store, tempdir_factory, log_warning_mock):
|
||||||
'If `pre-commit autoupdate` does not silence this warning consider '
|
'If `pre-commit autoupdate` does not silence this warning consider '
|
||||||
'making an issue / pull request.'.format(path)
|
'making an issue / pull request.'.format(path)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_python_language_version(store, tempdir_factory):
|
||||||
|
path = make_repo(tempdir_factory, 'python_hooks_repo')
|
||||||
|
repo_path = store.clone(path, get_head_sha(path))
|
||||||
|
manifest = Manifest(repo_path, path)
|
||||||
|
|
||||||
|
# This assertion is difficult as it is version dependent, just assert
|
||||||
|
# that it is *something*
|
||||||
|
assert manifest.hooks['foo']['language_version'] != 'default'
|
||||||
|
|
|
||||||
|
|
@ -442,7 +442,7 @@ def test_venvs(tempdir_factory, store):
|
||||||
config = make_config_from_repo(path)
|
config = make_config_from_repo(path)
|
||||||
repo = Repository.create(config, store)
|
repo = Repository.create(config, store)
|
||||||
venv, = repo._venvs
|
venv, = repo._venvs
|
||||||
assert venv == (mock.ANY, 'python', 'default', [])
|
assert venv == (mock.ANY, 'python', python.get_default_version(), [])
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.integration
|
@pytest.mark.integration
|
||||||
|
|
@ -452,7 +452,7 @@ def test_additional_dependencies(tempdir_factory, store):
|
||||||
config['hooks'][0]['additional_dependencies'] = ['pep8']
|
config['hooks'][0]['additional_dependencies'] = ['pep8']
|
||||||
repo = Repository.create(config, store)
|
repo = Repository.create(config, store)
|
||||||
venv, = repo._venvs
|
venv, = repo._venvs
|
||||||
assert venv == (mock.ANY, 'python', 'default', ['pep8'])
|
assert venv == (mock.ANY, 'python', python.get_default_version(), ['pep8'])
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.integration
|
@pytest.mark.integration
|
||||||
|
|
@ -591,7 +591,8 @@ def test_control_c_control_c_on_install(tempdir_factory, store):
|
||||||
repo.run_hook(hook, [])
|
repo.run_hook(hook, [])
|
||||||
|
|
||||||
# Should have made an environment, however this environment is broken!
|
# Should have made an environment, however this environment is broken!
|
||||||
assert os.path.exists(repo._cmd_runner.path('py_env-default'))
|
envdir = 'py_env-{}'.format(python.get_default_version())
|
||||||
|
assert repo._cmd_runner.exists(envdir)
|
||||||
|
|
||||||
# However, it should be perfectly runnable (reinstall after botched
|
# However, it should be perfectly runnable (reinstall after botched
|
||||||
# install)
|
# install)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue