Skip to content

Commit 17787e4

Browse files
committed
Restore mypy usage
1 parent de8de84 commit 17787e4

9 files changed

Lines changed: 35 additions & 14 deletions

File tree

.github/copilot-instructions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Welcome to the Cachier codebase! Please follow these guidelines to ensure code s
2626

2727
## 4. Coverage, Linting, and Typing
2828

29-
- Code must pass `ruff` and `pytest`.
29+
- Code must pass `mypy`, `ruff`, and `pytest`.
3030
- Use per-file or per-line ignores for known, justified issues (e.g., SQLAlchemy model base class typing, intentional use of `pickle`).
3131
- All new code must include full type annotations and docstrings matching the style of the existing codebase.
3232
- All docstrings should follow numpy docstring conventions.

.pre-commit-config.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ repos:
6565
name: Ruff check
6666
args: ["--fix"]
6767

68+
# it needs to be after formatting hooks because the lines might be changed
69+
- repo: https://github.com/pre-commit/mirrors-mypy
70+
rev: v1.16.1
71+
hooks:
72+
- id: mypy
73+
files: "src/*"
74+
6875

6976
- repo: https://github.com/tox-dev/pyproject-fmt
7077
rev: v2.6.0

AGENTS.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
- **Key Dependencies:** `portalocker`, `watchdog` (optional: `pymongo`, `sqlalchemy`, `redis`)
1010
- **Test Framework:** `pytest` with backend-specific markers
1111
- **Linting:** `ruff` (replaces black/flake8)
12+
- **Type Checking:** `mypy`
1213
- **CI:** GitHub Actions (matrix for backends/OS with Dockerized services)
1314
- **Issue Tracking:** GitHub Issues
1415
- **Additional Docs:** `.github/copilot-instructions.md` for contributor guidelines
@@ -64,10 +65,11 @@ ______________________________________________________________________
6465
pytest -m "not (mongo or sql)" # Exclude external service backends
6566
```
6667

67-
3. **Lint:**
68+
3. **Lint and type-check:**
6869

6970
```bash
7071
ruff check .
72+
mypy src/cachier/
7173
```
7274

7375
4. **Try an example:**
@@ -100,6 +102,7 @@ ______________________________________________________________________
100102
- **Type annotations** required for all new code.
101103
- **Docstrings:** Use numpy style, multi-line, no single-line docstrings.
102104
- **Lint:** Run `ruff` before PRs. Use per-line/file ignores only for justified cases.
105+
- **Type check:** Run `mypy` before PRs.
103106
- **Testing:** All public methods must have at least one test. Use `pytest.mark.<backend>` for backend-specific tests.
104107
- **No warnings/errors for missing optional dependencies at import time.** Only raise when backend is used.
105108

@@ -501,6 +504,7 @@ ______________________________________________________________________
501504
- **If adding new dependencies, use context7 MCP to get latest versions.**
502505
- **Always check GitHub Issues before starting new features/PRs.**
503506
- **Create a relevant issue for every new PR.**
507+
- **Use per-file or per-line ignores for mypy/ruff only when justified.**
504508
- **All new code must have full type annotations and numpy-style docstrings.**
505509

506510
______________________________________________________________________
@@ -552,6 +556,7 @@ ______________________________________________________________________
552556
| Test multiple backends | `pytest -m "redis or sql"` |
553557
| Exclude backends | `pytest -m "not mongo"` |
554558
| Lint | `ruff check .` |
559+
| Type check | `mypy src/cachier/` |
555560
| Format code | `ruff format .` |
556561
| Build package | `python -m build` |
557562
| Check docs | `python setup.py checkdocs` |

CLAUDE.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
- **Key Dependencies:** `portalocker`, `watchdog` (optional: `pymongo`, `sqlalchemy`, `redis`)
1010
- **Test Framework:** `pytest` with backend-specific markers
1111
- **Linting:** `ruff` (replaces black/flake8)
12+
- **Type Checking:** `mypy`
1213
- **CI:** GitHub Actions (matrix for backends/OS with Dockerized services)
1314
- **Issue Tracking:** GitHub Issues
1415
- **Additional Docs:** `.github/copilot-instructions.md` for contributor guidelines
@@ -68,6 +69,7 @@ ______________________________________________________________________
6869

6970
```bash
7071
ruff check .
72+
mypy src/cachier/
7173
```
7274

7375
4. **Try an example:**
@@ -100,6 +102,7 @@ ______________________________________________________________________
100102
- **Type annotations** required for all new code.
101103
- **Docstrings:** Use numpy style, multi-line, no single-line docstrings.
102104
- **Lint:** Run `ruff` before PRs. Use per-line/file ignores only for justified cases.
105+
- **Type check:** Run `mypy` before PRs.
103106
- **Testing:** All public methods must have at least one test. Use `pytest.mark.<backend>` for backend-specific tests.
104107
- **No warnings/errors for missing optional dependencies at import time.** Only raise when backend is used.
105108

@@ -501,6 +504,7 @@ ______________________________________________________________________
501504
- **If adding new dependencies, use context7 MCP to get latest versions.**
502505
- **Always check GitHub Issues before starting new features/PRs.**
503506
- **Create a relevant issue for every new PR.**
507+
- **Use per-file or per-line ignores for mypy/ruff only when justified.**
504508
- **All new code must have full type annotations and numpy-style docstrings.**
505509

506510
______________________________________________________________________
@@ -552,6 +556,7 @@ ______________________________________________________________________
552556
| Test multiple backends | `pytest -m "redis or sql"` |
553557
| Exclude backends | `pytest -m "not mongo"` |
554558
| Lint | `ruff check .` |
559+
| Type check | `mypy src/cachier/` |
555560
| Format code | `ruff format .` |
556561
| Build package | `python -m build` |
557562
| Check docs | `python setup.py checkdocs` |

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
test-mongo-local test-mongo-docker test-mongo-inmemory test-mongo-also-local \
66
test-redis-local test-sql-local \
77
services-start services-stop services-logs \
8-
mongo-start mongo-stop mongo-logs lint format clean \
8+
mongo-start mongo-stop mongo-logs lint type-check format clean \
99
install install-dev install-all
1010

1111
# Default target
@@ -30,6 +30,7 @@ help:
3030
@echo ""
3131
@echo "Code Quality:"
3232
@echo " make lint - Run ruff linter"
33+
@echo " make type-check - Run mypy type checker"
3334
@echo " make format - Format code with ruff"
3435
@echo ""
3536
@echo "Installation:"
@@ -130,6 +131,8 @@ mongo-logs:
130131
lint:
131132
ruff check .
132133

134+
type-check:
135+
mypy src/cachier/
133136

134137
format:
135138
ruff format .
@@ -142,6 +145,7 @@ clean:
142145
rm -rf .coverage
143146
rm -rf htmlcov/
144147
rm -rf .pytest_cache/
148+
rm -rf .mypy_cache/
145149
rm -rf .ruff_cache/
146150
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
147151
find . -type f -name "*.pyc" -delete

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,5 +198,5 @@ show_missing = true
198198
exclude_lines = [
199199
"pragma: no cover", # Have to re-enable the standard pragma
200200
"raise NotImplementedError", # Don't complain if tests don't hit defensive assertion code:
201-
"if TYPE_CHECKING:",
201+
"if TYPE_CHECKING:", # Is only true when running mypy, not tests
202202
]

src/cachier/cores/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from datetime import timedelta
1515
from typing import Any, Callable, Optional, Tuple
1616

17-
from pympler import asizeof
17+
from pympler import asizeof # type: ignore
1818

1919
from .._types import HashFunc
2020
from ..config import CacheEntry, _update_with_defaults

src/cachier/cores/pickle.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import time
1313
from contextlib import suppress
1414
from datetime import datetime, timedelta
15-
from typing import Any, Dict, Optional, Tuple, Union
15+
from typing import Any, Dict, Optional, Tuple, Union, IO, cast
1616

1717
import portalocker # to lock on pickle cache IO
1818
from watchdog.events import PatternMatchingEventHandler
@@ -120,7 +120,7 @@ def _convert_legacy_cache_entry(
120120
def _load_cache_dict(self) -> Dict[str, CacheEntry]:
121121
try:
122122
with portalocker.Lock(self.cache_fpath, mode="rb") as cf:
123-
cache = pickle.load(cf)
123+
cache = pickle.load(cast(IO[bytes], cf))
124124
self._cache_used_fpath = str(self.cache_fpath)
125125
except (FileNotFoundError, EOFError):
126126
cache = {}
@@ -147,7 +147,7 @@ def _load_cache_by_key(
147147
fpath += f"_{hash_str or key}"
148148
try:
149149
with portalocker.Lock(fpath, mode="rb") as cache_file:
150-
entry = pickle.load(cache_file)
150+
entry = pickle.load(cast(IO[bytes], cache_file))
151151
return _PickleCore._convert_legacy_cache_entry(entry)
152152
except (FileNotFoundError, EOFError):
153153
return None
@@ -186,7 +186,7 @@ def _save_cache(
186186
fpath += f"_{hash_str}"
187187
with self.lock:
188188
with portalocker.Lock(fpath, mode="wb") as cf:
189-
pickle.dump(cache, cf, protocol=4)
189+
pickle.dump(cache, cast(IO[bytes], cf), protocol=4)
190190
# the same as check for separate_file, but changed for typing
191191
if isinstance(cache, dict):
192192
self._cache_dict = cache

src/cachier/cores/sql.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import pickle
44
import threading
55
from datetime import datetime, timedelta
6-
from typing import Any, Callable, Optional, Tuple, Union
6+
from typing import Any, Callable, Optional, Tuple, Union, cast
77

88
try:
99
from sqlalchemy import (
@@ -112,10 +112,10 @@ def get_entry_by_key(self, key: str) -> Tuple[str, Optional[CacheEntry]]:
112112
value = pickle.loads(row.value) if row.value is not None else None
113113
entry = CacheEntry(
114114
value=value,
115-
time=row.timestamp,
116-
stale=row.stale,
117-
_processing=row.processing,
118-
_completed=row.completed,
115+
time=cast(datetime, row.timestamp),
116+
stale=cast(bool, row.stale),
117+
_processing=cast(bool, row.processing),
118+
_completed=cast(bool, row.completed),
119119
)
120120
return key, entry
121121

0 commit comments

Comments
 (0)