pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/pre-commit/pre-commit/commit/fd0177ae3ae5f94b36aafb54ab496f76fcead7b9

ef="https://github.githubassets.com/assets/global-d18f184ea1a06a2c.css" /> implement default_install_hook_types · pre-commit/pre-commit@fd0177a · GitHub
Skip to content

Commit fd0177a

Browse files
committed
implement default_install_hook_types
this implements a configurable fallback for the default value of `pre-commit install`
1 parent 934afb8 commit fd0177a

7 files changed

Lines changed: 86 additions & 55 deletions

File tree

pre_commit/clientlib.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,11 @@ def check(self, dct: dict[str, Any]) -> None:
336336
'Config', None,
337337

338338
cfgv.RequiredRecurse('repos', cfgv.Array(CONFIG_REPO_DICT)),
339+
cfgv.Optional(
340+
'default_install_hook_types',
341+
cfgv.check_array(cfgv.check_one_of(C.HOOK_TYPES)),
342+
['pre-commit'],
343+
),
339344
cfgv.OptionalRecurse(
340345
'default_language_version', DEFAULT_LANGUAGE_VERSION, {},
341346
),
@@ -355,6 +360,7 @@ def check(self, dct: dict[str, Any]) -> None:
355360
cfgv.WarnAdditionalKeys(
356361
(
357362
'repos',
363+
'default_install_hook_types',
358364
'default_language_version',
359365
'default_stages',
360366
'files',

pre_commit/commands/init_templatedir.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import logging
44
import os.path
5-
from typing import Sequence
65

76
from pre_commit.commands.install_uninstall import install
87
from pre_commit.store import Store
@@ -16,7 +15,7 @@ def init_templatedir(
1615
config_file: str,
1716
store: Store,
1817
directory: str,
19-
hook_types: Sequence[str],
18+
hook_types: list[str] | None,
2019
skip_on_missing_config: bool = True,
2120
) -> int:
2221
install(

pre_commit/commands/install_uninstall.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
import shlex
66
import shutil
77
import sys
8-
from typing import Sequence
98

109
from pre_commit import git
1110
from pre_commit import output
11+
from pre_commit.clientlib import InvalidConfigError
1212
from pre_commit.clientlib import load_config
1313
from pre_commit.repository import all_hooks
1414
from pre_commit.repository import install_hook_envs
@@ -32,6 +32,18 @@
3232
TEMPLATE_END = '# end templated\n'
3333

3434

35+
def _hook_types(cfg_filename: str, hook_types: list[str] | None) -> list[str]:
36+
if hook_types is not None:
37+
return hook_types
38+
else:
39+
try:
40+
cfg = load_config(cfg_filename)
41+
except InvalidConfigError:
42+
return ['pre-commit']
43+
else:
44+
return cfg['default_install_hook_types']
45+
46+
3547
def _hook_paths(
3648
hook_type: str,
3749
git_dir: str | None = None,
@@ -103,7 +115,7 @@ def _install_hook_script(
103115
def install(
104116
config_file: str,
105117
store: Store,
106-
hook_types: Sequence[str],
118+
hook_types: list[str] | None,
107119
overwrite: bool = False,
108120
hooks: bool = False,
109121
skip_on_missing_config: bool = False,
@@ -116,7 +128,7 @@ def install(
116128
)
117129
return 1
118130

119-
for hook_type in hook_types:
131+
for hook_type in _hook_types(config_file, hook_types):
120132
_install_hook_script(
121133
config_file, hook_type,
122134
overwrite=overwrite,
@@ -150,7 +162,7 @@ def _uninstall_hook_script(hook_type: str) -> None:
150162
output.write_line(f'Restored previous hooks to {hook_path}')
151163

152164

153-
def uninstall(hook_types: Sequence[str]) -> int:
154-
for hook_type in hook_types:
165+
def uninstall(config_file: str, hook_types: list[str] | None) -> int:
166+
for hook_type in _hook_types(config_file, hook_types):
155167
_uninstall_hook_script(hook_type)
156168
return 0

pre_commit/constants.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,10 @@
2424
'post-rewrite',
2525
)
2626

27+
HOOK_TYPES = (
28+
'pre-commit', 'pre-merge-commit', 'pre-push', 'prepare-commit-msg',
29+
'commit-msg', 'post-commit', 'post-checkout', 'post-merge',
30+
'post-rewrite',
31+
)
32+
2733
DEFAULT = 'default'

pre_commit/main.py

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import logging
55
import os
66
import sys
7-
from typing import Any
87
from typing import Sequence
98

109
import pre_commit.constants as C
@@ -46,34 +45,10 @@ def _add_config_option(parser: argparse.ArgumentParser) -> None:
4645
)
4746

4847

49-
class AppendReplaceDefault(argparse.Action):
50-
def __init__(self, *args: Any, **kwargs: Any) -> None:
51-
super().__init__(*args, **kwargs)
52-
self.appended = False
53-
54-
def __call__(
55-
self,
56-
parser: argparse.ArgumentParser,
57-
namespace: argparse.Namespace,
58-
values: str | Sequence[str] | None,
59-
option_string: str | None = None,
60-
) -> None:
61-
if not self.appended:
62-
setattr(namespace, self.dest, [])
63-
self.appended = True
64-
getattr(namespace, self.dest).append(values)
65-
66-
6748
def _add_hook_type_option(parser: argparse.ArgumentParser) -> None:
6849
parser.add_argument(
69-
'-t', '--hook-type', choices=(
70-
'pre-commit', 'pre-merge-commit', 'pre-push', 'prepare-commit-msg',
71-
'commit-msg', 'post-commit', 'post-checkout', 'post-merge',
72-
'post-rewrite',
73-
),
74-
action=AppendReplaceDefault,
75-
default=['pre-commit'],
76-
dest='hook_types',
50+
'-t', '--hook-type',
51+
choices=C.HOOK_TYPES, action='append', dest='hook_types',
7752
)
7853

7954

@@ -399,7 +374,10 @@ def main(argv: Sequence[str] | None = None) -> int:
399374
elif args.command == 'try-repo':
400375
return try_repo(args)
401376
elif args.command == 'uninstall':
402-
return uninstall(hook_types=args.hook_types)
377+
return uninstall(
378+
config_file=args.config,
379+
hook_types=args.hook_types,
380+
)
403381
else:
404382
raise NotImplementedError(
405383
f'Command {args.command} not implemented.',

tests/commands/install_uninstall_test.py

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import pre_commit.constants as C
99
from pre_commit import git
10+
from pre_commit.commands.install_uninstall import _hook_types
1011
from pre_commit.commands.install_uninstall import CURRENT_HASH
1112
from pre_commit.commands.install_uninstall import install
1213
from pre_commit.commands.install_uninstall import install_hooks
@@ -27,6 +28,36 @@
2728
from testing.util import git_commit
2829

2930

31+
def test_hook_types_explicitly_listed():
32+
assert _hook_types(os.devnull, ['pre-push']) == ['pre-push']
33+
34+
35+
def test_hook_types_default_value_when_not_specified():
36+
assert _hook_types(os.devnull, None) == ['pre-commit']
37+
38+
39+
def test_hook_types_configured(tmpdir):
40+
cfg = tmpdir.join('t.cfg')
41+
cfg.write('default_install_hook_types: [pre-push]\nrepos: []\n')
42+
43+
assert _hook_types(str(cfg), None) == ['pre-push']
44+
45+
46+
def test_hook_types_configured_nonsense(tmpdir):
47+
cfg = tmpdir.join('t.cfg')
48+
cfg.write('default_install_hook_types: []\nrepos: []\n')
49+
50+
# hopefully the user doesn't do this, but the code allows it!
51+
assert _hook_types(str(cfg), None) == []
52+
53+
54+
def test_hook_types_configuration_has_error(tmpdir):
55+
cfg = tmpdir.join('t.cfg')
56+
cfg.write('[')
57+
58+
assert _hook_types(str(cfg), None) == ['pre-commit']
59+
60+
3061
def test_is_not_script():
3162
assert is_our_script('setup.py') is False
3263

@@ -61,7 +92,7 @@ def test_install_multiple_hooks_at_once(in_git_dir, store):
6192
install(C.CONFIG_FILE, store, hook_types=['pre-commit', 'pre-push'])
6293
assert in_git_dir.join('.git/hooks/pre-commit').exists()
6394
assert in_git_dir.join('.git/hooks/pre-push').exists()
64-
uninstall(hook_types=['pre-commit', 'pre-push'])
95+
uninstall(C.CONFIG_FILE, hook_types=['pre-commit', 'pre-push'])
6596
assert not in_git_dir.join('.git/hooks/pre-commit').exists()
6697
assert not in_git_dir.join('.git/hooks/pre-push').exists()
6798

@@ -79,14 +110,14 @@ def test_install_hooks_dead_symlink(in_git_dir, store):
79110

80111

81112
def test_uninstall_does_not_blow_up_when_not_there(in_git_dir):
82-
assert uninstall(hook_types=['pre-commit']) == 0
113+
assert uninstall(C.CONFIG_FILE, hook_types=['pre-commit']) == 0
83114

84115

85116
def test_uninstall(in_git_dir, store):
86117
assert not in_git_dir.join('.git/hooks/pre-commit').exists()
87118
install(C.CONFIG_FILE, store, hook_types=['pre-commit'])
88119
assert in_git_dir.join('.git/hooks/pre-commit').exists()
89-
uninstall(hook_types=['pre-commit'])
120+
uninstall(C.CONFIG_FILE, hook_types=['pre-commit'])
90121
assert not in_git_dir.join('.git/hooks/pre-commit').exists()
91122

92123

@@ -416,7 +447,7 @@ def test_uninstall_restores_legacy_hooks(tempdir_factory, store):
416447

417448
# Now install and uninstall pre-commit
418449
assert install(C.CONFIG_FILE, store, hook_types=['pre-commit']) == 0
419-
assert uninstall(hook_types=['pre-commit']) == 0
450+
assert uninstall(C.CONFIG_FILE, hook_types=['pre-commit']) == 0
420451

421452
# Make sure we installed the "old" hook correctly
422453
ret, output = _get_commit_output(tempdir_factory, touch_file='baz')
@@ -451,7 +482,7 @@ def test_uninstall_doesnt_remove_not_our_hooks(in_git_dir):
451482
pre_commit.write('#!/usr/bin/env bash\necho 1\n')
452483
make_executable(pre_commit.strpath)
453484

454-
assert uninstall(hook_types=['pre-commit']) == 0
485+
assert uninstall(C.CONFIG_FILE, hook_types=['pre-commit']) == 0
455486

456487
assert pre_commit.exists()
457488

@@ -1007,3 +1038,16 @@ def test_install_temporarily_allow_mising_config(tempdir_factory, store):
10071038
'Skipping `pre-commit`.'
10081039
)
10091040
assert expected in output
1041+
1042+
1043+
def test_install_uninstall_default_hook_types(in_git_dir, store):
1044+
cfg_src = 'default_install_hook_types: [pre-commit, pre-push]\nrepos: []\n'
1045+
in_git_dir.join(C.CONFIG_FILE).write(cfg_src)
1046+
1047+
assert not install(C.CONFIG_FILE, store, hook_types=None)
1048+
assert os.access(in_git_dir.join('.git/hooks/pre-commit').strpath, os.X_OK)
1049+
assert os.access(in_git_dir.join('.git/hooks/pre-push').strpath, os.X_OK)
1050+
1051+
assert not uninstall(C.CONFIG_FILE, hook_types=None)
1052+
assert not in_git_dir.join('.git/hooks/pre-commit').exists()
1053+
assert not in_git_dir.join('.git/hooks/pre-push').exists()

tests/main_test.py

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,6 @@
1414
from testing.util import cwd
1515

1616

17-
@pytest.mark.parametrize(
18-
('argv', 'expected'),
19-
(
20-
((), ['f']),
21-
(('--f', 'x'), ['x']),
22-
(('--f', 'x', '--f', 'y'), ['x', 'y']),
23-
),
24-
)
25-
def test_append_replace_default(argv, expected):
26-
parser = argparse.ArgumentParser()
27-
parser.add_argument('--f', action=main.AppendReplaceDefault, default=['f'])
28-
assert parser.parse_args(argv).f == expected
29-
30-
3117
def _args(**kwargs):
3218
kwargs.setdefault('command', 'help')
3319
kwargs.setdefault('config', C.CONFIG_FILE)
@@ -172,7 +158,7 @@ def test_init_templatedir(mock_store_dir):
172158

173159
assert patch.call_count == 1
174160
assert 'tdir' in patch.call_args[0]
175-
assert patch.call_args[1]['hook_types'] == ['pre-commit']
161+
assert patch.call_args[1]['hook_types'] is None
176162
assert patch.call_args[1]['skip_on_missing_config'] is True
177163

178164

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy