def test_ci_map_key_allowed_at_top_level(caplog): cfg = { 'ci': {'skip': ['foo']}, 'repos': [{'repo': 'meta', 'hooks': [{'id': 'identity'}]}], } cfgv.validate(cfg, CONFIG_SCHEMA) assert not caplog.record_tuples
def test_validate_optional_sensible_regex_at_hook(caplog, regex, warning): config_obj = { 'id': 'flake8', 'files': regex, } cfgv.validate(config_obj, CONFIG_HOOK_DICT) assert caplog.record_tuples == [('pre_commit', logging.WARNING, warning)]
def test_validate_optional_sensible_regex_at_top_level(caplog, regex, warning): config_obj = { 'files': regex, 'repos': [], } cfgv.validate(config_obj, CONFIG_SCHEMA) assert caplog.record_tuples == [('pre_commit', logging.WARNING, warning)]
def test_warn_mutable_rev_conditional(): config_obj = { 'repo': 'meta', 'rev': '3.7.7', 'hooks': [{'id': 'flake8'}], } with pytest.raises(cfgv.ValidationError): cfgv.validate(config_obj, CONFIG_REPO_DICT)
def test_warn_mutable_rev_ok(caplog, rev): config_obj = { 'repo': 'https://gitlab.com/pycqa/flake8', 'rev': rev, 'hooks': [{'id': 'flake8'}], } cfgv.validate(config_obj, CONFIG_REPO_DICT) assert caplog.record_tuples == []
def test_ensure_absent_conditional_in(): with pytest.raises(ValidationError) as excinfo: validate({'key': 3, 'key2': True}, map_conditional_absent_in) expected = ( 'At foo(key=3)', 'Expected key2 to be absent when key is not any of (1, 2), ' 'found key2: True', ) _assert_exception_trace(excinfo.value, expected)
def test_no_additional_keys(): with pytest.raises(ValidationError) as excinfo: validate({True: True, False: False}, no_additional_keys) expected = ( 'At Map()', 'Additional keys found: False. Only these keys are allowed: True', ) _assert_exception_trace(excinfo.value, expected) validate({True: True}, no_additional_keys)
def test_validate_failure_nested(): with pytest.raises(ValidationError) as excinfo: validate({'repo': 1, 'hooks': [{}]}, nested_schema_required) expected = ( 'At Repository(repo=1)', 'At key: hooks', 'At foo(key=MISSING)', 'Missing required key: key', ) _assert_exception_trace(excinfo.value, expected)
def test_minimum_pre_commit_version_failing(): with pytest.raises(cfgv.ValidationError) as excinfo: cfg = {'repos': [], 'minimum_pre_commit_version': '999'} cfgv.validate(cfg, CONFIG_SCHEMA) assert str(excinfo.value) == ( f'\n' f'==> At Config()\n' f'==> At key: minimum_pre_commit_version\n' f'=====> pre-commit version 999 is required but version {C.VERSION} ' f'is installed. Perhaps run `pip install --upgrade pre-commit`.')
def test_skip_referencing_missing_hook(): cfg = {'ci': {'skip': ['identity']}, 'repos': []} with pytest.raises(cfgv.ValidationError) as excinfo: cfgv.validate(cfg, SCHEMA) assert _error_to_trace(excinfo.value) == ( 'At Config()', 'At key: ci', 'At key: skip', 'unexpected hook ids: identity', )
def test_validate_failure_optional_recurse(): with pytest.raises(ValidationError) as excinfo: validate({'links': [{}]}, optional_nested_schema) expected = ( 'At Config()', 'At key: links', 'At Link(key=MISSING)', 'Missing required key: key', ) _assert_exception_trace(excinfo.value, expected)
def test_conditional_optional_check(tvalue): with pytest.raises(ValidationError) as excinfo: validate({'t': tvalue, 'v': 2}, conditional_optional) expected = ( 'At Map()', 'At key: v', 'Expected bool got int', ) _assert_exception_trace(excinfo.value, expected) validate({'t': tvalue, 'v': tvalue}, conditional_optional)
def test_autoupdate_commit_msg_cannot_be_empty(): cfg = {'ci': {'autoupdate_commit_msg': ''}, 'repos': []} with pytest.raises(cfgv.ValidationError) as excinfo: cfgv.validate(cfg, SCHEMA) assert _error_to_trace(excinfo.value) == ( 'At Config()', 'At key: ci', 'At CI()', 'At key: autoupdate_commit_msg', 'string cannot be empty', )
def test_conditional_recurse_error(): with pytest.raises(ValidationError) as excinfo: val = {'type': 'type1', 'params': {'p2': True}} validate(val, conditional_nested_schema) expected = ( 'At Config()', 'At key: params', 'At Params1()', 'Missing required key: p1', ) _assert_exception_trace(excinfo.value, expected)
def test_minimum_pre_commit_version_failing(): with pytest.raises(cfgv.ValidationError) as excinfo: cfg = {'repos': [], 'minimum_pre_commit_version': '999'} cfgv.validate(cfg, CONFIG_SCHEMA) assert str(excinfo.value) == ( '\n' '==> At Config()\n' '==> At key: minimum_pre_commit_version\n' '=====> pre-commit version 999 is required but version {} is ' 'installed. Perhaps run `pip install --upgrade pre-commit`.'.format( C.VERSION, ) )
def test_validate_optional_sensible_regex_at_hook_level(caplog): config_obj = { 'id': 'flake8', 'files': 'dir/*.py', } cfgv.validate(config_obj, CONFIG_HOOK_DICT) assert caplog.record_tuples == [ ( 'pre_commit', logging.WARNING, "The 'files' field in hook 'flake8' is a regex, not a glob -- " "matching '/*' probably isn't what you want here", ), ]
def test_validate_optional_sensible_regex_at_top_level(caplog): config_obj = { 'files': 'dir/*.py', 'repos': [], } cfgv.validate(config_obj, CONFIG_SCHEMA) assert caplog.record_tuples == [ ( 'pre_commit', logging.WARNING, "The top-level 'files' field is a regex, not a glob -- matching " "'/*' probably isn't what you want here", ), ]
def _get_hook_no_install(repo_config, store, hook_id): config = {'repos': [repo_config]} config = cfgv.validate(config, CONFIG_SCHEMA) config = cfgv.apply_defaults(config, CONFIG_SCHEMA) hooks = all_hooks(config, store) hook, = [hook for hook in hooks if hook.id == hook_id] return hook
def from_yaml(cls, dct: Dict[str, Any]) -> 'GenerateOptions': dct = cfgv.apply_defaults(cfgv.validate(dct, SCHEMA), SCHEMA) return cls( skip_default_metrics=dct['skip_default_metrics'], metric_package_names=dct['metric_package_names'], repo=dct['repo'], database=dct['database'], exclude=re.compile(dct['exclude'].encode()), )
def test_config_with_local_hooks_definition_fails(): config_obj = { 'repos': [{ 'repo': 'local', 'rev': 'foo', 'hooks': [{ 'id': 'do_not_commit', 'name': 'Block if "DO NOT COMMIT" is found', 'entry': 'DO NOT COMMIT', 'language': 'pcre', 'files': '^(.*)$', }], }] } with pytest.raises(cfgv.ValidationError): cfgv.validate(config_obj, CONFIG_SCHEMA)
def test_warn_mutable_rev_invalid(caplog, rev): config_obj = { 'repo': 'https://gitlab.com/pycqa/flake8', 'rev': rev, 'hooks': [{'id': 'flake8'}], } cfgv.validate(config_obj, CONFIG_REPO_DICT) assert caplog.record_tuples == [ ( 'pre_commit', logging.WARNING, "The 'rev' field of repo 'https://gitlab.com/pycqa/flake8' " 'appears to be a mutable reference (moving tag / branch). ' 'Mutable references are never updated after first install and are ' 'not supported. ' 'See https://pre-commit.com/#using-the-latest-version-for-a-repository ' # noqa: E501 'for more details. ' 'Hint: `pre-commit autoupdate` often fixes this.', ), ]
def make_config_from_repo(repo_path, rev=None, hooks=None, check=True): manifest = load_manifest(os.path.join(repo_path, C.MANIFEST_FILE)) config = { 'repo': 'file://{}'.format(repo_path), 'rev': rev or git.head_rev(repo_path), 'hooks': hooks or [{'id': hook['id']} for hook in manifest], } if check: wrapped = validate({'repos': [config]}, CONFIG_SCHEMA) wrapped = apply_defaults(wrapped, CONFIG_SCHEMA) config, = wrapped['repos'] return config else: return config
def make_config_from_repo(repo_path, rev=None, hooks=None, check=True): manifest = load_manifest(os.path.join(repo_path, C.MANIFEST_FILE)) config = OrderedDict(( ('repo', 'file://{}'.format(repo_path)), ('rev', rev or git.head_rev(repo_path)), ( 'hooks', hooks or [OrderedDict((('id', hook['id']),)) for hook in manifest], ), )) if check: wrapped = validate({'repos': [config]}, CONFIG_SCHEMA) wrapped = apply_defaults(wrapped, CONFIG_SCHEMA) config, = wrapped['repos'] return config else: return config
def test_warn_additional_keys_when_no_extra_keys(warn_additional_keys): validate({True: True}, warn_additional_keys.schema) assert not warn_additional_keys.record.called
def test_warn_additional_keys_when_has_extra_keys(warn_additional_keys): validate({True: True, False: False}, warn_additional_keys.schema) assert warn_additional_keys.record.called
def test_default_language_version_invalid(mapping): with pytest.raises(cfgv.ValidationError): cfgv.validate(mapping, DEFAULT_LANGUAGE_VERSION)
def test_minimum_pre_commit_version_passing(): cfg = {'repos': [], 'minimum_pre_commit_version': '0'} cfgv.validate(cfg, CONFIG_SCHEMA)
def test_local_hooks_with_rev_fails(): config_obj = {'repos': [dict(sample_local_config(), rev='foo')]} with pytest.raises(cfgv.ValidationError): cfgv.validate(config_obj, CONFIG_SCHEMA)
def test_conditional_recurse_ok(val): validate(val, conditional_nested_schema)
def test_optional_recurse_ok_missing(): validate({}, optional_nested_schema)
def test_config_with_local_hooks_definition_passes(): config_obj = {'repos': [sample_local_config()]} cfgv.validate(config_obj, CONFIG_SCHEMA)
def test_no_error_conditional_absent(): validate({}, map_conditional_absent) validate({}, map_conditional_absent_not) validate({'key2': True}, map_conditional_absent) validate({'key2': True}, map_conditional_absent_not)
def test_not_ok_conditional_schemas(schema): with pytest.raises(ValidationError) as excinfo: validate({'key': True, 'key2': 5}, schema) expected = ('At foo(key=True)', 'At key: key2', 'Expected bool got int') _assert_exception_trace(excinfo.value, expected)
def test_ok_conditional_schemas(v, schema): validate(v, schema)
def test_meta_hook_invalid(config_repo): with pytest.raises(cfgv.ValidationError): cfgv.validate(config_repo, CONFIG_REPO_DICT)
def _hook_from_manifest_dct(dct): dct = validate(apply_defaults(dct, MANIFEST_HOOK_DICT), MANIFEST_HOOK_DICT) dct = _hook(dct) return dct
def is_valid_according_to_schema(obj, obj_schema): try: cfgv.validate(obj, obj_schema) return True except cfgv.ValidationError: return False