Add mypy annotations and mark it as checkable.#76
Conversation
Without a py.typed marker, mypy skips analyzing flask_compress with the error "module is installed, but missing library stubs or py.typed marker [import-untyped]". Adding the marker declares PEP 561 compliance so mypy will process the package's inline types. https://claude.ai/code/session_01PDkg6syU6fe15ngPYLPoyT
Annotates all functions and classes in flask_compress.py: - DictCache: typed dict storage with str keys and bytes values - Compress: Flask app parameter, cache, and config attribute types - _choose_algorithm, _format, _compress_data, _uncompress_data, _compress_chunks: full parameter and return type annotations Uses `from __future__ import annotations` for modern union syntax on Python 3.9+. https://claude.ai/code/session_01PDkg6syU6fe15ngPYLPoyT
- Silence brotli/brotlicffi import errors (no stubs available) - Add explicit type for algos_by_quality defaultdict (set[str | None]) - Assert cache_key is not None when cache is present - Pass weak=False directly in set_etag (is_weak is falsy in that branch) mypy now reports: "Success: no issues found in 4 source files" All 55 tests pass. https://claude.ai/code/session_01PDkg6syU6fe15ngPYLPoyT
for more information, see https://pre-commit.ci
|
The PR looks good, thanks! Would it be possible to enforce the type checking by either updating pre-commit or GitHub Actions? |
Configure mypy in strict mode via pre-commit (mirrors-mypy v1.19.1) with Flask as an additional dependency. Add [tool.mypy] config to pyproject.toml with warn_return_any disabled since third-party compression libraries lack type stubs. https://claude.ai/code/session_01PDkg6syU6fe15ngPYLPoyT
Keep mypy strict mode fully enabled. Suppress no-any-return only at the 8 specific call sites where untyped third-party compression libraries (brotli, zstd, gzip, zlib) return Any. https://claude.ai/code/session_01PDkg6syU6fe15ngPYLPoyT
| # This is used for tests purposes only. | ||
| if algorithm == "zstd": | ||
| return compression.zstd.decompress(data) | ||
| return compression.zstd.decompress(data) # type: ignore[no-any-return] |
There was a problem hiding this comment.
The type: ignore is needed because compression is a SimpleNamespace indirection instead of a pile of direct module references. Fortunately, if this ever changes, mypy will flag this ignore as unnecessary.
Along the way, added a CacheBackend Protocol to represent the common interface of flask_caching.Cache + DictCache for type-checking purposes.
Done. Thankfully I just needed to add some stuff to pre-commit (and a bunch of mostly repetitive updates to make the tests pass mypy). We could get rid of the I elected to just live with the boilerplate since I think it's more valuable for a library to have all the checks passing at their strictest, but I can do the above instead if you prefer. Also, sorry for the spammy commit history; I thought (and still think) such a mechanical cleanup would be a good task for LLMs, but I'm still learning how to use the tooling. |
|
Great, thanks! |
Currently, when I run mypy on my flask-compress-using project, I get the following sad message:
This PR does two things to fix that:
py.typedto tell mypy that, yes, it's typed and should not be skipped (nor requireimport-typedin mypy-using projects).The code changes in this PR were mostly generated by an AI, but under the close supervision of a human with substantial SWE experience. 🙂