dycw-pre-commit-hooks 0.12.0__tar.gz → 0.12.2__tar.gz

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.

Potentially problematic release.


This version of dycw-pre-commit-hooks might be problematic. Click here for more details.

Files changed (22) hide show
  1. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/PKG-INFO +3 -1
  2. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/pyproject.toml +4 -2
  3. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/src/pre_commit_hooks/__init__.py +1 -1
  4. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/src/pre_commit_hooks/common.py +11 -21
  5. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/src/pre_commit_hooks/run_bump_my_version/__init__.py +27 -5
  6. dycw_pre_commit_hooks-0.12.2/src/pre_commit_hooks/tag_commits/__init__.py +127 -0
  7. dycw_pre_commit_hooks-0.12.0/src/pre_commit_hooks/tag_commits/__init__.py +0 -70
  8. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/.gitignore +0 -0
  9. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/README.md +0 -0
  10. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/src/pre_commit_hooks/format_requirements/__init__.py +0 -0
  11. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/src/pre_commit_hooks/format_requirements/__main__.py +0 -0
  12. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/src/pre_commit_hooks/py.typed +0 -0
  13. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/src/pre_commit_hooks/replace_sequence_str/__init__.py +0 -0
  14. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/src/pre_commit_hooks/replace_sequence_str/__main__.py +0 -0
  15. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/src/pre_commit_hooks/run_bump_my_version/__main__.py +0 -0
  16. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/src/pre_commit_hooks/tag_commits/__main__.py +0 -0
  17. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/src/tests/__init__.py +0 -0
  18. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/src/tests/format_requirements/__init__.py +0 -0
  19. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/src/tests/format_requirements/in.toml +0 -0
  20. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/src/tests/format_requirements/out.toml +0 -0
  21. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/src/tests/format_requirements/test_format_requirements.py +0 -0
  22. {dycw_pre_commit_hooks-0.12.0 → dycw_pre_commit_hooks-0.12.2}/src/tests/test_main.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-pre-commit-hooks
3
- Version: 0.12.0
3
+ Version: 0.12.2
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  Requires-Python: >=3.12
6
6
  Requires-Dist: click<8.3,>=8.2.1
@@ -8,8 +8,10 @@ Requires-Dist: dycw-utilities<0.167,>=0.166.5
8
8
  Requires-Dist: gitpython<3.2,>=3.1.45
9
9
  Requires-Dist: libcst<1.9,>=1.8.2
10
10
  Requires-Dist: loguru<0.8,>=0.7.3
11
+ Requires-Dist: orjson<3.12,>=3.11.3
11
12
  Requires-Dist: packaging<25.1,>=25.0
12
13
  Requires-Dist: tomlkit<0.14,>=0.13.2
14
+ Requires-Dist: xdg-base-dirs<6.1,>=6.0.2
13
15
  Description-Content-Type: text/markdown
14
16
 
15
17
  # pre-commit-hooks
@@ -22,13 +22,15 @@ dependencies = [
22
22
  "gitpython >=3.1.45, <3.2",
23
23
  "libcst >=1.8.2, <1.9",
24
24
  "loguru >=0.7.3, <0.8",
25
+ "orjson >=3.11.3, <3.12",
25
26
  "packaging >=25.0, <25.1",
26
27
  "tomlkit >=0.13.2, <0.14",
28
+ "xdg-base-dirs >=6.0.2, <6.1",
27
29
  ]
28
30
  name = "dycw-pre-commit-hooks"
29
31
  readme = "README.md"
30
32
  requires-python = ">= 3.12"
31
- version = "0.12.0"
33
+ version = "0.12.2"
32
34
 
33
35
  [project.scripts]
34
36
  format-requirements = "pre_commit_hooks.format_requirements:main"
@@ -39,7 +41,7 @@ tag-commits = "pre_commit_hooks.tag_commits:main"
39
41
  # bump-my-version
40
42
  [tool.bumpversion]
41
43
  allow_dirty = true
42
- current_version = "0.12.0"
44
+ current_version = "0.12.2"
43
45
 
44
46
  [[tool.bumpversion.files]]
45
47
  filename = "src/pre_commit_hooks/__init__.py"
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.12.0"
3
+ __version__ = "0.12.2"
@@ -12,51 +12,41 @@ from utilities.version import Version, parse_version
12
12
  PYPROJECT_TOML = get_repo_root().joinpath("pyproject.toml")
13
13
 
14
14
 
15
- def get_version(
16
- path_or_text: Path | str | bytes | TOMLDocument, /, *, desc: str = ""
17
- ) -> Version:
18
- """Parse the version from a block of text."""
19
- match path_or_text:
15
+ def get_version(source: Path | str | bytes | TOMLDocument, /) -> Version:
16
+ """Get the `[tool.bumpversion]` version from a TOML file."""
17
+ match source:
20
18
  case Path() as path:
21
- return get_version(
22
- path.read_text(), desc=f" from {str(path)!r}" if desc == "" else desc
23
- )
19
+ return get_version(path.read_text())
24
20
  case str() | bytes() as text:
25
- return get_version(parse(text), desc=desc)
21
+ return get_version(parse(text))
26
22
  case TOMLDocument() as doc:
27
23
  try:
28
24
  tool = doc["tool"]
29
25
  except KeyError:
30
- logger.exception(
31
- f"Failed to get version{desc}; key 'tool' does not exist"
32
- )
26
+ logger.exception("Failed to get version; key 'tool' does not exist")
33
27
  raise
34
28
  if not isinstance(tool, Table):
35
- logger.exception(f"Failed to get version{desc}; `tool` is not a Table")
29
+ logger.exception("Failed to get version; `tool` is not a Table")
36
30
  raise TypeError
37
31
  try:
38
32
  bumpversion = tool["bumpversion"]
39
33
  except KeyError:
40
34
  logger.exception(
41
- f"Failed to get version{desc}; key 'bumpversion' does not exist"
35
+ "Failed to get version; key 'bumpversion' does not exist"
42
36
  )
43
37
  raise
44
38
  if not isinstance(bumpversion, Table):
45
- logger.exception(
46
- f"Failed to get version{desc}; `bumpversion` is not a Table"
47
- )
39
+ logger.exception("Failed to get version; `bumpversion` is not a Table")
48
40
  raise TypeError
49
41
  try:
50
42
  version = bumpversion["current_version"]
51
43
  except KeyError:
52
44
  logger.exception(
53
- f"Failed to get version{desc}; key 'current_version' does not exist"
45
+ "Failed to get version; key 'current_version' does not exist"
54
46
  )
55
47
  raise
56
48
  if not isinstance(version, str):
57
- logger.exception(
58
- f"Failed to get version{desc}; `version` is not a string"
59
- )
49
+ logger.exception("Failed to get version; `version` is not a string")
60
50
  raise TypeError
61
51
  return parse_version(version)
62
52
  case never: # pyright: ignore[reportUnnecessaryComparison]
@@ -2,21 +2,32 @@ from __future__ import annotations
2
2
 
3
3
  from pathlib import Path
4
4
  from subprocess import PIPE, STDOUT, CalledProcessError, check_call, check_output
5
+ from typing import Literal, assert_never
5
6
 
6
- from click import command
7
+ from click import Choice, command, option
7
8
  from loguru import logger
9
+ from utilities.pathlib import get_repo_root
8
10
 
9
11
  from pre_commit_hooks.common import PYPROJECT_TOML, get_version
10
12
 
13
+ type _Mode = Literal["pyproject", "bumpversion"]
14
+ _MODE: _Mode = "pyproject"
15
+
11
16
 
12
17
  @command()
13
- def main() -> bool:
18
+ @option(
19
+ "--mode",
20
+ type=Choice(["pyproject", "bumpversion"], case_sensitive=False),
21
+ default=_MODE,
22
+ show_default=True,
23
+ )
24
+ def main(*, mode: _Mode = _MODE) -> bool:
14
25
  """CLI for the `run_bump_my_version` hook."""
15
- return _process()
26
+ return _process(mode=mode)
16
27
 
17
28
 
18
- def _process() -> bool:
19
- path = PYPROJECT_TOML.relative_to(Path.cwd())
29
+ def _process(*, mode: _Mode = _MODE) -> bool:
30
+ path = _get_rel_path(mode=mode)
20
31
  current = get_version(path)
21
32
  commit = check_output(["git", "rev-parse", "origin/master"], text=True).rstrip("\n")
22
33
  contents = check_output(["git", "show", f"{commit}:{path}"], text=True)
@@ -44,4 +55,15 @@ def _process() -> bool:
44
55
  return False
45
56
 
46
57
 
58
+ def _get_rel_path(*, mode: _Mode = _MODE) -> Path:
59
+ match mode:
60
+ case "pyproject":
61
+ path = PYPROJECT_TOML
62
+ case "bumpversion":
63
+ path = get_repo_root().joinpath(".bumpversion.toml")
64
+ case never: # pyright: ignore[reportUnnecessaryComparison]
65
+ assert_never(never)
66
+ return path.relative_to(Path.cwd())
67
+
68
+
47
69
  __all__ = ["main"]
@@ -0,0 +1,127 @@
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.hashlib import md5_hash
10
+ from utilities.pathlib import get_repo_root
11
+ from utilities.tzlocal import LOCAL_TIME_ZONE_NAME
12
+ from utilities.whenever import from_timestamp, get_now_local
13
+ from whenever import DateTimeDelta, ZonedDateTime
14
+ from xdg_base_dirs import xdg_cache_home
15
+
16
+ from pre_commit_hooks.common import get_version
17
+
18
+ if TYPE_CHECKING:
19
+ from collections.abc import Set as AbstractSet
20
+
21
+ _RUN_EVERY: DateTimeDelta | None = None
22
+ _MAX_AGE: DateTimeDelta | None = None
23
+
24
+
25
+ @command()
26
+ @option(
27
+ "--run-every",
28
+ type=utilities.click.DateTimeDelta(),
29
+ default=_RUN_EVERY,
30
+ show_default=True,
31
+ )
32
+ @option(
33
+ "--max-age",
34
+ type=utilities.click.DateTimeDelta(),
35
+ default=_MAX_AGE,
36
+ show_default=True,
37
+ )
38
+ def main(
39
+ *,
40
+ run_every: DateTimeDelta | None = _RUN_EVERY,
41
+ max_age: DateTimeDelta | None = _MAX_AGE,
42
+ ) -> bool:
43
+ """CLI for the `tag_commits` hook."""
44
+ return _process(run_every=run_every, max_age=max_age)
45
+
46
+
47
+ def _process(
48
+ *,
49
+ run_every: DateTimeDelta | None = _RUN_EVERY,
50
+ max_age: DateTimeDelta | None = _MAX_AGE,
51
+ ) -> bool:
52
+ if run_every is not None:
53
+ last = _get_last_run()
54
+ min_date_time = get_now_local() - run_every
55
+ if (last is not None) and (min_date_time <= last):
56
+ return True
57
+ return _process_commits(max_age=max_age)
58
+
59
+
60
+ def _get_last_run() -> ZonedDateTime | None:
61
+ hash_ = md5_hash(get_repo_root())
62
+ path = xdg_cache_home().joinpath("tag-commits", hash_)
63
+ try:
64
+ text = path.read_text()
65
+ except FileNotFoundError:
66
+ return None
67
+ try:
68
+ return ZonedDateTime.parse_common_iso(text.strip("\n"))
69
+ except ValueError:
70
+ return None
71
+
72
+
73
+ def _process_commits(*, max_age: DateTimeDelta | None = None) -> bool:
74
+ repo = Repo(".", search_parent_directories=True)
75
+ tagged = {tag.commit.hexsha for tag in repo.tags}
76
+ min_date_time = None if max_age is None else (get_now_local() - max_age)
77
+ commits = reversed(list(repo.iter_commits(repo.refs["origin/master"])))
78
+ results = [
79
+ _process_commit(c, tagged, repo, min_date_time=min_date_time) for c in commits
80
+ ] # run all
81
+ return all(results)
82
+
83
+
84
+ def _process_commit(
85
+ commit: Commit,
86
+ tagged: AbstractSet[str],
87
+ repo: Repo,
88
+ /,
89
+ *,
90
+ min_date_time: ZonedDateTime | None = None,
91
+ ) -> bool:
92
+ if (commit.hexsha in tagged) or (
93
+ (min_date_time is not None) and (_get_date_time(commit) < min_date_time)
94
+ ):
95
+ return True
96
+ try:
97
+ _tag_commit(commit, repo)
98
+ except GitCommandError:
99
+ return False
100
+ return True
101
+
102
+
103
+ def _get_date_time(commit: Commit, /) -> ZonedDateTime:
104
+ return from_timestamp(commit.committed_date, time_zone=LOCAL_TIME_ZONE_NAME)
105
+
106
+
107
+ def _tag_commit(commit: Commit, repo: Repo, /) -> None:
108
+ sha = commit.hexsha[:7]
109
+ date = _get_date_time(commit)
110
+ try:
111
+ joined = commit.tree.join("pyproject.toml")
112
+ except KeyError:
113
+ logger.exception(f"`pyproject.toml` not found; failed to tag {sha!r} ({date})")
114
+ return
115
+ text = joined.data_stream.read()
116
+ version = get_version(text)
117
+ try:
118
+ tag = repo.create_tag(str(version), ref=sha)
119
+ except GitCommandError as error:
120
+ desc = error.stderr.strip("\n").strip()
121
+ logger.exception(f"Failed to tag {sha!r} ({date}) due to {desc}")
122
+ return
123
+ logger.info(f"Tagging {sha!r} ({date}) as {str(version)!r}...")
124
+ _ = repo.remotes.origin.push(f"refs/tags/{tag.name}")
125
+
126
+
127
+ __all__ = ["main"]
@@ -1,70 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING
4
-
5
- from click import command
6
- from git import Commit, GitCommandError, Repo
7
- from loguru import logger
8
- from utilities.tzlocal import LOCAL_TIME_ZONE_NAME
9
- from utilities.whenever import WEEK, from_timestamp, get_now_local
10
-
11
- from pre_commit_hooks.common import get_version
12
-
13
- if TYPE_CHECKING:
14
- from collections.abc import Set as AbstractSet
15
-
16
- from whenever import ZonedDateTime
17
-
18
-
19
- @command()
20
- def main() -> bool:
21
- """CLI for the `tag_commits` hook."""
22
- return _process()
23
-
24
-
25
- def _process() -> bool:
26
- repo = Repo(".", search_parent_directories=True)
27
- tagged = {tag.commit.hexsha for tag in repo.tags}
28
- min_dt = get_now_local() - WEEK
29
- commits = reversed(list(repo.iter_commits(repo.refs["origin/master"])))
30
- results = [_process_commit(c, tagged, min_dt, repo) for c in commits] # run all
31
- return all(results)
32
-
33
-
34
- def _process_commit(
35
- commit: Commit, tagged: AbstractSet[str], min_date: ZonedDateTime, repo: Repo, /
36
- ) -> bool:
37
- if (commit.hexsha in tagged) or (_get_date_time(commit) < min_date):
38
- return True
39
- try:
40
- _tag_commit(commit, repo)
41
- except GitCommandError:
42
- return False
43
- return True
44
-
45
-
46
- def _get_date_time(commit: Commit, /) -> ZonedDateTime:
47
- return from_timestamp(commit.committed_date, time_zone=LOCAL_TIME_ZONE_NAME)
48
-
49
-
50
- def _tag_commit(commit: Commit, repo: Repo, /) -> None:
51
- sha = commit.hexsha[:7]
52
- date = _get_date_time(commit)
53
- try:
54
- joined = commit.tree.join("pyproject.toml")
55
- except KeyError:
56
- logger.exception(f"`pyproject.toml` not found; failed to tag {sha!r} ({date})")
57
- return
58
- text = joined.data_stream.read()
59
- version = get_version(text, desc=f"'pyproject.toml' @ {sha}")
60
- try:
61
- tag = repo.create_tag(str(version), ref=sha)
62
- except GitCommandError as error:
63
- desc = error.stderr.strip("\n").strip()
64
- logger.exception(f"Failed to tag {sha!r} ({date}) due to {desc}")
65
- return
66
- logger.info(f"Tagging {sha!r} ({date}) as {str(version)!r}...")
67
- _ = repo.remotes.origin.push(f"refs/tags/{tag.name}")
68
-
69
-
70
- __all__ = ["main"]