mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-01-13 12:30:08 -06:00
Use a more intelligent default language version
This commit is contained in:
@@ -10,16 +10,18 @@ from pre_commit.languages import script
|
||||
from pre_commit.languages import swift
|
||||
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
|
||||
# ENVIRONMENT_DIR = 'foo_env'
|
||||
#
|
||||
# def install_environment(
|
||||
# repo_cmd_runner,
|
||||
# version='default',
|
||||
# additional_dependencies=(),
|
||||
# ):
|
||||
# def get_default_version():
|
||||
# """Return a value to replace the 'default' value for language_version.
|
||||
#
|
||||
# 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
|
||||
# working directory will already be inside the repository.
|
||||
#
|
||||
|
||||
@@ -14,6 +14,7 @@ from pre_commit.xargs import xargs
|
||||
|
||||
ENVIRONMENT_DIR = 'docker'
|
||||
PRE_COMMIT_LABEL = 'PRE_COMMIT'
|
||||
get_default_version = helpers.basic_get_default_version
|
||||
|
||||
|
||||
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(
|
||||
repo_cmd_runner,
|
||||
version='default',
|
||||
additional_dependencies=(),
|
||||
repo_cmd_runner, version, additional_dependencies,
|
||||
): # pragma: windows no cover
|
||||
assert repo_cmd_runner.exists('Dockerfile'), (
|
||||
'No Dockerfile was found in the hook repository'
|
||||
|
||||
@@ -14,6 +14,7 @@ from pre_commit.xargs import xargs
|
||||
|
||||
|
||||
ENVIRONMENT_DIR = 'golangenv'
|
||||
get_default_version = helpers.basic_get_default_version
|
||||
|
||||
|
||||
def get_env_patch(venv):
|
||||
@@ -44,11 +45,7 @@ def guess_go_dir(remote_url):
|
||||
return 'unknown_src_dir'
|
||||
|
||||
|
||||
def install_environment(
|
||||
repo_cmd_runner,
|
||||
version='default',
|
||||
additional_dependencies=(),
|
||||
):
|
||||
def install_environment(repo_cmd_runner, version, additional_dependencies):
|
||||
helpers.assert_version_default('golang', version)
|
||||
directory = repo_cmd_runner.path(
|
||||
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 '
|
||||
'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'
|
||||
get_default_version = helpers.basic_get_default_version
|
||||
|
||||
|
||||
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(
|
||||
repo_cmd_runner,
|
||||
version='default',
|
||||
additional_dependencies=(),
|
||||
repo_cmd_runner, version, additional_dependencies,
|
||||
): # pragma: windows no cover
|
||||
additional_dependencies = tuple(additional_dependencies)
|
||||
assert repo_cmd_runner.exists('package.json')
|
||||
|
||||
@@ -2,18 +2,16 @@ from __future__ import unicode_literals
|
||||
|
||||
import sys
|
||||
|
||||
from pre_commit.languages import helpers
|
||||
from pre_commit.xargs import xargs
|
||||
|
||||
|
||||
ENVIRONMENT_DIR = None
|
||||
GREP = 'ggrep' if sys.platform == 'darwin' else 'grep'
|
||||
get_default_version = helpers.basic_get_default_version
|
||||
|
||||
|
||||
def install_environment(
|
||||
repo_cmd_runner,
|
||||
version='default',
|
||||
additional_dependencies=(),
|
||||
):
|
||||
def install_environment(repo_cmd_runner, version, additional_dependencies):
|
||||
"""Installation for pcre type is a noop."""
|
||||
raise AssertionError('Cannot install pcre repo.')
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import contextlib
|
||||
import distutils.spawn
|
||||
import os
|
||||
import sys
|
||||
|
||||
@@ -9,11 +8,13 @@ from pre_commit.envcontext import envcontext
|
||||
from pre_commit.envcontext import UNSET
|
||||
from pre_commit.envcontext import Var
|
||||
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.xargs import xargs
|
||||
|
||||
|
||||
ENVIRONMENT_DIR = 'py_env'
|
||||
get_default_version = helpers.basic_get_default_version
|
||||
|
||||
|
||||
def bin_dir(venv):
|
||||
@@ -39,10 +40,53 @@ def in_env(repo_cmd_runner, language_version):
|
||||
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):
|
||||
if os.name == 'nt': # pragma: no cover (windows)
|
||||
# Try looking up by name
|
||||
if distutils.spawn.find_executable(version):
|
||||
if find_executable(version) and find_executable(version) != version:
|
||||
return version
|
||||
|
||||
# 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)
|
||||
|
||||
|
||||
def install_environment(
|
||||
repo_cmd_runner,
|
||||
version='default',
|
||||
additional_dependencies=(),
|
||||
):
|
||||
def install_environment(repo_cmd_runner, version, additional_dependencies):
|
||||
additional_dependencies = tuple(additional_dependencies)
|
||||
directory = helpers.environment_dir(ENVIRONMENT_DIR, version)
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ from pre_commit.xargs import xargs
|
||||
|
||||
|
||||
ENVIRONMENT_DIR = 'rbenv'
|
||||
get_default_version = helpers.basic_get_default_version
|
||||
|
||||
|
||||
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(
|
||||
repo_cmd_runner,
|
||||
version='default',
|
||||
additional_dependencies=(),
|
||||
repo_cmd_runner, version, additional_dependencies,
|
||||
): # pragma: windows no cover
|
||||
additional_dependencies = tuple(additional_dependencies)
|
||||
directory = helpers.environment_dir(ENVIRONMENT_DIR, version)
|
||||
|
||||
@@ -5,13 +5,10 @@ from pre_commit.xargs import xargs
|
||||
|
||||
|
||||
ENVIRONMENT_DIR = None
|
||||
get_default_version = helpers.basic_get_default_version
|
||||
|
||||
|
||||
def install_environment(
|
||||
repo_cmd_runner,
|
||||
version='default',
|
||||
additional_dependencies=(),
|
||||
):
|
||||
def install_environment(repo_cmd_runner, version, additional_dependencies):
|
||||
"""Installation for script type is a noop."""
|
||||
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
|
||||
|
||||
ENVIRONMENT_DIR = 'swift_env'
|
||||
get_default_version = helpers.basic_get_default_version
|
||||
BUILD_DIR = '.build'
|
||||
BUILD_CONFIG = 'release'
|
||||
|
||||
@@ -29,9 +30,7 @@ def in_env(repo_cmd_runner): # pragma: windows no cover
|
||||
|
||||
|
||||
def install_environment(
|
||||
repo_cmd_runner,
|
||||
version='default',
|
||||
additional_dependencies=(),
|
||||
repo_cmd_runner, version, additional_dependencies,
|
||||
): # pragma: windows no cover
|
||||
helpers.assert_version_default('swift', version)
|
||||
helpers.assert_no_additional_deps('swift', additional_dependencies)
|
||||
|
||||
@@ -5,13 +5,10 @@ from pre_commit.xargs import xargs
|
||||
|
||||
|
||||
ENVIRONMENT_DIR = None
|
||||
get_default_version = helpers.basic_get_default_version
|
||||
|
||||
|
||||
def install_environment(
|
||||
repo_cmd_runner,
|
||||
version='default',
|
||||
additional_dependencies=(),
|
||||
):
|
||||
def install_environment(repo_cmd_runner, version, additional_dependencies):
|
||||
"""Installation for system type is a noop."""
|
||||
raise AssertionError('Cannot install system repo.')
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ from cached_property import cached_property
|
||||
|
||||
import pre_commit.constants as C
|
||||
from pre_commit.clientlib import load_manifest
|
||||
from pre_commit.languages.all import languages
|
||||
|
||||
|
||||
logger = logging.getLogger('pre_commit')
|
||||
@@ -38,4 +39,10 @@ class Manifest(object):
|
||||
|
||||
@cached_property
|
||||
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):
|
||||
expected_argspec = inspect.ArgSpec(
|
||||
args=['repo_cmd_runner', 'version', 'additional_dependencies'],
|
||||
varargs=None,
|
||||
keywords=None,
|
||||
defaults=('default', ()),
|
||||
varargs=None, keywords=None, defaults=None,
|
||||
)
|
||||
argspec = inspect.getargspec(languages[language].install_environment)
|
||||
assert argspec == expected_argspec
|
||||
@@ -33,3 +31,12 @@ def test_run_hook_argpsec(language):
|
||||
)
|
||||
argspec = inspect.getargspec(languages[language].run_hook)
|
||||
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
|
||||
def manifest(store, tempdir_factory):
|
||||
path = make_repo(tempdir_factory, 'script_hooks_repo')
|
||||
head_sha = get_head_sha(path)
|
||||
repo_path = store.clone(path, head_sha)
|
||||
repo_path = store.clone(path, get_head_sha(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 '
|
||||
'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)
|
||||
repo = Repository.create(config, store)
|
||||
venv, = repo._venvs
|
||||
assert venv == (mock.ANY, 'python', 'default', [])
|
||||
assert venv == (mock.ANY, 'python', python.get_default_version(), [])
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
@@ -452,7 +452,7 @@ def test_additional_dependencies(tempdir_factory, store):
|
||||
config['hooks'][0]['additional_dependencies'] = ['pep8']
|
||||
repo = Repository.create(config, store)
|
||||
venv, = repo._venvs
|
||||
assert venv == (mock.ANY, 'python', 'default', ['pep8'])
|
||||
assert venv == (mock.ANY, 'python', python.get_default_version(), ['pep8'])
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
@@ -591,7 +591,8 @@ def test_control_c_control_c_on_install(tempdir_factory, store):
|
||||
repo.run_hook(hook, [])
|
||||
|
||||
# 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
|
||||
# install)
|
||||
|
||||
Reference in New Issue
Block a user