mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-01-14 04:50:20 -06:00
196 lines
5.7 KiB
Python
196 lines
5.7 KiB
Python
from __future__ import unicode_literals
|
|
|
|
import jsonschema
|
|
import pytest
|
|
|
|
from pre_commit.clientlib.validate_config import CONFIG_JSON_SCHEMA
|
|
from pre_commit.clientlib.validate_config import InvalidConfigError
|
|
from pre_commit.clientlib.validate_config import run
|
|
from pre_commit.clientlib.validate_config import validate_config_extra
|
|
from pre_commit.jsonschema_extensions import apply_defaults
|
|
from testing.util import get_resource_path
|
|
from testing.util import is_valid_according_to_schema
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
('input', 'expected_output'),
|
|
(
|
|
(['.pre-commit-config.yaml'], 0),
|
|
(['non_existent_file.yaml'], 1),
|
|
([get_resource_path('valid_yaml_but_invalid_config.yaml')], 1),
|
|
([get_resource_path('non_parseable_yaml_file.notyaml')], 1),
|
|
),
|
|
)
|
|
def test_run(input, expected_output):
|
|
assert run(input) == expected_output
|
|
|
|
|
|
@pytest.mark.parametrize(('config_obj', 'expected'), (
|
|
([], False),
|
|
(
|
|
[{
|
|
'repo': 'git@github.com:pre-commit/pre-commit-hooks',
|
|
'sha': 'cd74dc150c142c3be70b24eaf0b02cae9d235f37',
|
|
'hooks': [{'id': 'pyflakes', 'files': '\\.py$'}],
|
|
}],
|
|
True,
|
|
),
|
|
(
|
|
[{
|
|
'repo': 'git@github.com:pre-commit/pre-commit-hooks',
|
|
'sha': 'cd74dc150c142c3be70b24eaf0b02cae9d235f37',
|
|
'hooks': [
|
|
{
|
|
'id': 'pyflakes',
|
|
'files': '\\.py$',
|
|
'args': ['foo', 'bar', 'baz'],
|
|
},
|
|
],
|
|
}],
|
|
True,
|
|
),
|
|
(
|
|
[{
|
|
'repo': 'git@github.com:pre-commit/pre-commit-hooks',
|
|
'sha': 'cd74dc150c142c3be70b24eaf0b02cae9d235f37',
|
|
'hooks': [
|
|
{
|
|
'id': 'pyflakes',
|
|
'files': '\\.py$',
|
|
# Exclude pattern must be a string
|
|
'exclude': 0,
|
|
'args': ['foo', 'bar', 'baz'],
|
|
},
|
|
],
|
|
}],
|
|
False,
|
|
),
|
|
))
|
|
def test_is_valid_according_to_schema(config_obj, expected):
|
|
ret = is_valid_according_to_schema(config_obj, CONFIG_JSON_SCHEMA)
|
|
assert ret is expected
|
|
|
|
|
|
def test_config_with_failing_regexes_fails():
|
|
with pytest.raises(InvalidConfigError):
|
|
# Note the regex '(' is invalid (unbalanced parens)
|
|
config = apply_defaults(
|
|
[{
|
|
'repo': 'foo',
|
|
'sha': 'foo',
|
|
'hooks': [{'id': 'hook_id', 'files': '('}],
|
|
}],
|
|
CONFIG_JSON_SCHEMA,
|
|
)
|
|
validate_config_extra(config)
|
|
|
|
|
|
def test_config_with_ok_regexes_passes():
|
|
config = apply_defaults(
|
|
[{
|
|
'repo': 'foo',
|
|
'sha': 'foo',
|
|
'hooks': [{'id': 'hook_id', 'files': '\\.py$'}],
|
|
}],
|
|
CONFIG_JSON_SCHEMA,
|
|
)
|
|
validate_config_extra(config)
|
|
|
|
|
|
def test_config_with_invalid_exclude_regex_fails():
|
|
with pytest.raises(InvalidConfigError):
|
|
# Note the regex '(' is invalid (unbalanced parens)
|
|
config = apply_defaults(
|
|
[{
|
|
'repo': 'foo',
|
|
'sha': 'foo',
|
|
'hooks': [{'id': 'hook_id', 'files': '', 'exclude': '('}],
|
|
}],
|
|
CONFIG_JSON_SCHEMA,
|
|
)
|
|
validate_config_extra(config)
|
|
|
|
|
|
def test_config_with_ok_exclude_regex_passes():
|
|
config = apply_defaults(
|
|
[{
|
|
'repo': 'foo',
|
|
'sha': 'foo',
|
|
'hooks': [{'id': 'hook_id', 'files': '', 'exclude': '^vendor/'}],
|
|
}],
|
|
CONFIG_JSON_SCHEMA,
|
|
)
|
|
validate_config_extra(config)
|
|
|
|
|
|
@pytest.mark.parametrize('config_obj', (
|
|
[{
|
|
'repo': 'local',
|
|
'sha': 'foo',
|
|
'hooks': [{
|
|
'id': 'do_not_commit',
|
|
'name': 'Block if "DO NOT COMMIT" is found',
|
|
'entry': 'DO NOT COMMIT',
|
|
'language': 'pcre',
|
|
'files': '^(.*)$',
|
|
}],
|
|
}],
|
|
))
|
|
def test_config_with_local_hooks_definition_fails(config_obj):
|
|
with pytest.raises((
|
|
jsonschema.exceptions.ValidationError, InvalidConfigError
|
|
)):
|
|
jsonschema.validate(config_obj, CONFIG_JSON_SCHEMA)
|
|
config = apply_defaults(config_obj, CONFIG_JSON_SCHEMA)
|
|
validate_config_extra(config)
|
|
|
|
|
|
@pytest.mark.parametrize('config_obj', (
|
|
[{
|
|
'repo': 'local',
|
|
'hooks': [{
|
|
'id': 'arg-per-line',
|
|
'name': 'Args per line hook',
|
|
'entry': 'bin/hook.sh',
|
|
'language': 'script',
|
|
'files': '',
|
|
'args': ['hello', 'world'],
|
|
}],
|
|
}],
|
|
[{
|
|
'repo': 'local',
|
|
'hooks': [{
|
|
'id': 'arg-per-line',
|
|
'name': 'Args per line hook',
|
|
'entry': 'bin/hook.sh',
|
|
'language': 'script',
|
|
'files': '',
|
|
'args': ['hello', 'world'],
|
|
}]
|
|
}],
|
|
))
|
|
def test_config_with_local_hooks_definition_passes(config_obj):
|
|
jsonschema.validate(config_obj, CONFIG_JSON_SCHEMA)
|
|
config = apply_defaults(config_obj, CONFIG_JSON_SCHEMA)
|
|
validate_config_extra(config)
|
|
|
|
|
|
def test_does_not_contain_defaults():
|
|
"""Due to the way our merging works, if this schema has any defaults they
|
|
will clobber potentially useful values in the backing manifest. #227
|
|
"""
|
|
to_process = [(CONFIG_JSON_SCHEMA, ())]
|
|
while to_process:
|
|
schema, route = to_process.pop()
|
|
# Check this value
|
|
if isinstance(schema, dict):
|
|
if 'default' in schema:
|
|
raise AssertionError(
|
|
'Unexpected default in schema at {}'.format(
|
|
' => '.join(route),
|
|
)
|
|
)
|
|
|
|
for key, value in schema.items():
|
|
to_process.append((value, route + (key,)))
|