We’ve just uploaded mypy 2.0.0 to the Python Package Index (PyPI).
Mypy is a static type checker for Python. This release includes new features, performance
improvements and bug fixes. There are also changes to options and defaults.
You can install it as follows:
python3 -m pip install -U mypy
You can read the full documentation for this release on Read the Docs.
Enable --local-partial-types by Default
This flag affects the inference of types based on assignments in other scopes.
For now, explicitly disabling this continues to be supported, but this support will be removed
in the future as the legacy behaviour is hard to support with other current and future features
in mypy, like the daemon or the new implementation of flexible redefinitions.
Contributed by Ivan Levkivskyi, Jukka Lehtosalo, Shantanu in PR 21163.
Enable --strict-bytes by Default
Per PEP 688, mypy no longer treats bytearray and memoryview
values as assignable to the bytes type.
The --allow-redefinition flag now behaves like --allow-redefinition-new in mypy 1.20
and earlier. The new behavior is generally more flexible. For example, you can have different
types for a variable in different blocks:
# mypy: allow-redefinition
def foo(cond: bool) -> None:
if cond:
for x in ["a", "b"]:
# Type of "x" is "str" here
...
else:
for x in [1, 2]:
# Type of "x" is "int" here
...
The new behavior requires --local-partial-types, which is now enabled by default.
However, --allow-redefinition doesn't allow giving two type annotations for the same
variable. The old behavior (sometimes) allows this. Code like this now generates an error
when using --allow-redefinition:
You can still use --allow-redefinition-old to fall back to the old behavior. We have no
plans to remove the legacy behavior, but the old functionality is maintained on a best effort
basis.
Mypy now supports experimental parallel and incremental type checking. Use --num-workers N
or -nN to use N worker processes to type check in parallel. The speedup depends on the
import structure of your codebase and your environment, but for large projects we've seen
performance gains of up to 5x when using 8 worker processes.
Parallel type checking implicitly enables the new native parser. There are still some
minor semantic differences between parallel and non-parallel modes, which we will be fixing
in future mypy releases.
Contributed by Ivan Levkivskyi, with additional contributions from Emma Smith and Jukka
Lehtosalo.
Recent related changes since the last release:
Freeze garbage collection in parallel workers for 4-5% speedup (Ivan Levkivskyi, PR 21302)
Expose --num-workers and --native-parser (Ivan Levkivskyi, PR 21387)
Split type checking into interface and implementation in parallel workers (Ivan Levkivskyi, PR 21119)
Batch module groups for parallel processing (Ivan Levkivskyi, PR 21287)
Parse files in parallel when possible (Ivan Levkivskyi, PR 21175)
Use parallel parsing at all stages (Ivan Levkivskyi, PR 21266)
Fix sequential bottleneck in parallel parsing (Jukka Lehtosalo, PR 21291)
Fail fast when a user tries to generate reports with parallel workers (Ivan Levkivskyi, PR 21341)
Partially support old NumPy plugin in parallel type checking (Ivan Levkivskyi, PR 21324)
Handle reachability consistently in parallel type checking (Ivan Levkivskyi, PR 21322)
Always respect @no_type_check in parallel type checking (Ivan Levkivskyi, PR 21320)
Minor fixes in parallel checking (Ivan Levkivskyi, PR 21319)
Fix plugin logic in parallel type checking (Ivan Levkivskyi, PR 21252)
Fix Windows IPC race condition when using parallel checking (Jukka Lehtosalo, PR 21228)
Report parallel worker exit status on receive failure (Jukka Lehtosalo, PR 21224)
Drop Support for Targeting Python 3.9
Mypy no longer supports type checking code with --python-version 3.9.
Use --python-version 3.10 or newer.
Contributed by Shantanu, Marc Mueller in PR 21243.
Remove Special Casing of Legacy Bundled Stubs
Mypy used to bundle stubs for a few packages in versions 0.812 and earlier. To navigate the
transition, mypy used to report missing types for these packages even if --ignore-missing-imports
was set. Mypy now consistently respects --ignore-missing-imports for all packages.
Prevent Assignment to None for Non-Optional Class Variables with Type Comments
Mypy used to allow assignment to None for class variables when using type comments. This was a
common idiom in Python 3.5 and earlier, prior to the introduction of variable annotations.
However, this was a soundness hole and has now been removed.
librt.strings: String and Bytes Primitives for Mypyc
In mypy 1.20, we introduced librt as a standard library
for mypyc that fills in some gaps in the Python standard library and the C API.
This release adds the new module librt.strings, which contains utilities for building
string and bytes objects, and for accessing and generating binary data:
StringWriter and BytesWriter classes allow quickly building str and bytes objects from parts.
read_* and write_* functions provide fast reading and writing of binary-encoded data.
We’ve just uploaded mypy 1.20.0 to the Python Package Index (PyPI).
Mypy is a static type checker for Python. This release includes new features, performance
improvements and bug fixes. You can install it as follows:
python3 -m pip install -U mypy
You can read the full documentation for this release on Read the Docs.
Planned Changes to Defaults and Flags in Mypy 2.0
As a reminder, we are planning to enable --local-partial-types by default in mypy 2.0, which
will likely be the next feature release. This will often require at least minor code changes. This
option is implicitly enabled by mypy daemon, so this makes the behavior of daemon and non-daemon
modes consistent.
Note that this release improves the compatibility of --local-partial-types significantly to
make the switch easier (see below for more).
This can also be configured in a mypy configuration file (use False to disable):
We will also enable --strict-bytes by default in mypy 2.0. This usually requires at most
minor code changes to adopt. For more information, refer to the
documentation.
Finally, --allow-redefinition-new will be renamed to --allow-redefinition. If you want
to continue using the older --allow-redefinition semantics which are less flexible (e.g.
limited support for conditional redefinitions), you can switch to --allow-redefinition-old,
which is currently supported as an alias to the legacy --allow-redefinition behavior.
To use --allow-redefinition in the upcoming mypy 2.0, you can't use --no-local-partial-types.
For more information, refer to the
documentation.
Better Type Narrowing
Mypy's implementation of narrowing has been substantially reworked. Mypy will now narrow more
aggressively, more consistently, and more correctly. In particular, you are likely to notice new
narrowing behavior in equality expressions (==), containment expressions (in),
match statements, and additional expressions providing type guards.
Note that mypy (and other Python type checkers) do not model the potential for various non-local
operations to invalidate narrowing assumptions. This means mypy may conclude that some of your code
is unreachable and
avoid further checking of it. The --warn-unreachable flag is useful for highlighting these cases.
To reset narrowing, you can insert dummy reassignments, for instance var = var will reset
all narrowing of var.attr.
Future work includes better narrowing on initial assignments, more narrowing to Literal types,
and better checking of unreachable code.
Contributed by Shantanu Jain.
Rework narrowing logic for equality and identity (Shantanu, PR 20492)
Refactor equality and identity narrowing for clarity (Shantanu, PR 20595)
Treat NotImplemented as a singleton type (Shantanu, PR 20601)
Improve narrowing logic for Enum int and str subclasses (Shantanu, PR 20609)
Narrow types based on collection containment (Shantanu, PR 20602)
Refactor and improve narrowing for type(x) == t checks (Shantanu, PR 20634)
Narrow for type expr comparisons to type exprs (Shantanu, PR 20639)
Narrowing for comparisons against x.__class__ (Shantanu, PR 20642)
Better narrowing with custom equality (Shantanu, PR 20643)
Use a single pass for core narrowing logic, add comments (Shantanu, PR 20659)
Narrowing for final type objects (Shantanu, PR 20661)
Better match narrowing for unions of type objects (Shantanu, PR 20905)
Improve reachability in narrowing logic (Shantanu, PR 20660)
Better match narrowing for irrefutable mapping patterns (Shantanu, PR 20906)
Fix match statement semantic reachability (Shantanu, PR 20968)
Add some additional narrowing test cases (Shantanu, PR 20598)
Move tests to check-narrowing , improve them slightly (Shantanu, PR 20637)
Add more tests for narrowing logic (Shantanu, PR 20672)
More testing related improvements and updates (Shantanu, PR 20709)
Add --warn-unreachable to more tests (Shantanu, PR 20977)
Drop Support for Python 3.9
Mypy no longer supports running with Python 3.9, which has reached end of life.
When running mypy with Python 3.10+, it is still possible to type check code
that needs to support Python 3.9 with the --python-version 3.9 argument.
Support for this will be dropped in the first half of 2026!
Mypyc Accelerated Mypy Wheels for ARM Windows and Free Threading
For best performance, mypy can be compiled to C extension modules using mypyc. This makes
mypy 3-5x faster than when interpreted with pure Python. We now build and upload mypyc
accelerated mypy wheels for win_arm64 and cp314t-... to PyPI, making it easy for Windows
users on ARM and those using the free theading builds for Python 3.14 to realise this speedup
-- just pip install the latest mypy.
Compatibility between mypy's default behavior and the --local-partial-types flag
is now improved. This improves compatibility between mypy daemon and non-daemon modes,
since the mypy daemon requires local partial types to be enabled.
In particular, code like this now behaves consistently independent of
whether local partial types are enabled or not:
x = None
def foo() -> None:
global x
x = 1
# The inferred type of 'x' is always 'int | None'.
Also, we are planning to turn local partial types on by default in mypy 2.0 (to be
released soon), and this makes the change much less disruptive. Explicitly disabling local
partial types will continue to be supported, but the support will likely be
deprecated and removed eventually, as the legacy behavior is hard to support together with
some important changes we are working on, in addition to being incompatible with the mypy
daemon.
This feature was contributed by Ivan Levkivskyi (PR 20938).
Python 3.14 T-String Support (PEP 750)
Mypy now supports t-strings that were introduced in Python 3.14.
Add support for Python 3.14 t-strings (PEP 750) (Neil Schemenauer and Brian Schubert, PR 20850)
Add implicit module dependency if using t-string (Jukka Lehtosalo, PR 20900)
Experimental New Parser
If you install mypy using pip install mypy[native-parser] and run mypy with
--native-parser, you can experiment with a new Python parser. It is based on
the Ruff parser, and it's more efficient than the default parser. It will also enable
access to all Python syntax independent of which Python version you use to run mypy.
The new parser is still not feature-complete and has known issues.
Related changes:
Add work-in-progress implementation of a new Python parser (Jukka Lehtosalo, PR 20856)
Skip redundant analysis pass when using the native parser (Ivan Levkivskyi, PR 21015)
Add t-string support to native parser (Ivan Levkivskyi, PR 21007)
Add ast-serialize as an optional dependency (Ivan Levkivskyi, PR 21028)
Use native-parser instead of native-parse for optional dependency (Jukka Lehtosalo, PR 21115)
Performance Improvements
Mypy now uses a binary cache format (fixed-format cache) by default to speed up incremental
checking. You can still use --no-fixed-format-cache to use the legacy JSON cache format,
but we will remove the JSON cache format in a future release. Mypy includes a tool to convert
individual fixed-format cache files (.ff) to the JSON format to make it possible to inspect
cache contents:
python -m mypy.exportjson <path> ...
If the SQLite cache is enabled, you will first need to convert the SQLite cache into
individual files using the misc/convert-cache.py
tool available in the mypy GitHub repository. You can also disable the SQLite
cache using --no-sqlite-cache.
The SQLite cache (--sqlite-cache) is now enabled by default. It improves mypy
performance significantly in certain environments where slow file system operations
used to be a bottleneck.
List of all performance improvements (for mypyc improvements there is a separate section below):
Flip fixed-format cache to on by default (Ivan Levkivskyi, PR 20758)
Enable --sqlite-cache by default (Shantanu, PR 21041)
Save work on emitting ignored diagnostics (Shantanu, PR 20621)
Skip logging and stats collection calls if they are no-ops (Jukka Lehtosalo, PR 20839)
Speed up large incremental builds by optimizing internal state construction (Jukka Lehtosalo, PR 20838)
Speed up suppressed dependencies options processing (Jukka Lehtosalo, PR 20806)
Avoid path operations that need syscalls (Jukka Lehtosalo, PR 20802)
Use faster algorithm for topological sort (Jukka Lehtosalo, PR 20790)
Replace old topological sort (Jukka Lehtosalo, PR 20805)
Fix quadratic performance in dependency graph loading for incremental builds (Jukka Lehtosalo, PR 20786)
Avoid unnecessary work when checking deferred functions (Ivan Levkivskyi, PR 20860)
Improve --allow-redefinition-new performance for code with loops (Ivan Levkivskyi, PR 20862)
Avoid setattr/getattr with fixed format cache (Ivan Levkivskyi, PR 20826)
Improvements to Allowing Redefinitions
Mypy now allows significantly more flexible variable redefinitions when using --allow-redefinition-new.
In particular, function parameters can now be redefined with a different type:
# mypy: allow-redefinition-new, local-partial-types
def process(items: list[str]) -> None:
# Reassign parameter to a completely different type.
# Without --allow-redefinition-new, this is a type error
# because list[list[str]] is not compatible with
# list[str].
items = [item.split() for item in items]
...
In mypy 2.0, we will update --allow-redefinition to mean --allow-redefinition-new.
This release adds --allow-redefinition-old as an alias of --allow-redefinition, which
can be used to continue using the old redefinition behavior in mypy 2.0 and later.
List of changes:
Add --allow-redefinition-old as an alias of --allow-redefinition (Ivan Levkivskyi, PR 20764)
Allow redefinitions for function arguments (Ivan Levkivskyi, PR 20853)
Fix regression on redefinition in deferred loop (Ivan Levkivskyi, PR 20879)
Fix loop convergence with redefinitions (Ivan Levkivskyi, PR 20865)
Make sure new redefinition semantics only apply to inferred variables (Ivan Levkivskyi, PR 20909)
Fix union edge case in function argument redefinition (Ivan Levkivskyi, PR 20908)
Show an error when old and new redefinition are enabled in a file (Ivan Levkivskyi, PR 20920)
--allow-redefinition-new is no longer experimental (Jukka Lehtosalo, PR 21110)
Fix type inference for nested union types (Ivan Levkivskyi, PR 20912)
Fix type inference regression for multiple variables in loops (Ivan Levkivskyi, PR 20892)
Improve type inference for empty collections in conditional contexts (Ivan Levkivskyi, PR 20851)
Incremental Checking Improvements
This release includes multiple fixes to incremental type checking:
Invalidate cache when --enable-incomplete-feature changes (kaushal trivedi, PR 20849)
Add back support for warn_unused_configs (Ivan Levkivskyi, PR 20801)
Recover from corrupted fixed-format cache meta file (Jukka Lehtosalo, PR 20780)
Distinguish not found versus skipped modules (Ivan Levkivskyi, PR 20812)
Fix undetected submodule deletion on warm run (Ivan Levkivskyi, PR 20784)
Fix staleness on changed follow-imports options (Ivan Levkivskyi, PR 20773)
Verify indirect dependencies reachable on incremental run (Ivan Levkivskyi, PR 20735)
Fix indirect dependencies for protocols (Ivan Levkivskyi, PR 20752)
Show error locations in other modules on warm runs (Ivan Levkivskyi, PR 20635)
Don't read errors from cache on silent import (Sjoerd Job Postmus, PR 20509)
More robust fix for re-export of __all__ (Ivan Levkivskyi, PR 20487)
Fix crashes caused by type variable defaults in-place modifications (Stanislav Terliakov, PR 20139)
Fix crash when calling len() with no arguments (Jukka Lehtosalo, PR 20774)
Fix crash when checking async for inside nested comprehensions (A5rocks, PR 20540)
Fix ParamSpec related crash (Stanislav Terliakov, PR 20119)
Mypyc: Faster Imports on macOS
Imports in native (compiled) modules that target other native modules that are compiled
together are now significantly faster on macOS, especially on the first run after a compiled
package has been installed. This also speeds up the first mypy run after installation/update
on macOS.
This was contributed by Jukka Lehtosalo (PR 21101).
librt: Mypyc Standard Library
Mypyc now has a dedicated standard library, librt, to provide basic features that are optimized
for compiled code. They are faster than corresponding Python stdlib functionality. There is no
plan to replace the Python stdlib, though. We'll only include a carefully selected set of features
that help with common performance bottlenecks in compiled code.
Currently, we provide librt.base64 that has optimized SIMD (Single Instruction, Multiple
Data) base64 encoding and decoding functions. In future mypyc releases we are planning to
add efficient data structures, string/bytes utilities, and more.
Use python3 -m pip install librt to make librt available to compiled modules. Compiled
modules don't require librt unless they explicitly import librt. If you install mypy, you
will also get a compatible version of librt as a dependency. We will keep librt backward
compatible, so you should always be able to update to a newer version of the library.
Enable SIMD for librt.base64 on x86-64 (Jukka Lehtosalo, PR 20244)
Add primitive for librt.base64.b64decode (Jukka Lehtosalo, PR 20272)
Add urlsafe_b64encode and urlsafe_b64decode to librt.base64 (Jukka Lehtosalo, PR 20274)
Make librt.base64 non-experimental (Ivan Levkivskyi, PR 20783)
Support pyodide for Python 3.12 (Michael R. Crusoe, PR 20342)
Support pyodide via the NEON intrinsics (Michael R. Crusoe, PR 20316)
Fix librt compilation on platforms with OpenMP (Ivan Levkivskyi, PR 20583)
Fix cross-compiling librt by enabling x86_64 optimizations with pragmas (James Le Cuirot, PR 20815)
Use existing SIMD CPU dispatch by customizing build flags (Michael R. Crusoe, PR 20253)
Document librt and librt.base64 (Jukka Lehtosalo, PR 21114)
Mypyc: Acyclic Classes
Mypyc now supports defining acyclic native classes that don't participate in the tracing
garbage collection:
from mypy_extensions import mypyc_attr
@mypyc_attr(acyclic=True)
class Item:
def __init__(self, key: str, value: str) -> None:
self.key = key
self.value = value
Allocating and freeing instances of acyclic classes is faster than regular native class
instances, and they use less memory, but if they participate in reference cycles, there
may be memory leaks.
This was contributed by Jukka Lehtosalo (PR 20795).
Additional Mypyc Fixes and Improvements
Fix range loop variable off-by-one after loop exit (Vaggelis Danias, PR 21098)
Removed Flags --force-uppercase-builtins and --force-union-syntax
The --force-uppercase-builtins flag was deprecated and has been a no-op since mypy 1.17.0.
Since mypy has dropped support for Python 3.9, the --force-union-syntax flag is no longer
necessary.
Contributed by Marc Mueller (PR 20410)
and (PR 20405).
Stubgen Improvements
Fix mis-parsing of double colon ("::") (Jeremy Nimmer, PR 20285)
Stubtest Improvements
Attempt to resolve decorators from their type (Shantanu, PR 20867)
Fix crash on instances with redefined __class__ (sobolevn, PR 20926)
Improve checking of positional-only parameters in dunder methods (Brian Schubert, PR 19593)
Check Final variables with literal values against runtime (Vikash Kumar, PR 20858)
Fix duplicate errors with invalid line numbers (Joren Hammudoglu, PR 20417)