dycw-pre-commit-hooks 0.12.8__py3-none-any.whl → 0.14.26__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. dycw_pre_commit_hooks-0.14.26.dist-info/METADATA +57 -0
  2. dycw_pre_commit_hooks-0.14.26.dist-info/RECORD +23 -0
  3. {dycw_pre_commit_hooks-0.12.8.dist-info → dycw_pre_commit_hooks-0.14.26.dist-info}/WHEEL +1 -1
  4. dycw_pre_commit_hooks-0.14.26.dist-info/entry_points.txt +14 -0
  5. pre_commit_hooks/__init__.py +1 -1
  6. pre_commit_hooks/configs/gitignore +243 -0
  7. pre_commit_hooks/constants.py +149 -0
  8. pre_commit_hooks/hooks/__init__.py +1 -0
  9. pre_commit_hooks/hooks/add_future_import_annotations.py +63 -0
  10. pre_commit_hooks/hooks/add_hooks.py +373 -0
  11. pre_commit_hooks/hooks/check_versions_consistent.py +42 -0
  12. pre_commit_hooks/hooks/format_pre_commit_config.py +70 -0
  13. pre_commit_hooks/hooks/format_requirements.py +56 -0
  14. pre_commit_hooks/{replace_sequence_str/__init__.py → hooks/replace_sequence_str.py} +25 -19
  15. pre_commit_hooks/hooks/run_prek_autoupdate.py +56 -0
  16. pre_commit_hooks/hooks/run_version_bump.py +53 -0
  17. pre_commit_hooks/hooks/setup_git.py +40 -0
  18. pre_commit_hooks/hooks/setup_pyright.py +82 -0
  19. pre_commit_hooks/hooks/setup_ruff.py +129 -0
  20. pre_commit_hooks/hooks/update_requirements.py +165 -0
  21. pre_commit_hooks/types.py +18 -0
  22. pre_commit_hooks/utilities.py +658 -0
  23. dycw_pre_commit_hooks-0.12.8.dist-info/METADATA +0 -46
  24. dycw_pre_commit_hooks-0.12.8.dist-info/RECORD +0 -19
  25. dycw_pre_commit_hooks-0.12.8.dist-info/entry_points.txt +0 -7
  26. pre_commit_hooks/check_submodules/__init__.py +0 -50
  27. pre_commit_hooks/check_submodules/__main__.py +0 -6
  28. pre_commit_hooks/common.py +0 -131
  29. pre_commit_hooks/format_requirements/__init__.py +0 -107
  30. pre_commit_hooks/format_requirements/__main__.py +0 -6
  31. pre_commit_hooks/mirror_files/__init__.py +0 -57
  32. pre_commit_hooks/mirror_files/__main__.py +0 -6
  33. pre_commit_hooks/replace_sequence_str/__main__.py +0 -6
  34. pre_commit_hooks/run_bump_my_version/__init__.py +0 -53
  35. pre_commit_hooks/run_bump_my_version/__main__.py +0 -6
  36. pre_commit_hooks/tag_commits/__init__.py +0 -103
  37. pre_commit_hooks/tag_commits/__main__.py +0 -6
@@ -0,0 +1,373 @@
1
+ from __future__ import annotations
2
+
3
+ from functools import partial
4
+ from itertools import chain
5
+ from typing import TYPE_CHECKING
6
+
7
+ from click import command, option
8
+ from utilities.click import CONTEXT_SETTINGS
9
+ from utilities.os import is_pytest
10
+
11
+ from pre_commit_hooks.constants import (
12
+ BUILTIN,
13
+ DEFAULT_PYTHON_VERSION,
14
+ DYCW_PRE_COMMIT_HOOKS_URL,
15
+ PRE_COMMIT_CONFIG_YAML,
16
+ PYPROJECT_TOML,
17
+ RUFF_URL,
18
+ STD_PRE_COMMIT_HOOKS_URL,
19
+ paths_argument,
20
+ python_version_option,
21
+ )
22
+ from pre_commit_hooks.utilities import add_pre_commit_config_repo, run_all_maybe_raise
23
+
24
+ if TYPE_CHECKING:
25
+ from collections.abc import Callable
26
+ from pathlib import Path
27
+
28
+ from utilities.types import PathLike
29
+
30
+
31
+ @command(**CONTEXT_SETTINGS)
32
+ @paths_argument
33
+ @option("--python", is_flag=True, default=False)
34
+ @python_version_option
35
+ def _main(
36
+ *,
37
+ paths: tuple[Path, ...],
38
+ python: bool = False,
39
+ python_version: str = DEFAULT_PYTHON_VERSION,
40
+ ) -> None:
41
+ if is_pytest():
42
+ return
43
+ funcs: list[Callable[[], bool]] = list(
44
+ chain(
45
+ (partial(_add_check_versions_consistent, path=p) for p in paths),
46
+ (partial(_add_format_pre_commit_config, path=p) for p in paths),
47
+ (partial(_add_run_prek_autoupdate, path=p) for p in paths),
48
+ (partial(_add_run_version_bump, path=p) for p in paths),
49
+ (partial(_add_standard_hooks, path=p) for p in paths),
50
+ )
51
+ )
52
+ if python:
53
+ funcs.extend(partial(_add_add_future_import_annotations, path=p) for p in paths)
54
+ funcs.extend(partial(_add_format_requirements, path=p) for p in paths)
55
+ funcs.extend(partial(_add_replace_sequence_str, path=p) for p in paths)
56
+ funcs.extend(partial(_add_ruff_check, path=p) for p in paths)
57
+ funcs.extend(partial(_add_ruff_format, path=p) for p in paths)
58
+ funcs.extend(partial(_add_setup_git, path=p) for p in paths)
59
+ funcs.extend(
60
+ partial(_add_setup_pyright, path=p, python_version=python_version)
61
+ for p in paths
62
+ )
63
+ funcs.extend(
64
+ partial(_add_setup_ruff, path=p, python_version=python_version)
65
+ for p in paths
66
+ )
67
+ funcs.extend(partial(_add_update_requirements, path=p) for p in paths)
68
+ run_all_maybe_raise(*funcs)
69
+
70
+
71
+ def _add_check_versions_consistent(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
72
+ modifications: set[Path] = set()
73
+ add_pre_commit_config_repo(
74
+ DYCW_PRE_COMMIT_HOOKS_URL,
75
+ "check-versions-consistent",
76
+ path=path,
77
+ modifications=modifications,
78
+ type_="linter",
79
+ )
80
+ return len(modifications) == 0
81
+
82
+
83
+ def _add_format_pre_commit_config(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
84
+ modifications: set[Path] = set()
85
+ add_pre_commit_config_repo(
86
+ DYCW_PRE_COMMIT_HOOKS_URL,
87
+ "format-pre-commit-config",
88
+ path=path,
89
+ modifications=modifications,
90
+ type_="linter",
91
+ )
92
+ return len(modifications) == 0
93
+
94
+
95
+ def _add_run_prek_autoupdate(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
96
+ modifications: set[Path] = set()
97
+ add_pre_commit_config_repo(
98
+ DYCW_PRE_COMMIT_HOOKS_URL,
99
+ "run-prek-autoupdate",
100
+ path=path,
101
+ modifications=modifications,
102
+ type_="formatter",
103
+ )
104
+ return len(modifications) == 0
105
+
106
+
107
+ def _add_run_version_bump(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
108
+ modifications: set[Path] = set()
109
+ add_pre_commit_config_repo(
110
+ DYCW_PRE_COMMIT_HOOKS_URL,
111
+ "run-version-bump",
112
+ path=path,
113
+ modifications=modifications,
114
+ type_="formatter",
115
+ )
116
+ return len(modifications) == 0
117
+
118
+
119
+ def _add_standard_hooks(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
120
+ modifications: set[Path] = set()
121
+ add_pre_commit_config_repo(
122
+ BUILTIN,
123
+ "check-added-large-files",
124
+ path=path,
125
+ modifications=modifications,
126
+ type_="linter",
127
+ )
128
+ add_pre_commit_config_repo(
129
+ BUILTIN,
130
+ "check-case-conflict",
131
+ path=path,
132
+ modifications=modifications,
133
+ type_="linter",
134
+ )
135
+ add_pre_commit_config_repo(
136
+ BUILTIN,
137
+ "check-executables-have-shebangs",
138
+ path=path,
139
+ modifications=modifications,
140
+ type_="linter",
141
+ )
142
+ add_pre_commit_config_repo(
143
+ BUILTIN, "check-json", path=path, modifications=modifications, type_="linter"
144
+ )
145
+ add_pre_commit_config_repo(
146
+ BUILTIN, "check-json5", path=path, modifications=modifications, type_="linter"
147
+ )
148
+ add_pre_commit_config_repo(
149
+ BUILTIN,
150
+ "check-merge-conflict",
151
+ path=path,
152
+ modifications=modifications,
153
+ type_="linter",
154
+ )
155
+ add_pre_commit_config_repo(
156
+ BUILTIN,
157
+ "check-symlinks",
158
+ path=path,
159
+ modifications=modifications,
160
+ type_="linter",
161
+ )
162
+ add_pre_commit_config_repo(
163
+ BUILTIN, "check-toml", path=path, modifications=modifications, type_="linter"
164
+ )
165
+ add_pre_commit_config_repo(
166
+ BUILTIN, "check-xml", path=path, modifications=modifications, type_="linter"
167
+ )
168
+ add_pre_commit_config_repo(
169
+ BUILTIN, "check-yaml", path=path, modifications=modifications, type_="linter"
170
+ )
171
+ add_pre_commit_config_repo(
172
+ BUILTIN,
173
+ "detect-private-key",
174
+ path=path,
175
+ modifications=modifications,
176
+ type_="linter",
177
+ )
178
+ add_pre_commit_config_repo(
179
+ BUILTIN,
180
+ "end-of-file-fixer",
181
+ path=path,
182
+ modifications=modifications,
183
+ type_="formatter",
184
+ )
185
+ add_pre_commit_config_repo(
186
+ BUILTIN,
187
+ "fix-byte-order-marker",
188
+ path=path,
189
+ modifications=modifications,
190
+ type_="formatter",
191
+ )
192
+ add_pre_commit_config_repo(
193
+ BUILTIN,
194
+ "mixed-line-ending",
195
+ path=path,
196
+ modifications=modifications,
197
+ args=("add", ["--fix=lf"]),
198
+ type_="formatter",
199
+ )
200
+ add_pre_commit_config_repo(
201
+ BUILTIN,
202
+ "no-commit-to-branch",
203
+ path=path,
204
+ modifications=modifications,
205
+ type_="linter",
206
+ )
207
+ add_pre_commit_config_repo(
208
+ BUILTIN,
209
+ "trailing-whitespace",
210
+ path=path,
211
+ modifications=modifications,
212
+ type_="formatter",
213
+ )
214
+ add_pre_commit_config_repo(
215
+ STD_PRE_COMMIT_HOOKS_URL,
216
+ "check-illegal-windows-names",
217
+ path=path,
218
+ modifications=modifications,
219
+ rev=True,
220
+ type_="linter",
221
+ )
222
+ add_pre_commit_config_repo(
223
+ STD_PRE_COMMIT_HOOKS_URL,
224
+ "destroyed-symlinks",
225
+ path=path,
226
+ modifications=modifications,
227
+ rev=True,
228
+ type_="linter",
229
+ )
230
+ add_pre_commit_config_repo(
231
+ STD_PRE_COMMIT_HOOKS_URL,
232
+ "pretty-format-json",
233
+ path=path,
234
+ modifications=modifications,
235
+ rev=True,
236
+ args=("add", ["--autofix"]),
237
+ type_="formatter",
238
+ )
239
+ return len(modifications) == 0
240
+
241
+
242
+ def _add_add_future_import_annotations(
243
+ *, path: PathLike = PRE_COMMIT_CONFIG_YAML
244
+ ) -> bool:
245
+ modifications: set[Path] = set()
246
+ add_pre_commit_config_repo(
247
+ DYCW_PRE_COMMIT_HOOKS_URL,
248
+ "add-future-import-annotations",
249
+ path=path,
250
+ modifications=modifications,
251
+ rev=True,
252
+ type_="formatter",
253
+ )
254
+ return len(modifications) == 0
255
+
256
+
257
+ def _add_format_requirements(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
258
+ modifications: set[Path] = set()
259
+ add_pre_commit_config_repo(
260
+ DYCW_PRE_COMMIT_HOOKS_URL,
261
+ "format-requirements",
262
+ path=path,
263
+ modifications=modifications,
264
+ rev=True,
265
+ type_="formatter",
266
+ )
267
+ return len(modifications) == 0
268
+
269
+
270
+ def _add_replace_sequence_str(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
271
+ modifications: set[Path] = set()
272
+ add_pre_commit_config_repo(
273
+ DYCW_PRE_COMMIT_HOOKS_URL,
274
+ "replace-sequence-str",
275
+ path=path,
276
+ modifications=modifications,
277
+ rev=True,
278
+ type_="formatter",
279
+ )
280
+ return len(modifications) == 0
281
+
282
+
283
+ def _add_ruff_check(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
284
+ modifications: set[Path] = set()
285
+ add_pre_commit_config_repo(
286
+ RUFF_URL,
287
+ "ruff-check",
288
+ path=path,
289
+ modifications=modifications,
290
+ rev=True,
291
+ args=("exact", ["--fix"]),
292
+ type_="linter",
293
+ )
294
+ return len(modifications) == 0
295
+
296
+
297
+ def _add_ruff_format(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
298
+ modifications: set[Path] = set()
299
+ add_pre_commit_config_repo(
300
+ RUFF_URL,
301
+ "ruff-format",
302
+ path=path,
303
+ modifications=modifications,
304
+ rev=True,
305
+ type_="formatter",
306
+ )
307
+ return len(modifications) == 0
308
+
309
+
310
+ def _add_setup_git(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
311
+ modifications: set[Path] = set()
312
+ add_pre_commit_config_repo(
313
+ DYCW_PRE_COMMIT_HOOKS_URL,
314
+ "setup-git",
315
+ path=path,
316
+ modifications=modifications,
317
+ rev=True,
318
+ type_="formatter",
319
+ )
320
+ return len(modifications) == 0
321
+
322
+
323
+ def _add_setup_pyright(
324
+ *,
325
+ path: PathLike = PRE_COMMIT_CONFIG_YAML,
326
+ python_version: str = DEFAULT_PYTHON_VERSION,
327
+ ) -> bool:
328
+ modifications: set[Path] = set()
329
+ add_pre_commit_config_repo(
330
+ DYCW_PRE_COMMIT_HOOKS_URL,
331
+ "setup-pyright",
332
+ path=path,
333
+ modifications=modifications,
334
+ rev=True,
335
+ args=("exact", [f"--python-version={python_version}"]),
336
+ type_="formatter",
337
+ )
338
+ return len(modifications) == 0
339
+
340
+
341
+ def _add_setup_ruff(
342
+ *,
343
+ path: PathLike = PRE_COMMIT_CONFIG_YAML,
344
+ python_version: str = DEFAULT_PYTHON_VERSION,
345
+ ) -> bool:
346
+ modifications: set[Path] = set()
347
+ add_pre_commit_config_repo(
348
+ DYCW_PRE_COMMIT_HOOKS_URL,
349
+ "setup-ruff",
350
+ path=path,
351
+ modifications=modifications,
352
+ rev=True,
353
+ args=("exact", [f"--python-version={python_version}"]),
354
+ type_="formatter",
355
+ )
356
+ return len(modifications) == 0
357
+
358
+
359
+ def _add_update_requirements(*, path: PathLike = PYPROJECT_TOML) -> bool:
360
+ modifications: set[Path] = set()
361
+ add_pre_commit_config_repo(
362
+ DYCW_PRE_COMMIT_HOOKS_URL,
363
+ "update-requirements",
364
+ path=path,
365
+ modifications=modifications,
366
+ rev=True,
367
+ type_="formatter",
368
+ )
369
+ return len(modifications) == 0
370
+
371
+
372
+ if __name__ == "__main__":
373
+ _main()
@@ -0,0 +1,42 @@
1
+ from __future__ import annotations
2
+
3
+ from functools import partial
4
+ from subprocess import CalledProcessError
5
+ from typing import TYPE_CHECKING
6
+
7
+ from click import command
8
+ from utilities.click import CONTEXT_SETTINGS
9
+ from utilities.os import is_pytest
10
+
11
+ from pre_commit_hooks.constants import BUMPVERSION_TOML, paths_argument
12
+ from pre_commit_hooks.utilities import (
13
+ get_version_from_path,
14
+ run_all_maybe_raise,
15
+ run_bump_my_version,
16
+ )
17
+
18
+ if TYPE_CHECKING:
19
+ from pathlib import Path
20
+
21
+ from utilities.types import PathLike
22
+
23
+
24
+ @command(**CONTEXT_SETTINGS)
25
+ @paths_argument
26
+ def _main(*, paths: tuple[Path, ...]) -> None:
27
+ if is_pytest():
28
+ return
29
+ run_all_maybe_raise(*(partial(_run, path=p) for p in paths))
30
+
31
+
32
+ def _run(*, path: PathLike = BUMPVERSION_TOML) -> bool:
33
+ version = get_version_from_path(path=path)
34
+ try:
35
+ run_bump_my_version(version, path=path)
36
+ except CalledProcessError:
37
+ return False
38
+ return True
39
+
40
+
41
+ if __name__ == "__main__":
42
+ _main()
@@ -0,0 +1,70 @@
1
+ from __future__ import annotations
2
+
3
+ from contextlib import suppress
4
+ from functools import partial
5
+ from pathlib import Path
6
+ from typing import TYPE_CHECKING
7
+
8
+ from click import command
9
+ from utilities.click import CONTEXT_SETTINGS
10
+ from utilities.os import is_pytest
11
+ from utilities.types import PathLike
12
+
13
+ from pre_commit_hooks.constants import (
14
+ PRE_COMMIT_CONFIG_HOOK_KEYS,
15
+ PRE_COMMIT_CONFIG_REPO_KEYS,
16
+ PRE_COMMIT_CONFIG_YAML,
17
+ PRE_COMMIT_HOOKS_HOOK_KEYS,
18
+ paths_argument,
19
+ )
20
+ from pre_commit_hooks.utilities import (
21
+ get_list_dicts,
22
+ run_all_maybe_raise,
23
+ yield_yaml_dict,
24
+ )
25
+
26
+ if TYPE_CHECKING:
27
+ from utilities.types import PathLike, StrDict, StrMapping
28
+
29
+
30
+ @command(**CONTEXT_SETTINGS)
31
+ @paths_argument
32
+ def _main(*, paths: tuple[Path, ...]) -> None:
33
+ if is_pytest():
34
+ return
35
+ run_all_maybe_raise(*(partial(_run, path=p) for p in paths))
36
+
37
+
38
+ def _run(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
39
+ path = Path(path)
40
+ current = path.read_text()
41
+ with yield_yaml_dict(path, sort_keys=False) as dict_:
42
+ repos_list = get_list_dicts(dict_, "repos")
43
+ repos_list.sort(key=_sort_key)
44
+ for repo_dict in repos_list:
45
+ _re_insert(repo_dict, PRE_COMMIT_CONFIG_REPO_KEYS)
46
+ hooks_list = get_list_dicts(repo_dict, "hooks")
47
+ hooks_list.sort(key=lambda x: x["id"])
48
+ if repo_dict["repo"] == "local":
49
+ keys = PRE_COMMIT_HOOKS_HOOK_KEYS
50
+ else:
51
+ keys = PRE_COMMIT_CONFIG_HOOK_KEYS
52
+ for hook_dict in hooks_list:
53
+ _re_insert(hook_dict, keys)
54
+ return path.read_text() == current
55
+
56
+
57
+ def _re_insert(dict_: StrDict, keys: list[str], /) -> None:
58
+ copy = dict_.copy()
59
+ dict_.clear()
60
+ for key in keys:
61
+ with suppress(KeyError):
62
+ dict_[key] = copy[key]
63
+
64
+
65
+ def _sort_key(mapping: StrMapping, /) -> tuple[str, str]:
66
+ return mapping["repo"], mapping.get("rev", "")
67
+
68
+
69
+ if __name__ == "__main__":
70
+ _main()
@@ -0,0 +1,56 @@
1
+ from __future__ import annotations
2
+
3
+ from functools import partial
4
+ from pathlib import Path
5
+ from typing import TYPE_CHECKING
6
+
7
+ from click import command
8
+ from tomlkit import string
9
+ from tomlkit.items import Array
10
+ from utilities.click import CONTEXT_SETTINGS
11
+ from utilities.functions import ensure_str
12
+ from utilities.os import is_pytest
13
+ from utilities.packaging import Requirement
14
+ from utilities.types import PathLike
15
+
16
+ from pre_commit_hooks.constants import PYPROJECT_TOML, paths_argument
17
+ from pre_commit_hooks.utilities import (
18
+ get_pyproject_dependencies,
19
+ run_all_maybe_raise,
20
+ yield_toml_doc,
21
+ )
22
+
23
+ if TYPE_CHECKING:
24
+ from pathlib import Path
25
+
26
+ from tomlkit.items import Array
27
+ from utilities.types import PathLike
28
+
29
+
30
+ @command(**CONTEXT_SETTINGS)
31
+ @paths_argument
32
+ def _main(*, paths: tuple[Path, ...]) -> None:
33
+ if is_pytest():
34
+ return
35
+ run_all_maybe_raise(*(partial(_run, path=p) for p in paths))
36
+
37
+
38
+ def _run(*, path: PathLike = PYPROJECT_TOML) -> bool:
39
+ modifications: set[Path] = set()
40
+ with yield_toml_doc(path, modifications=modifications) as doc:
41
+ get_pyproject_dependencies(doc).map_array(_transform)
42
+ return len(modifications) == 0
43
+
44
+
45
+ def _transform(array: Array, /) -> None:
46
+ new: list[str] = []
47
+ for curr_i in array:
48
+ req = Requirement(ensure_str(curr_i))
49
+ new.append(str(req))
50
+ array.clear()
51
+ for new_i in sorted(new):
52
+ array.append(string(new_i))
53
+
54
+
55
+ if __name__ == "__main__":
56
+ _main()
@@ -1,38 +1,43 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from functools import partial
3
4
  from typing import TYPE_CHECKING, override
4
5
 
5
- import utilities.click
6
- from click import argument, command
7
- from libcst import CSTTransformer, Name, Subscript, parse_module
6
+ from click import command
7
+ from libcst import CSTTransformer, Name, Subscript
8
8
  from libcst.matchers import Index as MIndex
9
9
  from libcst.matchers import Name as MName
10
10
  from libcst.matchers import Subscript as MSubscript
11
11
  from libcst.matchers import SubscriptElement as MSubscriptElement
12
12
  from libcst.matchers import matches
13
13
  from libcst.metadata import MetadataWrapper
14
+ from utilities.click import CONTEXT_SETTINGS
15
+ from utilities.os import is_pytest
16
+
17
+ from pre_commit_hooks.constants import paths_argument
18
+ from pre_commit_hooks.utilities import run_all_maybe_raise, yield_python_file
14
19
 
15
20
  if TYPE_CHECKING:
16
21
  from pathlib import Path
17
22
 
23
+ from utilities.types import PathLike
24
+
18
25
 
19
- @command()
20
- @argument("paths", nargs=-1, type=utilities.click.Path())
21
- def main(*, paths: tuple[Path, ...]) -> bool:
22
- """CLI for the `replace-sequence-str` hook."""
23
- results = list(map(_process, paths)) # run all
24
- return all(results)
26
+ @command(**CONTEXT_SETTINGS)
27
+ @paths_argument
28
+ def _main(*, paths: tuple[Path, ...]) -> None:
29
+ if is_pytest():
30
+ return
31
+ run_all_maybe_raise(*(partial(_run, p) for p in paths))
25
32
 
26
33
 
27
- def _process(path: Path, /) -> bool:
28
- existing = path.read_text()
29
- wrapper = MetadataWrapper(parse_module(existing))
30
- transformed = wrapper.module.visit(SequenceToListTransformer())
31
- new = transformed.code
32
- if existing == new:
33
- return True
34
- _ = path.write_text(new)
35
- return False
34
+ def _run(path: PathLike, /) -> bool:
35
+ modifications: set[Path] = set()
36
+ with yield_python_file(path, modifications=modifications) as context:
37
+ context.output = MetadataWrapper(context.input).module.visit(
38
+ SequenceToListTransformer()
39
+ )
40
+ return len(modifications) == 0
36
41
 
37
42
 
38
43
  class SequenceToListTransformer(CSTTransformer):
@@ -52,4 +57,5 @@ class SequenceToListTransformer(CSTTransformer):
52
57
  return updated_node
53
58
 
54
59
 
55
- __all__ = ["main"]
60
+ if __name__ == "__main__":
61
+ _main()
@@ -0,0 +1,56 @@
1
+ from __future__ import annotations
2
+
3
+ from functools import partial
4
+ from pathlib import Path
5
+ from typing import TYPE_CHECKING
6
+
7
+ from click import command
8
+ from utilities.click import CONTEXT_SETTINGS
9
+ from utilities.os import is_pytest
10
+ from utilities.subprocess import run
11
+ from utilities.throttle import throttle
12
+
13
+ from pre_commit_hooks.constants import (
14
+ PRE_COMMIT_CONFIG_YAML,
15
+ THROTTLE_DURATION,
16
+ paths_argument,
17
+ throttle_option,
18
+ )
19
+ from pre_commit_hooks.utilities import path_throttle_cache, run_all_maybe_raise
20
+
21
+ if TYPE_CHECKING:
22
+ from collections.abc import MutableSet
23
+ from pathlib import Path
24
+
25
+
26
+ @command(**CONTEXT_SETTINGS)
27
+ @paths_argument
28
+ @throttle_option
29
+ def _main(*, paths: tuple[Path, ...], throttle: bool = True) -> None:
30
+ if is_pytest():
31
+ return
32
+ if len(paths) >= 1:
33
+ run_all_maybe_raise(partial(_run, throttle=throttle))
34
+
35
+
36
+ def _run(*, throttle: bool = False) -> bool:
37
+ modifications: set[Path] = set()
38
+ func = _run_throttled if throttle else _run_unthrottled
39
+ func(modifications=modifications)
40
+ return len(modifications) == 0
41
+
42
+
43
+ def _run_unthrottled(*, modifications: MutableSet[Path] | None = None) -> None:
44
+ current = PRE_COMMIT_CONFIG_YAML.read_text()
45
+ run("prek", "autoupdate")
46
+ if (modifications is not None) and (PRE_COMMIT_CONFIG_YAML.read_text() != current):
47
+ modifications.add(PRE_COMMIT_CONFIG_YAML)
48
+
49
+
50
+ _run_throttled = throttle(
51
+ duration=THROTTLE_DURATION, path=path_throttle_cache("run-prek-autoupdate")
52
+ )(_run_unthrottled)
53
+
54
+
55
+ if __name__ == "__main__":
56
+ _main()