Merging upstream version 3.1.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
f7ee0eb8fc
commit
c4c52947de
88 changed files with 1083 additions and 974 deletions
|
@ -10,15 +10,12 @@ import pytest
|
|||
import re_assert
|
||||
|
||||
import pre_commit.constants as C
|
||||
from pre_commit import git
|
||||
from pre_commit import lang_base
|
||||
from pre_commit.all_languages import languages
|
||||
from pre_commit.clientlib import CONFIG_SCHEMA
|
||||
from pre_commit.clientlib import load_manifest
|
||||
from pre_commit.envcontext import envcontext
|
||||
from pre_commit.hook import Hook
|
||||
from pre_commit.languages import golang
|
||||
from pre_commit.languages import helpers
|
||||
from pre_commit.languages import python
|
||||
from pre_commit.languages.all import languages
|
||||
from pre_commit.prefix import Prefix
|
||||
from pre_commit.repository import _hook_installed
|
||||
from pre_commit.repository import all_hooks
|
||||
|
@ -28,26 +25,24 @@ from pre_commit.util import cmd_output_b
|
|||
from testing.fixtures import make_config_from_repo
|
||||
from testing.fixtures import make_repo
|
||||
from testing.fixtures import modify_manifest
|
||||
from testing.language_helpers import run_language
|
||||
from testing.util import cwd
|
||||
from testing.util import get_resource_path
|
||||
from testing.util import skipif_cant_run_docker
|
||||
|
||||
|
||||
def _norm_out(b):
|
||||
return b.replace(b'\r\n', b'\n')
|
||||
|
||||
|
||||
def _hook_run(hook, filenames, color):
|
||||
with languages[hook.language].in_env(hook.prefix, hook.language_version):
|
||||
return languages[hook.language].run_hook(
|
||||
hook.prefix,
|
||||
hook.entry,
|
||||
hook.args,
|
||||
filenames,
|
||||
is_local=hook.src == 'local',
|
||||
require_serial=hook.require_serial,
|
||||
color=color,
|
||||
)
|
||||
return run_language(
|
||||
path=hook.prefix.prefix_dir,
|
||||
language=languages[hook.language],
|
||||
exe=hook.entry,
|
||||
args=hook.args,
|
||||
file_args=filenames,
|
||||
version=hook.language_version,
|
||||
deps=hook.additional_dependencies,
|
||||
is_local=hook.src == 'local',
|
||||
require_serial=hook.require_serial,
|
||||
color=color,
|
||||
)
|
||||
|
||||
|
||||
def _get_hook_no_install(repo_config, store, hook_id):
|
||||
|
@ -81,7 +76,7 @@ def _test_hook_repo(
|
|||
hook = _get_hook(config, store, hook_id)
|
||||
ret, out = _hook_run(hook, args, color=color)
|
||||
assert ret == expected_return_code
|
||||
assert _norm_out(out) == expected
|
||||
assert out == expected
|
||||
|
||||
|
||||
def test_python_hook(tempdir_factory, store):
|
||||
|
@ -129,66 +124,21 @@ def test_python_hook_weird_setup_cfg(in_git_dir, tempdir_factory, store):
|
|||
)
|
||||
|
||||
|
||||
def test_python_venv(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'python_venv_hooks_repo',
|
||||
'foo', [os.devnull],
|
||||
f'[{os.devnull!r}]\nHello World\n'.encode(),
|
||||
)
|
||||
|
||||
|
||||
def test_language_versioned_python_hook(tempdir_factory, store):
|
||||
# we patch this force virtualenv executing with `-p` since we can't
|
||||
# reliably have multiple pythons available in CI
|
||||
with mock.patch.object(
|
||||
python,
|
||||
'_sys_executable_matches',
|
||||
return_value=False,
|
||||
):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'python3_hooks_repo',
|
||||
'python3-hook',
|
||||
[os.devnull],
|
||||
f'3\n[{os.devnull!r}]\nHello World\n'.encode(),
|
||||
)
|
||||
|
||||
|
||||
@skipif_cant_run_docker # pragma: win32 no cover
|
||||
def test_run_a_docker_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'docker_hooks_repo',
|
||||
'docker-hook',
|
||||
['Hello World from docker'], b'Hello World from docker\n',
|
||||
)
|
||||
|
||||
|
||||
@skipif_cant_run_docker # pragma: win32 no cover
|
||||
def test_run_a_docker_hook_with_entry_args(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'docker_hooks_repo',
|
||||
'docker-hook-arg',
|
||||
['Hello World from docker'], b'Hello World from docker',
|
||||
)
|
||||
|
||||
|
||||
@skipif_cant_run_docker # pragma: win32 no cover
|
||||
def test_run_a_failing_docker_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'docker_hooks_repo',
|
||||
'docker-hook-failing',
|
||||
['Hello World from docker'],
|
||||
mock.ANY, # an error message about `bork` not existing
|
||||
expected_return_code=127,
|
||||
)
|
||||
|
||||
|
||||
@skipif_cant_run_docker # pragma: win32 no cover
|
||||
@pytest.mark.parametrize('hook_id', ('echo-entrypoint', 'echo-cmd'))
|
||||
def test_run_a_docker_image_hook(tempdir_factory, store, hook_id):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'docker_image_hooks_repo',
|
||||
hook_id,
|
||||
['Hello World from docker'], b'Hello World from docker\n',
|
||||
def test_python_venv_deprecation(store, caplog):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'example',
|
||||
'name': 'example',
|
||||
'language': 'python_venv',
|
||||
'entry': 'echo hi',
|
||||
}],
|
||||
}
|
||||
_get_hook(config, store, 'example')
|
||||
assert caplog.messages[-1] == (
|
||||
'`repo: local` uses deprecated `language: python_venv`. '
|
||||
'This is an alias for `language: python`. '
|
||||
'Often `pre-commit autoupdate --repo local` will fix this.'
|
||||
)
|
||||
|
||||
|
||||
|
@ -199,92 +149,6 @@ def test_system_hook_with_spaces(tempdir_factory, store):
|
|||
)
|
||||
|
||||
|
||||
def test_golang_system_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'golang_hooks_repo',
|
||||
'golang-hook', ['system'], b'hello world from system\n',
|
||||
config_kwargs={
|
||||
'hooks': [{
|
||||
'id': 'golang-hook',
|
||||
'language_version': 'system',
|
||||
}],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def test_golang_versioned_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'golang_hooks_repo',
|
||||
'golang-hook', [], b'hello world from go1.18.4\n',
|
||||
config_kwargs={
|
||||
'hooks': [{
|
||||
'id': 'golang-hook',
|
||||
'language_version': '1.18.4',
|
||||
}],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def test_golang_hook_still_works_when_gobin_is_set(tempdir_factory, store):
|
||||
gobin_dir = tempdir_factory.get()
|
||||
with envcontext((('GOBIN', gobin_dir),)):
|
||||
test_golang_system_hook(tempdir_factory, store)
|
||||
assert os.listdir(gobin_dir) == []
|
||||
|
||||
|
||||
def test_golang_with_recursive_submodule(tmpdir, tempdir_factory, store):
|
||||
sub_go = '''\
|
||||
package sub
|
||||
|
||||
import "fmt"
|
||||
|
||||
func Func() {
|
||||
fmt.Println("hello hello world")
|
||||
}
|
||||
'''
|
||||
sub = tmpdir.join('sub').ensure_dir()
|
||||
sub.join('sub.go').write(sub_go)
|
||||
cmd_output('git', '-C', str(sub), 'init', '.')
|
||||
cmd_output('git', '-C', str(sub), 'add', '.')
|
||||
git.commit(str(sub))
|
||||
|
||||
pre_commit_hooks = '''\
|
||||
- id: example
|
||||
name: example
|
||||
entry: example
|
||||
language: golang
|
||||
verbose: true
|
||||
'''
|
||||
go_mod = '''\
|
||||
module github.com/asottile/example
|
||||
|
||||
go 1.14
|
||||
'''
|
||||
main_go = '''\
|
||||
package main
|
||||
|
||||
import "github.com/asottile/example/sub"
|
||||
|
||||
func main() {
|
||||
sub.Func()
|
||||
}
|
||||
'''
|
||||
repo = tmpdir.join('repo').ensure_dir()
|
||||
repo.join('.pre-commit-hooks.yaml').write(pre_commit_hooks)
|
||||
repo.join('go.mod').write(go_mod)
|
||||
repo.join('main.go').write(main_go)
|
||||
cmd_output('git', '-C', str(repo), 'init', '.')
|
||||
cmd_output('git', '-C', str(repo), 'add', '.')
|
||||
cmd_output('git', '-C', str(repo), 'submodule', 'add', str(sub), 'sub')
|
||||
git.commit(str(repo))
|
||||
|
||||
config = make_config_from_repo(str(repo))
|
||||
hook = _get_hook(config, store, 'example')
|
||||
ret, out = _hook_run(hook, (), color=False)
|
||||
assert ret == 0
|
||||
assert _norm_out(out) == b'hello hello world\n'
|
||||
|
||||
|
||||
def test_missing_executable(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'not_found_exe',
|
||||
|
@ -345,52 +209,6 @@ def test_output_isatty(tempdir_factory, store):
|
|||
)
|
||||
|
||||
|
||||
def _make_grep_repo(entry, store, args=()):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'grep-hook',
|
||||
'name': 'grep-hook',
|
||||
'language': 'pygrep',
|
||||
'entry': entry,
|
||||
'args': args,
|
||||
'types': ['text'],
|
||||
}],
|
||||
}
|
||||
return _get_hook(config, store, 'grep-hook')
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def greppable_files(tmpdir):
|
||||
with tmpdir.as_cwd():
|
||||
cmd_output_b('git', 'init', '.')
|
||||
tmpdir.join('f1').write_binary(b"hello'hi\nworld\n")
|
||||
tmpdir.join('f2').write_binary(b'foo\nbar\nbaz\n')
|
||||
tmpdir.join('f3').write_binary(b'[WARN] hi\n')
|
||||
yield tmpdir
|
||||
|
||||
|
||||
def test_grep_hook_matching(greppable_files, store):
|
||||
hook = _make_grep_repo('ello', store)
|
||||
ret, out = _hook_run(hook, ('f1', 'f2', 'f3'), color=False)
|
||||
assert ret == 1
|
||||
assert _norm_out(out) == b"f1:1:hello'hi\n"
|
||||
|
||||
|
||||
def test_grep_hook_case_insensitive(greppable_files, store):
|
||||
hook = _make_grep_repo('ELLO', store, args=['-i'])
|
||||
ret, out = _hook_run(hook, ('f1', 'f2', 'f3'), color=False)
|
||||
assert ret == 1
|
||||
assert _norm_out(out) == b"f1:1:hello'hi\n"
|
||||
|
||||
|
||||
@pytest.mark.parametrize('regex', ('nope', "foo'bar", r'^\[INFO\]'))
|
||||
def test_grep_hook_not_matching(regex, greppable_files, store):
|
||||
hook = _make_grep_repo(regex, store)
|
||||
ret, out = _hook_run(hook, ('f1', 'f2', 'f3'), color=False)
|
||||
assert (ret, out) == (0, b'')
|
||||
|
||||
|
||||
def _norm_pwd(path):
|
||||
# Under windows bash's temp and windows temp is different.
|
||||
# This normalizes to the bash /tmp
|
||||
|
@ -440,7 +258,7 @@ def test_repository_state_compatibility(tempdir_factory, store, v):
|
|||
|
||||
config = make_config_from_repo(path)
|
||||
hook = _get_hook(config, store, 'foo')
|
||||
envdir = helpers.environment_dir(
|
||||
envdir = lang_base.environment_dir(
|
||||
hook.prefix,
|
||||
python.ENVIRONMENT_DIR,
|
||||
hook.language_version,
|
||||
|
@ -449,67 +267,6 @@ def test_repository_state_compatibility(tempdir_factory, store, v):
|
|||
assert _hook_installed(hook) is True
|
||||
|
||||
|
||||
def test_additional_golang_dependencies_installed(
|
||||
tempdir_factory, store,
|
||||
):
|
||||
path = make_repo(tempdir_factory, 'golang_hooks_repo')
|
||||
config = make_config_from_repo(path)
|
||||
# A small go package
|
||||
deps = ['golang.org/x/example/hello@latest']
|
||||
config['hooks'][0]['additional_dependencies'] = deps
|
||||
hook = _get_hook(config, store, 'golang-hook')
|
||||
envdir = helpers.environment_dir(
|
||||
hook.prefix,
|
||||
golang.ENVIRONMENT_DIR,
|
||||
golang.get_default_version(),
|
||||
)
|
||||
binaries = os.listdir(os.path.join(envdir, 'bin'))
|
||||
# normalize for windows
|
||||
binaries = [os.path.splitext(binary)[0] for binary in binaries]
|
||||
assert 'hello' in binaries
|
||||
|
||||
|
||||
def test_local_golang_additional_dependencies(store):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'hello',
|
||||
'name': 'hello',
|
||||
'entry': 'hello',
|
||||
'language': 'golang',
|
||||
'additional_dependencies': ['golang.org/x/example/hello@latest'],
|
||||
}],
|
||||
}
|
||||
hook = _get_hook(config, store, 'hello')
|
||||
ret, out = _hook_run(hook, (), color=False)
|
||||
assert ret == 0
|
||||
assert _norm_out(out) == b'Hello, Go examples!\n'
|
||||
|
||||
|
||||
def test_fail_hooks(store):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'fail',
|
||||
'name': 'fail',
|
||||
'language': 'fail',
|
||||
'entry': 'make sure to name changelogs as .rst!',
|
||||
'files': r'changelog/.*(?<!\.rst)$',
|
||||
}],
|
||||
}
|
||||
hook = _get_hook(config, store, 'fail')
|
||||
ret, out = _hook_run(
|
||||
hook, ('changelog/123.bugfix', 'changelog/wat'), color=False,
|
||||
)
|
||||
assert ret == 1
|
||||
assert out == (
|
||||
b'make sure to name changelogs as .rst!\n'
|
||||
b'\n'
|
||||
b'changelog/123.bugfix\n'
|
||||
b'changelog/wat\n'
|
||||
)
|
||||
|
||||
|
||||
def test_unknown_keys(store, caplog):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
|
@ -553,7 +310,7 @@ def test_control_c_control_c_on_install(tempdir_factory, store):
|
|||
# raise as well.
|
||||
with pytest.raises(MyKeyboardInterrupt):
|
||||
with mock.patch.object(
|
||||
helpers, 'run_setup_cmd', side_effect=MyKeyboardInterrupt,
|
||||
lang_base, 'setup_cmd', side_effect=MyKeyboardInterrupt,
|
||||
):
|
||||
with mock.patch.object(
|
||||
shutil, 'rmtree', side_effect=MyKeyboardInterrupt,
|
||||
|
@ -562,7 +319,7 @@ def test_control_c_control_c_on_install(tempdir_factory, store):
|
|||
|
||||
# Should have made an environment, however this environment is broken!
|
||||
hook, = hooks
|
||||
envdir = helpers.environment_dir(
|
||||
envdir = lang_base.environment_dir(
|
||||
hook.prefix,
|
||||
python.ENVIRONMENT_DIR,
|
||||
hook.language_version,
|
||||
|
@ -585,7 +342,7 @@ def test_invalidated_virtualenv(tempdir_factory, store):
|
|||
hook = _get_hook(config, store, 'foo')
|
||||
|
||||
# Simulate breaking of the virtualenv
|
||||
envdir = helpers.environment_dir(
|
||||
envdir = lang_base.environment_dir(
|
||||
hook.prefix,
|
||||
python.ENVIRONMENT_DIR,
|
||||
hook.language_version,
|
||||
|
@ -667,7 +424,7 @@ def test_local_python_repo(store, local_python_config):
|
|||
assert hook.language_version != C.DEFAULT
|
||||
ret, out = _hook_run(hook, ('filename',), color=False)
|
||||
assert ret == 0
|
||||
assert _norm_out(out) == b"['filename']\nHello World\n"
|
||||
assert out == b"['filename']\nHello World\n"
|
||||
|
||||
|
||||
def test_default_language_version(store, local_python_config):
|
||||
|
@ -781,22 +538,6 @@ def test_manifest_hooks(tempdir_factory, store):
|
|||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'repo',
|
||||
(
|
||||
'dotnet_hooks_csproj_repo',
|
||||
'dotnet_hooks_sln_repo',
|
||||
'dotnet_hooks_combo_repo',
|
||||
'dotnet_hooks_csproj_prefix_repo',
|
||||
),
|
||||
)
|
||||
def test_dotnet_hook(tempdir_factory, store, repo):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, repo,
|
||||
'dotnet-example-hook', [], b'Hello from dotnet!\n',
|
||||
)
|
||||
|
||||
|
||||
def test_non_installable_hook_error_for_language_version(store, caplog):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue