Skip to content

Commit b804583

Browse files
feat: add mypy strict type checking and Prompt.__repr__
1 parent 089c4c3 commit b804583

4 files changed

Lines changed: 29 additions & 12 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ jobs:
2323

2424
- run: pip install -e ".[dev]"
2525
- run: ruff check .
26+
- run: mypy graver/
2627
- run: pytest -q

graver/core.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from pathlib import Path
2+
from typing import Any
23

34
from graver.exceptions import PromptNotFoundError
45
from graver.storage import Storage
@@ -11,6 +12,9 @@ def __init__(self, name: str, base_dir: str = ".graver") -> None:
1112
self.name = name
1213
self._storage = Storage(base_dir=base_dir)
1314

15+
def __repr__(self) -> str:
16+
return f"Prompt({self.name!r}, base_dir={str(self._storage._base)!r})"
17+
1418
@staticmethod
1519
def list_all(base_dir: str = ".graver") -> list[str]:
1620
"""Return the names of all saved prompts in the given base directory."""
@@ -34,7 +38,7 @@ def get(self, version: str | None = None) -> str:
3438
"""Return the prompt text for the given version, or the latest if None."""
3539
return self._storage.get(self.name, version)
3640

37-
def log(self) -> list[dict]:
41+
def log(self) -> list[dict[str, Any]]:
3842
"""Return the full version history, oldest to newest, with is_main flag."""
3943
main = self._storage.get_main(self.name)
4044
history = self._storage.history(self.name)
@@ -63,7 +67,7 @@ def delete_version(self, version: str) -> None:
6367
"""Delete a specific version; clears the main pointer if it was main."""
6468
self._storage.delete_version(self.name, version)
6569

66-
def diff(self, v1: str, v2: str) -> dict:
70+
def diff(self, v1: str, v2: str) -> dict[str, list[str]]:
6771
"""Return raw line-by-line diff between two versions."""
6872
return self._storage.diff(self.name, v1, v2)
6973

@@ -73,10 +77,9 @@ def changes(self, v1: str | None = None, v2: str | None = None) -> str:
7377
if len(history) < 2:
7478
return "Need at least 2 versions to compare."
7579

76-
if v1 is None and v2 is None:
80+
if v1 is None:
7781
v1 = history[-2]["version"]
78-
v2 = history[-1]["version"]
79-
elif v2 is None:
82+
if v2 is None:
8083
v2 = history[-1]["version"]
8184

8285
result = self._storage.diff(self.name, v1, v2)

graver/storage.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import json
33
from datetime import datetime
44
from pathlib import Path
5+
from typing import Any
56

67
from graver.exceptions import (
78
PromptNotFoundError,
@@ -57,7 +58,7 @@ def save(self, name: str, content: str) -> str:
5758

5859
history_path = self._history_file(name)
5960
try:
60-
history: list[dict] = (
61+
history: list[dict[str, Any]] = (
6162
json.loads(history_path.read_text(encoding="utf-8"))
6263
if history_path.exists()
6364
else []
@@ -94,7 +95,7 @@ def get(self, name: str, version: str | None = None) -> str:
9495

9596
return target.read_text(encoding="utf-8")
9697

97-
def history(self, name: str) -> list[dict]:
98+
def history(self, name: str) -> list[dict[str, Any]]:
9899
prompt_dir = self._prompt_dir(name)
99100
if not prompt_dir.exists():
100101
raise PromptNotFoundError(
@@ -105,9 +106,12 @@ def history(self, name: str) -> list[dict]:
105106
if not history_path.exists():
106107
return []
107108

108-
return json.loads(history_path.read_text(encoding="utf-8"))
109+
result: list[dict[str, Any]] = json.loads(
110+
history_path.read_text(encoding="utf-8")
111+
)
112+
return result
109113

110-
def diff(self, name: str, v1: str, v2: str) -> dict:
114+
def diff(self, name: str, v1: str, v2: str) -> dict[str, list[str]]:
111115
lines1 = self.get(name, v1).splitlines(keepends=True)
112116
lines2 = self.get(name, v2).splitlines(keepends=True)
113117

@@ -151,7 +155,9 @@ def delete_version(self, name: str, version: str) -> None:
151155
history_path = self._history_file(name)
152156
if history_path.exists():
153157
try:
154-
history = json.loads(history_path.read_text(encoding="utf-8"))
158+
history: list[dict[str, Any]] = json.loads(
159+
history_path.read_text(encoding="utf-8")
160+
)
155161
history = [e for e in history if e["version"] != version]
156162
history_path.write_text(
157163
json.dumps(history, indent=2, ensure_ascii=False), encoding="utf-8"
@@ -182,5 +188,6 @@ def get_main(self, name: str) -> str | None:
182188
main_path = self._main_file(name)
183189
if not main_path.exists():
184190
return None
185-
data = json.loads(main_path.read_text(encoding="utf-8"))
186-
return data.get("version")
191+
data: dict[str, Any] = json.loads(main_path.read_text(encoding="utf-8"))
192+
version: str | None = data.get("version")
193+
return version

pyproject.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ dev = [
3535
"pytest>=7.0",
3636
"black>=23.0",
3737
"ruff>=0.1.0",
38+
"mypy>=1.10",
3839
]
3940

4041
[project.urls]
@@ -60,3 +61,8 @@ exclude = ["tests/"]
6061

6162
[tool.pytest.ini_options]
6263
testpaths = ["tests"]
64+
65+
[tool.mypy]
66+
python_version = "3.10"
67+
strict = true
68+
files = ["graver"]

0 commit comments

Comments
 (0)