dycw-pre-commit-hooks 0.14.26__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.
- {dycw_pre_commit_hooks-0.14.26.dist-info → dycw_pre_commit_hooks-0.14.53.dist-info}/METADATA +3 -31
- dycw_pre_commit_hooks-0.14.53.dist-info/RECORD +33 -0
- {dycw_pre_commit_hooks-0.14.26.dist-info → dycw_pre_commit_hooks-0.14.53.dist-info}/entry_points.txt +10 -0
- pre_commit_hooks/__init__.py +1 -1
- pre_commit_hooks/constants.py +38 -1
- pre_commit_hooks/hooks/add_hooks.py +706 -65
- pre_commit_hooks/hooks/check_version_bumped.py +37 -0
- pre_commit_hooks/hooks/check_versions_consistent.py +2 -2
- pre_commit_hooks/hooks/format_pre_commit_config.py +14 -9
- pre_commit_hooks/hooks/run_version_bump.py +9 -14
- pre_commit_hooks/hooks/setup_bump_my_version.py +106 -0
- pre_commit_hooks/hooks/setup_ci_pull_request.py +260 -0
- pre_commit_hooks/hooks/setup_ci_push.py +133 -0
- pre_commit_hooks/hooks/setup_coverage.py +58 -0
- pre_commit_hooks/hooks/setup_direnv.py +144 -0
- pre_commit_hooks/hooks/setup_pyproject.py +179 -0
- pre_commit_hooks/hooks/setup_pyright.py +6 -8
- pre_commit_hooks/hooks/setup_readme.py +76 -0
- pre_commit_hooks/hooks/setup_ruff.py +6 -6
- pre_commit_hooks/hooks/update_ci_action_versions.py +47 -0
- pre_commit_hooks/hooks/update_ci_extensions.py +34 -0
- pre_commit_hooks/hooks/update_requirements.py +6 -6
- pre_commit_hooks/utilities.py +52 -114
- dycw_pre_commit_hooks-0.14.26.dist-info/RECORD +0 -23
- {dycw_pre_commit_hooks-0.14.26.dist-info → dycw_pre_commit_hooks-0.14.53.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from click import command
|
|
6
|
+
from utilities.click import CONTEXT_SETTINGS
|
|
7
|
+
from utilities.os import is_pytest
|
|
8
|
+
|
|
9
|
+
from pre_commit_hooks.constants import BUMPVERSION_TOML
|
|
10
|
+
from pre_commit_hooks.utilities import (
|
|
11
|
+
get_version_from_path,
|
|
12
|
+
get_version_origin_master,
|
|
13
|
+
run_all_maybe_raise,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from utilities.types import PathLike
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@command(**CONTEXT_SETTINGS)
|
|
21
|
+
def _main() -> None:
|
|
22
|
+
if is_pytest():
|
|
23
|
+
return
|
|
24
|
+
run_all_maybe_raise(_run)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _run(*, path: PathLike = BUMPVERSION_TOML) -> bool:
|
|
28
|
+
try:
|
|
29
|
+
current = get_version_from_path(path=path)
|
|
30
|
+
prev = get_version_origin_master(path=path)
|
|
31
|
+
except ValueError:
|
|
32
|
+
return False
|
|
33
|
+
return current != prev
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
if __name__ == "__main__":
|
|
37
|
+
_main()
|
|
@@ -12,7 +12,7 @@ from pre_commit_hooks.constants import BUMPVERSION_TOML, paths_argument
|
|
|
12
12
|
from pre_commit_hooks.utilities import (
|
|
13
13
|
get_version_from_path,
|
|
14
14
|
run_all_maybe_raise,
|
|
15
|
-
|
|
15
|
+
set_version,
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
if TYPE_CHECKING:
|
|
@@ -32,7 +32,7 @@ def _main(*, paths: tuple[Path, ...]) -> None:
|
|
|
32
32
|
def _run(*, path: PathLike = BUMPVERSION_TOML) -> bool:
|
|
33
33
|
version = get_version_from_path(path=path)
|
|
34
34
|
try:
|
|
35
|
-
|
|
35
|
+
set_version(version, path=path)
|
|
36
36
|
except CalledProcessError:
|
|
37
37
|
return False
|
|
38
38
|
return True
|
|
@@ -7,6 +7,7 @@ from typing import TYPE_CHECKING
|
|
|
7
7
|
|
|
8
8
|
from click import command
|
|
9
9
|
from utilities.click import CONTEXT_SETTINGS
|
|
10
|
+
from utilities.constants import sentinel
|
|
10
11
|
from utilities.os import is_pytest
|
|
11
12
|
from utilities.types import PathLike
|
|
12
13
|
|
|
@@ -39,18 +40,22 @@ def _run(*, path: PathLike = PRE_COMMIT_CONFIG_YAML) -> bool:
|
|
|
39
40
|
path = Path(path)
|
|
40
41
|
current = path.read_text()
|
|
41
42
|
with yield_yaml_dict(path, sort_keys=False) as dict_:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
for
|
|
45
|
-
_re_insert(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if
|
|
43
|
+
repos = get_list_dicts(dict_, "repos")
|
|
44
|
+
repos.sort(key=_sort_key)
|
|
45
|
+
for repo in repos:
|
|
46
|
+
_re_insert(repo, PRE_COMMIT_CONFIG_REPO_KEYS)
|
|
47
|
+
hooks = get_list_dicts(repo, "hooks")
|
|
48
|
+
hooks.sort(key=lambda x: x["id"])
|
|
49
|
+
if repo["repo"] == "local":
|
|
49
50
|
keys = PRE_COMMIT_HOOKS_HOOK_KEYS
|
|
50
51
|
else:
|
|
51
52
|
keys = PRE_COMMIT_CONFIG_HOOK_KEYS
|
|
52
|
-
for
|
|
53
|
-
_re_insert(
|
|
53
|
+
for hook in hooks:
|
|
54
|
+
_re_insert(hook, keys)
|
|
55
|
+
repos.append({"repo": str(sentinel)})
|
|
56
|
+
with yield_yaml_dict(path, sort_keys=False) as dict_:
|
|
57
|
+
repos = get_list_dicts(dict_, "repos")
|
|
58
|
+
_ = repos.pop(-1)
|
|
54
59
|
return path.read_text() == current
|
|
55
60
|
|
|
56
61
|
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from functools import partial
|
|
4
|
-
from subprocess import CalledProcessError
|
|
5
4
|
from typing import TYPE_CHECKING
|
|
6
5
|
|
|
7
6
|
from click import command
|
|
8
7
|
from utilities.click import CONTEXT_SETTINGS
|
|
9
8
|
from utilities.os import is_pytest
|
|
10
|
-
from utilities.version import Version3
|
|
9
|
+
from utilities.version import Version3
|
|
11
10
|
|
|
12
11
|
from pre_commit_hooks.constants import BUMPVERSION_TOML, paths_argument
|
|
13
12
|
from pre_commit_hooks.utilities import (
|
|
14
|
-
get_version_from_git_show,
|
|
15
|
-
get_version_from_git_tag,
|
|
16
13
|
get_version_from_path,
|
|
14
|
+
get_version_origin_master,
|
|
17
15
|
run_all_maybe_raise,
|
|
18
|
-
|
|
16
|
+
set_version,
|
|
19
17
|
)
|
|
20
18
|
|
|
21
19
|
if TYPE_CHECKING:
|
|
@@ -34,18 +32,15 @@ def _main(*, paths: tuple[Path, ...]) -> None:
|
|
|
34
32
|
|
|
35
33
|
def _run(*, path: PathLike = BUMPVERSION_TOML) -> bool:
|
|
36
34
|
try:
|
|
37
|
-
prev =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
run_bump_my_version(Version3(0, 1, 0), path=path)
|
|
43
|
-
return False
|
|
44
|
-
current = get_version_from_path(path=path)
|
|
35
|
+
prev = get_version_origin_master(path=path)
|
|
36
|
+
current = get_version_from_path(path=path)
|
|
37
|
+
except ValueError:
|
|
38
|
+
set_version(Version3(0, 1, 0), path=path)
|
|
39
|
+
return False
|
|
45
40
|
patched = prev.bump_patch()
|
|
46
41
|
if current in {patched, prev.bump_minor(), prev.bump_major()}:
|
|
47
42
|
return True
|
|
48
|
-
|
|
43
|
+
set_version(patched, path=path)
|
|
49
44
|
return False
|
|
50
45
|
|
|
51
46
|
|
|
@@ -0,0 +1,106 @@
|
|
|
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 table
|
|
9
|
+
from utilities.click import CONTEXT_SETTINGS
|
|
10
|
+
from utilities.os import is_pytest
|
|
11
|
+
from utilities.string import substitute
|
|
12
|
+
from utilities.text import snake_case
|
|
13
|
+
from utilities.version import Version3
|
|
14
|
+
|
|
15
|
+
from pre_commit_hooks.constants import (
|
|
16
|
+
BUMPVERSION_TOML,
|
|
17
|
+
PYPROJECT_TOML,
|
|
18
|
+
paths_argument,
|
|
19
|
+
python_package_name_internal_option,
|
|
20
|
+
)
|
|
21
|
+
from pre_commit_hooks.utilities import (
|
|
22
|
+
ensure_contains,
|
|
23
|
+
get_set_aot,
|
|
24
|
+
get_set_table,
|
|
25
|
+
get_table,
|
|
26
|
+
run_all_maybe_raise,
|
|
27
|
+
yield_toml_doc,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
if TYPE_CHECKING:
|
|
31
|
+
from collections.abc import Callable, MutableSet
|
|
32
|
+
|
|
33
|
+
from utilities.types import PathLike
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@command(**CONTEXT_SETTINGS)
|
|
37
|
+
@paths_argument
|
|
38
|
+
@python_package_name_internal_option
|
|
39
|
+
def _main(
|
|
40
|
+
*, paths: tuple[Path, ...], python_package_name_internal: str | None = None
|
|
41
|
+
) -> None:
|
|
42
|
+
if is_pytest():
|
|
43
|
+
return
|
|
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
|
+
)
|
|
50
|
+
for p in paths
|
|
51
|
+
]
|
|
52
|
+
run_all_maybe_raise(*funcs)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _run(
|
|
56
|
+
*,
|
|
57
|
+
path: PathLike = BUMPVERSION_TOML,
|
|
58
|
+
python_package_name_internal: str | None = None,
|
|
59
|
+
) -> bool:
|
|
60
|
+
path = Path(path)
|
|
61
|
+
modifications: set[Path] = set()
|
|
62
|
+
with yield_toml_doc(path, modifications=modifications) as doc:
|
|
63
|
+
tool = get_set_table(doc, "tool")
|
|
64
|
+
bumpversion = get_set_table(tool, "bumpversion")
|
|
65
|
+
bumpversion["allow_dirty"] = True
|
|
66
|
+
bumpversion.setdefault("current_version", str(Version3(0, 1, 0)))
|
|
67
|
+
if python_package_name_internal is not None:
|
|
68
|
+
_add_file(
|
|
69
|
+
path.parent / PYPROJECT_TOML,
|
|
70
|
+
'version = "${version}"',
|
|
71
|
+
path_bumpversion_toml=path,
|
|
72
|
+
modifications=modifications,
|
|
73
|
+
)
|
|
74
|
+
_add_file(
|
|
75
|
+
path.parent
|
|
76
|
+
/ "src"
|
|
77
|
+
/ snake_case(python_package_name_internal)
|
|
78
|
+
/ "__init__.py",
|
|
79
|
+
'__version__ = "${version}"',
|
|
80
|
+
path_bumpversion_toml=path,
|
|
81
|
+
modifications=modifications,
|
|
82
|
+
)
|
|
83
|
+
return len(modifications) == 0
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _add_file(
|
|
87
|
+
path_data: PathLike,
|
|
88
|
+
template: PathLike,
|
|
89
|
+
/,
|
|
90
|
+
*,
|
|
91
|
+
path_bumpversion_toml: PathLike = BUMPVERSION_TOML,
|
|
92
|
+
modifications: MutableSet[Path] | None = None,
|
|
93
|
+
) -> None:
|
|
94
|
+
with yield_toml_doc(path_bumpversion_toml, modifications=modifications) as doc:
|
|
95
|
+
tool = get_table(doc, "tool")
|
|
96
|
+
bumpversion = get_table(tool, "bumpversion")
|
|
97
|
+
files = get_set_aot(bumpversion, "files")
|
|
98
|
+
tab = table()
|
|
99
|
+
tab["filename"] = str(path_data)
|
|
100
|
+
tab["search"] = substitute(template, version="{current_version}")
|
|
101
|
+
tab["replace"] = substitute(template, version="{new_version}")
|
|
102
|
+
ensure_contains(files, tab)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
if __name__ == "__main__":
|
|
106
|
+
_main()
|
|
@@ -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()
|