fix: type CachedResponse.__init__ for mypy --strict (#628)#643
Open
jbbqqf wants to merge 2 commits into
Open
Conversation
…s-eco#628) Without ``-> None`` and parameter annotations, calling ``CachedResponse(response, timeout)`` in a mypy --strict codebase raises ``[no-untyped-call]``. Annotate the constructor and document the in-place ``__dict__`` swap that adopts an existing Response.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
CachedResponse.__init__is currently un-annotated, so mypy--strictcodebases that import and call
CachedResponse(...)get a[no-untyped-call]error even though the class is part of the publicAPI. Annotate the constructor (
response: Response,timeout: int | None,-> None) and document the in-place__dict__swap so the intent is clear to reviewers.
Fixes #628.
Context
CachedResponseis exported fromflask_cachingand is intended to beconstructed by user view code (e.g.
return CachedResponse(make_response(...), timeout=2),as in
tests/test_view.py::test_cache_timeout_dynamic). Withoutannotations, mypy refuses to consider it a typed callable. The class
already inherits typing from
flask.Response, andtimeoutis alreadydeclared as a class attribute, so this change just exposes those types
on the constructor signature.
Changes
src/flask_caching/__init__.py: add parameter and return annotationson
CachedResponse.__init__, type thetimeoutclass attribute asint | None, and leave a short comment explaining the in-place__dict__adoption.tests/test_init.py: newtest_cached_response_init_is_typedregression test that introspects
inspect.signatureto assert theconstructor declares
-> Noneand all non-selfparameters carry anannotation; plus
test_cached_response_construction_with_flask_responsewhich exercises construction end-to-end.
CHANGES.rst: add Unreleased entry.Reproduce BEFORE/AFTER yourself (copy-paste)
What I ran locally
The skipped test is the redis-server-dependent
test_cache_unlink.Edge cases
CachedResponse(make_response("hi"), 10).timeout == 10,.get_data(as_text=True) == "hi"test_cached_response_construction_with_flask_responsetimeout=NonepassedCachedResponse(resp, None)int | NoneannotationNoneinspect.signatureintrospectioninspect.signature(CachedResponse.__init__)None, params have annotationstest_cached_response_init_is_typed@cachedflowCachedResponsetest_cache_timeout_dynamic(unchanged)Risk / blast radius
Annotation-only change to the public class constructor signature. No
runtime behavior changes:
__init__still copies__dict__from thewrapped
Responseand assignstimeout. The class attribute typenarrows from implicit
Nonetoint | None, which matches existingusage at
tests/test_view.py::test_cache_timeout_dynamicand theisinstance(rv, CachedResponse); rv.timeoutaccess path atsrc/flask_caching/__init__.py:432.PR drafted with assistance from Claude Code (Anthropic). The change
was reviewed manually against pallets-eco/flask-caching's source. The
reproducer block above is the one I used during development; reviewers
can paste it verbatim.