Skip to content

Commit a95f488

Browse files
committed
extend warning if globs are used instead of regex to local hooks
1 parent b1de333 commit a95f488

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

pre_commit/clientlib.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,14 @@ def check(self, dct: dict[str, Any]) -> None:
298298
OptionalSensibleRegexAtHook('files', cfgv.check_string),
299299
OptionalSensibleRegexAtHook('exclude', cfgv.check_string),
300300
)
301+
LOCAL_HOOK_DICT = cfgv.Map(
302+
'Hook', 'id',
303+
304+
*MANIFEST_HOOK_DICT.items,
305+
306+
OptionalSensibleRegexAtHook('files', cfgv.check_string),
307+
OptionalSensibleRegexAtHook('exclude', cfgv.check_string),
308+
)
301309
CONFIG_REPO_DICT = cfgv.Map(
302310
'Repository', 'repo',
303311

@@ -308,7 +316,7 @@ def check(self, dct: dict[str, Any]) -> None:
308316
'repo', cfgv.NotIn(LOCAL, META),
309317
),
310318
cfgv.ConditionalRecurse(
311-
'hooks', cfgv.Array(MANIFEST_HOOK_DICT),
319+
'hooks', cfgv.Array(LOCAL_HOOK_DICT),
312320
'repo', LOCAL,
313321
),
314322
cfgv.ConditionalRecurse(

tests/clientlib_test.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
from pre_commit.clientlib import MANIFEST_SCHEMA
1616
from pre_commit.clientlib import META_HOOK_DICT
1717
from pre_commit.clientlib import MigrateShaToRev
18+
from pre_commit.clientlib import OptionalSensibleRegexAtHook
19+
from pre_commit.clientlib import OptionalSensibleRegexAtTop
1820
from pre_commit.clientlib import validate_config_main
1921
from pre_commit.clientlib import validate_manifest_main
2022
from testing.fixtures import sample_local_config
@@ -261,6 +263,27 @@ def test_warn_mutable_rev_conditional():
261263
cfgv.validate(config_obj, CONFIG_REPO_DICT)
262264

263265

266+
@pytest.mark.parametrize(
267+
'validator_cls',
268+
(
269+
OptionalSensibleRegexAtHook,
270+
OptionalSensibleRegexAtTop,
271+
),
272+
)
273+
def test_sensible_regex_validators_dont_pass_none(validator_cls):
274+
key = 'files'
275+
with pytest.raises(cfgv.ValidationError) as excinfo:
276+
validator = validator_cls(key, cfgv.check_string)
277+
validator.check({key: None})
278+
279+
assert str(excinfo.value) == (
280+
'\n'
281+
f'==> At key: {key}'
282+
'\n'
283+
'=====> Expected string got NoneType'
284+
)
285+
286+
264287
@pytest.mark.parametrize(
265288
('regex', 'warning'),
266289
(
@@ -296,6 +319,22 @@ def test_validate_optional_sensible_regex_at_hook(caplog, regex, warning):
296319
assert caplog.record_tuples == [('pre_commit', logging.WARNING, warning)]
297320

298321

322+
def test_validate_optional_sensible_regex_at_local_hook(caplog):
323+
config_obj = sample_local_config()
324+
config_obj['hooks'][0]['files'] = r'dir/*.py'
325+
326+
cfgv.validate(config_obj, CONFIG_REPO_DICT)
327+
328+
assert caplog.record_tuples == [
329+
(
330+
'pre_commit',
331+
logging.WARNING,
332+
"The 'files' field in hook 'do_not_commit' is a regex, not a glob "
333+
"-- matching '/*' probably isn't what you want here",
334+
),
335+
]
336+
337+
299338
@pytest.mark.parametrize(
300339
('regex', 'warning'),
301340
(

0 commit comments

Comments
 (0)