Type check with pyrefly, and fix what it found - #23
Open
tomchop wants to merge 1 commit into
Open
Conversation
The package had no type checking of its own, so problems in it surfaced only downstream. Pyrefly reported 26 errors; all are fixed rather than suppressed, because all were the same mistake. A dict literal fixes its value type from whichever key is set first, so a dict built up conditionally is inferred far more narrowly than it is used. The worst was request_kwargs: it starts by holding headers, is inferred as dict[str, dict[str, Any]], and is then splatted into requests' typed parameters -- which produced 18 of the 26 errors from three call sites. Annotating the seven such dicts as dict[str, Any], which is what they are, clears all of them. Nothing about the runtime changes; the 31 existing tests pass unchanged.
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.
Adds pyrefly, and fixes everything it found. Follow-up to #22.
What it found
26 errors, all the same mistake: a dict literal fixes its value type from whichever key is set first, so a dict built up conditionally is inferred far more narrowly than it is used.
The worst was
request_kwargs. It starts out holdingheaders, so it is inferred asdict[str, dict[str, Any]], and is then splatted into requests' typed parameters:That one produced 18 of the 26 errors from three call sites — one per request method per typed parameter.
Six other dicts had the same shape (
query,paramsbuilt up conditionally). Annotating all seven asdict[str, Any]— which is what they are — clears every error.Fixed rather than suppressed. No ignores, no ratchet: the annotations describe the code accurately, and the runtime is untouched.
pyrefly checkreports 0 errors and the 31 existing tests pass unchanged.Setup
pyreflyas a dev dependency, pinned to^1.2.0(the current release).[tool.pyrefly]inpyproject.toml, checkingyetiand excludingtests, which leans onunittest.mockand would report noise about the tests rather than the library.Type checkworkflow on pull requests, mirroring the existing unittest one.What this will and will not catch
Worth being explicit, because it is the reason #22 exists.
In CI, dependencies are installed, so
requestsresolves through its stubs andSession.verifyisbool | str. A consumer that vendors this package and checks it against requests' own source seesboolinstead — inferred fromself.verify = TrueinSession.__init__, since requests ships no annotations — and reports the CA-bundle assignment as an error.So this job would not have caught that one. It is fixed in #22 with a comment recording why, and I could not reproduce it here even with requests vendored, which suggests the downstream configuration differs further. If you can share that pyrefly config, matching it here would close the gap properly.