Merging upstream version 3.0.2.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
962b6a60c2
commit
3904671ae3
107 changed files with 1775 additions and 2323 deletions
|
@ -14,11 +14,9 @@ from pre_commit.clientlib import CONFIG_SCHEMA
|
|||
from pre_commit.clientlib import DEFAULT_LANGUAGE_VERSION
|
||||
from pre_commit.clientlib import MANIFEST_SCHEMA
|
||||
from pre_commit.clientlib import META_HOOK_DICT
|
||||
from pre_commit.clientlib import MigrateShaToRev
|
||||
from pre_commit.clientlib import OptionalSensibleRegexAtHook
|
||||
from pre_commit.clientlib import OptionalSensibleRegexAtTop
|
||||
from pre_commit.clientlib import validate_config_main
|
||||
from pre_commit.clientlib import validate_manifest_main
|
||||
from pre_commit.clientlib import parse_version
|
||||
from testing.fixtures import sample_local_config
|
||||
|
||||
|
||||
|
@ -112,78 +110,6 @@ def test_config_schema_does_not_contain_defaults():
|
|||
assert not isinstance(item, cfgv.Optional)
|
||||
|
||||
|
||||
def test_validate_manifest_main_ok():
|
||||
assert not validate_manifest_main(('.pre-commit-hooks.yaml',))
|
||||
|
||||
|
||||
def test_validate_config_main_ok():
|
||||
assert not validate_config_main(('.pre-commit-config.yaml',))
|
||||
|
||||
|
||||
def test_validate_config_old_list_format_ok(tmpdir, cap_out):
|
||||
f = tmpdir.join('cfg.yaml')
|
||||
f.write('- {repo: meta, hooks: [{id: identity}]}')
|
||||
assert not validate_config_main((f.strpath,))
|
||||
msg = '[WARNING] normalizing pre-commit configuration to a top-level map'
|
||||
assert msg in cap_out.get()
|
||||
|
||||
|
||||
def test_validate_warn_on_unknown_keys_at_repo_level(tmpdir, caplog):
|
||||
f = tmpdir.join('cfg.yaml')
|
||||
f.write(
|
||||
'repos:\n'
|
||||
'- repo: https://gitlab.com/pycqa/flake8\n'
|
||||
' rev: 3.7.7\n'
|
||||
' hooks:\n'
|
||||
' - id: flake8\n'
|
||||
' args: [--some-args]\n',
|
||||
)
|
||||
ret_val = validate_config_main((f.strpath,))
|
||||
assert not ret_val
|
||||
assert caplog.record_tuples == [
|
||||
(
|
||||
'pre_commit',
|
||||
logging.WARNING,
|
||||
'pre-commit-validate-config is deprecated -- '
|
||||
'use `pre-commit validate-config` instead.',
|
||||
),
|
||||
(
|
||||
'pre_commit',
|
||||
logging.WARNING,
|
||||
'Unexpected key(s) present on https://gitlab.com/pycqa/flake8: '
|
||||
'args',
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def test_validate_warn_on_unknown_keys_at_top_level(tmpdir, caplog):
|
||||
f = tmpdir.join('cfg.yaml')
|
||||
f.write(
|
||||
'repos:\n'
|
||||
'- repo: https://gitlab.com/pycqa/flake8\n'
|
||||
' rev: 3.7.7\n'
|
||||
' hooks:\n'
|
||||
' - id: flake8\n'
|
||||
'foo:\n'
|
||||
' id: 1.0.0\n',
|
||||
)
|
||||
ret_val = validate_config_main((f.strpath,))
|
||||
assert not ret_val
|
||||
assert caplog.record_tuples == [
|
||||
(
|
||||
'pre_commit',
|
||||
logging.WARNING,
|
||||
'pre-commit-validate-config is deprecated -- '
|
||||
'use `pre-commit validate-config` instead.',
|
||||
),
|
||||
(
|
||||
'pre_commit',
|
||||
logging.WARNING,
|
||||
'Unexpected key(s) present at root: foo',
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def test_ci_map_key_allowed_at_top_level(caplog):
|
||||
cfg = {
|
||||
'ci': {'skip': ['foo']},
|
||||
|
@ -370,18 +296,6 @@ def test_validate_optional_sensible_regex_at_top_level(caplog, regex, warning):
|
|||
assert caplog.record_tuples == [('pre_commit', logging.WARNING, warning)]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('fn', (validate_config_main, validate_manifest_main))
|
||||
def test_mains_not_ok(tmpdir, fn):
|
||||
not_yaml = tmpdir.join('f.notyaml')
|
||||
not_yaml.write('{')
|
||||
not_schema = tmpdir.join('notconfig.yaml')
|
||||
not_schema.write('{}')
|
||||
|
||||
assert fn(('does-not-exist',))
|
||||
assert fn((not_yaml.strpath,))
|
||||
assert fn((not_schema.strpath,))
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
('manifest_obj', 'expected'),
|
||||
(
|
||||
|
@ -425,48 +339,6 @@ def test_valid_manifests(manifest_obj, expected):
|
|||
assert ret is expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'dct',
|
||||
(
|
||||
{'repo': 'local'}, {'repo': 'meta'},
|
||||
{'repo': 'wat', 'sha': 'wat'}, {'repo': 'wat', 'rev': 'wat'},
|
||||
),
|
||||
)
|
||||
def test_migrate_sha_to_rev_ok(dct):
|
||||
MigrateShaToRev().check(dct)
|
||||
|
||||
|
||||
def test_migrate_sha_to_rev_dont_specify_both():
|
||||
with pytest.raises(cfgv.ValidationError) as excinfo:
|
||||
MigrateShaToRev().check({'repo': 'a', 'sha': 'b', 'rev': 'c'})
|
||||
msg, = excinfo.value.args
|
||||
assert msg == 'Cannot specify both sha and rev'
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'dct',
|
||||
(
|
||||
{'repo': 'a'},
|
||||
{'repo': 'meta', 'sha': 'a'}, {'repo': 'meta', 'rev': 'a'},
|
||||
),
|
||||
)
|
||||
def test_migrate_sha_to_rev_conditional_check_failures(dct):
|
||||
with pytest.raises(cfgv.ValidationError):
|
||||
MigrateShaToRev().check(dct)
|
||||
|
||||
|
||||
def test_migrate_to_sha_apply_default():
|
||||
dct = {'repo': 'a', 'sha': 'b'}
|
||||
MigrateShaToRev().apply_default(dct)
|
||||
assert dct == {'repo': 'a', 'rev': 'b'}
|
||||
|
||||
|
||||
def test_migrate_to_sha_ok():
|
||||
dct = {'repo': 'a', 'rev': 'b'}
|
||||
MigrateShaToRev().apply_default(dct)
|
||||
assert dct == {'repo': 'a', 'rev': 'b'}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'config_repo',
|
||||
(
|
||||
|
@ -513,6 +385,12 @@ def test_default_language_version_invalid(mapping):
|
|||
cfgv.validate(mapping, DEFAULT_LANGUAGE_VERSION)
|
||||
|
||||
|
||||
def test_parse_version():
|
||||
assert parse_version('0.0') == parse_version('0.0')
|
||||
assert parse_version('0.1') > parse_version('0.0')
|
||||
assert parse_version('2.1') >= parse_version('2')
|
||||
|
||||
|
||||
def test_minimum_pre_commit_version_failing():
|
||||
with pytest.raises(cfgv.ValidationError) as excinfo:
|
||||
cfg = {'repos': [], 'minimum_pre_commit_version': '999'}
|
||||
|
|
|
@ -4,12 +4,11 @@ import shlex
|
|||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
|
||||
import pre_commit.constants as C
|
||||
from pre_commit import envcontext
|
||||
from pre_commit import git
|
||||
from pre_commit import util
|
||||
from pre_commit import yaml
|
||||
from pre_commit.commands.autoupdate import _check_hooks_still_exist_at_rev
|
||||
from pre_commit.commands.autoupdate import autoupdate
|
||||
from pre_commit.commands.autoupdate import RepositoryCannotBeUpdatedError
|
||||
|
@ -206,7 +205,7 @@ def test_autoupdate_with_core_useBuiltinFSMonitor(out_of_date, tmpdir, store):
|
|||
|
||||
|
||||
def test_autoupdate_pure_yaml(out_of_date, tmpdir, store):
|
||||
with mock.patch.object(util, 'Dumper', yaml.SafeDumper):
|
||||
with mock.patch.object(yaml, 'Dumper', yaml.yaml.SafeDumper):
|
||||
test_autoupdate_out_of_date_repo(out_of_date, tmpdir, store)
|
||||
|
||||
|
||||
|
|
|
@ -248,7 +248,7 @@ def test_install_idempotent(tempdir_factory, store):
|
|||
def _path_without_us():
|
||||
# Choose a path which *probably* doesn't include us
|
||||
env = dict(os.environ)
|
||||
exe = find_executable('pre-commit', _environ=env)
|
||||
exe = find_executable('pre-commit', env=env)
|
||||
while exe:
|
||||
parts = env['PATH'].split(os.pathsep)
|
||||
after = [
|
||||
|
@ -258,7 +258,7 @@ def _path_without_us():
|
|||
if parts == after:
|
||||
raise AssertionError(exe, parts)
|
||||
env['PATH'] = os.pathsep.join(after)
|
||||
exe = find_executable('pre-commit', _environ=env)
|
||||
exe = find_executable('pre-commit', env=env)
|
||||
return env['PATH']
|
||||
|
||||
|
||||
|
@ -276,18 +276,19 @@ def test_environment_not_sourced(tempdir_factory, store):
|
|||
|
||||
# Use a specific homedir to ignore --user installs
|
||||
homedir = tempdir_factory.get()
|
||||
ret, out = git_commit(
|
||||
env={
|
||||
'HOME': homedir,
|
||||
'PATH': _path_without_us(),
|
||||
# Git needs this to make a commit
|
||||
'GIT_AUTHOR_NAME': os.environ['GIT_AUTHOR_NAME'],
|
||||
'GIT_COMMITTER_NAME': os.environ['GIT_COMMITTER_NAME'],
|
||||
'GIT_AUTHOR_EMAIL': os.environ['GIT_AUTHOR_EMAIL'],
|
||||
'GIT_COMMITTER_EMAIL': os.environ['GIT_COMMITTER_EMAIL'],
|
||||
},
|
||||
check=False,
|
||||
)
|
||||
env = {
|
||||
'HOME': homedir,
|
||||
'PATH': _path_without_us(),
|
||||
# Git needs this to make a commit
|
||||
'GIT_AUTHOR_NAME': os.environ['GIT_AUTHOR_NAME'],
|
||||
'GIT_COMMITTER_NAME': os.environ['GIT_COMMITTER_NAME'],
|
||||
'GIT_AUTHOR_EMAIL': os.environ['GIT_AUTHOR_EMAIL'],
|
||||
'GIT_COMMITTER_EMAIL': os.environ['GIT_COMMITTER_EMAIL'],
|
||||
}
|
||||
if os.name == 'nt' and 'PATHEXT' in os.environ: # pragma: no cover
|
||||
env['PATHEXT'] = os.environ['PATHEXT']
|
||||
|
||||
ret, out = git_commit(env=env, check=False)
|
||||
assert ret == 1
|
||||
assert out == (
|
||||
'`pre-commit` not found. '
|
||||
|
@ -739,20 +740,22 @@ def test_commit_msg_legacy(commit_msg_repo, tempdir_factory, store):
|
|||
|
||||
def test_post_commit_integration(tempdir_factory, store):
|
||||
path = git_dir(tempdir_factory)
|
||||
config = [
|
||||
{
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'post-commit',
|
||||
'name': 'Post commit',
|
||||
'entry': 'touch post-commit.tmp',
|
||||
'language': 'system',
|
||||
'always_run': True,
|
||||
'verbose': True,
|
||||
'stages': ['post-commit'],
|
||||
}],
|
||||
},
|
||||
]
|
||||
config = {
|
||||
'repos': [
|
||||
{
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'post-commit',
|
||||
'name': 'Post commit',
|
||||
'entry': 'touch post-commit.tmp',
|
||||
'language': 'system',
|
||||
'always_run': True,
|
||||
'verbose': True,
|
||||
'stages': ['post-commit'],
|
||||
}],
|
||||
},
|
||||
],
|
||||
}
|
||||
write_config(path, config)
|
||||
with cwd(path):
|
||||
_get_commit_output(tempdir_factory)
|
||||
|
@ -765,20 +768,22 @@ def test_post_commit_integration(tempdir_factory, store):
|
|||
|
||||
def test_post_merge_integration(tempdir_factory, store):
|
||||
path = git_dir(tempdir_factory)
|
||||
config = [
|
||||
{
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'post-merge',
|
||||
'name': 'Post merge',
|
||||
'entry': 'touch post-merge.tmp',
|
||||
'language': 'system',
|
||||
'always_run': True,
|
||||
'verbose': True,
|
||||
'stages': ['post-merge'],
|
||||
}],
|
||||
},
|
||||
]
|
||||
config = {
|
||||
'repos': [
|
||||
{
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'post-merge',
|
||||
'name': 'Post merge',
|
||||
'entry': 'touch post-merge.tmp',
|
||||
'language': 'system',
|
||||
'always_run': True,
|
||||
'verbose': True,
|
||||
'stages': ['post-merge'],
|
||||
}],
|
||||
},
|
||||
],
|
||||
}
|
||||
write_config(path, config)
|
||||
with cwd(path):
|
||||
# create a simple diamond of commits for a non-trivial merge
|
||||
|
@ -807,20 +812,22 @@ def test_post_merge_integration(tempdir_factory, store):
|
|||
|
||||
def test_post_rewrite_integration(tempdir_factory, store):
|
||||
path = git_dir(tempdir_factory)
|
||||
config = [
|
||||
{
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'post-rewrite',
|
||||
'name': 'Post rewrite',
|
||||
'entry': 'touch post-rewrite.tmp',
|
||||
'language': 'system',
|
||||
'always_run': True,
|
||||
'verbose': True,
|
||||
'stages': ['post-rewrite'],
|
||||
}],
|
||||
},
|
||||
]
|
||||
config = {
|
||||
'repos': [
|
||||
{
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'post-rewrite',
|
||||
'name': 'Post rewrite',
|
||||
'entry': 'touch post-rewrite.tmp',
|
||||
'language': 'system',
|
||||
'always_run': True,
|
||||
'verbose': True,
|
||||
'stages': ['post-rewrite'],
|
||||
}],
|
||||
},
|
||||
],
|
||||
}
|
||||
write_config(path, config)
|
||||
with cwd(path):
|
||||
open('init', 'a').close()
|
||||
|
@ -836,21 +843,23 @@ def test_post_rewrite_integration(tempdir_factory, store):
|
|||
|
||||
def test_post_checkout_integration(tempdir_factory, store):
|
||||
path = git_dir(tempdir_factory)
|
||||
config = [
|
||||
{
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'post-checkout',
|
||||
'name': 'Post checkout',
|
||||
'entry': 'bash -c "echo ${PRE_COMMIT_TO_REF}"',
|
||||
'language': 'system',
|
||||
'always_run': True,
|
||||
'verbose': True,
|
||||
'stages': ['post-checkout'],
|
||||
}],
|
||||
},
|
||||
{'repo': 'meta', 'hooks': [{'id': 'identity'}]},
|
||||
]
|
||||
config = {
|
||||
'repos': [
|
||||
{
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'post-checkout',
|
||||
'name': 'Post checkout',
|
||||
'entry': 'bash -c "echo ${PRE_COMMIT_TO_REF}"',
|
||||
'language': 'system',
|
||||
'always_run': True,
|
||||
'verbose': True,
|
||||
'stages': ['post-checkout'],
|
||||
}],
|
||||
},
|
||||
{'repo': 'meta', 'hooks': [{'id': 'identity'}]},
|
||||
],
|
||||
}
|
||||
write_config(path, config)
|
||||
with cwd(path):
|
||||
cmd_output('git', 'add', '.')
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
import pre_commit.constants as C
|
||||
from pre_commit.clientlib import InvalidConfigError
|
||||
from pre_commit.commands.migrate_config import migrate_config
|
||||
|
||||
|
||||
|
@ -129,3 +132,13 @@ def test_migrate_config_sha_to_rev(tmpdir):
|
|||
' rev: v1.2.0\n'
|
||||
' hooks: []\n'
|
||||
)
|
||||
|
||||
|
||||
def test_migrate_config_invalid_yaml(tmpdir):
|
||||
contents = '['
|
||||
cfg = tmpdir.join(C.CONFIG_FILE)
|
||||
cfg.write(contents)
|
||||
with tmpdir.as_cwd(), pytest.raises(InvalidConfigError) as excinfo:
|
||||
migrate_config(C.CONFIG_FILE)
|
||||
expected = '\n==> File .pre-commit-config.yaml\n=====> '
|
||||
assert str(excinfo.value).startswith(expected)
|
||||
|
|
64
tests/commands/validate_config_test.py
Normal file
64
tests/commands/validate_config_test.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from pre_commit.commands.validate_config import validate_config
|
||||
|
||||
|
||||
def test_validate_config_ok():
|
||||
assert not validate_config(('.pre-commit-config.yaml',))
|
||||
|
||||
|
||||
def test_validate_warn_on_unknown_keys_at_repo_level(tmpdir, caplog):
|
||||
f = tmpdir.join('cfg.yaml')
|
||||
f.write(
|
||||
'repos:\n'
|
||||
'- repo: https://gitlab.com/pycqa/flake8\n'
|
||||
' rev: 3.7.7\n'
|
||||
' hooks:\n'
|
||||
' - id: flake8\n'
|
||||
' args: [--some-args]\n',
|
||||
)
|
||||
ret_val = validate_config((f.strpath,))
|
||||
assert not ret_val
|
||||
assert caplog.record_tuples == [
|
||||
(
|
||||
'pre_commit',
|
||||
logging.WARNING,
|
||||
'Unexpected key(s) present on https://gitlab.com/pycqa/flake8: '
|
||||
'args',
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def test_validate_warn_on_unknown_keys_at_top_level(tmpdir, caplog):
|
||||
f = tmpdir.join('cfg.yaml')
|
||||
f.write(
|
||||
'repos:\n'
|
||||
'- repo: https://gitlab.com/pycqa/flake8\n'
|
||||
' rev: 3.7.7\n'
|
||||
' hooks:\n'
|
||||
' - id: flake8\n'
|
||||
'foo:\n'
|
||||
' id: 1.0.0\n',
|
||||
)
|
||||
ret_val = validate_config((f.strpath,))
|
||||
assert not ret_val
|
||||
assert caplog.record_tuples == [
|
||||
(
|
||||
'pre_commit',
|
||||
logging.WARNING,
|
||||
'Unexpected key(s) present at root: foo',
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def test_mains_not_ok(tmpdir):
|
||||
not_yaml = tmpdir.join('f.notyaml')
|
||||
not_yaml.write('{')
|
||||
not_schema = tmpdir.join('notconfig.yaml')
|
||||
not_schema.write('{}')
|
||||
|
||||
assert validate_config(('does-not-exist',))
|
||||
assert validate_config((not_yaml.strpath,))
|
||||
assert validate_config((not_schema.strpath,))
|
18
tests/commands/validate_manifest_test.py
Normal file
18
tests/commands/validate_manifest_test.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pre_commit.commands.validate_manifest import validate_manifest
|
||||
|
||||
|
||||
def test_validate_manifest_ok():
|
||||
assert not validate_manifest(('.pre-commit-hooks.yaml',))
|
||||
|
||||
|
||||
def test_not_ok(tmpdir):
|
||||
not_yaml = tmpdir.join('f.notyaml')
|
||||
not_yaml.write('{')
|
||||
not_schema = tmpdir.join('notconfig.yaml')
|
||||
not_schema.write('{}')
|
||||
|
||||
assert validate_manifest(('does-not-exist',))
|
||||
assert validate_manifest((not_yaml.strpath,))
|
||||
assert validate_manifest((not_schema.strpath,))
|
|
@ -1,9 +1,13 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import os.path
|
||||
|
||||
import pytest
|
||||
|
||||
from pre_commit import envcontext
|
||||
from pre_commit.languages.conda import _conda_exe
|
||||
from pre_commit.languages import conda
|
||||
from pre_commit.store import _make_local_repo
|
||||
from testing.language_helpers import run_language
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
@ -37,4 +41,32 @@ from pre_commit.languages.conda import _conda_exe
|
|||
)
|
||||
def test_conda_exe(ctx, expected):
|
||||
with envcontext.envcontext(ctx):
|
||||
assert _conda_exe() == expected
|
||||
assert conda._conda_exe() == expected
|
||||
|
||||
|
||||
def test_conda_language(tmp_path):
|
||||
environment_yml = '''\
|
||||
channels: [conda-forge, defaults]
|
||||
dependencies: [python, pip]
|
||||
'''
|
||||
tmp_path.joinpath('environment.yml').write_text(environment_yml)
|
||||
|
||||
ret, out = run_language(
|
||||
tmp_path,
|
||||
conda,
|
||||
'python -c "import sys; print(sys.prefix)"',
|
||||
)
|
||||
assert ret == 0
|
||||
assert os.path.basename(out.strip()) == b'conda-default'
|
||||
|
||||
|
||||
def test_conda_additional_deps(tmp_path):
|
||||
_make_local_repo(tmp_path)
|
||||
|
||||
ret = run_language(
|
||||
tmp_path,
|
||||
conda,
|
||||
'python -c "import botocore; print(1)"',
|
||||
deps=('botocore',),
|
||||
)
|
||||
assert ret == (0, b'1\n')
|
||||
|
|
45
tests/languages/coursier_test.py
Normal file
45
tests/languages/coursier_test.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from pre_commit.errors import FatalError
|
||||
from pre_commit.languages import coursier
|
||||
from testing.language_helpers import run_language
|
||||
|
||||
|
||||
def test_coursier_hook(tmp_path):
|
||||
echo_java_json = '''\
|
||||
{
|
||||
"repositories": ["central"],
|
||||
"dependencies": ["io.get-coursier:echo:latest.stable"]
|
||||
}
|
||||
'''
|
||||
|
||||
channel_dir = tmp_path.joinpath('.pre-commit-channel')
|
||||
channel_dir.mkdir()
|
||||
channel_dir.joinpath('echo-java.json').write_text(echo_java_json)
|
||||
|
||||
ret = run_language(
|
||||
tmp_path,
|
||||
coursier,
|
||||
'echo-java',
|
||||
args=('Hello', 'World', 'from', 'coursier'),
|
||||
)
|
||||
assert ret == (0, b'Hello World from coursier\n')
|
||||
|
||||
|
||||
def test_coursier_hook_additional_dependencies(tmp_path):
|
||||
ret = run_language(
|
||||
tmp_path,
|
||||
coursier,
|
||||
'scalafmt --version',
|
||||
deps=('scalafmt:3.6.1',),
|
||||
)
|
||||
assert ret == (0, b'scalafmt 3.6.1\n')
|
||||
|
||||
|
||||
def test_error_if_no_deps_or_channel(tmp_path):
|
||||
with pytest.raises(FatalError) as excinfo:
|
||||
run_language(tmp_path, coursier, 'dne')
|
||||
msg, = excinfo.value.args
|
||||
assert msg == 'expected .pre-commit-channel dir or additional_dependencies'
|
62
tests/languages/dart_test.py
Normal file
62
tests/languages/dart_test.py
Normal file
|
@ -0,0 +1,62 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import re_assert
|
||||
|
||||
from pre_commit.languages import dart
|
||||
from pre_commit.store import _make_local_repo
|
||||
from testing.language_helpers import run_language
|
||||
|
||||
|
||||
def test_dart(tmp_path):
|
||||
pubspec_yaml = '''\
|
||||
environment:
|
||||
sdk: '>=2.10.0 <3.0.0'
|
||||
|
||||
name: hello_world_dart
|
||||
|
||||
executables:
|
||||
hello-world-dart:
|
||||
|
||||
dependencies:
|
||||
ansicolor: ^2.0.1
|
||||
'''
|
||||
hello_world_dart_dart = '''\
|
||||
import 'package:ansicolor/ansicolor.dart';
|
||||
|
||||
void main() {
|
||||
AnsiPen pen = new AnsiPen()..red();
|
||||
print("hello hello " + pen("world"));
|
||||
}
|
||||
'''
|
||||
tmp_path.joinpath('pubspec.yaml').write_text(pubspec_yaml)
|
||||
bin_dir = tmp_path.joinpath('bin')
|
||||
bin_dir.mkdir()
|
||||
bin_dir.joinpath('hello-world-dart.dart').write_text(hello_world_dart_dart)
|
||||
|
||||
expected = (0, b'hello hello world\n')
|
||||
assert run_language(tmp_path, dart, 'hello-world-dart') == expected
|
||||
|
||||
|
||||
def test_dart_additional_deps(tmp_path):
|
||||
_make_local_repo(str(tmp_path))
|
||||
|
||||
ret = run_language(
|
||||
tmp_path,
|
||||
dart,
|
||||
'hello-world-dart',
|
||||
deps=('hello_world_dart',),
|
||||
)
|
||||
assert ret == (0, b'hello hello world\n')
|
||||
|
||||
|
||||
def test_dart_additional_deps_versioned(tmp_path):
|
||||
_make_local_repo(str(tmp_path))
|
||||
|
||||
ret, out = run_language(
|
||||
tmp_path,
|
||||
dart,
|
||||
'secure-random -l 4 -b 16',
|
||||
deps=('encrypt:5.0.0',),
|
||||
)
|
||||
assert ret == 0
|
||||
re_assert.Matches('^[a-f0-9]{8}\n$').assert_matches(out.decode())
|
|
@ -1,22 +1,43 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
||||
from pre_commit.languages.golang import guess_go_dir
|
||||
import pre_commit.constants as C
|
||||
from pre_commit.languages import golang
|
||||
from pre_commit.languages import helpers
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
('url', 'expected'),
|
||||
(
|
||||
('/im/a/path/on/disk', 'unknown_src_dir'),
|
||||
('file:///im/a/path/on/disk', 'unknown_src_dir'),
|
||||
('git@github.com:golang/lint', 'github.com/golang/lint'),
|
||||
('git://github.com/golang/lint', 'github.com/golang/lint'),
|
||||
('http://github.com/golang/lint', 'github.com/golang/lint'),
|
||||
('https://github.com/golang/lint', 'github.com/golang/lint'),
|
||||
('ssh://git@github.com/golang/lint', 'github.com/golang/lint'),
|
||||
('git@github.com:golang/lint.git', 'github.com/golang/lint'),
|
||||
),
|
||||
)
|
||||
def test_guess_go_dir(url, expected):
|
||||
assert guess_go_dir(url) == expected
|
||||
ACTUAL_GET_DEFAULT_VERSION = golang.get_default_version.__wrapped__
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def exe_exists_mck():
|
||||
with mock.patch.object(helpers, 'exe_exists') as mck:
|
||||
yield mck
|
||||
|
||||
|
||||
def test_golang_default_version_system_available(exe_exists_mck):
|
||||
exe_exists_mck.return_value = True
|
||||
assert ACTUAL_GET_DEFAULT_VERSION() == 'system'
|
||||
|
||||
|
||||
def test_golang_default_version_system_not_available(exe_exists_mck):
|
||||
exe_exists_mck.return_value = False
|
||||
assert ACTUAL_GET_DEFAULT_VERSION() == C.DEFAULT
|
||||
|
||||
|
||||
ACTUAL_INFER_GO_VERSION = golang._infer_go_version.__wrapped__
|
||||
|
||||
|
||||
def test_golang_infer_go_version_not_default():
|
||||
assert ACTUAL_INFER_GO_VERSION('1.19.4') == '1.19.4'
|
||||
|
||||
|
||||
def test_golang_infer_go_version_default():
|
||||
version = ACTUAL_INFER_GO_VERSION(C.DEFAULT)
|
||||
|
||||
assert version != C.DEFAULT
|
||||
assert re.match(r'^\d+\.\d+\.\d+$', version)
|
||||
|
|
|
@ -12,7 +12,6 @@ from pre_commit import parse_shebang
|
|||
from pre_commit.languages import helpers
|
||||
from pre_commit.prefix import Prefix
|
||||
from pre_commit.util import CalledProcessError
|
||||
from testing.auto_namedtuple import auto_namedtuple
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -94,31 +93,22 @@ def test_assert_no_additional_deps():
|
|||
)
|
||||
|
||||
|
||||
SERIAL_FALSE = auto_namedtuple(require_serial=False)
|
||||
SERIAL_TRUE = auto_namedtuple(require_serial=True)
|
||||
|
||||
|
||||
def test_target_concurrency_normal():
|
||||
with mock.patch.object(multiprocessing, 'cpu_count', return_value=123):
|
||||
with mock.patch.dict(os.environ, {}, clear=True):
|
||||
assert helpers.target_concurrency(SERIAL_FALSE) == 123
|
||||
|
||||
|
||||
def test_target_concurrency_cpu_count_require_serial_true():
|
||||
with mock.patch.dict(os.environ, {}, clear=True):
|
||||
assert helpers.target_concurrency(SERIAL_TRUE) == 1
|
||||
assert helpers.target_concurrency() == 123
|
||||
|
||||
|
||||
def test_target_concurrency_testing_env_var():
|
||||
with mock.patch.dict(
|
||||
os.environ, {'PRE_COMMIT_NO_CONCURRENCY': '1'}, clear=True,
|
||||
):
|
||||
assert helpers.target_concurrency(SERIAL_FALSE) == 1
|
||||
assert helpers.target_concurrency() == 1
|
||||
|
||||
|
||||
def test_target_concurrency_on_travis():
|
||||
with mock.patch.dict(os.environ, {'TRAVIS': '1'}, clear=True):
|
||||
assert helpers.target_concurrency(SERIAL_FALSE) == 2
|
||||
assert helpers.target_concurrency() == 2
|
||||
|
||||
|
||||
def test_target_concurrency_cpu_count_not_implemented():
|
||||
|
@ -126,10 +116,20 @@ def test_target_concurrency_cpu_count_not_implemented():
|
|||
multiprocessing, 'cpu_count', side_effect=NotImplementedError,
|
||||
):
|
||||
with mock.patch.dict(os.environ, {}, clear=True):
|
||||
assert helpers.target_concurrency(SERIAL_FALSE) == 1
|
||||
assert helpers.target_concurrency() == 1
|
||||
|
||||
|
||||
def test_shuffled_is_deterministic():
|
||||
seq = [str(i) for i in range(10)]
|
||||
expected = ['4', '0', '5', '1', '8', '6', '2', '3', '7', '9']
|
||||
assert helpers._shuffled(seq) == expected
|
||||
|
||||
|
||||
def test_xargs_require_serial_is_not_shuffled():
|
||||
ret, out = helpers.run_xargs(
|
||||
('echo',), [str(i) for i in range(10)],
|
||||
require_serial=True,
|
||||
color=False,
|
||||
)
|
||||
assert ret == 0
|
||||
assert out.strip() == b'0 1 2 3 4 5 6 7 8 9'
|
||||
|
|
58
tests/languages/lua_test.py
Normal file
58
tests/languages/lua_test.py
Normal file
|
@ -0,0 +1,58 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
from pre_commit.languages import lua
|
||||
from pre_commit.util import make_executable
|
||||
from testing.language_helpers import run_language
|
||||
|
||||
pytestmark = pytest.mark.skipif(
|
||||
sys.platform == 'win32',
|
||||
reason='lua is not supported on windows',
|
||||
)
|
||||
|
||||
|
||||
def test_lua(tmp_path): # pragma: win32 no cover
|
||||
rockspec = '''\
|
||||
package = "hello"
|
||||
version = "dev-1"
|
||||
|
||||
source = {
|
||||
url = "git+ssh://git@github.com/pre-commit/pre-commit.git"
|
||||
}
|
||||
description = {}
|
||||
dependencies = {}
|
||||
build = {
|
||||
type = "builtin",
|
||||
modules = {},
|
||||
install = {
|
||||
bin = {"bin/hello-world-lua"}
|
||||
},
|
||||
}
|
||||
'''
|
||||
hello_world_lua = '''\
|
||||
#!/usr/bin/env lua
|
||||
print('hello world')
|
||||
'''
|
||||
tmp_path.joinpath('hello-dev-1.rockspec').write_text(rockspec)
|
||||
bin_dir = tmp_path.joinpath('bin')
|
||||
bin_dir.mkdir()
|
||||
bin_file = bin_dir.joinpath('hello-world-lua')
|
||||
bin_file.write_text(hello_world_lua)
|
||||
make_executable(bin_file)
|
||||
|
||||
expected = (0, b'hello world\n')
|
||||
assert run_language(tmp_path, lua, 'hello-world-lua') == expected
|
||||
|
||||
|
||||
def test_lua_additional_dependencies(tmp_path): # pragma: win32 no cover
|
||||
ret, out = run_language(
|
||||
tmp_path,
|
||||
lua,
|
||||
'luacheck --version',
|
||||
deps=('luacheck',),
|
||||
)
|
||||
assert ret == 0
|
||||
assert out.startswith(b'Luacheck: ')
|
69
tests/languages/perl_test.py
Normal file
69
tests/languages/perl_test.py
Normal file
|
@ -0,0 +1,69 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pre_commit.languages import perl
|
||||
from pre_commit.store import _make_local_repo
|
||||
from pre_commit.util import make_executable
|
||||
from testing.language_helpers import run_language
|
||||
|
||||
|
||||
def test_perl_install(tmp_path):
|
||||
makefile_pl = '''\
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use ExtUtils::MakeMaker;
|
||||
|
||||
WriteMakefile(
|
||||
NAME => "PreCommitHello",
|
||||
VERSION_FROM => "lib/PreCommitHello.pm",
|
||||
EXE_FILES => [qw(bin/pre-commit-perl-hello)],
|
||||
);
|
||||
'''
|
||||
bin_perl_hello = '''\
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use PreCommitHello;
|
||||
|
||||
PreCommitHello::hello();
|
||||
'''
|
||||
lib_hello_pm = '''\
|
||||
package PreCommitHello;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = "0.1.0";
|
||||
|
||||
sub hello {
|
||||
print "Hello from perl-commit Perl!\n";
|
||||
}
|
||||
|
||||
1;
|
||||
'''
|
||||
tmp_path.joinpath('Makefile.PL').write_text(makefile_pl)
|
||||
bin_dir = tmp_path.joinpath('bin')
|
||||
bin_dir.mkdir()
|
||||
exe = bin_dir.joinpath('pre-commit-perl-hello')
|
||||
exe.write_text(bin_perl_hello)
|
||||
make_executable(exe)
|
||||
lib_dir = tmp_path.joinpath('lib')
|
||||
lib_dir.mkdir()
|
||||
lib_dir.joinpath('PreCommitHello.pm').write_text(lib_hello_pm)
|
||||
|
||||
ret = run_language(tmp_path, perl, 'pre-commit-perl-hello')
|
||||
assert ret == (0, b'Hello from perl-commit Perl!\n')
|
||||
|
||||
|
||||
def test_perl_additional_dependencies(tmp_path):
|
||||
_make_local_repo(str(tmp_path))
|
||||
|
||||
ret, out = run_language(
|
||||
tmp_path,
|
||||
perl,
|
||||
'perltidy --version',
|
||||
deps=('SHANCOCK/Perl-Tidy-20211029.tar.gz',),
|
||||
)
|
||||
assert ret == 0
|
||||
assert out.startswith(b'This is perltidy, v20211029')
|
|
@ -1,136 +1,119 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import os.path
|
||||
import shutil
|
||||
|
||||
import pytest
|
||||
|
||||
from pre_commit import envcontext
|
||||
from pre_commit.languages import r
|
||||
from pre_commit.prefix import Prefix
|
||||
from pre_commit.store import _make_local_repo
|
||||
from pre_commit.util import win_exe
|
||||
from testing.fixtures import make_config_from_repo
|
||||
from testing.fixtures import make_repo
|
||||
from tests.repository_test import _get_hook_no_install
|
||||
from testing.language_helpers import run_language
|
||||
|
||||
|
||||
def _test_r_parsing(
|
||||
tempdir_factory,
|
||||
store,
|
||||
hook_id,
|
||||
expected_hook_expr={},
|
||||
expected_args={},
|
||||
config={},
|
||||
expect_path_prefix=True,
|
||||
):
|
||||
repo_path = 'r_hooks_repo'
|
||||
path = make_repo(tempdir_factory, repo_path)
|
||||
config = config or make_config_from_repo(path)
|
||||
hook = _get_hook_no_install(config, store, hook_id)
|
||||
ret = r._cmd_from_hook(hook)
|
||||
expected_cmd = 'Rscript'
|
||||
expected_opts = (
|
||||
def test_r_parsing_file_no_opts_no_args(tmp_path):
|
||||
cmd = r._cmd_from_hook(
|
||||
Prefix(str(tmp_path)),
|
||||
'Rscript some-script.R',
|
||||
(),
|
||||
is_local=False,
|
||||
)
|
||||
assert cmd == (
|
||||
'Rscript',
|
||||
'--no-save', '--no-restore', '--no-site-file', '--no-environ',
|
||||
str(tmp_path.joinpath('some-script.R')),
|
||||
)
|
||||
expected_path = os.path.join(
|
||||
hook.prefix.prefix_dir if expect_path_prefix else '',
|
||||
f'{hook_id}.R',
|
||||
)
|
||||
expected = (
|
||||
expected_cmd,
|
||||
*expected_opts,
|
||||
*(expected_hook_expr or (expected_path,)),
|
||||
*expected_args,
|
||||
)
|
||||
assert ret == expected
|
||||
|
||||
|
||||
def test_r_parsing_file_no_opts_no_args(tempdir_factory, store):
|
||||
hook_id = 'parse-file-no-opts-no-args'
|
||||
_test_r_parsing(tempdir_factory, store, hook_id)
|
||||
|
||||
|
||||
def test_r_parsing_file_opts_no_args(tempdir_factory, store):
|
||||
def test_r_parsing_file_opts_no_args():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
r._entry_validate(['Rscript', '--no-init', '/path/to/file'])
|
||||
|
||||
msg = excinfo.value.args
|
||||
msg, = excinfo.value.args
|
||||
assert msg == (
|
||||
'The only valid syntax is `Rscript -e {expr}`',
|
||||
'or `Rscript path/to/hook/script`',
|
||||
'The only valid syntax is `Rscript -e {expr}`'
|
||||
'or `Rscript path/to/hook/script`'
|
||||
)
|
||||
|
||||
|
||||
def test_r_parsing_file_no_opts_args(tempdir_factory, store):
|
||||
hook_id = 'parse-file-no-opts-args'
|
||||
expected_args = ['--no-cache']
|
||||
_test_r_parsing(
|
||||
tempdir_factory, store, hook_id, expected_args=expected_args,
|
||||
def test_r_parsing_file_no_opts_args(tmp_path):
|
||||
cmd = r._cmd_from_hook(
|
||||
Prefix(str(tmp_path)),
|
||||
'Rscript some-script.R',
|
||||
('--no-cache',),
|
||||
is_local=False,
|
||||
)
|
||||
assert cmd == (
|
||||
'Rscript',
|
||||
'--no-save', '--no-restore', '--no-site-file', '--no-environ',
|
||||
str(tmp_path.joinpath('some-script.R')),
|
||||
'--no-cache',
|
||||
)
|
||||
|
||||
|
||||
def test_r_parsing_expr_no_opts_no_args1(tempdir_factory, store):
|
||||
hook_id = 'parse-expr-no-opts-no-args-1'
|
||||
_test_r_parsing(
|
||||
tempdir_factory, store, hook_id, expected_hook_expr=('-e', '1+1'),
|
||||
def test_r_parsing_expr_no_opts_no_args1(tmp_path):
|
||||
cmd = r._cmd_from_hook(
|
||||
Prefix(str(tmp_path)),
|
||||
"Rscript -e '1+1'",
|
||||
(),
|
||||
is_local=False,
|
||||
)
|
||||
assert cmd == (
|
||||
'Rscript',
|
||||
'--no-save', '--no-restore', '--no-site-file', '--no-environ',
|
||||
'-e', '1+1',
|
||||
)
|
||||
|
||||
|
||||
def test_r_parsing_expr_no_opts_no_args2(tempdir_factory, store):
|
||||
with pytest.raises(ValueError) as execinfo:
|
||||
def test_r_parsing_local_hook_path_is_not_expanded(tmp_path):
|
||||
cmd = r._cmd_from_hook(
|
||||
Prefix(str(tmp_path)),
|
||||
'Rscript path/to/thing.R',
|
||||
(),
|
||||
is_local=True,
|
||||
)
|
||||
assert cmd == (
|
||||
'Rscript',
|
||||
'--no-save', '--no-restore', '--no-site-file', '--no-environ',
|
||||
'path/to/thing.R',
|
||||
)
|
||||
|
||||
|
||||
def test_r_parsing_expr_no_opts_no_args2():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
r._entry_validate(['Rscript', '-e', '1+1', '-e', 'letters'])
|
||||
msg = execinfo.value.args
|
||||
assert msg == ('You can supply at most one expression.',)
|
||||
msg, = excinfo.value.args
|
||||
assert msg == 'You can supply at most one expression.'
|
||||
|
||||
|
||||
def test_r_parsing_expr_opts_no_args2(tempdir_factory, store):
|
||||
with pytest.raises(ValueError) as execinfo:
|
||||
def test_r_parsing_expr_opts_no_args2():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
r._entry_validate(
|
||||
[
|
||||
'Rscript', '--vanilla', '-e', '1+1', '-e', 'letters',
|
||||
],
|
||||
['Rscript', '--vanilla', '-e', '1+1', '-e', 'letters'],
|
||||
)
|
||||
msg = execinfo.value.args
|
||||
msg, = excinfo.value.args
|
||||
assert msg == (
|
||||
'The only valid syntax is `Rscript -e {expr}`',
|
||||
'or `Rscript path/to/hook/script`',
|
||||
'The only valid syntax is `Rscript -e {expr}`'
|
||||
'or `Rscript path/to/hook/script`'
|
||||
)
|
||||
|
||||
|
||||
def test_r_parsing_expr_args_in_entry2(tempdir_factory, store):
|
||||
with pytest.raises(ValueError) as execinfo:
|
||||
def test_r_parsing_expr_args_in_entry2():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
r._entry_validate(['Rscript', '-e', 'expr1', '--another-arg'])
|
||||
|
||||
msg = execinfo.value.args
|
||||
assert msg == ('You can supply at most one expression.',)
|
||||
msg, = excinfo.value.args
|
||||
assert msg == 'You can supply at most one expression.'
|
||||
|
||||
|
||||
def test_r_parsing_expr_non_Rscirpt(tempdir_factory, store):
|
||||
with pytest.raises(ValueError) as execinfo:
|
||||
def test_r_parsing_expr_non_Rscirpt():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
r._entry_validate(['AnotherScript', '-e', '{{}}'])
|
||||
|
||||
msg = execinfo.value.args
|
||||
assert msg == ('entry must start with `Rscript`.',)
|
||||
|
||||
|
||||
def test_r_parsing_file_local(tempdir_factory, store):
|
||||
path = 'path/to/script.R'
|
||||
hook_id = 'local-r'
|
||||
config = {
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': hook_id,
|
||||
'name': 'local-r',
|
||||
'entry': f'Rscript {path}',
|
||||
'language': 'r',
|
||||
}],
|
||||
}
|
||||
_test_r_parsing(
|
||||
tempdir_factory,
|
||||
store,
|
||||
hook_id=hook_id,
|
||||
expected_hook_expr=(path,),
|
||||
config=config,
|
||||
expect_path_prefix=False,
|
||||
)
|
||||
msg, = excinfo.value.args
|
||||
assert msg == 'entry must start with `Rscript`.'
|
||||
|
||||
|
||||
def test_rscript_exec_relative_to_r_home():
|
||||
|
@ -142,3 +125,99 @@ def test_rscript_exec_relative_to_r_home():
|
|||
def test_path_rscript_exec_no_r_home_set():
|
||||
with envcontext.envcontext((('R_HOME', envcontext.UNSET),)):
|
||||
assert r._rscript_exec() == 'Rscript'
|
||||
|
||||
|
||||
def test_r_hook(tmp_path):
|
||||
renv_lock = '''\
|
||||
{
|
||||
"R": {
|
||||
"Version": "4.0.3",
|
||||
"Repositories": [
|
||||
{
|
||||
"Name": "CRAN",
|
||||
"URL": "https://cloud.r-project.org"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Packages": {
|
||||
"renv": {
|
||||
"Package": "renv",
|
||||
"Version": "0.12.5",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "5c0cdb37f063c58cdab3c7e9fbb8bd2c"
|
||||
},
|
||||
"rprojroot": {
|
||||
"Package": "rprojroot",
|
||||
"Version": "1.0",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "86704667fe0860e4fec35afdfec137f3"
|
||||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
description = '''\
|
||||
Package: gli.clu
|
||||
Title: What the Package Does (One Line, Title Case)
|
||||
Type: Package
|
||||
Version: 0.0.0.9000
|
||||
Authors@R:
|
||||
person(given = "First",
|
||||
family = "Last",
|
||||
role = c("aut", "cre"),
|
||||
email = "first.last@example.com",
|
||||
comment = c(ORCID = "YOUR-ORCID-ID"))
|
||||
Description: What the package does (one paragraph).
|
||||
License: `use_mit_license()`, `use_gpl3_license()` or friends to
|
||||
pick a license
|
||||
Encoding: UTF-8
|
||||
LazyData: true
|
||||
Roxygen: list(markdown = TRUE)
|
||||
RoxygenNote: 7.1.1
|
||||
Imports:
|
||||
rprojroot
|
||||
'''
|
||||
hello_world_r = '''\
|
||||
stopifnot(
|
||||
packageVersion('rprojroot') == '1.0',
|
||||
packageVersion('gli.clu') == '0.0.0.9000'
|
||||
)
|
||||
cat("Hello, World, from R!\n")
|
||||
'''
|
||||
|
||||
tmp_path.joinpath('renv.lock').write_text(renv_lock)
|
||||
tmp_path.joinpath('DESCRIPTION').write_text(description)
|
||||
tmp_path.joinpath('hello-world.R').write_text(hello_world_r)
|
||||
renv_dir = tmp_path.joinpath('renv')
|
||||
renv_dir.mkdir()
|
||||
shutil.copy(
|
||||
os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
'../../pre_commit/resources/empty_template_activate.R',
|
||||
),
|
||||
renv_dir.joinpath('activate.R'),
|
||||
)
|
||||
|
||||
expected = (0, b'Hello, World, from R!\n')
|
||||
assert run_language(tmp_path, r, 'Rscript hello-world.R') == expected
|
||||
|
||||
|
||||
def test_r_inline(tmp_path):
|
||||
_make_local_repo(str(tmp_path))
|
||||
|
||||
cmd = '''\
|
||||
Rscript -e '
|
||||
stopifnot(packageVersion("rprojroot") == "1.0")
|
||||
cat(commandArgs(trailingOnly = TRUE), "from R!\n", sep=", ")
|
||||
'
|
||||
'''
|
||||
|
||||
ret = run_language(
|
||||
tmp_path,
|
||||
r,
|
||||
cmd,
|
||||
deps=('rprojroot@1.0',),
|
||||
args=('hi', 'hello'),
|
||||
)
|
||||
assert ret == (0, b'hi, hello, from R!\n')
|
||||
|
|
|
@ -71,10 +71,10 @@ def test_install_ruby_default(fake_gem_prefix):
|
|||
|
||||
@xfailif_windows # pragma: win32 no cover
|
||||
def test_install_ruby_with_version(fake_gem_prefix):
|
||||
ruby.install_environment(fake_gem_prefix, '3.1.0', ())
|
||||
ruby.install_environment(fake_gem_prefix, '3.2.0', ())
|
||||
|
||||
# Should be able to activate and use rbenv install
|
||||
with ruby.in_env(fake_gem_prefix, '3.1.0'):
|
||||
with ruby.in_env(fake_gem_prefix, '3.2.0'):
|
||||
cmd_output('rbenv', 'install', '--help')
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import Mapping
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
@ -48,7 +49,9 @@ def test_installs_with_bootstrapped_rustup(tmpdir, language_version):
|
|||
|
||||
original_find_executable = parse_shebang.find_executable
|
||||
|
||||
def mocked_find_executable(exe: str) -> str | None:
|
||||
def mocked_find_executable(
|
||||
exe: str, *, env: Mapping[str, str] | None = None,
|
||||
) -> str | None:
|
||||
"""
|
||||
Return `None` the first time `find_executable` is called to ensure
|
||||
that the bootstrapping code is executed, then just let the function
|
||||
|
@ -59,7 +62,7 @@ def test_installs_with_bootstrapped_rustup(tmpdir, language_version):
|
|||
find_executable_exes.append(exe)
|
||||
if len(find_executable_exes) == 1:
|
||||
return None
|
||||
return original_find_executable(exe)
|
||||
return original_find_executable(exe, env=env)
|
||||
|
||||
with mock.patch.object(parse_shebang, 'find_executable') as find_exe_mck:
|
||||
find_exe_mck.side_effect = mocked_find_executable
|
||||
|
|
31
tests/languages/swift_test.py
Normal file
31
tests/languages/swift_test.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
from pre_commit.languages import swift
|
||||
from testing.language_helpers import run_language
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
sys.platform == 'win32',
|
||||
reason='swift is not supported on windows',
|
||||
)
|
||||
def test_swift_language(tmp_path): # pragma: win32 no cover
|
||||
package_swift = '''\
|
||||
// swift-tools-version:5.0
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "swift_hooks_repo",
|
||||
targets: [.target(name: "swift_hooks_repo")]
|
||||
)
|
||||
'''
|
||||
tmp_path.joinpath('Package.swift').write_text(package_swift)
|
||||
src_dir = tmp_path.joinpath('Sources/swift_hooks_repo')
|
||||
src_dir.mkdir(parents=True)
|
||||
src_dir.joinpath('main.swift').write_text('print("Hello, world!")\n')
|
||||
|
||||
expected = (0, b'Hello, world!\n')
|
||||
assert run_language(tmp_path, swift, 'swift_hooks_repo') == expected
|
|
@ -75,10 +75,10 @@ def test_find_executable_path_ext(in_tmpdir):
|
|||
env_path = {'PATH': os.path.dirname(exe_path)}
|
||||
env_path_ext = dict(env_path, PATHEXT=os.pathsep.join(('.exe', '.myext')))
|
||||
assert parse_shebang.find_executable('run') is None
|
||||
assert parse_shebang.find_executable('run', _environ=env_path) is None
|
||||
ret = parse_shebang.find_executable('run.myext', _environ=env_path)
|
||||
assert parse_shebang.find_executable('run', env=env_path) is None
|
||||
ret = parse_shebang.find_executable('run.myext', env=env_path)
|
||||
assert ret == exe_path
|
||||
ret = parse_shebang.find_executable('run', _environ=env_path_ext)
|
||||
ret = parse_shebang.find_executable('run', env=env_path_ext)
|
||||
assert ret == exe_path
|
||||
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ from pre_commit.languages import ruby
|
|||
from pre_commit.languages import rust
|
||||
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
|
||||
from pre_commit.repository import install_hook_envs
|
||||
from pre_commit.util import cmd_output
|
||||
|
@ -32,10 +33,7 @@ from testing.fixtures import make_repo
|
|||
from testing.fixtures import modify_manifest
|
||||
from testing.util import cwd
|
||||
from testing.util import get_resource_path
|
||||
from testing.util import skipif_cant_run_coursier
|
||||
from testing.util import skipif_cant_run_docker
|
||||
from testing.util import skipif_cant_run_lua
|
||||
from testing.util import skipif_cant_run_swift
|
||||
from testing.util import xfailif_windows
|
||||
|
||||
|
||||
|
@ -44,7 +42,16 @@ def _norm_out(b):
|
|||
|
||||
|
||||
def _hook_run(hook, filenames, color):
|
||||
return languages[hook.language].run_hook(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,
|
||||
)
|
||||
|
||||
|
||||
def _get_hook_no_install(repo_config, store, hook_id):
|
||||
|
@ -81,47 +88,6 @@ def _test_hook_repo(
|
|||
assert _norm_out(out) == expected
|
||||
|
||||
|
||||
def test_conda_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'conda_hooks_repo',
|
||||
'sys-exec', [os.devnull],
|
||||
b'conda-default\n',
|
||||
)
|
||||
|
||||
|
||||
def test_conda_with_additional_dependencies_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'conda_hooks_repo',
|
||||
'additional-deps', [os.devnull],
|
||||
b'OK\n',
|
||||
config_kwargs={
|
||||
'hooks': [{
|
||||
'id': 'additional-deps',
|
||||
'args': ['-c', 'import tzdata; print("OK")'],
|
||||
'additional_dependencies': ['python-tzdata'],
|
||||
}],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def test_local_conda_additional_dependencies(store):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'local-conda',
|
||||
'name': 'local-conda',
|
||||
'entry': 'python',
|
||||
'language': 'conda',
|
||||
'args': ['-c', 'import botocore; print("OK")'],
|
||||
'additional_dependencies': ['botocore'],
|
||||
}],
|
||||
}
|
||||
hook = _get_hook(config, store, 'local-conda')
|
||||
ret, out = _hook_run(hook, (), color=False)
|
||||
assert ret == 0
|
||||
assert _norm_out(out) == b'OK\n'
|
||||
|
||||
|
||||
def test_python_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'python_hooks_repo',
|
||||
|
@ -133,9 +99,11 @@ def test_python_hook(tempdir_factory, store):
|
|||
def test_python_hook_default_version(tempdir_factory, store):
|
||||
# make sure that this continues to work for platforms where default
|
||||
# language detection does not work
|
||||
returns_default = mock.Mock(return_value=C.DEFAULT)
|
||||
lang = languages['python']._replace(get_default_version=returns_default)
|
||||
with mock.patch.dict(languages, python=lang):
|
||||
with mock.patch.object(
|
||||
python,
|
||||
'get_default_version',
|
||||
return_value=C.DEFAULT,
|
||||
):
|
||||
test_python_hook(tempdir_factory, store)
|
||||
|
||||
|
||||
|
@ -189,15 +157,6 @@ def test_language_versioned_python_hook(tempdir_factory, store):
|
|||
)
|
||||
|
||||
|
||||
@skipif_cant_run_coursier # pragma: win32 no cover
|
||||
def test_run_a_coursier_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'coursier_hooks_repo',
|
||||
'echo-java',
|
||||
['Hello World from coursier'], b'Hello World from coursier\n',
|
||||
)
|
||||
|
||||
|
||||
@skipif_cant_run_docker # pragma: win32 no cover
|
||||
def test_run_a_docker_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
|
@ -247,9 +206,11 @@ def test_run_a_node_hook(tempdir_factory, store):
|
|||
def test_run_a_node_hook_default_version(tempdir_factory, store):
|
||||
# make sure that this continues to work for platforms where node is not
|
||||
# installed at the system
|
||||
returns_default = mock.Mock(return_value=C.DEFAULT)
|
||||
lang = languages['node']._replace(get_default_version=returns_default)
|
||||
with mock.patch.dict(languages, node=lang):
|
||||
with mock.patch.object(
|
||||
node,
|
||||
'get_default_version',
|
||||
return_value=C.DEFAULT,
|
||||
):
|
||||
test_run_a_node_hook(tempdir_factory, store)
|
||||
|
||||
|
||||
|
@ -267,54 +228,6 @@ def test_node_hook_with_npm_userconfig_set(tempdir_factory, store, tmpdir):
|
|||
test_run_a_node_hook(tempdir_factory, store)
|
||||
|
||||
|
||||
def test_r_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'r_hooks_repo',
|
||||
'hello-world', [os.devnull],
|
||||
b'Hello, World, from R!\n',
|
||||
)
|
||||
|
||||
|
||||
def test_r_inline_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'r_hooks_repo',
|
||||
'hello-world-inline', ['some-file'],
|
||||
b'Hi-there, some-file, from R!\n',
|
||||
)
|
||||
|
||||
|
||||
def test_r_with_additional_dependencies_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'r_hooks_repo',
|
||||
'additional-deps', [os.devnull],
|
||||
b'OK\n',
|
||||
config_kwargs={
|
||||
'hooks': [{
|
||||
'id': 'additional-deps',
|
||||
'additional_dependencies': ['cachem@1.0.4'],
|
||||
}],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def test_r_local_with_additional_dependencies_hook(store):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'local-r',
|
||||
'name': 'local-r',
|
||||
'entry': 'Rscript -e',
|
||||
'language': 'r',
|
||||
'args': ['if (packageVersion("R6") == "2.1.3") cat("OK\n")'],
|
||||
'additional_dependencies': ['R6@2.1.3'],
|
||||
}],
|
||||
}
|
||||
hook = _get_hook(config, store, 'local-r')
|
||||
ret, out = _hook_run(hook, (), color=False)
|
||||
assert ret == 0
|
||||
assert _norm_out(out) == b'OK\n'
|
||||
|
||||
|
||||
def test_run_a_ruby_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'ruby_hooks_repo',
|
||||
|
@ -335,7 +248,7 @@ def test_run_versioned_ruby_hook(tempdir_factory, store):
|
|||
tempdir_factory, store, 'ruby_versioned_hooks_repo',
|
||||
'ruby_hook',
|
||||
[os.devnull],
|
||||
b'3.1.0\nHello world from a ruby hook\n',
|
||||
b'3.2.0\nHello world from a ruby hook\n',
|
||||
)
|
||||
|
||||
|
||||
|
@ -357,7 +270,7 @@ def test_run_ruby_hook_with_disable_shared_gems(
|
|||
tempdir_factory, store, 'ruby_versioned_hooks_repo',
|
||||
'ruby_hook',
|
||||
[os.devnull],
|
||||
b'3.1.0\nHello world from a ruby hook\n',
|
||||
b'3.2.0\nHello world from a ruby hook\n',
|
||||
)
|
||||
|
||||
|
||||
|
@ -368,25 +281,36 @@ def test_system_hook_with_spaces(tempdir_factory, store):
|
|||
)
|
||||
|
||||
|
||||
@skipif_cant_run_swift # pragma: win32 no cover
|
||||
def test_swift_hook(tempdir_factory, store):
|
||||
def test_golang_system_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'swift_hooks_repo',
|
||||
'swift-hooks-repo', [], b'Hello, world!\n',
|
||||
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_hook(tempdir_factory, store):
|
||||
def test_golang_versioned_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'golang_hooks_repo',
|
||||
'golang-hook', [], b'hello world\n',
|
||||
'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_hook(tempdir_factory, store)
|
||||
test_golang_system_hook(tempdir_factory, store)
|
||||
assert os.listdir(gobin_dir) == []
|
||||
|
||||
|
||||
|
@ -459,11 +383,12 @@ def test_additional_rust_cli_dependencies_installed(
|
|||
# A small rust package with no dependencies.
|
||||
config['hooks'][0]['additional_dependencies'] = [dep]
|
||||
hook = _get_hook(config, store, 'rust-hook')
|
||||
binaries = os.listdir(
|
||||
hook.prefix.path(
|
||||
helpers.environment_dir(rust.ENVIRONMENT_DIR, 'system'), 'bin',
|
||||
),
|
||||
envdir = helpers.environment_dir(
|
||||
hook.prefix,
|
||||
rust.ENVIRONMENT_DIR,
|
||||
'system',
|
||||
)
|
||||
binaries = os.listdir(os.path.join(envdir, 'bin'))
|
||||
# normalize for windows
|
||||
binaries = [os.path.splitext(binary)[0] for binary in binaries]
|
||||
assert 'shellharden' in binaries
|
||||
|
@ -478,11 +403,12 @@ def test_additional_rust_lib_dependencies_installed(
|
|||
deps = ['shellharden:3.1.0', 'git-version']
|
||||
config['hooks'][0]['additional_dependencies'] = deps
|
||||
hook = _get_hook(config, store, 'rust-hook')
|
||||
binaries = os.listdir(
|
||||
hook.prefix.path(
|
||||
helpers.environment_dir(rust.ENVIRONMENT_DIR, 'system'), 'bin',
|
||||
),
|
||||
envdir = helpers.environment_dir(
|
||||
hook.prefix,
|
||||
rust.ENVIRONMENT_DIR,
|
||||
'system',
|
||||
)
|
||||
binaries = os.listdir(os.path.join(envdir, 'bin'))
|
||||
# normalize for windows
|
||||
binaries = [os.path.splitext(binary)[0] for binary in binaries]
|
||||
assert 'rust-hello-world' in binaries
|
||||
|
@ -638,6 +564,21 @@ def test_additional_dependencies_roll_forward(tempdir_factory, store):
|
|||
assert 'mccabe' not in cmd_output('pip', 'freeze', '-l')[1]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('v', ('v1', 'v2'))
|
||||
def test_repository_state_compatibility(tempdir_factory, store, v):
|
||||
path = make_repo(tempdir_factory, 'python_hooks_repo')
|
||||
|
||||
config = make_config_from_repo(path)
|
||||
hook = _get_hook(config, store, 'foo')
|
||||
envdir = helpers.environment_dir(
|
||||
hook.prefix,
|
||||
python.ENVIRONMENT_DIR,
|
||||
hook.language_version,
|
||||
)
|
||||
os.remove(os.path.join(envdir, f'.install_state_{v}'))
|
||||
assert _hook_installed(hook) is True
|
||||
|
||||
|
||||
def test_additional_ruby_dependencies_installed(tempdir_factory, store):
|
||||
path = make_repo(tempdir_factory, 'ruby_hooks_repo')
|
||||
config = make_config_from_repo(path)
|
||||
|
@ -668,11 +609,12 @@ def test_additional_golang_dependencies_installed(
|
|||
deps = ['golang.org/x/example/hello@latest']
|
||||
config['hooks'][0]['additional_dependencies'] = deps
|
||||
hook = _get_hook(config, store, 'golang-hook')
|
||||
binaries = os.listdir(
|
||||
hook.prefix.path(
|
||||
helpers.environment_dir(golang.ENVIRONMENT_DIR, C.DEFAULT), 'bin',
|
||||
),
|
||||
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
|
||||
|
@ -788,10 +730,14 @@ def test_control_c_control_c_on_install(tempdir_factory, store):
|
|||
|
||||
# Should have made an environment, however this environment is broken!
|
||||
hook, = hooks
|
||||
assert hook.prefix.exists(
|
||||
helpers.environment_dir(python.ENVIRONMENT_DIR, hook.language_version),
|
||||
envdir = helpers.environment_dir(
|
||||
hook.prefix,
|
||||
python.ENVIRONMENT_DIR,
|
||||
hook.language_version,
|
||||
)
|
||||
|
||||
assert os.path.exists(envdir)
|
||||
|
||||
# However, it should be perfectly runnable (reinstall after botched
|
||||
# install)
|
||||
install_hook_envs(hooks, store)
|
||||
|
@ -807,10 +753,12 @@ def test_invalidated_virtualenv(tempdir_factory, store):
|
|||
hook = _get_hook(config, store, 'foo')
|
||||
|
||||
# Simulate breaking of the virtualenv
|
||||
libdir = hook.prefix.path(
|
||||
helpers.environment_dir(python.ENVIRONMENT_DIR, hook.language_version),
|
||||
'lib', hook.language_version,
|
||||
envdir = helpers.environment_dir(
|
||||
hook.prefix,
|
||||
python.ENVIRONMENT_DIR,
|
||||
hook.language_version,
|
||||
)
|
||||
libdir = os.path.join(envdir, 'lib', hook.language_version)
|
||||
paths = [
|
||||
os.path.join(libdir, p) for p in ('site.py', 'site.pyc', '__pycache__')
|
||||
]
|
||||
|
@ -1001,30 +949,6 @@ def test_manifest_hooks(tempdir_factory, store):
|
|||
)
|
||||
|
||||
|
||||
def test_perl_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'perl_hooks_repo',
|
||||
'perl-hook', [], b'Hello from perl-commit Perl!\n',
|
||||
)
|
||||
|
||||
|
||||
def test_local_perl_additional_dependencies(store):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'hello',
|
||||
'name': 'hello',
|
||||
'entry': 'perltidy --version',
|
||||
'language': 'perl',
|
||||
'additional_dependencies': ['SHANCOCK/Perl-Tidy-20211029.tar.gz'],
|
||||
}],
|
||||
}
|
||||
hook = _get_hook(config, store, 'hello')
|
||||
ret, out = _hook_run(hook, (), color=False)
|
||||
assert ret == 0
|
||||
assert _norm_out(out).startswith(b'This is perltidy, v20211029')
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'repo',
|
||||
(
|
||||
|
@ -1041,46 +965,6 @@ def test_dotnet_hook(tempdir_factory, store, repo):
|
|||
)
|
||||
|
||||
|
||||
def test_dart_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'dart_repo',
|
||||
'hello-world-dart', [], b'hello hello world\n',
|
||||
)
|
||||
|
||||
|
||||
def test_local_dart_additional_dependencies(store):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'local-dart',
|
||||
'name': 'local-dart',
|
||||
'entry': 'hello-world-dart',
|
||||
'language': 'dart',
|
||||
'additional_dependencies': ['hello_world_dart'],
|
||||
}],
|
||||
}
|
||||
hook = _get_hook(config, store, 'local-dart')
|
||||
ret, out = _hook_run(hook, (), color=False)
|
||||
assert (ret, _norm_out(out)) == (0, b'hello hello world\n')
|
||||
|
||||
|
||||
def test_local_dart_additional_dependencies_versioned(store):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'local-dart',
|
||||
'name': 'local-dart',
|
||||
'entry': 'secure-random -l 4 -b 16',
|
||||
'language': 'dart',
|
||||
'additional_dependencies': ['encrypt:5.0.0'],
|
||||
}],
|
||||
}
|
||||
hook = _get_hook(config, store, 'local-dart')
|
||||
ret, out = _hook_run(hook, (), color=False)
|
||||
assert ret == 0
|
||||
re_assert.Matches('^[a-f0-9]{8}\r?\n$').assert_matches(out.decode())
|
||||
|
||||
|
||||
def test_non_installable_hook_error_for_language_version(store, caplog):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
|
@ -1125,29 +1009,3 @@ def test_non_installable_hook_error_for_additional_dependencies(store, caplog):
|
|||
'using language `system` which does not install an environment. '
|
||||
'Perhaps you meant to use a specific language?'
|
||||
)
|
||||
|
||||
|
||||
@skipif_cant_run_lua # pragma: win32 no cover
|
||||
def test_lua_hook(tempdir_factory, store):
|
||||
_test_hook_repo(
|
||||
tempdir_factory, store, 'lua_repo',
|
||||
'hello-world-lua', [], b'hello world\n',
|
||||
)
|
||||
|
||||
|
||||
@skipif_cant_run_lua # pragma: win32 no cover
|
||||
def test_local_lua_additional_dependencies(store):
|
||||
config = {
|
||||
'repo': 'local',
|
||||
'hooks': [{
|
||||
'id': 'local-lua',
|
||||
'name': 'local-lua',
|
||||
'entry': 'luacheck --version',
|
||||
'language': 'lua',
|
||||
'additional_dependencies': ['luacheck'],
|
||||
}],
|
||||
}
|
||||
hook = _get_hook(config, store, 'local-lua')
|
||||
ret, out = _hook_run(hook, (), color=False)
|
||||
assert b'Luacheck' in out
|
||||
assert ret == 0
|
||||
|
|
|
@ -9,6 +9,7 @@ import pytest
|
|||
|
||||
from pre_commit import git
|
||||
from pre_commit.store import _get_default_directory
|
||||
from pre_commit.store import _LOCAL_RESOURCES
|
||||
from pre_commit.store import Store
|
||||
from pre_commit.util import CalledProcessError
|
||||
from pre_commit.util import cmd_output
|
||||
|
@ -188,7 +189,7 @@ def test_local_resources_reflects_reality():
|
|||
for res in os.listdir('pre_commit/resources')
|
||||
if res.startswith('empty_template_')
|
||||
}
|
||||
assert on_disk == {os.path.basename(x) for x in Store.LOCAL_RESOURCES}
|
||||
assert on_disk == {os.path.basename(x) for x in _LOCAL_RESOURCES}
|
||||
|
||||
|
||||
def test_mark_config_as_used(store, tmpdir):
|
||||
|
|
|
@ -12,9 +12,7 @@ from pre_commit.util import cmd_output
|
|||
from pre_commit.util import cmd_output_b
|
||||
from pre_commit.util import cmd_output_p
|
||||
from pre_commit.util import make_executable
|
||||
from pre_commit.util import parse_version
|
||||
from pre_commit.util import rmtree
|
||||
from pre_commit.util import tmpdir
|
||||
|
||||
|
||||
def test_CalledProcessError_str():
|
||||
|
@ -74,12 +72,6 @@ def test_clean_path_on_failure_cleans_for_system_exit(in_tmpdir):
|
|||
assert not os.path.exists('foo')
|
||||
|
||||
|
||||
def test_tmpdir():
|
||||
with tmpdir() as tempdir:
|
||||
assert os.path.exists(tempdir)
|
||||
assert not os.path.exists(tempdir)
|
||||
|
||||
|
||||
def test_cmd_output_exe_not_found():
|
||||
ret, out, _ = cmd_output('dne', check=False)
|
||||
assert ret == 1
|
||||
|
@ -105,12 +97,6 @@ def test_cmd_output_no_shebang(tmpdir, fn):
|
|||
assert out.endswith(b'\n')
|
||||
|
||||
|
||||
def test_parse_version():
|
||||
assert parse_version('0.0') == parse_version('0.0')
|
||||
assert parse_version('0.1') > parse_version('0.0')
|
||||
assert parse_version('2.1') >= parse_version('2')
|
||||
|
||||
|
||||
def test_rmtree_read_only_directories(tmpdir):
|
||||
"""Simulates the go module tree. See #1042"""
|
||||
tmpdir.join('x/y/z').ensure_dir().join('a').ensure()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue