Pyrefly v1.4.0-dev.2
Pre-releaseRelease date: September 28, 2026
About dev releases
Dev releases (versions likeX.Y.Z-dev.N) are non-stable snapshots cut periodically from trunk. They give early adopters a chance to try in-progress features and surface issues before the next stable release, but they don't carry the same stability or compatibility guarantees as a stable release — don't pin production projects to a dev version.
Pyrefly v1.4.0-dev.2 bundles 493 commits from 20 contributors.
⚠️ Notable change: X | None annotations with an unknown X
Pyrefly now decides whether | builds a type union from the type-form context of the expression, instead of from the types of its operands. Before this change, an annotation such as UnresolvedType | None (for example, when UnresolvedType comes from a missing import) was evaluated as plain Unknown, and the | None was silently dropped. Pyrefly now evaluates it as Unknown | None.
This is more correct, but it can surface new errors, such as missing-attribute on None, in code that uses unresolved types in Optional-style annotations. Please try this dev release and report any false positives. (#4846)
✨ New & Improved
Type Checking
- Pyrefly now respects the
stdlib/VERSIONSfile of a custom typeshed, and it notices when that file changes. - Build systems can now supply a default configuration.
- Unreachable-code reporting is more precise: Pyrefly reports dead code after a run of
withstatements, branches that are decided by the type of their test, andexceptclauses that can never match. - Pydantic
Stricttypes, such asStrictInt, now enable strict mode for the field. TypeVarTuplevariance is now checked.NewTypeover an abstract class no longer produces a false-positivebad-instantiationerror.
Language Server
- The status indicator refreshes when a
pyrefly.tomlfile is added or removed, and Pyrefly rewatches files when an explicitly configured config file changes. - The TSP
initializeresponse now includesserverInfo. - In a
matchvalue pattern, attribute completion now ranks enum members that earliercasearms already cover lower. - Baseline matching supports a new
column-orderedmode, and the language server matches baselines in batches.
Other
- Pyrefly now has an experimental programmatic API for Monty.
- When some warnings are hidden, the message now explains how to show them.
- Memory usage and commit latency in the incremental state are improved.
🐛 Bug fixes
- #4846: Fixed regressions from v1.3.0 in type inference after a variable is reassigned to
Any. See also the notable change above. - #4858, #4618:
Enum.valueno longer widens a literal value to its base type (for example, tostr). - #4400: Pydantic private attributes (
PrivateAttr) are no longer treated as frozen. - #4995: Django models now give
pkthe correct type when the primary key is aForeignKey(..., primary_key=True). - #4991:
pyrefly suppressnow writes# pyrefly: ignore[code]without a space before the bracket, which matches the documentation. - #4986: Hover now works on attribute assignments in
__init__. - #4813: Pyrefly no longer rejects a duck-typed
Mappingin a**dict unpacking. - #4650:
stubgenno longer keeps the full analysis of the whole import closure in memory. - #4592: A
__get__overload with a self type ofConcatenate[ObjT, P1]and a siblingTypeVarnow matches correctly.
Thank-you to all our contributors who found these bugs and reported them! Did you know this is one of the most helpful contributions you can make to an open-source project? If you find any bugs in Pyrefly we want to know about them! Please open a bug report issue here.
📦 Upgrade
pip install --upgrade pyrefly==1.4.0-dev.2How to safely upgrade your codebase
Upgrading the version of Pyrefly you're using or a third-party library you depend on can reveal new type errors in your code. Fixing them all at once is often unrealistic. We've written scripts to help you temporarily silence them. After upgrading, follow these steps:
pyrefly check --suppress-errors- Run your code formatter of choice
pyrefly check --remove-unused-ignores- Repeat until you achieve a clean formatting run and a clean type check.
This will add # pyrefly: ignore comments to your code, enabling you to silence errors and return to fix them later. This can make the process of upgrading a large codebase much more manageable.
Read more about error suppressions in the Pyrefly documentation.
🖊️ Contributors this release
@stroxler, @connernilsen, @rchen152, @kinto0, @asukaminato0721, @samwgoldman, @jakevdp, @yeetypete, @MarcoGorelli, @grievejia, Abby Mitchell, @Pager-dot, @arthaud, @digvijaysai29, David Tolnay, @yangdanny97, @Aniketsy, @QEDady, @alexander-beedie, Alan Kurusingal
🔬 Tensor Shape Support
JAX stub support is still under development and is not yet available on PyPI. The JAX improvements below describe ongoing work in the repository rather than an installable stub package in this release.
- Torch shape stubs cover much more of the public API, including more pointwise, reduction, indexing, FFT, pooling, convolution, and attention operations, and they report unknown top-level Torch APIs.
- A new
IntVar[N]runtime wrapper supports dimension arithmetic. Bare*tuple[...]and*IntTuplesplats are now accepted in shapes. - JAX and NumPy stubs have improved shape inference for
random,lax,pad,split,expand_dims, and other operations, and the top-leveljaxnamespace now has stubs.
Please note: These release notes summarize major updates and features. For brevity, not all individual commits are listed.