Pyrefly v1.2 is here!

Pyrefly v1.2 is now available 🎉 This release adds support for Bazel and attrs, along with improvements to type checking, the language server, and the CLI.
This release includes 901 commits from 59 contributors. To get started, run:
pip install --upgrade pyrefly==1.2.0
attrs Support
Pyrefly now type-checks attrs classes with no plugin or configuration required. It recognizes the modern API (@define, @frozen, @mutable, attrs.field) and the classic API (@attr.s, @attr.ib, @attr.dataclass) in the attr. and attrs. namespaces. Pyrefly synthesizes __init__ signatures, including converter input types, and catches misconfigurations that cause errors when the class is created.
from attrs import define, field
def to_bpm(s: str) -> int:
return int(s.removesuffix(" bpm"))
@define
class Chart:
title: str
tempo: int = field(converter=to_bpm)
Chart("Blue Bossa", "120 bpm") # OK: converter accepts str
Chart("Blue Bossa", 120) # Error: expected str, got int
See the attrs documentation and dedicated blog post for details.
Bazel Support
Before v1.2, teams using Pyrefly with Bazel had to write custom build logic to collect sources, dependencies, import paths, and generated files for each target. Pyrefly v1.2 provides a standard integration through the new pyrefly bazel-check command and rules_pyrefly.
rules_pyrefly uses an aspect to apply Pyrefly across existing py_library, py_binary, and py_test targets. It follows the Bazel target graph, reading the Python version from the rules_python toolchain and the platform from Bazel platform constraints. Projects do not need wrapper rules or Pyrefly declarations in each BUILD file.
Once configured, run Pyrefly for any target or target pattern:
bazel build --config=pyrefly //path/to/package:target
rules_pyrefly 0.1.0 is available via the Bazel Central Registry. The integration is still at an early stage. Some import layouts are not yet supported, and the rules_pyrefly and bazel-check interfaces may change as we expand coverage. If you build Python with Bazel, please try the integration and let us know how it works for you. Bug reports and PRs are always welcome!
Type Coverage
pyrefly coverage is now stable and ready for production use. It provides two subcommands:
pyrefly coverage reportwrites a JSON report with project, module, and per-symbol coverage data, including the locations of missing annotations.pyrefly coverage checkreports incomplete coverage and can enforce a minimum coverage threshold in CI.
Projects including NumPy, Narwhals, sh, and scipy-stubs already use Pyrefly to track their type coverage.
Our collaborator Joren Hammudoglu (@jorenham) has led the development of the coverage feature. We will publish a dedicated post about this topic soon.
Tensor Shape Checking
Tensor shape checking remains early alpha. This release adds a NumPy stubs package that covers array construction, broadcasting, ufuncs, reductions, and parts of linalg and random. Arithmetic and broadcasting have moved from the type checker's Rust internals into the editable shape DSL. The shape primitives are now named Int, IntVar, and IntTuple. Dim has been removed.
The API will continue to change as this work develops. The tensor shapes documentation tracks the current API.
Other Type Checking Improvements
Other type-checking improvements in v1.2 include:
functools.partialsupport: bound arguments are validated at thepartial(...)call, and Pyrefly synthesizes a signature for the remaining parameters. This catches errors when the partial is created and when it is called.functools.singledispatchsupport: calls are checked against the signature of the function you decorated, and each registered implementation is checked against that function's first parameter.- Pattern matching: narrowing and exhaustiveness checks are more precise for class and sequence patterns.
- Pydantic and Django support: Pydantic constructor synthesis honors
populate_by_nameand built-inalias_generatorfunctions. DjangoForeignKeystring references such as"app_label.Model"now resolve with the correct relation and<field>_idtypes. TypedDictmethods and attributes: classes synthesize__required_keys__and__optional_keys__, allowing them to satisfy protocols that require these attributes, including protocols used by LangGraph. Calls to.get()and.pop()with literal defaults also preserve the field type.- Enum
.valuetypes:.valueon an enum type is inferred as the union of its member literal values, preserving the type of each value.
The Pyrefly documentation and release notes cover the full set of changes.
Language Server / IDE Improvements
Language server improvements in v1.2 cover hover information, imports, rename, and editor compatibility:
- Baseline diagnostics: baselined errors now use hint severity, which helps distinguish new problems from known technical debt. Baselining also applies to unused-ignore diagnostics.
- Hover information: keyword arguments resolve, callable protocols render as their
__call__signature, overload docstrings remain available at call sites, and enum fields are shown. Nested callable andConcatenate[...]signatures also wrap for readability. - Alias-aware auto-imports: completions preserve existing import aliases and reuse modules already in scope, avoiding duplicate imports. Deprecated typing aliases are ranked below modern equivalents.
- More reliable rename: rename now works on aliased imports, and keyword argument renames update references across files. Protocol class names and their references can also be renamed correctly.
- Editor compatibility: document symbols fall back to flat
SymbolInformationfor clients such as Helix, cross-file diagnostics refresh on save in clients such as Zed, andlspArgumentsdefaults to["lsp"], preventing startup failures in dev containers and remote environments. - Inlay hints: a server-side debounce of 150ms prevents width jitter while typing.
Other Usability Improvements
v1.2 also includes updates to the CLI, configuration, import resolution, and stub generation:
pyrefly infer --dry-runpreviews inferred annotations without touching your files and exits unsuccessfully if changes would be made, so CI can fail when a file is missing annotations Pyrefly could have inferred.- 16 new opt-in diagnostics, including
implicit-bool,invalid-cast,unused-call-result,empty-body,missing-super-call,implicit-reexport,no-any-return, and a family ofunknown-*-typechecks for finding sources ofAny. - Selective file-level suppressions:
# pyrefly: ignore-errors[code]suppresses a specific diagnostic throughout a file. - PEP 561 partial stub packages: Pyrefly reads the
partialmarker frompy.typedand merges the stubs with the runtime package, deferring to the runtime package for omitted modules. - Multiple target platforms:
python-platformaccepts multiple platforms or all platforms. Platform guards are folded only when every configured platform agrees. - Stub generation: explicit
TypeAliasright-hand sides and static__all__literals are preserved so re-exports remain in generated stubs. Implicit class variables are wrapped inClassVar[...], and multi-line parenthesized expressions keep their parentheses, preventing anIndentationErrorin the generated file.
Performance
Pyrefly gets faster with every release. In our benchmarks across eight projects from Astral's ty_benchmark suite, v1.2 was about 8% faster than v1.1. We also measured 2% to 4% lower memory use on tested repositories.
Bug Fixes
Between v1.1 and v1.2, we closed 137 bug issues. The fixes cover false positives, crashes, stack overflows, narrowing, and library support. You can browse the full list on GitHub.
What's Next & How to get Involved
Our priorities for v1.3 include reducing false positives, improving performance, and expanding library support. Follow development or get involved through these resources:
- GitHub milestones: see what's planned for upcoming releases
- Join our Discord: chat with the team and community
- Open an issue: suggest features and report bugs
Thank you to the 59 contributors who made v1.2 possible, and to everyone who filed an issue or joined a discussion. We look forward to building v1.3 together.