We've just uploaded mypy 2.3.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.
The Upcoming Switch to the New Native Parser
We are planning to enable the new native parser (--native-parser) by
default soon. We recommend that you test the native parser in your projects and report
any issues in the mypy issue tracker.
Mypyc Free-threading Memory Safety
Free-threaded Python builds that don't have the GIL require additional synchronization
primitives or lock-free algorithms to ensure memory safety when there are race conditions
(for example, when a thread reads a list item while another thread writes the same list
item concurrently). This release greatly improves memory safety of free threading.
List operations are now memory-safe on free threaded Python builds, even in the presence of
race conditions. This has some performance cost. For list-heavy workloads, using
librt.vecs.vec instead of list is often significantly faster, but note that vec is not
(and likely won't be) fully memory safe, and the user is expected to avoid race conditions.
The newly introduced librt.threading.Lock helps with this. Using variable-length tuples
can also be more efficient than lists, since tuples are immutable and don't require
expensive synchronization to ensure memory safety.
Instance attribute access is also (mostly) memory safe now on free-threaded builds in
the presence of race conditions. We are planning to fix the remaining unsafe cases in a
future release.
Full list of changes:
Make attribute access memory safe on free-threaded builds (Jukka Lehtosalo, PR 21705)
Fix unsafe borrowing of instance attributes with free-threading (Jukka Lehtosalo, PR 21688)
Make list get/set item more memory safe on free-threaded builds (Jukka Lehtosalo, PR 21683)
Don't borrow list items on free-threaded builds (Jukka Lehtosalo, PR 21679)
Make multiple assignment from list memory-safe on free-threaded builds (Jukka Lehtosalo, PR 21684)
Make for loop over list memory-safe on free-threaded builds (Jukka Lehtosalo, PR 21686)
Fix memory safety of list.count on free-threaded builds (Jukka Lehtosalo, PR 21680)
Make vec creation from list memory safe on free-threaded builds (Jukka Lehtosalo, PR 21681)
### librt.threading: Fast Native Lock Type
Mypyc now supports librt.threading.Lock, which is a lock type optimized for use
in compiled code. It can be 2x to 4x faster than threading.Lock.
This feature was contributed by Jukka Lehtosalo (PR 21690, PR 21697).
Mypyc: Read-only Final Instance Attributes
Instance attributes of native classes declared as Final are now read-only at runtime.
This enables additional optimizations, and it's now recommended to use Final for
all performance-sensitive attributes when feasible.
Related changes:
Make instance attribute read-only at runtime if Final (Jukka Lehtosalo, PR 21666)
Borrow final attributes more aggressively (Jukka Lehtosalo, PR 21702)
Improve documentation of Final in mypyc (Jukka Lehtosalo, PR 21713)
Mypyc Documentation Updates
Update documentation of race conditions under free threading (Jukka Lehtosalo, PR 21726)
We've just uploaded mypy 2.2.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.
Support for Closed TypedDicts (PEP 728)
Mypy now supports closed TypedDicts as specified in PEP 728. A closed TypedDict cannot have extra
keys beyond those explicitly defined. This allows the type checker to determine that certain
operations are safe when they otherwise wouldn't be due to the potential presence of unknown keys.
You can use the closed keyword argument with TypedDict:
HasName = TypedDict("HasName", {"name": str})
HasOnlyName = TypedDict("HasOnlyName", {"name": str}, closed=True)
Movie = TypedDict("Movie", {"name": str, "year": int})
movie: Movie = {"name": "Nimona", "year": 2023}
has_name: HasName = movie # OK: HasName is open (default)
has_only_name: HasOnlyName = movie # Error: HasOnlyName is closed and Movie has extra "year" key
Closed TypedDicts enable more precise type checking because the type checker knows exactly which
keys are present. This is particularly useful when working with TypedDict unions or when you want
to ensure that a TypedDict conforms to an exact shape.
The closed keyword also enables safe type narrowing with in checks:
Book = TypedDict('Book', {'book': str}, closed=True)
DVD = TypedDict('DVD', {'dvd': str}, closed=True)
type Inventory = Book | DVD
def print_type(inventory: Inventory) -> None:
if "book" in inventory:
# Type is narrowed to Book here - safe because DVD is closed
print(inventory["book"])
else:
# Type is narrowed to DVD here
print(inventory["dvd"])
The closed keyword is also supported in class-based syntax:
class HasOnlyName(TypedDict, closed=True):
name: str
Note that closed TypedDicts are structural types, so a closed TypedDict is assignable to an open
TypedDict with the same keys, but not vice versa.
Complete Support for Type Variable Defaults (PEP 696)
Mypy now has complete support for type variable defaults as specified in PEP 696. This allows you to
specify default values for type parameters in generic classes, functions, and type aliases.
Traditional syntax (Python 3.11 and earlier):
T = TypeVar("T", default=int) # This means that if no type is specified T = int
@dataclass
class Box(Generic[T]):
value: T | None = None
reveal_type(Box()) # type is Box[int]
reveal_type(Box(value="Hello World!")) # type is Box[str]
New syntax (Python 3.12+):
class Box[T = int]:
def __init__(self, value: T) -> None:
self.value = value
reveal_type(Box()) # type is Box[int]
reveal_type(Box(value="Hello World!")) # type is Box[str]
Type variable defaults work with all forms of generics, including classes, functions, and type aliases.
This release completes the implementation by fixing various edge cases involving recursive defaults,
dependencies between type variables, and interactions with variadic generics.
Mypy now respects explicitly annotated return types in __new__() methods. Previously, mypy would
always assume that __new__() returns an instance of the current class, ignoring explicit annotations.
With this change, if you explicitly annotate a return type that differs from the implicit type, mypy
will use the explicit annotation:
class Factory:
def __new__(cls) -> Product:
return Product()
reveal_type(Factory()) # type is Product, not Factory
Note that mypy still gives an error at the definition site if the explicit annotation is not a
subtype of the current class, since this is technically not type-safe.
For backwards compatibility, there are two exceptions:
If the return type is Any, mypy will still use the current class as the return type.
If the explicit return type comes from a superclass and is a supertype of the implicit return type,
mypy will use the implicit (more specific) type:
class A:
def __new__(cls) -> A: ...
reveal_type(A()) # type is A
class B:
def __new__(cls) -> B:
return cls()
class C(B): ...
reveal_type(C()) # type is C
This fixes several long-standing issues where explicit __new__() return types were ignored.
Support for TypeForm is no longer experimental. TypeForm (introduced in Python 3.14) allows you
to annotate parameters that accept type expressions, providing better type checking for functions
that work with types as values.
from typing import TypeForm
def make_list(tp: TypeForm[T]) -> list[T]:
...
# Correctly typed as list[int]
int_list = make_list(int)
TypeForm support was previously reverted from mypy 2.1 due to a performance regression, but this
has now been mitigated.
Contributed by Ivan Levkivskyi and Jelle Zijlstra (PRs 21262, 21591,
21459).
Experimental WASM Wheel for Python 3.14
Mypy now ships an experimental WebAssembly (WASM) wheel for Python 3.14. This allows mypy to run
in WASM environments such as Pyodide and browser-based Python implementations.
The WASM wheel is considered experimental and may have limitations compared to native builds. Please
report any issues you encounter when using mypy in WASM environments.