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.
- dycw_pre_commit_hooks-0.14.26.dist-info/METADATA +57 -0
- dycw_pre_commit_hooks-0.14.26.dist-info/RECORD +23 -0
- {dycw_pre_commit_hooks-0.12.8.dist-info → dycw_pre_commit_hooks-0.14.26.dist-info}/WHEEL +1 -1
- dycw_pre_commit_hooks-0.14.26.dist-info/entry_points.txt +14 -0
- pre_commit_hooks/__init__.py +1 -1
- pre_commit_hooks/configs/gitignore +243 -0
- pre_commit_hooks/constants.py +149 -0
- pre_commit_hooks/hooks/__init__.py +1 -0
- pre_commit_hooks/hooks/add_future_import_annotations.py +63 -0
- pre_commit_hooks/hooks/add_hooks.py +373 -0
- pre_commit_hooks/hooks/check_versions_consistent.py +42 -0
- pre_commit_hooks/hooks/format_pre_commit_config.py +70 -0
- pre_commit_hooks/hooks/format_requirements.py +56 -0
- pre_commit_hooks/{replace_sequence_str/__init__.py → hooks/replace_sequence_str.py} +25 -19
- pre_commit_hooks/hooks/run_prek_autoupdate.py +56 -0
- pre_commit_hooks/hooks/run_version_bump.py +53 -0
- pre_commit_hooks/hooks/setup_git.py +40 -0
- pre_commit_hooks/hooks/setup_pyright.py +82 -0
- pre_commit_hooks/hooks/setup_ruff.py +129 -0
- pre_commit_hooks/hooks/update_requirements.py +165 -0
- pre_commit_hooks/types.py +18 -0
- pre_commit_hooks/utilities.py +658 -0
- dycw_pre_commit_hooks-0.12.8.dist-info/METADATA +0 -46
- dycw_pre_commit_hooks-0.12.8.dist-info/RECORD +0 -19
- dycw_pre_commit_hooks-0.12.8.dist-info/entry_points.txt +0 -7
- pre_commit_hooks/check_submodules/__init__.py +0 -50
- pre_commit_hooks/check_submodules/__main__.py +0 -6
- pre_commit_hooks/common.py +0 -131
- pre_commit_hooks/format_requirements/__init__.py +0 -107
- pre_commit_hooks/format_requirements/__main__.py +0 -6
- pre_commit_hooks/mirror_files/__init__.py +0 -57
- pre_commit_hooks/mirror_files/__main__.py +0 -6
- pre_commit_hooks/replace_sequence_str/__main__.py +0 -6
- pre_commit_hooks/run_bump_my_version/__init__.py +0 -53
- pre_commit_hooks/run_bump_my_version/__main__.py +0 -6
- pre_commit_hooks/tag_commits/__init__.py +0 -103
- pre_commit_hooks/tag_commits/__main__.py +0 -6
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
pre_commit_hooks/__init__.py,sha256=YLG1ztMLECr37VVZERdQ_nviI-TnuwzwSfl9cBayIv8,59
|
|
2
|
-
pre_commit_hooks/common.py,sha256=Ovg0kK5CBSBEalGdVxLKjvRX3gbjpzTFRNRopB8tEiw,4247
|
|
3
|
-
pre_commit_hooks/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
pre_commit_hooks/check_submodules/__init__.py,sha256=8aJ6sbDclOML5uahK4TNf80Sxf6gCx1kIOYwkv37g9s,1092
|
|
5
|
-
pre_commit_hooks/check_submodules/__main__.py,sha256=foSVebwCfSkKcAc3cD5YTzkmrWd7Wso9_mR9-zuyG-o,153
|
|
6
|
-
pre_commit_hooks/format_requirements/__init__.py,sha256=dORQ5sNZaOWYY6cw0X1YIic4OHZeTt9EhI21D1uQFyE,3322
|
|
7
|
-
pre_commit_hooks/format_requirements/__main__.py,sha256=15JSp_rhjI_Ddoj4MRkHFShfnYxs6GggUhLRlGtrQ0E,156
|
|
8
|
-
pre_commit_hooks/mirror_files/__init__.py,sha256=XUmUYHz4otEF5wIK8X0ntH0vkYFBmJwJfXkI8Bz3n0I,1682
|
|
9
|
-
pre_commit_hooks/mirror_files/__main__.py,sha256=YzOSNKR2XrVST5dgIVJrpRL28QkcziciOomuKtVX7Jo,149
|
|
10
|
-
pre_commit_hooks/replace_sequence_str/__init__.py,sha256=nDjiKV14th2uWbnte1rSvXckysl7ooaLgWo6IP4HI2s,1618
|
|
11
|
-
pre_commit_hooks/replace_sequence_str/__main__.py,sha256=B1dxOxngV4vUVnDVrXSywiySOs1P_zF30_4ZMRsOSaY,157
|
|
12
|
-
pre_commit_hooks/run_bump_my_version/__init__.py,sha256=OsMY0boz3VTqAtgLCHtC8AvCXx6OYvOXA5H-VAwBFoY,1444
|
|
13
|
-
pre_commit_hooks/run_bump_my_version/__main__.py,sha256=w2V3y61jrSau-zxjl8ciHtWPlJQwXbYxNJ2tGYVyI4s,156
|
|
14
|
-
pre_commit_hooks/tag_commits/__init__.py,sha256=097p0gfZcykpOPUgGYsrLePe8Nar04eKlCMn_mqPepg,2945
|
|
15
|
-
pre_commit_hooks/tag_commits/__main__.py,sha256=qefgYw7LWbvmzZS45-ym6olS4cHqw1Emw2wlqZBXN_o,148
|
|
16
|
-
dycw_pre_commit_hooks-0.12.8.dist-info/METADATA,sha256=SPMmd6uxKS3rmwv3zR0RGgv44Py_NYMGWom8R7kIlcI,1105
|
|
17
|
-
dycw_pre_commit_hooks-0.12.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
18
|
-
dycw_pre_commit_hooks-0.12.8.dist-info/entry_points.txt,sha256=0xGzim6HTjeOXJpusYjBk0aEYkXQR2IwrmfzM6KT_r0,368
|
|
19
|
-
dycw_pre_commit_hooks-0.12.8.dist-info/RECORD,,
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
[console_scripts]
|
|
2
|
-
check-submodules = pre_commit_hooks.check_submodules:main
|
|
3
|
-
format-requirements = pre_commit_hooks.format_requirements:main
|
|
4
|
-
mirror-files = pre_commit_hooks.mirror_files:main
|
|
5
|
-
replace-sequence-str = pre_commit_hooks.replace_sequence_str:main
|
|
6
|
-
run-bump-my-version = pre_commit_hooks.run_bump_my_version:main
|
|
7
|
-
tag-commits = pre_commit_hooks.tag_commits:main
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
4
|
-
|
|
5
|
-
from click import command
|
|
6
|
-
from git import Repo, Submodule
|
|
7
|
-
|
|
8
|
-
from pre_commit_hooks.common import (
|
|
9
|
-
DEFAULT_MODE,
|
|
10
|
-
Mode,
|
|
11
|
-
get_toml_path,
|
|
12
|
-
get_version,
|
|
13
|
-
mode_option,
|
|
14
|
-
run_every_option,
|
|
15
|
-
throttled_run,
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
if TYPE_CHECKING:
|
|
19
|
-
from whenever import DateTimeDelta
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@command()
|
|
23
|
-
@run_every_option
|
|
24
|
-
def main(*, run_every: DateTimeDelta | None = None) -> bool:
|
|
25
|
-
"""CLI for the `check-submodules` hook."""
|
|
26
|
-
return throttled_run("check-submodules", run_every, _process)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def _process() -> bool:
|
|
30
|
-
repo = Repo(".", search_parent_directories=True)
|
|
31
|
-
results = [_process_submodule(s) for s in repo.submodules] # run all
|
|
32
|
-
return all(results)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def _process_submodule(submodule: Submodule, /) -> bool:
|
|
36
|
-
repo = submodule.module()
|
|
37
|
-
_ = repo.remotes.origin.fetch()
|
|
38
|
-
local = repo.commit("master")
|
|
39
|
-
remote = repo.commit("origin/master")
|
|
40
|
-
return local.hexsha == remote.hexsha
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
__all__ = [
|
|
44
|
-
"DEFAULT_MODE",
|
|
45
|
-
"Mode",
|
|
46
|
-
"get_toml_path",
|
|
47
|
-
"get_version",
|
|
48
|
-
"main",
|
|
49
|
-
"mode_option",
|
|
50
|
-
]
|
pre_commit_hooks/common.py
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from typing import TYPE_CHECKING, Literal, assert_never
|
|
5
|
-
|
|
6
|
-
import utilities.click
|
|
7
|
-
from click import Choice, option
|
|
8
|
-
from loguru import logger
|
|
9
|
-
from tomlkit import TOMLDocument, parse
|
|
10
|
-
from tomlkit.items import Table
|
|
11
|
-
from utilities.atomicwrites import writer
|
|
12
|
-
from utilities.hashlib import md5_hash
|
|
13
|
-
from utilities.pathlib import get_repo_root
|
|
14
|
-
from utilities.typing import get_literal_elements
|
|
15
|
-
from utilities.version import Version, parse_version
|
|
16
|
-
from utilities.whenever import get_now_local, to_zoned_date_time
|
|
17
|
-
from xdg_base_dirs import xdg_cache_home
|
|
18
|
-
|
|
19
|
-
if TYPE_CHECKING:
|
|
20
|
-
from collections.abc import Callable
|
|
21
|
-
|
|
22
|
-
from whenever import DateTimeDelta
|
|
23
|
-
|
|
24
|
-
type Mode = Literal["pyproject", "bumpversion"]
|
|
25
|
-
DEFAULT_MODE: Mode = "pyproject"
|
|
26
|
-
mode_option = option(
|
|
27
|
-
"--mode",
|
|
28
|
-
type=Choice(get_literal_elements(Mode), case_sensitive=False),
|
|
29
|
-
default=DEFAULT_MODE,
|
|
30
|
-
show_default=True,
|
|
31
|
-
)
|
|
32
|
-
run_every_option = option(
|
|
33
|
-
"--run-every", type=utilities.click.DateTimeDelta(), default=None, show_default=True
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def get_version(source: Mode | Path | str | bytes | TOMLDocument, /) -> Version:
|
|
38
|
-
"""Get the `[tool.bumpversion]` version from a TOML file."""
|
|
39
|
-
match source:
|
|
40
|
-
case "pyproject" | "bumpversion" as mode:
|
|
41
|
-
return get_version(get_toml_path(mode))
|
|
42
|
-
case Path() as path:
|
|
43
|
-
return get_version(path.read_text())
|
|
44
|
-
case str() | bytes() as text:
|
|
45
|
-
return get_version(parse(text))
|
|
46
|
-
case TOMLDocument() as doc:
|
|
47
|
-
try:
|
|
48
|
-
tool = doc["tool"]
|
|
49
|
-
except KeyError:
|
|
50
|
-
logger.exception("Failed to get version; key 'tool' does not exist")
|
|
51
|
-
raise
|
|
52
|
-
if not isinstance(tool, Table):
|
|
53
|
-
logger.exception("Failed to get version; `tool` is not a Table")
|
|
54
|
-
raise TypeError
|
|
55
|
-
try:
|
|
56
|
-
bumpversion = tool["bumpversion"]
|
|
57
|
-
except KeyError:
|
|
58
|
-
logger.exception(
|
|
59
|
-
"Failed to get version; key 'bumpversion' does not exist"
|
|
60
|
-
)
|
|
61
|
-
raise
|
|
62
|
-
if not isinstance(bumpversion, Table):
|
|
63
|
-
logger.exception("Failed to get version; `bumpversion` is not a Table")
|
|
64
|
-
raise TypeError
|
|
65
|
-
try:
|
|
66
|
-
version = bumpversion["current_version"]
|
|
67
|
-
except KeyError:
|
|
68
|
-
logger.exception(
|
|
69
|
-
"Failed to get version; key 'current_version' does not exist"
|
|
70
|
-
)
|
|
71
|
-
raise
|
|
72
|
-
if not isinstance(version, str):
|
|
73
|
-
logger.exception("Failed to get version; `version` is not a string")
|
|
74
|
-
raise TypeError
|
|
75
|
-
return parse_version(version)
|
|
76
|
-
case never: # pyright: ignore[reportUnnecessaryComparison]
|
|
77
|
-
assert_never(never)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def get_toml_path(mode: Mode = DEFAULT_MODE, /) -> Path:
|
|
81
|
-
"""Get the path of the TOML file with the version."""
|
|
82
|
-
match mode:
|
|
83
|
-
case "pyproject":
|
|
84
|
-
return Path("pyproject.toml")
|
|
85
|
-
case "bumpversion":
|
|
86
|
-
return Path(".bumpversion.toml")
|
|
87
|
-
case never: # pyright: ignore[reportUnnecessaryComparison]
|
|
88
|
-
assert_never(never)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def throttled_run[**P](
|
|
92
|
-
name: str,
|
|
93
|
-
run_every: DateTimeDelta | None,
|
|
94
|
-
func: Callable[P, bool],
|
|
95
|
-
/,
|
|
96
|
-
*args: P.args,
|
|
97
|
-
**kwargs: P.kwargs,
|
|
98
|
-
) -> bool:
|
|
99
|
-
"""Throttled run."""
|
|
100
|
-
hash_ = md5_hash(get_repo_root())
|
|
101
|
-
path = xdg_cache_home().joinpath(name, hash_)
|
|
102
|
-
if run_every is not None:
|
|
103
|
-
min_date_time = get_now_local() - run_every
|
|
104
|
-
try:
|
|
105
|
-
text = path.read_text()
|
|
106
|
-
except FileNotFoundError:
|
|
107
|
-
pass
|
|
108
|
-
else:
|
|
109
|
-
try:
|
|
110
|
-
last_run = to_zoned_date_time(text.strip("\n"))
|
|
111
|
-
except ValueError:
|
|
112
|
-
pass
|
|
113
|
-
else:
|
|
114
|
-
if min_date_time <= last_run:
|
|
115
|
-
return True
|
|
116
|
-
try:
|
|
117
|
-
return func(*args, **kwargs)
|
|
118
|
-
finally:
|
|
119
|
-
with writer(path, overwrite=True) as temp:
|
|
120
|
-
_ = temp.write_text(str(get_now_local()))
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
__all__ = [
|
|
124
|
-
"DEFAULT_MODE",
|
|
125
|
-
"Mode",
|
|
126
|
-
"get_toml_path",
|
|
127
|
-
"get_version",
|
|
128
|
-
"mode_option",
|
|
129
|
-
"run_every_option",
|
|
130
|
-
"throttled_run",
|
|
131
|
-
]
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING, Any, override
|
|
4
|
-
|
|
5
|
-
import utilities.click
|
|
6
|
-
from click import argument, command
|
|
7
|
-
from packaging._tokenizer import ParserSyntaxError
|
|
8
|
-
from packaging.requirements import (
|
|
9
|
-
InvalidRequirement,
|
|
10
|
-
Requirement,
|
|
11
|
-
_parse_requirement, # pyright: ignore[reportPrivateImportUsage]
|
|
12
|
-
)
|
|
13
|
-
from packaging.specifiers import Specifier, SpecifierSet
|
|
14
|
-
from tomlkit import array, dumps, loads, string
|
|
15
|
-
from tomlkit.items import Array, Table
|
|
16
|
-
from utilities.atomicwrites import writer
|
|
17
|
-
|
|
18
|
-
if TYPE_CHECKING:
|
|
19
|
-
from collections.abc import Iterator
|
|
20
|
-
from pathlib import Path
|
|
21
|
-
|
|
22
|
-
from tomlkit.toml_document import TOMLDocument
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
@command()
|
|
26
|
-
@argument("paths", nargs=-1, type=utilities.click.Path())
|
|
27
|
-
def main(*, paths: tuple[Path, ...]) -> bool:
|
|
28
|
-
"""CLI for the `format-requirements` hook."""
|
|
29
|
-
results = list(map(_process, paths)) # run all
|
|
30
|
-
return all(results)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def _process(path: Path, /) -> bool:
|
|
34
|
-
doc = loads(path.read_text())
|
|
35
|
-
expected = _format_path(path)
|
|
36
|
-
if doc == expected:
|
|
37
|
-
return True
|
|
38
|
-
with writer(path, overwrite=True) as temp:
|
|
39
|
-
_ = temp.write_text(dumps(expected))
|
|
40
|
-
return False
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def _format_path(path: Path, /) -> TOMLDocument:
|
|
44
|
-
doc = loads(path.read_text())
|
|
45
|
-
if isinstance(dep_grps := doc.get("dependency-groups"), Table):
|
|
46
|
-
for key, value in dep_grps.items():
|
|
47
|
-
if isinstance(value, Array):
|
|
48
|
-
dep_grps[key] = _format_array(value)
|
|
49
|
-
if isinstance(project := doc["project"], Table):
|
|
50
|
-
if isinstance(deps := project["dependencies"], Array):
|
|
51
|
-
project["dependencies"] = _format_array(deps)
|
|
52
|
-
if isinstance(optional := project.get("optional-dependencies"), Table):
|
|
53
|
-
for key, value in optional.items():
|
|
54
|
-
if isinstance(value, Array):
|
|
55
|
-
optional[key] = _format_array(value)
|
|
56
|
-
return doc
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def _format_array(dependencies: Array, /) -> Array:
|
|
60
|
-
new = array().multiline(multiline=True)
|
|
61
|
-
new.extend(map(_format_item, dependencies))
|
|
62
|
-
return new
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def _format_item(item: Any, /) -> Any:
|
|
66
|
-
if not isinstance(item, str):
|
|
67
|
-
return item
|
|
68
|
-
return string(str(_CustomRequirement(item)))
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
class _CustomRequirement(Requirement):
|
|
72
|
-
@override
|
|
73
|
-
def __init__(self, requirement_string: str) -> None:
|
|
74
|
-
super().__init__(requirement_string)
|
|
75
|
-
try:
|
|
76
|
-
parsed = _parse_requirement(requirement_string)
|
|
77
|
-
except ParserSyntaxError as e:
|
|
78
|
-
raise InvalidRequirement(str(e)) from e
|
|
79
|
-
self.specifier = _CustomSpecifierSet(parsed.specifier)
|
|
80
|
-
|
|
81
|
-
@override
|
|
82
|
-
def _iter_parts(self, name: str) -> Iterator[str]:
|
|
83
|
-
yield name
|
|
84
|
-
if self.extras:
|
|
85
|
-
formatted_extras = ",".join(sorted(self.extras))
|
|
86
|
-
yield f"[{formatted_extras}]"
|
|
87
|
-
if self.specifier:
|
|
88
|
-
yield f" {self.specifier}"
|
|
89
|
-
if self.url:
|
|
90
|
-
yield f"@ {self.url}"
|
|
91
|
-
if self.marker:
|
|
92
|
-
yield " "
|
|
93
|
-
if self.marker:
|
|
94
|
-
yield f"; {self.marker}"
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
class _CustomSpecifierSet(SpecifierSet):
|
|
98
|
-
@override
|
|
99
|
-
def __str__(self) -> str:
|
|
100
|
-
specs = sorted(self._specs, key=self._key)
|
|
101
|
-
return ", ".join(map(str, specs))
|
|
102
|
-
|
|
103
|
-
def _key(self, spec: Specifier, /) -> int:
|
|
104
|
-
return [">=", "<"].index(spec.operator)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
__all__ = ["main"]
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING, Literal
|
|
4
|
-
|
|
5
|
-
import utilities.click
|
|
6
|
-
from click import argument, command
|
|
7
|
-
from loguru import logger
|
|
8
|
-
from more_itertools import chunked
|
|
9
|
-
from utilities.atomicwrites import writer
|
|
10
|
-
|
|
11
|
-
from pre_commit_hooks.common import run_every_option, throttled_run
|
|
12
|
-
|
|
13
|
-
if TYPE_CHECKING:
|
|
14
|
-
from collections.abc import Iterable
|
|
15
|
-
from pathlib import Path
|
|
16
|
-
|
|
17
|
-
from whenever import DateTimeDelta
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
@command()
|
|
21
|
-
@argument("paths", nargs=-1, type=utilities.click.Path())
|
|
22
|
-
@run_every_option
|
|
23
|
-
def main(*, paths: tuple[Path, ...], run_every: DateTimeDelta | None = None) -> bool:
|
|
24
|
-
"""CLI for the `format-requirements` hook."""
|
|
25
|
-
return throttled_run("mirror-files", run_every, _process, paths)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def _process(paths: Iterable[Path], /) -> bool:
|
|
29
|
-
paths = list(paths)
|
|
30
|
-
if len(paths) % 2 == 1:
|
|
31
|
-
logger.exception(f"Expected an even number of paths; got {len(paths)}")
|
|
32
|
-
raise RuntimeError
|
|
33
|
-
results = list(map(_process_pair, chunked(paths, 2, strict=True))) # run all
|
|
34
|
-
return all(results)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def _process_pair(paths: Iterable[Path], /) -> bool:
|
|
38
|
-
path_from, path_to = paths
|
|
39
|
-
try:
|
|
40
|
-
text_from = path_from.read_text()
|
|
41
|
-
except FileNotFoundError:
|
|
42
|
-
logger.exception(f"Source file {str(path_from)!r} not found")
|
|
43
|
-
raise
|
|
44
|
-
try:
|
|
45
|
-
text_to = path_to.read_text()
|
|
46
|
-
except FileNotFoundError:
|
|
47
|
-
return _write_text(text_from, path_to)
|
|
48
|
-
return True if text_from == text_to else _write_text(text_from, path_to)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def _write_text(text: str, path: Path, /) -> Literal[False]:
|
|
52
|
-
with writer(path, overwrite=True) as temp:
|
|
53
|
-
_ = temp.write_text(text)
|
|
54
|
-
return False
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
__all__ = ["main"]
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from subprocess import PIPE, STDOUT, CalledProcessError, check_call, check_output
|
|
4
|
-
|
|
5
|
-
from click import command
|
|
6
|
-
from loguru import logger
|
|
7
|
-
|
|
8
|
-
from pre_commit_hooks.common import (
|
|
9
|
-
DEFAULT_MODE,
|
|
10
|
-
Mode,
|
|
11
|
-
get_toml_path,
|
|
12
|
-
get_version,
|
|
13
|
-
mode_option,
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@command()
|
|
18
|
-
@mode_option
|
|
19
|
-
def main(*, mode: Mode = DEFAULT_MODE) -> bool:
|
|
20
|
-
"""CLI for the `run-bump-my-version` hook."""
|
|
21
|
-
return _process(mode=mode)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def _process(*, mode: Mode = DEFAULT_MODE) -> bool:
|
|
25
|
-
current = get_version(mode)
|
|
26
|
-
commit = check_output(["git", "rev-parse", "origin/master"], text=True).rstrip("\n")
|
|
27
|
-
path = get_toml_path(mode)
|
|
28
|
-
contents = check_output(["git", "show", f"{commit}:{path}"], text=True)
|
|
29
|
-
master = get_version(contents)
|
|
30
|
-
if current in {master.bump_patch(), master.bump_minor(), master.bump_major()}:
|
|
31
|
-
return True
|
|
32
|
-
cmd = [
|
|
33
|
-
"bump-my-version",
|
|
34
|
-
"replace",
|
|
35
|
-
"--new-version",
|
|
36
|
-
str(master.bump_patch()),
|
|
37
|
-
str(path),
|
|
38
|
-
]
|
|
39
|
-
try:
|
|
40
|
-
_ = check_call(cmd, stdout=PIPE, stderr=STDOUT)
|
|
41
|
-
except CalledProcessError as error:
|
|
42
|
-
if error.returncode != 1:
|
|
43
|
-
logger.exception("Failed to run {cmd!r}", cmd=" ".join(cmd))
|
|
44
|
-
except FileNotFoundError:
|
|
45
|
-
logger.exception(
|
|
46
|
-
"Failed to run {cmd!r}. Is `bump-my-version` installed?", cmd=" ".join(cmd)
|
|
47
|
-
)
|
|
48
|
-
else:
|
|
49
|
-
return True
|
|
50
|
-
return False
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
__all__ = ["main"]
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
4
|
-
|
|
5
|
-
import utilities.click
|
|
6
|
-
from click import command, option
|
|
7
|
-
from git import Commit, GitCommandError, Repo
|
|
8
|
-
from loguru import logger
|
|
9
|
-
from utilities.tzlocal import LOCAL_TIME_ZONE_NAME
|
|
10
|
-
from utilities.whenever import from_timestamp, get_now_local
|
|
11
|
-
|
|
12
|
-
from pre_commit_hooks.common import (
|
|
13
|
-
DEFAULT_MODE,
|
|
14
|
-
Mode,
|
|
15
|
-
get_toml_path,
|
|
16
|
-
get_version,
|
|
17
|
-
mode_option,
|
|
18
|
-
run_every_option,
|
|
19
|
-
throttled_run,
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
if TYPE_CHECKING:
|
|
23
|
-
from collections.abc import Set as AbstractSet
|
|
24
|
-
|
|
25
|
-
from whenever import DateTimeDelta, ZonedDateTime
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
@command()
|
|
29
|
-
@run_every_option
|
|
30
|
-
@option(
|
|
31
|
-
"--max-age", type=utilities.click.DateTimeDelta(), default=None, show_default=True
|
|
32
|
-
)
|
|
33
|
-
@mode_option
|
|
34
|
-
def main(
|
|
35
|
-
*,
|
|
36
|
-
run_every: DateTimeDelta | None = None,
|
|
37
|
-
max_age: DateTimeDelta | None = None,
|
|
38
|
-
mode: Mode = DEFAULT_MODE,
|
|
39
|
-
) -> bool:
|
|
40
|
-
"""CLI for the `tag-commits` hook."""
|
|
41
|
-
return throttled_run("tag-commits", run_every, _process, max_age=max_age, mode=mode)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def _process(
|
|
45
|
-
*, max_age: DateTimeDelta | None = None, mode: Mode = DEFAULT_MODE
|
|
46
|
-
) -> bool:
|
|
47
|
-
repo = Repo(".", search_parent_directories=True)
|
|
48
|
-
tagged = {tag.commit.hexsha for tag in repo.tags}
|
|
49
|
-
min_date_time = None if max_age is None else (get_now_local() - max_age)
|
|
50
|
-
commits = reversed(list(repo.iter_commits(repo.refs["origin/master"])))
|
|
51
|
-
results = [
|
|
52
|
-
_process_commit(c, tagged, repo, min_date_time=min_date_time, mode=mode)
|
|
53
|
-
for c in commits
|
|
54
|
-
] # run all
|
|
55
|
-
return all(results)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
def _process_commit(
|
|
59
|
-
commit: Commit,
|
|
60
|
-
tagged: AbstractSet[str],
|
|
61
|
-
repo: Repo,
|
|
62
|
-
/,
|
|
63
|
-
*,
|
|
64
|
-
min_date_time: ZonedDateTime | None = None,
|
|
65
|
-
mode: Mode = DEFAULT_MODE,
|
|
66
|
-
) -> bool:
|
|
67
|
-
if (commit.hexsha in tagged) or (
|
|
68
|
-
(min_date_time is not None) and (_get_date_time(commit) < min_date_time)
|
|
69
|
-
):
|
|
70
|
-
return True
|
|
71
|
-
try:
|
|
72
|
-
_tag_commit(commit, repo, mode=mode)
|
|
73
|
-
except GitCommandError:
|
|
74
|
-
return False
|
|
75
|
-
return True
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def _get_date_time(commit: Commit, /) -> ZonedDateTime:
|
|
79
|
-
return from_timestamp(commit.committed_date, time_zone=LOCAL_TIME_ZONE_NAME)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def _tag_commit(commit: Commit, repo: Repo, /, *, mode: Mode = DEFAULT_MODE) -> None:
|
|
83
|
-
sha = commit.hexsha[:7]
|
|
84
|
-
date = _get_date_time(commit)
|
|
85
|
-
path = get_toml_path(mode)
|
|
86
|
-
try:
|
|
87
|
-
joined = commit.tree.join(str(path))
|
|
88
|
-
except KeyError:
|
|
89
|
-
logger.exception(f"`{str(path)!r}` not found; failed to tag {sha!r} ({date})")
|
|
90
|
-
return
|
|
91
|
-
text = joined.data_stream.read()
|
|
92
|
-
version = get_version(text)
|
|
93
|
-
try:
|
|
94
|
-
tag = repo.create_tag(str(version), ref=sha)
|
|
95
|
-
except GitCommandError as error:
|
|
96
|
-
desc = error.stderr.strip("\n").strip()
|
|
97
|
-
logger.exception(f"Failed to tag {sha!r} ({date}) due to {desc}")
|
|
98
|
-
return
|
|
99
|
-
logger.info(f"Tagging {sha!r} ({date}) as {str(version)!r}...")
|
|
100
|
-
_ = repo.remotes.origin.push(f"refs/tags/{tag.name}")
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
__all__ = ["main"]
|