dycw-pre-commit-hooks 0.12.8__py3-none-any.whl → 0.14.39__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 (42) hide show
  1. dycw_pre_commit_hooks-0.14.39.dist-info/METADATA +57 -0
  2. dycw_pre_commit_hooks-0.14.39.dist-info/RECORD +28 -0
  3. {dycw_pre_commit_hooks-0.12.8.dist-info → dycw_pre_commit_hooks-0.14.39.dist-info}/WHEEL +1 -1
  4. dycw_pre_commit_hooks-0.14.39.dist-info/entry_points.txt +19 -0
  5. pre_commit_hooks/__init__.py +1 -1
  6. pre_commit_hooks/configs/gitignore +243 -0
  7. pre_commit_hooks/constants.py +166 -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 +785 -0
  11. pre_commit_hooks/hooks/check_version_bumped.py +37 -0
  12. pre_commit_hooks/hooks/check_versions_consistent.py +42 -0
  13. pre_commit_hooks/hooks/format_pre_commit_config.py +70 -0
  14. pre_commit_hooks/hooks/format_requirements.py +56 -0
  15. pre_commit_hooks/{replace_sequence_str/__init__.py → hooks/replace_sequence_str.py} +25 -19
  16. pre_commit_hooks/hooks/run_prek_autoupdate.py +56 -0
  17. pre_commit_hooks/hooks/run_version_bump.py +48 -0
  18. pre_commit_hooks/hooks/setup_bump_my_version.py +99 -0
  19. pre_commit_hooks/hooks/setup_direnv.py +142 -0
  20. pre_commit_hooks/hooks/setup_git.py +40 -0
  21. pre_commit_hooks/hooks/setup_pyright.py +82 -0
  22. pre_commit_hooks/hooks/setup_ruff.py +129 -0
  23. pre_commit_hooks/hooks/update_ci_action_versions.py +47 -0
  24. pre_commit_hooks/hooks/update_ci_extensions.py +34 -0
  25. pre_commit_hooks/hooks/update_requirements.py +165 -0
  26. pre_commit_hooks/types.py +18 -0
  27. pre_commit_hooks/utilities.py +599 -0
  28. dycw_pre_commit_hooks-0.12.8.dist-info/METADATA +0 -46
  29. dycw_pre_commit_hooks-0.12.8.dist-info/RECORD +0 -19
  30. dycw_pre_commit_hooks-0.12.8.dist-info/entry_points.txt +0 -7
  31. pre_commit_hooks/check_submodules/__init__.py +0 -50
  32. pre_commit_hooks/check_submodules/__main__.py +0 -6
  33. pre_commit_hooks/common.py +0 -131
  34. pre_commit_hooks/format_requirements/__init__.py +0 -107
  35. pre_commit_hooks/format_requirements/__main__.py +0 -6
  36. pre_commit_hooks/mirror_files/__init__.py +0 -57
  37. pre_commit_hooks/mirror_files/__main__.py +0 -6
  38. pre_commit_hooks/replace_sequence_str/__main__.py +0 -6
  39. pre_commit_hooks/run_bump_my_version/__init__.py +0 -53
  40. pre_commit_hooks/run_bump_my_version/__main__.py +0 -6
  41. pre_commit_hooks/tag_commits/__init__.py +0 -103
  42. pre_commit_hooks/tag_commits/__main__.py +0 -6
@@ -0,0 +1,785 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Callable
4
+ from functools import partial
5
+ from pathlib import Path
6
+ from typing import TYPE_CHECKING, Literal, assert_never
7
+
8
+ from click import command, option
9
+ from utilities.click import CONTEXT_SETTINGS
10
+ from utilities.concurrent import concurrent_map
11
+ from utilities.iterables import always_iterable
12
+ from utilities.os import is_pytest
13
+ from utilities.types import PathLike
14
+
15
+ from pre_commit_hooks.constants import (
16
+ BUILTIN,
17
+ DEFAULT_PYTHON_VERSION,
18
+ DOCKERFMT_URL,
19
+ DYCW_PRE_COMMIT_HOOKS_URL,
20
+ FORMATTER_PRIORITY,
21
+ LINTER_PRIORITY,
22
+ LOCAL,
23
+ PRE_COMMIT_CONFIG_YAML,
24
+ PYPROJECT_TOML,
25
+ RUFF_URL,
26
+ SHELLCHECK_URL,
27
+ SHFMT_URL,
28
+ STD_PRE_COMMIT_HOOKS_URL,
29
+ STYLUA_URL,
30
+ TAPLO_URL,
31
+ UV_URL,
32
+ XMLFORMATTER_URL,
33
+ paths_argument,
34
+ python_option,
35
+ python_package_name_option,
36
+ python_uv_index_option,
37
+ python_uv_native_tls_option,
38
+ python_version_option,
39
+ )
40
+ from pre_commit_hooks.utilities import (
41
+ apply,
42
+ ensure_contains_partial_dict,
43
+ get_set_list_dicts,
44
+ run_all_maybe_raise,
45
+ yield_yaml_dict,
46
+ )
47
+
48
+ if TYPE_CHECKING:
49
+ from collections.abc import Callable, MutableSet
50
+ from pathlib import Path
51
+
52
+ from utilities.types import IntOrAll, MaybeSequenceStr, PathLike
53
+
54
+
55
+ @command(**CONTEXT_SETTINGS)
56
+ @paths_argument
57
+ @option("--ci", is_flag=True, default=False)
58
+ @option("--direnv", is_flag=True, default=False)
59
+ @option("--docker", is_flag=True, default=False)
60
+ @option("--fish", is_flag=True, default=False)
61
+ @option("--lua", is_flag=True, default=False)
62
+ @option("--prettier", is_flag=True, default=False)
63
+ @python_option
64
+ @python_package_name_option
65
+ @python_uv_index_option
66
+ @python_uv_native_tls_option
67
+ @python_version_option
68
+ @option("--shell", is_flag=True, default=False)
69
+ @option("--toml", is_flag=True, default=False)
70
+ @option("--xml", is_flag=True, default=False)
71
+ @option("--max-workers", type=int, default=None)
72
+ def _main(
73
+ *,
74
+ paths: tuple[Path, ...],
75
+ ci: bool = False,
76
+ direnv: bool = False,
77
+ docker: bool = False,
78
+ fish: bool = False,
79
+ lua: bool = False,
80
+ prettier: bool = False,
81
+ python: bool = False,
82
+ python_package_name: str | None = None,
83
+ python_uv_index: MaybeSequenceStr | None = None,
84
+ python_uv_native_tls: bool = False,
85
+ python_version: str = DEFAULT_PYTHON_VERSION,
86
+ shell: bool = False,
87
+ toml: bool = False,
88
+ xml: bool = False,
89
+ max_workers: int | None = None,
90
+ ) -> None:
91
+ if is_pytest():
92
+ return
93
+ run_all_maybe_raise(
94
+ *(
95
+ partial(
96
+ _run,
97
+ path=p,
98
+ ci=ci,
99
+ direnv=direnv,
100
+ docker=docker,
101
+ fish=fish,
102
+ lua=lua,
103
+ prettier=prettier,
104
+ python=python,
105
+ python_package_name=python_package_name,
106
+ python_uv_index=python_uv_index,
107
+ python_uv_native_tls=python_uv_native_tls,
108
+ python_version=python_version,
109
+ shell=shell,
110
+ toml=toml,
111
+ xml=xml,
112
+ max_workers="all" if max_workers is None else max_workers,
113
+ )
114
+ for p in paths
115
+ )
116
+ )
117
+
118
+
119
+ def _run(
120
+ *,
121
+ path: PathLike = PRE_COMMIT_CONFIG_YAML,
122
+ ci: bool = False,
123
+ direnv: bool = False,
124
+ docker: bool = False,
125
+ fish: bool = False,
126
+ lua: bool = False,
127
+ prettier: bool = False,
128
+ python: bool = False,
129
+ python_package_name: str | None = None,
130
+ python_uv_index: MaybeSequenceStr | None = None,
131
+ python_uv_native_tls: bool = False,
132
+ python_version: str = DEFAULT_PYTHON_VERSION,
133
+ shell: bool = False,
134
+ toml: bool = False,
135
+ xml: bool = False,
136
+ max_workers: IntOrAll = "all",
137
+ ) -> bool:
138
+ funcs: list[Callable[[], bool]] = [
139
+ partial(_add_check_version_bumped, path=path),
140
+ partial(_add_check_versions_consistent, path=path),
141
+ partial(_add_format_pre_commit_config, path=path),
142
+ partial(_add_run_prek_autoupdate, path=path),
143
+ partial(_add_run_version_bump, path=path),
144
+ partial(_add_setup_bump_my_version, path=path),
145
+ partial(_add_standard_hooks, path=path),
146
+ ]
147
+ if ci:
148
+ funcs.append(partial(_add_update_ci_action_versions, path=path))
149
+ funcs.append(partial(_add_update_ci_extensions, path=path))
150
+ if direnv:
151
+ funcs.append(partial(_add_setup_direnv, path=path))
152
+ if docker:
153
+ funcs.append(partial(_add_dockerfmt, path=path))
154
+ if fish:
155
+ funcs.append(partial(_add_fish_indent, path=path))
156
+ if lua:
157
+ funcs.append(partial(_add_stylua, path=path))
158
+ if prettier:
159
+ funcs.append(partial(_add_prettier, path=path))
160
+ if python:
161
+ funcs.append(partial(_add_add_future_import_annotations, path=path))
162
+ funcs.append(partial(_add_format_requirements, path=path))
163
+ funcs.append(partial(_add_replace_sequence_str, path=path))
164
+ funcs.append(partial(_add_ruff_check, path=path))
165
+ funcs.append(partial(_add_ruff_format, path=path))
166
+ funcs.append(
167
+ partial(
168
+ _add_setup_bump_my_version,
169
+ path=path,
170
+ python_package_name=python_package_name,
171
+ )
172
+ )
173
+ funcs.append(
174
+ partial(
175
+ _add_setup_direnv,
176
+ path=path,
177
+ python=python,
178
+ python_uv_index=python_uv_index,
179
+ python_uv_native_tls=python_uv_native_tls,
180
+ python_version=python_version,
181
+ )
182
+ )
183
+ funcs.append(partial(_add_setup_git, path=path))
184
+ funcs.append(
185
+ partial(_add_setup_pyright, path=path, python_version=python_version)
186
+ )
187
+ funcs.append(partial(_add_setup_ruff, path=path, python_version=python_version))
188
+ funcs.append(partial(_add_update_requirements, path=path))
189
+ funcs.append(partial(_add_uv_lock, path=path))
190
+ if shell:
191
+ funcs.append(partial(_add_shellcheck, path=path))
192
+ funcs.append(partial(_add_shfmt, path=path))
193
+ if toml:
194
+ funcs.append(partial(_add_taplo_format, path=path))
195
+ if xml:
196
+ funcs.append(partial(_add_xmlformatter, path=path))
197
+ return all(
198
+ concurrent_map(apply, funcs, parallelism="threads", max_workers=max_workers)
199
+ )
200
+
201
+
202
+ def _add_check_version_bumped(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
203
+ modifications: set[Path] = set()
204
+ _add_hook(
205
+ DYCW_PRE_COMMIT_HOOKS_URL,
206
+ "check-version-bumped",
207
+ path=path,
208
+ modifications=modifications,
209
+ rev=True,
210
+ type_="linter",
211
+ )
212
+ return len(modifications) == 0
213
+
214
+
215
+ def _add_check_versions_consistent(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
216
+ modifications: set[Path] = set()
217
+ _add_hook(
218
+ DYCW_PRE_COMMIT_HOOKS_URL,
219
+ "check-versions-consistent",
220
+ path=path,
221
+ modifications=modifications,
222
+ rev=True,
223
+ type_="linter",
224
+ )
225
+ return len(modifications) == 0
226
+
227
+
228
+ def _add_format_pre_commit_config(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
229
+ modifications: set[Path] = set()
230
+ _add_hook(
231
+ DYCW_PRE_COMMIT_HOOKS_URL,
232
+ "format-pre-commit-config",
233
+ path=path,
234
+ modifications=modifications,
235
+ rev=True,
236
+ type_="linter",
237
+ )
238
+ return len(modifications) == 0
239
+
240
+
241
+ def _add_run_prek_autoupdate(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
242
+ modifications: set[Path] = set()
243
+ _add_hook(
244
+ DYCW_PRE_COMMIT_HOOKS_URL,
245
+ "run-prek-autoupdate",
246
+ path=path,
247
+ modifications=modifications,
248
+ rev=True,
249
+ type_="formatter",
250
+ )
251
+ return len(modifications) == 0
252
+
253
+
254
+ def _add_run_version_bump(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
255
+ modifications: set[Path] = set()
256
+ _add_hook(
257
+ DYCW_PRE_COMMIT_HOOKS_URL,
258
+ "run-version-bump",
259
+ path=path,
260
+ modifications=modifications,
261
+ rev=True,
262
+ type_="formatter",
263
+ )
264
+ return len(modifications) == 0
265
+
266
+
267
+ def _add_setup_bump_my_version(
268
+ *, path: PathLike = PRE_COMMIT_CONFIG_YAML, python_package_name: str | None = None
269
+ ) -> bool:
270
+ modifications: set[Path] = set()
271
+ args: list[str] = []
272
+ if python_package_name is not None:
273
+ args.append(f"--python-package-name={python_package_name}")
274
+ _add_hook(
275
+ DYCW_PRE_COMMIT_HOOKS_URL,
276
+ "setup-bump-my-version",
277
+ path=path,
278
+ modifications=modifications,
279
+ rev=True,
280
+ args=args if len(args) >= 1 else None,
281
+ type_="formatter",
282
+ )
283
+ return len(modifications) == 0
284
+
285
+
286
+ def _add_standard_hooks(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
287
+ modifications: set[Path] = set()
288
+ _add_hook(
289
+ BUILTIN,
290
+ "check-added-large-files",
291
+ path=path,
292
+ modifications=modifications,
293
+ type_="linter",
294
+ )
295
+ _add_hook(
296
+ BUILTIN,
297
+ "check-case-conflict",
298
+ path=path,
299
+ modifications=modifications,
300
+ type_="linter",
301
+ )
302
+ _add_hook(
303
+ BUILTIN,
304
+ "check-executables-have-shebangs",
305
+ path=path,
306
+ modifications=modifications,
307
+ type_="linter",
308
+ )
309
+ _add_hook(
310
+ BUILTIN, "check-json", path=path, modifications=modifications, type_="linter"
311
+ )
312
+ _add_hook(
313
+ BUILTIN, "check-json5", path=path, modifications=modifications, type_="linter"
314
+ )
315
+ _add_hook(
316
+ BUILTIN,
317
+ "check-merge-conflict",
318
+ path=path,
319
+ modifications=modifications,
320
+ type_="linter",
321
+ )
322
+ _add_hook(
323
+ BUILTIN,
324
+ "check-symlinks",
325
+ path=path,
326
+ modifications=modifications,
327
+ type_="linter",
328
+ )
329
+ _add_hook(
330
+ BUILTIN, "check-toml", path=path, modifications=modifications, type_="linter"
331
+ )
332
+ _add_hook(
333
+ BUILTIN, "check-xml", path=path, modifications=modifications, type_="linter"
334
+ )
335
+ _add_hook(
336
+ BUILTIN, "check-yaml", path=path, modifications=modifications, type_="linter"
337
+ )
338
+ _add_hook(
339
+ BUILTIN,
340
+ "detect-private-key",
341
+ path=path,
342
+ modifications=modifications,
343
+ type_="linter",
344
+ )
345
+ _add_hook(
346
+ BUILTIN,
347
+ "end-of-file-fixer",
348
+ path=path,
349
+ modifications=modifications,
350
+ type_="formatter",
351
+ )
352
+ _add_hook(
353
+ BUILTIN,
354
+ "fix-byte-order-marker",
355
+ path=path,
356
+ modifications=modifications,
357
+ type_="formatter",
358
+ )
359
+ _add_hook(
360
+ BUILTIN,
361
+ "mixed-line-ending",
362
+ path=path,
363
+ modifications=modifications,
364
+ args=["--fix=lf"],
365
+ type_="formatter",
366
+ )
367
+ _add_hook(
368
+ BUILTIN,
369
+ "no-commit-to-branch",
370
+ path=path,
371
+ modifications=modifications,
372
+ type_="linter",
373
+ )
374
+ _add_hook(
375
+ BUILTIN,
376
+ "trailing-whitespace",
377
+ path=path,
378
+ modifications=modifications,
379
+ type_="formatter",
380
+ )
381
+ _add_hook(
382
+ STD_PRE_COMMIT_HOOKS_URL,
383
+ "check-illegal-windows-names",
384
+ path=path,
385
+ modifications=modifications,
386
+ rev=True,
387
+ type_="linter",
388
+ )
389
+ _add_hook(
390
+ STD_PRE_COMMIT_HOOKS_URL,
391
+ "destroyed-symlinks",
392
+ path=path,
393
+ modifications=modifications,
394
+ rev=True,
395
+ type_="linter",
396
+ )
397
+ _add_hook(
398
+ STD_PRE_COMMIT_HOOKS_URL,
399
+ "pretty-format-json",
400
+ path=path,
401
+ modifications=modifications,
402
+ rev=True,
403
+ args=["--autofix"],
404
+ type_="formatter",
405
+ )
406
+ return len(modifications) == 0
407
+
408
+
409
+ def _add_update_ci_action_versions(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
410
+ modifications: set[Path] = set()
411
+ _add_hook(
412
+ DYCW_PRE_COMMIT_HOOKS_URL,
413
+ "update-ci-action-versions",
414
+ path=path,
415
+ modifications=modifications,
416
+ rev=True,
417
+ type_="formatter",
418
+ )
419
+ return len(modifications) == 0
420
+
421
+
422
+ def _add_update_ci_extensions(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
423
+ modifications: set[Path] = set()
424
+ _add_hook(
425
+ DYCW_PRE_COMMIT_HOOKS_URL,
426
+ "update-ci-extensions",
427
+ path=path,
428
+ modifications=modifications,
429
+ rev=True,
430
+ type_="formatter",
431
+ )
432
+ return len(modifications) == 0
433
+
434
+
435
+ def _add_setup_direnv(
436
+ *,
437
+ path: PathLike = PRE_COMMIT_CONFIG_YAML,
438
+ python: bool = False,
439
+ python_uv_index: MaybeSequenceStr | None = None,
440
+ python_uv_native_tls: bool = False,
441
+ python_version: str = DEFAULT_PYTHON_VERSION,
442
+ ) -> bool:
443
+ modifications: set[Path] = set()
444
+ args: list[str] = []
445
+ if python:
446
+ args.append("--python")
447
+ if python_uv_index is not None:
448
+ args.append(f"--python-uv-index={','.join(always_iterable(python_uv_index))}")
449
+ if python_uv_native_tls:
450
+ args.append("--python-uv-native-tls")
451
+ if python_version is not None:
452
+ args.append(f"--python-version={python_version}")
453
+ _add_hook(
454
+ DYCW_PRE_COMMIT_HOOKS_URL,
455
+ "setup-direnv",
456
+ path=path,
457
+ modifications=modifications,
458
+ rev=True,
459
+ args=args if len(args) >= 1 else None,
460
+ type_="formatter",
461
+ )
462
+ return len(modifications) == 0
463
+
464
+
465
+ def _add_dockerfmt(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
466
+ modifications: set[Path] = set()
467
+ _add_hook(
468
+ DOCKERFMT_URL,
469
+ "dockerfmt",
470
+ path=path,
471
+ modifications=modifications,
472
+ rev=True,
473
+ args=["--newline", "--write"],
474
+ type_="formatter",
475
+ )
476
+ return len(modifications) == 0
477
+
478
+
479
+ def _add_fish_indent(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
480
+ modifications: set[Path] = set()
481
+ _add_hook(
482
+ LOCAL,
483
+ "fish_indent",
484
+ path=path,
485
+ modifications=modifications,
486
+ name="fish_indent",
487
+ entry="fish_indent",
488
+ language="unsupported",
489
+ files=r"\.fish$",
490
+ args=["--write"],
491
+ type_="formatter",
492
+ )
493
+ return len(modifications) == 0
494
+
495
+
496
+ def _add_stylua(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
497
+ modifications: set[Path] = set()
498
+ _add_hook(
499
+ STYLUA_URL,
500
+ "stlya",
501
+ path=path,
502
+ modifications=modifications,
503
+ rev=True,
504
+ type_="formatter",
505
+ )
506
+ return len(modifications) == 0
507
+
508
+
509
+ def _add_prettier(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
510
+ modifications: set[Path] = set()
511
+ _add_hook(
512
+ LOCAL,
513
+ "prettier",
514
+ path=path,
515
+ modifications=modifications,
516
+ name="prettier",
517
+ entry="npx prettier --write",
518
+ language="unsupported",
519
+ types_or=["markdown", "yaml"],
520
+ type_="formatter",
521
+ )
522
+ return len(modifications) == 0
523
+
524
+
525
+ def _add_add_future_import_annotations(
526
+ *, path: PathLike = PRE_COMMIT_CONFIG_YAML
527
+ ) -> bool:
528
+ modifications: set[Path] = set()
529
+ _add_hook(
530
+ DYCW_PRE_COMMIT_HOOKS_URL,
531
+ "add-future-import-annotations",
532
+ path=path,
533
+ modifications=modifications,
534
+ rev=True,
535
+ type_="formatter",
536
+ )
537
+ return len(modifications) == 0
538
+
539
+
540
+ def _add_format_requirements(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
541
+ modifications: set[Path] = set()
542
+ _add_hook(
543
+ DYCW_PRE_COMMIT_HOOKS_URL,
544
+ "format-requirements",
545
+ path=path,
546
+ modifications=modifications,
547
+ rev=True,
548
+ type_="formatter",
549
+ )
550
+ return len(modifications) == 0
551
+
552
+
553
+ def _add_replace_sequence_str(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
554
+ modifications: set[Path] = set()
555
+ _add_hook(
556
+ DYCW_PRE_COMMIT_HOOKS_URL,
557
+ "replace-sequence-str",
558
+ path=path,
559
+ modifications=modifications,
560
+ rev=True,
561
+ type_="formatter",
562
+ )
563
+ return len(modifications) == 0
564
+
565
+
566
+ def _add_ruff_check(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
567
+ modifications: set[Path] = set()
568
+ _add_hook(
569
+ RUFF_URL,
570
+ "ruff-check",
571
+ path=path,
572
+ modifications=modifications,
573
+ rev=True,
574
+ args=["--fix"],
575
+ type_="linter",
576
+ )
577
+ return len(modifications) == 0
578
+
579
+
580
+ def _add_ruff_format(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
581
+ modifications: set[Path] = set()
582
+ _add_hook(
583
+ RUFF_URL,
584
+ "ruff-format",
585
+ path=path,
586
+ modifications=modifications,
587
+ rev=True,
588
+ type_="formatter",
589
+ )
590
+ return len(modifications) == 0
591
+
592
+
593
+ def _add_setup_git(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
594
+ modifications: set[Path] = set()
595
+ _add_hook(
596
+ DYCW_PRE_COMMIT_HOOKS_URL,
597
+ "setup-git",
598
+ path=path,
599
+ modifications=modifications,
600
+ rev=True,
601
+ type_="formatter",
602
+ )
603
+ return len(modifications) == 0
604
+
605
+
606
+ def _add_setup_pyright(
607
+ *,
608
+ path: PathLike = PRE_COMMIT_CONFIG_YAML,
609
+ python_version: str = DEFAULT_PYTHON_VERSION,
610
+ ) -> bool:
611
+ modifications: set[Path] = set()
612
+ _add_hook(
613
+ DYCW_PRE_COMMIT_HOOKS_URL,
614
+ "setup-pyright",
615
+ path=path,
616
+ modifications=modifications,
617
+ rev=True,
618
+ args=[f"--python-version={python_version}"],
619
+ type_="formatter",
620
+ )
621
+ return len(modifications) == 0
622
+
623
+
624
+ def _add_setup_ruff(
625
+ *,
626
+ path: PathLike = PRE_COMMIT_CONFIG_YAML,
627
+ python_version: str = DEFAULT_PYTHON_VERSION,
628
+ ) -> bool:
629
+ modifications: set[Path] = set()
630
+ _add_hook(
631
+ DYCW_PRE_COMMIT_HOOKS_URL,
632
+ "setup-ruff",
633
+ path=path,
634
+ modifications=modifications,
635
+ rev=True,
636
+ args=[f"--python-version={python_version}"],
637
+ type_="formatter",
638
+ )
639
+ return len(modifications) == 0
640
+
641
+
642
+ def _add_update_requirements(*, path: PathLike = PYPROJECT_TOML) -> bool:
643
+ modifications: set[Path] = set()
644
+ _add_hook(
645
+ DYCW_PRE_COMMIT_HOOKS_URL,
646
+ "update-requirements",
647
+ path=path,
648
+ modifications=modifications,
649
+ rev=True,
650
+ type_="formatter",
651
+ )
652
+ return len(modifications) == 0
653
+
654
+
655
+ def _add_uv_lock(*, path: PathLike = PYPROJECT_TOML) -> bool:
656
+ modifications: set[Path] = set()
657
+ _add_hook(
658
+ UV_URL,
659
+ "uv-lock",
660
+ path=path,
661
+ modifications=modifications,
662
+ rev=True,
663
+ args=["--upgrade", "--resolution", "highest", "--prerelease", "disallow"],
664
+ type_="formatter",
665
+ )
666
+ return len(modifications) == 0
667
+
668
+
669
+ def _add_shellcheck(*, path: PathLike = PYPROJECT_TOML) -> bool:
670
+ modifications: set[Path] = set()
671
+ _add_hook(
672
+ SHELLCHECK_URL,
673
+ "shellcheck",
674
+ path=path,
675
+ modifications=modifications,
676
+ rev=True,
677
+ type_="linter",
678
+ )
679
+ return len(modifications) == 0
680
+
681
+
682
+ def _add_shfmt(*, path: PathLike = PYPROJECT_TOML) -> bool:
683
+ modifications: set[Path] = set()
684
+ _add_hook(
685
+ SHFMT_URL,
686
+ "shfmt",
687
+ path=path,
688
+ modifications=modifications,
689
+ rev=True,
690
+ type_="formatter",
691
+ )
692
+ return len(modifications) == 0
693
+
694
+
695
+ def _add_taplo_format(*, path: PathLike = PYPROJECT_TOML) -> bool:
696
+ modifications: set[Path] = set()
697
+ _add_hook(
698
+ TAPLO_URL,
699
+ "taplo-format",
700
+ path=path,
701
+ modifications=modifications,
702
+ rev=True,
703
+ args=[
704
+ "--option",
705
+ "indent_tables=true",
706
+ "--option",
707
+ "indent_entries=true",
708
+ "--option",
709
+ "reorder_keys=true",
710
+ ],
711
+ type_="linter",
712
+ )
713
+ return len(modifications) == 0
714
+
715
+
716
+ def _add_xmlformatter(*, path: PathLike = PYPROJECT_TOML) -> bool:
717
+ modifications: set[Path] = set()
718
+ _add_hook(
719
+ XMLFORMATTER_URL,
720
+ "xml-formatter",
721
+ path=path,
722
+ modifications=modifications,
723
+ rev=True,
724
+ types=[],
725
+ types_or=["plist", "xml"],
726
+ args=["--eof-newline"],
727
+ type_="formatter",
728
+ )
729
+ return len(modifications) == 0
730
+
731
+
732
+ ##
733
+
734
+
735
+ def _add_hook(
736
+ url: str,
737
+ id_: str,
738
+ /,
739
+ *,
740
+ path: PathLike = PRE_COMMIT_CONFIG_YAML,
741
+ modifications: MutableSet[Path] | None = None,
742
+ rev: bool = False,
743
+ name: str | None = None,
744
+ entry: str | None = None,
745
+ language: str | None = None,
746
+ files: str | None = None,
747
+ types: list[str] | None = None,
748
+ types_or: list[str] | None = None,
749
+ args: list[str] | None = None,
750
+ type_: Literal["formatter", "linter"] | None = None,
751
+ ) -> None:
752
+ with yield_yaml_dict(path, modifications=modifications) as dict_:
753
+ repos_list = get_set_list_dicts(dict_, "repos")
754
+ repo_dict = ensure_contains_partial_dict(
755
+ repos_list, {"repo": url}, extra={"rev": "master"} if rev else {}
756
+ )
757
+ hooks_list = get_set_list_dicts(repo_dict, "hooks")
758
+ hook_dict = ensure_contains_partial_dict(hooks_list, {"id": id_})
759
+ if name is not None:
760
+ hook_dict["name"] = name
761
+ if entry is not None:
762
+ hook_dict["entry"] = entry
763
+ if language is not None:
764
+ hook_dict["language"] = language
765
+ if files is not None:
766
+ hook_dict["files"] = files
767
+ if types is not None:
768
+ hook_dict["types"] = types
769
+ if types_or is not None:
770
+ hook_dict["types_or"] = types_or
771
+ if args is not None:
772
+ hook_dict["args"] = args
773
+ match type_:
774
+ case "formatter":
775
+ hook_dict["priority"] = FORMATTER_PRIORITY
776
+ case "linter":
777
+ hook_dict["priority"] = LINTER_PRIORITY
778
+ case None:
779
+ ...
780
+ case never:
781
+ assert_never(never)
782
+
783
+
784
+ if __name__ == "__main__":
785
+ _main()