dycw-pre-commit-hooks 0.14.39__py3-none-any.whl → 0.14.53__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.
@@ -9,13 +9,14 @@ from tomlkit import table
9
9
  from utilities.click import CONTEXT_SETTINGS
10
10
  from utilities.os import is_pytest
11
11
  from utilities.string import substitute
12
+ from utilities.text import snake_case
12
13
  from utilities.version import Version3
13
14
 
14
15
  from pre_commit_hooks.constants import (
15
16
  BUMPVERSION_TOML,
16
17
  PYPROJECT_TOML,
17
18
  paths_argument,
18
- python_package_name_option,
19
+ python_package_name_internal_option,
19
20
  )
20
21
  from pre_commit_hooks.utilities import (
21
22
  ensure_contains,
@@ -27,31 +28,34 @@ from pre_commit_hooks.utilities import (
27
28
  )
28
29
 
29
30
  if TYPE_CHECKING:
30
- from collections.abc import MutableSet
31
+ from collections.abc import Callable, MutableSet
31
32
 
32
33
  from utilities.types import PathLike
33
34
 
34
35
 
35
36
  @command(**CONTEXT_SETTINGS)
36
37
  @paths_argument
37
- @python_package_name_option
38
- def _main(*, paths: tuple[Path, ...], python_package_name: str | None = None) -> None:
38
+ @python_package_name_internal_option
39
+ def _main(
40
+ *, paths: tuple[Path, ...], python_package_name_internal: str | None = None
41
+ ) -> None:
39
42
  if is_pytest():
40
43
  return
41
- run_all_maybe_raise(
42
- *(
43
- partial(
44
- _run,
45
- path=p.parent / BUMPVERSION_TOML,
46
- python_package_name=python_package_name,
47
- )
48
- for p in paths
44
+ funcs: list[Callable[[], bool]] = [
45
+ partial(
46
+ _run,
47
+ path=p.parent / BUMPVERSION_TOML,
48
+ python_package_name_internal=python_package_name_internal,
49
49
  )
50
- )
50
+ for p in paths
51
+ ]
52
+ run_all_maybe_raise(*funcs)
51
53
 
52
54
 
53
55
  def _run(
54
- *, path: PathLike = BUMPVERSION_TOML, python_package_name: str | None = None
56
+ *,
57
+ path: PathLike = BUMPVERSION_TOML,
58
+ python_package_name_internal: str | None = None,
55
59
  ) -> bool:
56
60
  path = Path(path)
57
61
  modifications: set[Path] = set()
@@ -60,16 +64,19 @@ def _run(
60
64
  bumpversion = get_set_table(tool, "bumpversion")
61
65
  bumpversion["allow_dirty"] = True
62
66
  bumpversion.setdefault("current_version", str(Version3(0, 1, 0)))
63
- if python_package_name is not None:
67
+ if python_package_name_internal is not None:
64
68
  _add_file(
65
- 'version = "${version}"',
66
69
  path.parent / PYPROJECT_TOML,
70
+ 'version = "${version}"',
67
71
  path_bumpversion_toml=path,
68
72
  modifications=modifications,
69
73
  )
70
74
  _add_file(
75
+ path.parent
76
+ / "src"
77
+ / snake_case(python_package_name_internal)
78
+ / "__init__.py",
71
79
  '__version__ = "${version}"',
72
- path.parent / "src" / python_package_name / "__init__.py",
73
80
  path_bumpversion_toml=path,
74
81
  modifications=modifications,
75
82
  )
@@ -0,0 +1,260 @@
1
+ from __future__ import annotations
2
+
3
+ from functools import partial
4
+ from hashlib import blake2b
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.iterables import always_iterable
11
+ from utilities.os import is_pytest
12
+ from utilities.re import extract_groups
13
+ from utilities.types import PathLike
14
+
15
+ from pre_commit_hooks.constants import (
16
+ DEFAULT_PYTHON_VERSION,
17
+ GITEA_PULL_REQUEST_YAML,
18
+ GITHUB_PULL_REQUEST_YAML,
19
+ MAX_PYTHON_VERSION,
20
+ ci_pytest_os_option,
21
+ ci_pytest_python_version_option,
22
+ ci_pytest_runs_on_option,
23
+ gitea_option,
24
+ paths_argument,
25
+ python_uv_native_tls_option,
26
+ python_version_option,
27
+ repo_name_option,
28
+ )
29
+ from pre_commit_hooks.utilities import (
30
+ ensure_contains,
31
+ ensure_contains_partial_dict,
32
+ get_set_dict,
33
+ get_set_list_dicts,
34
+ get_set_list_strs,
35
+ run_all_maybe_raise,
36
+ yield_yaml_dict,
37
+ )
38
+
39
+ if TYPE_CHECKING:
40
+ from collections.abc import Callable, Iterator, MutableSet
41
+ from pathlib import Path
42
+
43
+ from utilities.types import MaybeSequenceStr, PathLike, StrDict
44
+
45
+
46
+ @command(**CONTEXT_SETTINGS)
47
+ @paths_argument
48
+ @gitea_option
49
+ @ci_pytest_os_option
50
+ @ci_pytest_python_version_option
51
+ @ci_pytest_runs_on_option
52
+ @python_uv_native_tls_option
53
+ @python_version_option
54
+ @repo_name_option
55
+ def _main(
56
+ *,
57
+ paths: tuple[Path, ...],
58
+ gitea: bool = False,
59
+ ci_pytest_os: MaybeSequenceStr | None = None,
60
+ ci_pytest_python_version: MaybeSequenceStr | None = None,
61
+ ci_pytest_runs_on: MaybeSequenceStr | None = None,
62
+ python_uv_native_tls: bool = False,
63
+ python_version: str = DEFAULT_PYTHON_VERSION,
64
+ repo_name: str | None = None,
65
+ ) -> None:
66
+ if is_pytest():
67
+ return
68
+ funcs: list[Callable[[], bool]] = [
69
+ partial(
70
+ _run,
71
+ path=p.parent
72
+ / (GITEA_PULL_REQUEST_YAML if gitea else GITHUB_PULL_REQUEST_YAML),
73
+ pytest_os=ci_pytest_os,
74
+ pytest_python_version=ci_pytest_python_version,
75
+ pytest_runs_on=ci_pytest_runs_on,
76
+ python_version=python_version,
77
+ uv_native_tls=python_uv_native_tls,
78
+ repo_name=repo_name,
79
+ )
80
+ for p in paths
81
+ ]
82
+ run_all_maybe_raise(*funcs)
83
+
84
+
85
+ def _run(
86
+ *,
87
+ path: PathLike = GITHUB_PULL_REQUEST_YAML,
88
+ pytest_os: MaybeSequenceStr | None = None,
89
+ pytest_python_version: MaybeSequenceStr | None = None,
90
+ pytest_runs_on: MaybeSequenceStr | None = None,
91
+ python_version: str = DEFAULT_PYTHON_VERSION,
92
+ uv_native_tls: bool = False,
93
+ repo_name: str | None = None,
94
+ ) -> bool:
95
+ modifications: set[Path] = set()
96
+ with yield_yaml_dict(path, modifications=modifications) as dict_:
97
+ dict_["name"] = "pull-request"
98
+ on = get_set_dict(dict_, "on")
99
+ pull_request = get_set_dict(on, "pull_request")
100
+ branches = get_set_list_strs(pull_request, "branches")
101
+ ensure_contains(branches, "master")
102
+ schedule = get_set_list_dicts(on, "schedule")
103
+ ensure_contains(schedule, {"cron": _get_cron_job(repo_name=repo_name)})
104
+ _add_pyright(
105
+ path=path,
106
+ modifications=modifications,
107
+ python_version=python_version,
108
+ uv_native_tls=uv_native_tls,
109
+ )
110
+ _add_pytest(
111
+ path=path,
112
+ modifications=modifications,
113
+ pytest_os=pytest_os,
114
+ pytest_runs_on=pytest_runs_on,
115
+ pytest_python_version=pytest_python_version,
116
+ python_version=python_version,
117
+ uv_native_tls=uv_native_tls,
118
+ )
119
+ _add_ruff(path=path, modifications=modifications, uv_native_tls=uv_native_tls)
120
+ return len(modifications) == 0
121
+
122
+
123
+ def _get_cron_job(*, repo_name: str | None = None) -> str:
124
+ if repo_name is None:
125
+ minute = hour = 0
126
+ else:
127
+ digest = blake2b(repo_name.encode(), digest_size=8).digest()
128
+ value = int.from_bytes(digest, "big")
129
+ minute = value % 60
130
+ hour = (value // 60) % 24
131
+ return f"{minute} {hour} * * *"
132
+
133
+
134
+ def _add_pyright(
135
+ *,
136
+ path: PathLike = GITHUB_PULL_REQUEST_YAML,
137
+ modifications: MutableSet[Path] | None = None,
138
+ python_version: str = DEFAULT_PYTHON_VERSION,
139
+ uv_native_tls: bool = False,
140
+ ) -> None:
141
+ with yield_yaml_dict(path, modifications=modifications) as dict_:
142
+ jobs = get_set_dict(dict_, "jobs")
143
+ pyright = get_set_dict(jobs, "pyright")
144
+ pyright["runs-on"] = "ubuntu-latest"
145
+ steps = get_set_list_dicts(pyright, "steps")
146
+ if uv_native_tls:
147
+ _add_update_certificates(steps)
148
+ step = ensure_contains_partial_dict(
149
+ steps, {"name": "Run 'pyright'", "uses": "dycw/action-pyright@latest"}
150
+ )
151
+ with_ = get_set_dict(step, "with")
152
+ with_["python-version"] = python_version
153
+ if uv_native_tls:
154
+ with_["native-tls"] = True
155
+
156
+
157
+ def _add_pytest(
158
+ *,
159
+ path: PathLike = GITHUB_PULL_REQUEST_YAML,
160
+ modifications: MutableSet[Path] | None = None,
161
+ pytest_os: MaybeSequenceStr | None = None,
162
+ pytest_python_version: MaybeSequenceStr | None = None,
163
+ pytest_runs_on: MaybeSequenceStr | None = None,
164
+ python_version: str = DEFAULT_PYTHON_VERSION,
165
+ uv_native_tls: bool = False,
166
+ ) -> None:
167
+ with yield_yaml_dict(path, modifications=modifications) as dict_:
168
+ jobs = get_set_dict(dict_, "jobs")
169
+ pytest = get_set_dict(jobs, "pytest")
170
+ env = get_set_dict(pytest, "env")
171
+ env["CI"] = "1"
172
+ pytest["name"] = (
173
+ "pytest (${{matrix.os}}, ${{matrix.python-version}}, ${{matrix.resolution}})"
174
+ )
175
+ runs_on = get_set_list_strs(pytest, "runs-on")
176
+ ensure_contains(runs_on, "${{matrix.os}}")
177
+ if pytest_runs_on is not None:
178
+ ensure_contains(runs_on, *always_iterable(pytest_runs_on))
179
+ steps = get_set_list_dicts(pytest, "steps")
180
+ if uv_native_tls:
181
+ _add_update_certificates(steps)
182
+ step = ensure_contains_partial_dict(
183
+ steps, {"name": "Run 'pytest'", "uses": "dycw/action-pytest@latest"}
184
+ )
185
+ with_ = get_set_dict(step, "with")
186
+ with_["python-version"] = "${{matrix.python-version}}"
187
+ with_["resolution"] = "${{matrix.resolution}}"
188
+ if uv_native_tls:
189
+ with_["native-tls"] = True
190
+ strategy = get_set_dict(pytest, "strategy")
191
+ strategy["fail-fast"] = False
192
+ matrix = get_set_dict(strategy, "matrix")
193
+ os = get_set_list_strs(matrix, "os")
194
+ if pytest_os is None:
195
+ pytest_os_use = ["macos-latest", "ubuntu-latest"]
196
+ else:
197
+ pytest_os_use = list(always_iterable(pytest_os))
198
+ ensure_contains(os, *pytest_os_use)
199
+ python_version_dict = get_set_list_strs(matrix, "python-version")
200
+ if pytest_python_version is None:
201
+ pytest_python_version_use = list(
202
+ _yield_python_versions(version=python_version)
203
+ )
204
+ else:
205
+ pytest_python_version_use = list(always_iterable(pytest_python_version))
206
+ ensure_contains(python_version_dict, *pytest_python_version_use)
207
+ resolution = get_set_list_strs(matrix, "resolution")
208
+ ensure_contains(resolution, "highest", "lowest-direct")
209
+ pytest["timeout-minutes"] = 10
210
+
211
+
212
+ def _add_ruff(
213
+ *,
214
+ path: PathLike = GITHUB_PULL_REQUEST_YAML,
215
+ modifications: MutableSet[Path] | None = None,
216
+ uv_native_tls: bool = False,
217
+ ) -> None:
218
+ with yield_yaml_dict(path, modifications=modifications) as dict_:
219
+ jobs = get_set_dict(dict_, "jobs")
220
+ ruff = get_set_dict(jobs, "ruff")
221
+ ruff["runs-on"] = "ubuntu-latest"
222
+ steps = get_set_list_dicts(ruff, "steps")
223
+ if uv_native_tls:
224
+ _add_update_certificates(steps)
225
+ step = ensure_contains_partial_dict(
226
+ steps, {"name": "Run 'ruff'", "uses": "dycw/action-ruff@latest"}
227
+ )
228
+ with_ = get_set_dict(step, "with")
229
+ if uv_native_tls:
230
+ with_["native-tls"] = True
231
+
232
+
233
+ def _add_update_certificates(steps: list[StrDict], /) -> None:
234
+ ensure_contains(
235
+ steps, {"name": "Update CA certificates", "run": "sudo update-ca-certificates"}
236
+ )
237
+
238
+
239
+ def _yield_python_versions(
240
+ *, version: str = DEFAULT_PYTHON_VERSION, max_: str = MAX_PYTHON_VERSION
241
+ ) -> Iterator[str]:
242
+ major, minor = _extract_python_version_tuple(version)
243
+ max_major, max_minor = _extract_python_version_tuple(max_)
244
+ if major != max_major:
245
+ msg = f"Major versions must be equal; got {major} and {max_major}"
246
+ raise ValueError(msg)
247
+ if minor > max_minor:
248
+ msg = f"Minor version must be at most {max_minor}; got {minor}"
249
+ raise ValueError(msg)
250
+ for i in range(minor, max_minor + 1):
251
+ yield f"{major}.{i}"
252
+
253
+
254
+ def _extract_python_version_tuple(version: str, /) -> tuple[int, int]:
255
+ major, minor = extract_groups(r"^(\d+)\.(\d+)$", version)
256
+ return int(major), int(minor)
257
+
258
+
259
+ if __name__ == "__main__":
260
+ _main()
@@ -0,0 +1,133 @@
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.types import PathLike
11
+
12
+ from pre_commit_hooks.constants import (
13
+ GITEA_PUSH_YAML,
14
+ GITHUB_PULL_REQUEST_YAML,
15
+ GITHUB_PUSH_YAML,
16
+ gitea_option,
17
+ paths_argument,
18
+ python_uv_native_tls_option,
19
+ )
20
+ from pre_commit_hooks.utilities import (
21
+ add_update_certificates,
22
+ ensure_contains,
23
+ ensure_contains_partial_dict,
24
+ get_set_dict,
25
+ get_set_list_dicts,
26
+ get_set_list_strs,
27
+ run_all_maybe_raise,
28
+ yield_yaml_dict,
29
+ )
30
+
31
+ if TYPE_CHECKING:
32
+ from collections.abc import Callable, MutableSet
33
+ from pathlib import Path
34
+
35
+ from utilities.types import PathLike
36
+
37
+
38
+ @command(**CONTEXT_SETTINGS)
39
+ @paths_argument
40
+ @gitea_option
41
+ @python_uv_native_tls_option
42
+ def _main(
43
+ *, paths: tuple[Path, ...], gitea: bool = False, python_uv_native_tls: bool = False
44
+ ) -> None:
45
+ if is_pytest():
46
+ return
47
+ funcs: list[Callable[[], bool]] = [
48
+ partial(
49
+ _run,
50
+ path=p.parent / (GITEA_PUSH_YAML if gitea else GITHUB_PUSH_YAML),
51
+ gitea=gitea,
52
+ uv_native_tls=python_uv_native_tls,
53
+ )
54
+ for p in paths
55
+ ]
56
+ run_all_maybe_raise(*funcs)
57
+
58
+
59
+ def _run(
60
+ *,
61
+ path: PathLike = GITHUB_PULL_REQUEST_YAML,
62
+ gitea: bool = False,
63
+ uv_native_tls: bool = False,
64
+ ) -> bool:
65
+ modifications: set[Path] = set()
66
+ with yield_yaml_dict(path, modifications=modifications) as dict_:
67
+ dict_["name"] = "push"
68
+ on = get_set_dict(dict_, "on")
69
+ push = get_set_dict(on, "push")
70
+ branches = get_set_list_strs(push, "branches")
71
+ ensure_contains(branches, "master")
72
+ _add_publish(
73
+ path=path, modifications=modifications, gitea=gitea, uv_native_tls=uv_native_tls
74
+ )
75
+ _add_tag(path=path, modifications=modifications, uv_native_tls=uv_native_tls)
76
+ return len(modifications) == 0
77
+
78
+
79
+ def _add_publish(
80
+ *,
81
+ path: PathLike = GITHUB_PULL_REQUEST_YAML,
82
+ modifications: MutableSet[Path] | None = None,
83
+ gitea: bool = False,
84
+ uv_native_tls: bool = False,
85
+ ) -> None:
86
+ with yield_yaml_dict(path, modifications=modifications) as dict_:
87
+ jobs = get_set_dict(dict_, "jobs")
88
+ publish = get_set_dict(jobs, "publish")
89
+ if not gitea:
90
+ environment = get_set_dict(publish, "environment")
91
+ environment["name"] = "pypi"
92
+ permissions = get_set_dict(publish, "permissions")
93
+ permissions["id-token"] = "write"
94
+ publish["runs-on"] = "ubuntu-latest"
95
+ steps = get_set_list_dicts(publish, "steps")
96
+ if uv_native_tls:
97
+ add_update_certificates(steps)
98
+ step = ensure_contains_partial_dict(
99
+ steps,
100
+ {
101
+ "name": "Build and publish the package",
102
+ "uses": "dycw/action-publish-package@latest",
103
+ },
104
+ )
105
+ with_ = get_set_dict(step, "with")
106
+ if uv_native_tls:
107
+ with_["native-tls"] = True
108
+
109
+
110
+ def _add_tag(
111
+ *,
112
+ path: PathLike = GITHUB_PULL_REQUEST_YAML,
113
+ modifications: MutableSet[Path] | None = None,
114
+ uv_native_tls: bool = False,
115
+ ) -> None:
116
+ with yield_yaml_dict(path, modifications=modifications) as dict_:
117
+ jobs = get_set_dict(dict_, "jobs")
118
+ tag = get_set_dict(jobs, "tag")
119
+ tag["runs-on"] = "ubuntu-latest"
120
+ steps = get_set_list_dicts(tag, "steps")
121
+ if uv_native_tls:
122
+ add_update_certificates(steps)
123
+ step = ensure_contains_partial_dict(
124
+ steps,
125
+ {"name": "Tag the latest commit", "uses": "dycw/action-tag-commit@latest"},
126
+ )
127
+ with_ = get_set_dict(step, "with")
128
+ if uv_native_tls:
129
+ with_["native-tls"] = True
130
+
131
+
132
+ if __name__ == "__main__":
133
+ _main()
@@ -0,0 +1,58 @@
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.types import PathLike
11
+
12
+ from pre_commit_hooks.constants import COVERAGERC_TOML, paths_argument
13
+ from pre_commit_hooks.utilities import (
14
+ ensure_contains,
15
+ get_set_array,
16
+ get_set_table,
17
+ run_all_maybe_raise,
18
+ yield_toml_doc,
19
+ )
20
+
21
+ if TYPE_CHECKING:
22
+ from collections.abc import Callable
23
+ from pathlib import Path
24
+
25
+ from utilities.types import PathLike
26
+
27
+
28
+ @command(**CONTEXT_SETTINGS)
29
+ @paths_argument
30
+ def _main(*, paths: tuple[Path, ...]) -> None:
31
+ if is_pytest():
32
+ return
33
+ funcs: list[Callable[[], bool]] = [
34
+ partial(_run, path=p.parent / COVERAGERC_TOML) for p in paths
35
+ ]
36
+ run_all_maybe_raise(*funcs)
37
+
38
+
39
+ def _run(*, path: PathLike = COVERAGERC_TOML) -> bool:
40
+ modifications: set[Path] = set()
41
+ with yield_toml_doc(path, modifications=modifications) as doc:
42
+ html = get_set_table(doc, "html")
43
+ html["directory"] = ".coverage/html"
44
+ report = get_set_table(doc, "report")
45
+ exclude_also = get_set_array(report, "exclude_also")
46
+ ensure_contains(exclude_also, "@overload", "if TYPE_CHECKING:")
47
+ report["fail_under"] = 100.0
48
+ report["skip_covered"] = True
49
+ report["skip_empty"] = True
50
+ run = get_set_table(doc, "run")
51
+ run["branch"] = True
52
+ run["data_file"] = ".coverage/data"
53
+ run["parallel"] = True
54
+ return len(modifications) == 0
55
+
56
+
57
+ if __name__ == "__main__":
58
+ _main()
@@ -24,7 +24,7 @@ from pre_commit_hooks.constants import (
24
24
  from pre_commit_hooks.utilities import run_all_maybe_raise, yield_text_file
25
25
 
26
26
  if TYPE_CHECKING:
27
- from collections.abc import MutableSet
27
+ from collections.abc import Callable, MutableSet
28
28
  from pathlib import Path
29
29
 
30
30
  from utilities.types import MaybeSequenceStr, PathLike
@@ -46,19 +46,18 @@ def _main(
46
46
  ) -> None:
47
47
  if is_pytest():
48
48
  return
49
- run_all_maybe_raise(
50
- *(
51
- partial(
52
- _run,
53
- path=p.parent / ENVRC,
54
- python=python,
55
- python_uv_index=python_uv_index,
56
- python_uv_native_tls=python_uv_native_tls,
57
- python_version=python_version,
58
- )
59
- for p in paths
49
+ funcs: list[Callable[[], bool]] = [
50
+ partial(
51
+ _run,
52
+ path=p.parent / ENVRC,
53
+ python=python,
54
+ python_uv_index=python_uv_index,
55
+ python_uv_native_tls=python_uv_native_tls,
56
+ python_version=python_version,
60
57
  )
61
- )
58
+ for p in paths
59
+ ]
60
+ run_all_maybe_raise(*funcs)
62
61
 
63
62
 
64
63
  def _run(
@@ -71,12 +70,15 @@ def _run(
71
70
  ) -> bool:
72
71
  modifications: set[Path] = set()
73
72
  with yield_text_file(path, modifications=modifications) as context:
74
- shebang = strip_and_dedent("""
73
+ text = strip_and_dedent("""
75
74
  #!/usr/bin/env sh
76
75
  # shellcheck source=/dev/null
76
+
77
+ # echo
78
+ echo_date() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] $*" >&2; }
77
79
  """)
78
- if search(escape(shebang), context.output, flags=MULTILINE) is None:
79
- context.output += f"\n\n{shebang}"
80
+ if search(escape(text), context.output, flags=MULTILINE) is None:
81
+ context.output += f"\n\n{text}"
80
82
  if python:
81
83
  _add_python(
82
84
  path=path,