diff --git a/pre_commit/clientlib.py b/pre_commit/clientlib.py index 2f16650a..a16a73ac 100644 --- a/pre_commit/clientlib.py +++ b/pre_commit/clientlib.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals import argparse import functools +import logging import pipes import sys @@ -15,6 +16,8 @@ from pre_commit.error_handler import FatalError from pre_commit.languages.all import all_languages from pre_commit.util import parse_version +logger = logging.getLogger('pre_commit') + def check_type_tag(tag): if tag not in ALL_TAGS: @@ -144,6 +147,16 @@ def _entry(modname): ) +def warn_on_unknown_keys_at_top_level(extra, orig_keys): + logger.warning( + 'Your pre-commit-config contain these extra keys: {}. ' + 'while the only valid keys are: {}.'.format( + ', '.join(extra), + ', '.join(sorted(orig_keys)), + ), + ), + + _meta = ( ( 'check-hooks-apply', ( @@ -222,6 +235,10 @@ CONFIG_REPO_DICT = cfgv.Map( ), MigrateShaToRev(), + cfgv.WarnAdditionalKeys( + {'repo', 'rev', 'hooks'}, + warn_on_unknown_keys_at_top_level, + ), ) DEFAULT_LANGUAGE_VERSION = cfgv.Map( 'DefaultLanguageVersion', None, diff --git a/tests/clientlib_test.py b/tests/clientlib_test.py index 2cdc1528..069dca36 100644 --- a/tests/clientlib_test.py +++ b/tests/clientlib_test.py @@ -1,5 +1,7 @@ from __future__ import unicode_literals +import logging + import cfgv import pytest @@ -116,6 +118,27 @@ def test_validate_config_old_list_format_ok(tmpdir): assert not validate_config_main((f.strpath,)) +def test_validate_warn_on_unknown_keys_at_top_level(tmpdir, caplog): + f = tmpdir.join('cfg.yaml') + f.write( + '- 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, + 'Your pre-commit-config contain these extra keys: args. ' + 'while the only valid keys are: hooks, repo, rev.', + ), + ] + + @pytest.mark.parametrize('fn', (validate_config_main, validate_manifest_main)) def test_mains_not_ok(tmpdir, fn): not_yaml = tmpdir.join('f.notyaml')