Tuesday, 8 November 2022

Mypy 0.991 Released

We’ve just uploaded mypy 0.991 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.

Basic Python 3.11 Support

Mypy and mypyc now have partial official support for Python 3.11. We provide compiled wheels for 3.11, and many 3.11 stdlib features are supported.

Most new language and typing features are still unsupported or are experimental. Adding support for the remaining 3.11 features is a priority for the mypy team.

Breaking Change: No Implicit Optional Types for Arguments

Mypy now disables implicit optional types such as these by default to fix a long-standing incompatibility with PEP 484, and they will have to be explicitly enabled:

    def foo(s: str = None) -> int: ...  # Error!

Mypy will now only accept the example with an explicit optional type (e.g. str | None) for the s argument, when using the default options:

    # s: Optional[str] also works
    def foo(s: str | None = None) -> int: ...  # OK

You can still explicitly enable implicit optional types via --implicit-optional or no_implicit_optional = False in your mypy config file. We don’t recommend relying on implicit optional types, since they are a non-standard feature, but we have no plans to stop supporting them.

You can also use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase to explicit optional types.

This was contributed by Shantanu:

  • Use --no-implicit-optional by default (Shantanu, PR 13401)
  • Suggest codemod for --no-implicit-optional (Shantanu, PR 13747)

Breaking Change: Namespace Packages Enabled by Default

Mypy now enables --namespace-packages by default (PEP 420), so that namespace packages (packages with a missing __init__.py file) are supported without any extra configuration.

Refer to the documentation of --namespace-packages and to Mapping file paths to modules in mypy documentation for more information.

In some cases you may need to use --explicit-package-bases and to explicitly declare additional package roots that mypy can’t figure out automatically by using the MYPYPATH environment variable or using mypy_path = <dirs> in your config file. Otherwise you may get errors about missing imports.

You can explicitly disable the option by using --no-namespace-packages or namespace_packages = False in your config file to return to the old behavior. We recommend first trying --explicit-package-bases discussed above if you encounter any issues.

This was contributed by Shantanu (PR 9636).

Recursive Types Enabled By Default

Mypy support for general recursive types is now official. These were available in mypy 0.981 through the --enable-recursive-aliases flag. Now you no longer need to explicitly enable them. Example:

    # This is now allowed by default
    NaiveJSON = str | list["NaiveJSON"] | dict[str, "NaiveJSON"]
    test_data: NaiveJSON = {"foo": {"bar": "baz"}}  # OK

Note that you will need to use string escapes on the right hand side (e.g. "NaiveJSON") if you define recursive types outside of stub files, since Python doesn’t support forward references at runtime. Also, mypy generally doesn’t infer recursive types by default. Similar to TypedDict types, you will often need to explicitly annotate a variable with a recursive type or mypy will try to infer a non-recursive type instead.

You can still disable recursive types using --disable-recursive-aliases if they cause any problems. Please open an issue on the mypy issue tracker if this is the case.

See “Experimental Support for General Recursive Types” in the mypy 0.981 release blog post for more details.

This change was contributed by Ivan Levkivskyi in (PR 13516), (PR 13852) and (PR 13754).

Error Codes Shown by Default

Mypy now shows error codes at the end of each error message by default, within square brackets. Example:

    error: 
    Unsupported operand types for + ("int" and "str")  [operator]

This makes it easier to silence only specific error codes on a line by using # type: ignore[<error-code>]. Example:

    print(1 + "x")  # type: ignore[operator]

You can find helpful information about specific errors by looking up the error code in the documentation.

You can hide error codes by using --hide-error-codes or by adding show_error_codes = False to your configuration file.

This was contributed by Marc Mueller (PR 13542).

Safe Handling of Empty Function Bodies

For historical reasons, mypy used to always allow trivial function/method bodies (e.g. a body with only a single pass statement and/or a docstring), even if this is not type safe. Example:

    # Error: Missing return statement (no error before 0.990)
    def some_func(arg: str) -> int:
        pass

This could hide bugs and was a generally confusing behavior. Mypy is now handling such empty bodies safely. In the example above you will now get an error (unless you are using --no-strict-optional). Mypy only allows an empty/trivial body in a method with a non-optional return type if the method is abstract:

    class Base(ABC):
        @abstractmethod
        def must_implement_in_subclass(self, arg: str) -> int:
            pass  # Still OK

Additionally, mypy now flags unsafe super() calls to a method with an empty body that’s decorated with @abstractmethod. Mypy will now issue an error in this case.

To disable this functionality, use the --allow-empty-bodies flag.

This change was contributed by Ivan Levkivskyi in (PR 13729).

Enabling Experimental Features Individually

Experimental mypy features can now be enabled individually. With this change, using --enable-incomplete-features to enable all of them becomes deprecated and the recommended way forward is to enable experimental features individually with --enable-incomplete-features=FEATURE.

This change was contributed by Ivan Levkivskyi and Nikita Sobolev in (PR 13790).

Configuring Packages/Modules in the Config File

It is now possible to tell mypy to implicitly type check specific packages by using the options modules and packages in the configuration file, without having to explicitly include these on the command line. These options take a comma separated list of packages which will be checked by mypy if none are given on the command line.

Mypy will not recursively type check any submodules of the provided modules by modules and will recursively type check any submodules of the provided modules by packages.

These options may only be set in the global section. See also the documentation.

This feature was contributed by sameer-here (PR 12639).

Warn about Variable Annotations in Unchecked Functions

Mypy will no generate a note if you use a type annotation in a function without a type annotation (and you are not using --check-untyped-defs), since these annotations have no effect. Example:

    def foo():
        x: int = bar()
        print(x)

This is treated as a warning, so it doesn’t cause a mypy run to fail:

    $ mypy prog.py
    prog.py:2: note: By default the bodies of untyped functions 
        are not checked, consider using --check-untyped-defs  
        [annotation-unchecked]
    Success: no issues found in 1 source file

This was contributed by Ivan Levkivskyi (PR 13851).

Error Code for Using an Abstract Class as type[T]

Mypy disallows using an abstract type object (ABC) if type type[T] is expected. This would be unsafe, since mypy always allows calling type[T] values to instantiate objects, and ABCs can’t be instantiated.

Now this error has the dedicated error code type-abstract, and you can use --disable-error-code type-abstract to disable this check, since it can generate undesirable errors in some use cases. Example:

    import abc
    
    class A(abc.ABC):
        @abc.abstractmethod
        def m(self) -> None: pass
    
    class C(A):
        def m(self) -> None: print('m')
    
    def check(o: object t: type[A]) -> bool:
        return isinstance(o, t)
    
    # Error: Only concrete class can be given here [type-abstract]
    check(C(), A)
    check(C(), C)  # OK

This was contributed by Ivan Levkivskyi (PR 13785).

Performance Improvements

Mypy includes a potential fix for a performance regression edge case introduced in mypy 0.982:

  • Revert literal type change in builtins.sum (Shantanu, PR 13961)

Changes to Error Reporting and Messages

  • Return exit status 0 if there are only notes and no errors (Ivan Levkivskyi, PR 13879)
  • Generate an error if a function object is used in a boolean context, with the truthy-function error code, even if the truthy-bool error code is disabled (Marc Mueller, PR 13686)
  • Silence errors from third-party packages in mypy daemon (Jukka Lehtosalo, PR 13768)
  • Preserve file order of messages during successive daemon runs (Jukka Lehtosalo, PR 13780)
  • Suggest additional types-* packages from typeshed (Jukka Lehtosalo, PR 13698)
  • Better diagnostic for conditional function mismatch (Shantanu, PR 13604)
  • Use consistent capitalization for TypeVar (Marti Raudsepp, PR 13687)
  • Suggest using upper bound for unbound type variable (Shantanu, PR 13730)
  • Show error codes for some notes (Ivan Levkivskyi, PR 13880)
  • Suggest using a protocol if trying to use a module as a type (Nikita Sobolev, PR 13861)
  • Improve error message for --strict-concatenate (Shantanu, PR 13777)
  • Improve error message for implicitly abstract functions (Shantanu, PR 13776)
  • Mention implicit export on missing attribute access (Shantanu, PR 13917)
  • Always mention explicit export when relevant (Shantanu, PR 13925)
  • Fix error code when reporting an invalid Literal type (Shantanu, PR 13763)
  • Replace invalid __set__ with __get__ in messages (Ilya Konstantinov, PR 13913)

Mypyc Fixes and Improvements

  • Add support for building mypyc code on WASM (Ethan Smith and Shantanu, PR 13446)
  • Fix C errors about shifting negative integers (Jukka Lehtosalo, PR 13876)

Documentation Updates

Several parts of the documentation received major updates.

  • Major update to "Using mypy with existing codebase" (Shantanu, PR 13683)
  • Update cheat sheet (PR 13873, PR 13679) (Shantanu)
  • Update “Runtime troubles” (Shantanu, PR 13680)
  • Mention files config file option in "Specifying code to check" (Shantanu, PR 13682)
  • Make language more consistent (Shantanu, PR 13677)
  • Update “Getting started” (Shantanu, PR 13734)
  • Update “Type inference and annotations” (Shantanu, PR 13736)
  • Discuss user defined protocols before built-in protocols (Shantanu, PR 13737)
  • Reorder sections in “Running mypy” (Shantanu, PR 13738)
  • Improve "Precise typing of alternative constructors" example (Jelle Zijlstra)
  • Improve “Getting started” docs (Shantanu, PR 13875)
  • Update “Extending mypy” docs (Nikita Sobolev, PR 13924)
  • Add clear warning about stubtest code execution (Nikita Sobolev, PR 13927)

Stubgen Improvements

Stubgen is a tool for automatically generating draft stubs for libraries.

  • Introduce an object-oriented system for extracting function signatures (Chad Dombrova, PR 13473)
  • Add known return types to magic methods (Nikita Sobolev, PR 13909)

Stubtest Improvements

Stubtest is a tool for testing that stubs conform to the implementations.

  • Detect abstract properties mismatches (Nikita Sobolev, PR 13647)
  • Catch SyntaxError from inspect.getsourcelines (Shantanu, PR 13848)

Other Notable Fixes and Improvements

  • Detect invalid ParamSpec annotations used with *args and **kwargs (Nikita Sobolev, PR 13892)
  • Fix crash with generic class definition in function (Michael Lee, PR 13678)
  • Fix joining a function against metaclass-using object constructors (Michael Lee, PR 13648)
  • Fixes to attrs magic attribute handling (Tin Tvrtković and Nikita Sobolev, PR 13522)
  • Support __attrs_init__ method in attrs classes (Spencer Brown, PR 13865)
  • Fix crash on match statement with value restricted TypeVar (Shantanu, PR 13728)
  • Fix crash in match statement with unmatchable class pattern (Shantanu)
  • Fix unsound variance (Shantanu, PR 13714)
  • Fix crash with report generation on namespace packages (Shantanu, PR 13733)
  • Remove use of LiteralString in builtins (Shantanu, PR 13743)
  • Treat __dataclass_fields__ as a ClassVar (Shantanu, PR 13721)
  • Respect per-module follow_import for empty folders (Shantanu, PR 13758)
  • Fix a crash related to dataclasses and type aliases (Ivan Levkivskyi, PR 13759)
  • Add install-types extra that depends on pip (David Runge, PR 13739)
  • Restore Type vs Callable special-casing that was broken in refactoring (Ivan Levkivskyi, PR 13784)
  • Fix module and protocol subtyping and hasattr with a module (Shantanu, PR 13778)
  • Make join of recursive types more robust (Ivan Levkivskyi, PR 13808)
  • Fix minor issues with **kwargs that use TypedDict unpacking (Ivan Levkivskyi, PR 13854)
  • Fix crash on missing indirect dependencies (Ivan Levkivskyi, PR 13847)
  • Ignore promotions when simplifying unions (Ivan Levkivskyi, PR 13781)
  • Fall back to FORCE_COLOR environment variable if MYPY_FORCE_COLOR is not present (Alex Waygood, PR 13814)

Typeshed Updates

Typeshed is now modular and distributed as separate PyPI packages for everything except the standard library stubs. Please see git log for full list of typeshed changes.

Acknowledgements

Thanks to all mypy contributors who contributed to this release:

  • Alex Waygood
  • Bas van Beek
  • Ben Raz
  • Chad Dombrova
  • David Runge
  • Ethan Smith
  • Ilya Konstantinov
  • Ivan Levkivskyi
  • iyanging
  • Jared Hance
  • Jelle Zijlstra
  • Jeroen Van Goey
  • Jinze Wu
  • Jukka Lehtosalo
  • Kevin Kirsche
  • KotlinIsland
  • Marc Mueller
  • Marti Raudsepp
  • Matt Wozniski
  • Michael Lee
  • Nikita Sobolev
  • pranavrajpal
  • Richard Si
  • Ryan Soklaski
  • sameer-here
  • Shantanu
  • Spencer Brown
  • Stas Ilinskiy
  • Tim D. Smith
  • Tin Tvrtković
  • Valentin Stanciu

We’d also like to thank our employer, Dropbox, for funding the mypy core team.

Monday, 26 September 2022

Mypy 0.981 Released

 

We’ve just uploaded mypy 0.981 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 Python 3.6 and 2 Dropped

Support for Python 2 has been completely removed in this release.

Support for Python 3.6 has also been dropped, since Python 3.6 has reached its end of life. It is still possible to target Python 3.6 using --python-version in future mypy versions, but no bugs will be fixed that affect only Python 3.6 (unless they are regressions). Also note that typeshed just recently dropped Python 3.6 support, so standard library features only available in Python 3.6 will not be supported.

The implementation was jointly contributed by Shantanu, Nikita Sobolev and Ivan Levkivskyi.

Generate Error on Unbound TypeVar Return Type

Code like this will now generate an error, since the value of T cannot be inferred in calls:

    from typing import TypeVar
    
    T = TypeVar("T")
    
    # Error: A function returning TypeVar should receive at least one 
    # argument containing the same Typevar
    def f() -> T: ... 

Having an unbound type variable in a nested position (e.g. list[T]) is still accepted in a return type, since it has valid use cases. This was contributed by Aurélien Jaquier (PR 13166).

Methods with Empty Bodies in Protocols Are Abstract

Any method with an empty body in a protocol is now correctly treated as implicitly abstract and must be implemented even if a class explicitly inherits the protocol:

    from typing import Protocol
    
    class P(Protocol):
        # "..." is the literal ellipsis and indicates an empty body
        def meth(self) -> int: ...
    
    class Cls(P):
        pass
    
    # Error: Cannot instantiate abstract class "Cls" with abstract 
    # attribute "method"
    Cls()

This was contributed by Thomas MK (PR 12118).

Implicit Optional Types Will Be Disabled by Default

A future mypy feature release (possibly the next one after 0.98x) will disable implicit optional types such as these by default, and they will have to be explicitly enabled:

    def foo(s: str = None) -> int: ...  No error currently
    
    foo(None)  # Ok

In the future mypy will only accept the example with an explicit optional type (e.g. str | None) for the s argument, when using the default options:

    # s: Optional[str] also works
    def foo(s: str | None = None) -> int: ...
    
    foo(None)  # No change to callers

To prepare for the change, you can set the relevant configuration option explicitly. Either disable implicit optional types by using --no-implicit-optional, or no_implicit_optional = True in your mypy configuration file, or enable them via --implicit-optional or no_implicit_optional = False. We don’t recommend relying on implicit optional types, since they are a non-standard feature, but we have no plans to stop supporting them.

We hope to provide a migration tool that will automatically switch implicit optional types to explicit ones in function signatures.

Precise Types for **kwds Using TypedDict

Mypy now supports precise type annotations for kwds parameters. You can use this feature as following:

    from typing import TypedDict
    from typing_extensions import Unpack
    
    class Style(TypedDict, total=False):
        margin: int
        sticky: bool
    
    def add_button(label: str, **kwds: Unpack[Style]) -> None:
        ...
    def add_check_box(active: bool, **kwds: Unpack[Style]) -> None:
        ...
    
    add_button("Cancel", margin=0, sticky=False)  # This works
    tight: Style = {"margin": 0}
    add_button("OK", **tight)  # This works as well

You can alternatively use Required[...] and NotRequired[...] TypedDict annotations to control whether a keyword argument is required or not. Note that arbitrary extra keywords are not allowed for such functions (this is consistent with how mypy currently handles TypedDicts). Although this feature is complete, Unpack[...] is still considered experimental, so you will need to use --enable-incomplete-features to enable it.

This feature was contributed by Ivan Levkivskyi (PR 13471).

Experimental Support for General Recursive Types

Until recently mypy only supported recursively defined classes (e.g. trees), but not arbitrary recursive types. In this version we add (experimental) support for arbitrary recursively defined types, including type aliases, TypedDicts, NamedTuples, and so on. This example uses a recursively defined type alias:

    from typing import TypeVar, Sequence
    
    T = TypeVar("T")
    
    # String literal escaping needed to avoid NameError at runtime
    Nested = Sequence[T | "Nested[T]"]
    
    def flatten(seq: Nested[T]) -> list[T]:
        result = []
        for item in seq:
            if isinstance(item, list):
                result.extend(flatten(item))
            else:
                result.append(item)
        return result
    
    flatten([1, [2, 3]])  # This works, inferred type is list[int]

This feature can be enabled using --enable-recursive-aliases. If mypy doesn’t work as expected with some recursive types, you can try adding more explicit annotations, and/or using covariant collections (e.g. Sequence instead of list). Please file an issue on the issue tracker if you think you have found a bug.

List of relevant PRs:

  • Enable recursive type aliases behind a flag (Ivan Levkivskyi, PR 13297)
  • Simplify types in some error messages (Ivan Levkivskyi, PR 13326)
  • Support recursive TypedDicts (Ivan Levkivskyi, PR 13373)
  • Support recursive named tuples (Ivan Levkivskyi, PR 13371)
  • Fail gracefully on diverging recursive type aliases (Ivan Levkivskyi, PR 13352)
  • Fail gracefully on invalid and/or unsupported recursive type aliases (Ivan Levkivskyi, PR 13336)
  • Handle interactions between recursive aliases and recursive instances (Ivan Levkivskyi, PR 13328)
  • Fix crash on deferred upper bound with recursive aliases enabled (Ivan Levkivskyi, PR 13410)
  • Remove Optional[...] special-casing to avoid infinite recursion (Ivan Levkivskyi, PR 13357)

Generic NamedTuples and TypedDicts

Mypy now supports defining generic TypedDicts, NamedTuples, and user defined tuple types. You can use either the class or call syntax for this:

    from typing import Generic, TypeVar
    from typing_extensions import TypedDict  # From "typing" on Python 3.11
    
    T = TypeVar("T")
    
    class Param(TypedDict, Generic[T]):
        name: str
        value: T
    
    Opt = TypedDict("Opt", {"value": T, "is_set": bool})
    
    def apply(param: Param[T]) -> T: ...
    
    x = apply({"name": "test", "value": 42})  # Inferred type is "int"
Note: While you can freely use this feature in stub files, if you want to use it in source files, you will need to either use Python 3.11 (which is not officially supported by mypy yet), import TypedDict/NamedTuple from typing_extensions, or use an if TYPE_CHECKING: ... block.

List of relevant PRs:

  • Enable generic TypedDicts (Ivan Levkivskyi, PR 13389)
  • Enable generic NamedTuples (Ivan Levkivskyi, PR 13396)

Better Support for Callable Attributes

Mypy now has better support for instance attributes with Callable[...] types. Previously, mypy couldn’t reliably distinguish between callable instance attributes and method aliases. Now there are consistent rules. If a variable is defined using and assignment and/or annotation in a class body and has a callable type, it is an instance attribute if both these conditions are true:

  • There is an explicit annotation, and it is not a ClassVar[...].
  • The variable name is not a special dunder method name, such as __add__.

Conversely, such an assignment/annotation defines a method in these cases:

  • There is no explicit annotation, or there is a ClassVar[...] annotation.
  • The variable name is a special dunder method name.

Example:

    from typing import ClassVar, Callable
    
    class Test:
        runner: Callable[[], None]  # An instance variable
    
        def hook(self) -> None: ...
            self.runner = lambda: print("pass")
    
        legacy_hook = hook  # A method
        other_hook: ClassVar[Callable[[Test], None]]  # Also a method
    
    Test.other_hook = lambda self: None
    t = Test()
    t.legacy_hook()
    t.runner()
    t.other_hook()

This feature was contribute by Ivan Levkivskyi (PR 13400).

Per-Module Error Code Configuration

You can now disable and/or enable individual error codes per module and per directory using config files and/or inline # mypy: comments. Example:

    # mypy.ini
    [mypy]
    strict = True
    
    [mypy-tests.*]
    allow_untyped_defs = True
    allow_untyped_calls = True
    disable_error_code = var-annotated
    # source.py
    x = []  # Error: Need type annotation for "x"
    # tests/foo.py
    x = []  # OK
    # tests/bar.py
    # mypy: enable-error-code="var-annotated"
    x = []  # Error: Need type annotation for "x"

Note that these per-directory settings act as incremental overrides. The precedence is the following:

  • Command line options and/or the main section of a config file set global codes.
  • Config sections adjust them per glob/module.
  • Inline # mypy: comments adjust them again.

You can, for example, enable an error code globally, disable it for all tests in the config file, and then re-enable it in a particular file by using an inline comment.

This feature was contributed by Ivan Levkivskyi (PR 13502).

Experimental Support for Interactive Inspection of Expressions

Mypy now has an experimental support for various static inspections using the mypy daemon dmypy inspect command. These inspections are currently included:

  • Print the type of an expression at given location.
  • Print the attributes defined for a given expression.
  • Go to definition of a reference expression (name or attribute).

Note that you can run this only after the file has been type-checked by the daemon, for example by using dmypy check or dmypy run. Basic usage is like this:

    dmypy inspect [--show type|attrs|definition] \
        path/to/file.py:line:column[:end_line:end_column]

Please read the docs for more details. This feature was contributed by Ivan Levkivskyi (PR 13209).

Mypyc Improvements

Mypyc compiles Python modules to C extensions and is bundled with mypy. It uses standard Python type hints to generate fast code (documentation).

  • Support async for as a statement and in comprehensions (Michael J. Sullivan, PR 13444)
  • Support async with (Michael J. Sullivan, PR 13442)
  • Fix clang warning on different signs integer (Paul m. p. Peny, PR 13239)
  • Fix AttributeError message (Jukka Lehtosalo, PR 13382)
  • Fix __call__ subclasses (Ken Jin, PR 13152)
  • Fix setup conflict with attributes named up (davfsa, PR 13012)
  • Fix bad C generated for multiple assignment (Jukka Lehtosalo, PR 13147)
  • Update, simplify check version test (Shantanu, PR 13125)

Documentation Updates

  • Update theme to furo (Michael Wentz, PR 13345)
  • Use ParamSpec in "Declaring decorators" (Ilya Konstantinov, PR 13237)
  • Fix protocols documentation (Zsolt Cserna, PR 13137)
  • Prefer f-strings over format and underscores in numeric literals in docs (Kevin Kirsche, PR 13317)
  • Use GitHub's zipball as alternative to 'git+https' in README.md (Peter Badida, PR 13208)

Stubgen Improvements

Stubgen is a tool for automatically generating draft stubs for libraries.

  • Allow passing arguments to stubgen.main (Matthew Woehlke, PR 13095)
  • Increase import timeout (Matthew Woehlke, PR 13109)

Stubtest Improvements

Stubtest is a tool for testing that stubs conform to the implementations.

  • Fallback to getattr_static on AttributeError (Alex Waygood, PR 13285)
  • Reduce false positives on runtime type aliases (Alex Waygood, PR 13116)
  • Catch-all for errors from the runtime (Shantanu, PR 13160)
  • Allow stubtest to ignore Python 2 only magic methods (Nikita Sobolev, PR 13290)
  • Improve docs (Shantanu, PR 13293)
  • Ignore __pyx_vtable__ (Shantanu, PR 13302)
  • Improve signature checking (Shantanu, PR 13307)
  • Show path to stub file (Shantanu, PR 13342)
  • Allow stubtest to raise errors on abstract state mismatch (Nikita Sobolev, PR 13323)
  • Fix broken error message for async/sync mismatch (Alex Waygood, PR 13414)
  • Don't error for a missing submodule if the submodule name is private (Alex Waygood, PR 13417)
  • Ignore __vectorcalloffset__ (Alex Waygood, PR 13416)
  • Use single line error message (Shantanu, PR 13301)
  • Verify the contents of __all__ in a stub (Alex Waygood, PR 12214)
  • Fix error for Protocol.__init__ and __annotations__ (Alex Waygood, PR 13179)
  • Fix custom_typeshed_dir regression (PR 13658, PR 13656) (Shantanu)

Miscellaneous New Features

  • Enable support for decorated properties where possible (Ivan Levkivskyi, PR 13409)
  • Make any callable compatible with (*args: Any, kwargs: Any) (Shantanu, PR 11203)
  • Allow generic decorators on abstract classes (Ivan Levkivskyi, PR 13398)
  • Print and show error end locations (Ivan Levkivskyi, PR 13148)
  • Basic support for typing_extensions.NamedTuple (Alex Waygood, PR 13178)
  • Union types: Support narrowing to Ellipsis (...) cases of Unions (László Vaskó, PR 13157)

Other Notable Fixes and Improvements

  • Allow unpacking from TypeVars with iterable bounds (PR 13644, PR 13425) (Shantanu)
  • Fix error codes option serialization (Ivan Levkivskyi, PR 13523)
  • Fix daemon crashes related to ParamSpec and TypeVarTuple (Jukka Lehtosalo, PR 13381)
  • Allow stubs to use newer syntax than 3.7 (Shantanu, PR 13500)
  • Fix --custom-typeshed-dir handling (Ivan Levkivskyi, PR 13629)
  • Remove blocking special cased error for bool subclass (wookie184, PR 13420)
  • Remove useless parameter script_path of mypy.main() and make arguments keyword-only (Jingchen Ye, PR 13399)
  • Fix type inference for tuples in iterable context (Ivan Levkivskyi, PR 13406)
  • Fix type narrowing of TypedDict value with key name in final variable (Jingchen Ye, PR 11813)
  • Fix crash from invalid location in aliased types (Michael Krasnyk, PR 12745)
  • Advertise typing status via Trove classifier (Mike Fiedler, PR 13350)
  • Use a better colour for gray in mypy output (Ivan Levkivskyi, PR 13338)
  • Support type aliases in metaclasses (Nikita Sobolev, PR 13335)
  • Handle files ending with __init__ better (Shantanu, PR 13314)
  • Respect tuple.__getitem__ from typeshed (Shantanu, PR 13313)
  • Make subtype checks more consistent in edge cases (Ivan Levkivskyi, PR 13303)
  • Fix --custom-typeshed-dir crash (Alex Waygood, PR 13296)
  • Ensure builtin modules are from typeshed sooner (Konstantin, PR 13155)
  • Disallow bytes in TypeVar, NewType, and TypedDict names (Jelle Zijlstra, PR 13273)
  • Prohibit bytes literals in named tuples (Ivan Levkivskyi, PR 13271)
  • Suggest using a newer Python version if possibly needed (Shantanu, PR 13197)
  • Check implicit None return is valid when using --no-warn-no-return (Shantanu, PR 13219)
  • Fix site package on MYPYPATH check (Shantanu, PR 13223)
  • Make None compatible with SupportsStr protocol (Nikita Sobolev, PR 13184)
  • Fix caching of PEP 561 namespace packages (Shantanu, PR 13124)
  • Improve error message for direct __init__ calls (Shantanu, PR 13183)
  • Allow nonlocal in function scoped classes (Shantanu, PR 13158)
  • Support for Python 3.11's "safe_path" in pyinfo (Shantanu, PR 13164)
  • Generate error when using NoneType instead of None as a type (Jakub Strnad, PR 13153)
  • Add musllinux wheel support, Use 'official' llvm build for compilation (Ben Raz, PR 13228)
  • Skip musllinux wheels, update for lxml changes (Shantanu, PR 13129)

Typeshed Updates

Typeshed is now modular and distributed as separate PyPI packages for everything except the standard library stubs. Please see git log for full list of typeshed changes.

Acknowledgements

Thanks to all mypy contributors who contributed to this release:

  • Alex Waygood
  • anilbey
  • Aurélien Jaquier
  • Ben Raz
  • davfsa
  • Ilya Konstantinov
  • Ivan Levkivskyi
  • Jakub Strnad
  • Jared Hance
  • Jelle Zijlstra
  • Jingchen Ye
  • Jukka Lehtosalo
  • Ken Jin
  • Kevin Kirsche
  • Konstantin
  • KotlinIsland
  • László Vaskó
  • Marc Mueller
  • Matthew Woehlke
  • Michael Krasnyk
  • Michael Sullivan
  • Michael Wentz
  • Mike Fiedler
  • Nikita Sobolev
  • Patryk Gałczyński
  • Paul m. p. Peny
  • Peter Badida
  • Richard Si
  • Shantanu
  • Thomas MK
  • wookie184
  • Zsolt Cserna
  • Zsolt Dollenstein

We’d also like to thank our employer, Dropbox, for funding the mypy core team.

Tuesday, 19 July 2022

Mypy 0.971 Released

We’ve just uploaded mypy 0.971 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.

Last Release Officially Supporting Python 2 and 3.6

Support for Python 2 will be completely removed in the next mypy feature release after this one, mypy 0.980.

Support for Python 3.6 will also be dropped in mypy 0.980, since Python 3.6 has reached its end of life. It will be still possible to target Python 3.6 using --python-version in future mypy versions, but no bugs will be fixed that affect only Python 3.6 (unless they are regressions). Also note that typeshed just recently dropped Python 3.6 support, so standard library features only available in Python 3.6 will not be supported.

Mypyc Improvements and Fixes

Mypyc compiles Python modules to C extensions and is bundled with mypy. It uses standard Python type hints to generate fast code (documentation).

  • Speed up accessing always defined native attributes (Jukka Lehtosalo, PR 12600)
  • Reduce the overhead of reference counting (Jukka Lehtosalo, PR 12805, PR 12810, PR 12817)
  • Fix Python 3.11 C API errors (97littleleaf11, PR 12850)
  • Generate smaller code for casts and some implicit type coercions (Jukka Lehtosalo, PR 12839)
  • Optimize calling Python objects with zero or one arguments (97littleleaf11, PR 12862)
  • Replace integer floor division by a power of two with a shift (Jukka Lehtosalo, PR 12870)
  • Add primitives for faster access of float and tuple type objects (Richard Si, PR 13078)
  • Fix compile error related to operator assignment in a generator function (Zsolt Dollenstein, PR 13144)

Stubtest Improvements

Stubtest is a tool for testing that stubs conform to the implementations.

  • Allow ellipsis as default argument (Shantanu, PR 12838)
  • Support --version (Shantanu, PR 12852)
  • Check type variables and ParamSpecs (Shantanu, PR 12851)
  • Add error summary and other output tweaks (KotlinIsland, PR 12855)

Other Notable Fixes and Improvements

  • Disallow assignments to awaited coroutines that do not return (Shantanu, PR 12853)
  • Search sys.path for PEP 561 compliant packages (Ashley Whetter, PR 11143)
  • Treat generators with await as async (Jared Hance, PR 12925)
  • Fix bug in constraints solver regarding ParamSpec upper bounds (Alex Waygood, PR 12938)
  • Fix crash on redefined class variable annotated with Final[<type>] (Alex Waygood, PR 12951)
  • Improve handling of overloads with ParamSpec (Alex Waygood, PR 12953)
  • Don’t suggest installing types packages for some third-party packages that now include types or are obsolete (Shantanu, PR 12959)
  • Add a short note when an error may be fixed by adding an await (Ivan Levkivskyi, PR 12958)
  • Support unannotated converters for attr.ib (t4lz, PR 12815)
  • Disallow undesirable implicit reexport with a from import (Shantanu, PR 12704)
  • Fix crash when subclass method has the same name as a type alias (Wesley Collin Wright, PR 13015)
  • Include end column offset in the mypy AST (bruno messias, PR 12972)
  • Fix "attribute 'arguments' of 'FuncDef' undefined" incremental crash (Frédéric Perrin, PR 12324)
  • Fix false positive error on multiple enum base classes (Alex Waygood, PR 12963)
  • Don't add __match_args__ for dataclasses and named tuples on Python versions lower than 3.10 (Stanislav K, PR 12503)
  • Fix crash when overriding partial-type attribute with method (Jake Lishman, PR 12943)
  • Fix editable installs to current working directory (Shantanu, PR 13161)

Typeshed Updates

Typeshed is now modular and distributed as separate PyPI packages for everything except the standard library stubs. Please see git log for full list of typeshed changes.

Acknowledgements

Thanks to all mypy contributors who contributed to this release:

  • 97littleleaf11
  • Alex Waygood
  • Ashley Whetter
  • Bruno Messias
  • denballakh
  • Erik Kemperman
  • Ethan Smith
  • Fabian Keller
  • Frédéric Perrin
  • Hal Blackburn
  • Ivan Levkivskyi
  • Jake Lishman
  • Jared Hance
  • Jingchen Ye
  • KotlinIsland
  • Poruri Sai Rahul
  • Pranav Rajpal
  • Ramazan Elsunakev
  • Richard Si
  • Shantanu
  • Stanislav K
  • t4lz
  • Wesley Collin Wright

I would like to thank Ivan Levkivskyi, in particular, who did most of the preparations for this mypy release. My contribution was mainly to finish and publish this blog post.

We’d also like to thank our employer, Dropbox, for funding the mypy core team.

Wednesday, 25 May 2022

Mypy 0.960 Released

We’ve just uploaded mypy 0.960 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.

Minimal Support for LiteralString

Recognise typing.LiteralString and typing_extensions.LiteralString as aliases to str.

This does not add proper support for LiteralString, but this allows it to be used in type annotations and stubs. LiteralString will be included in Python 3.11 (PEP 675), and it can be used to require that a value is an arbitrary literal string (once fully supported).

This feature was contributed by Shantanu (PR 12559).

Per-file Timing Stats

When mypy is run with the (currently hidden) --timing-stats FILE option, mypy will record detailed information about time spent type checking each file (microseconds). When profiling mypy runs over a large codebase, it can be useful to know which files are the slowest to type check. We are happy to receive bug reports about unexpectedly slow type checking.

This feature was contributed by Hugues (PR 12639).

Performance Improvements

  • Cache type of container literals when possible (Hugues, PR 12707)
  • Speed up type checking of nested if expressions (Hugues, PR 12700)
  • Speed up type checking of container literals with tuple entries (Hugues, PR 12706)
  • Speed up argument count check (Hugues, PR 12703)
  • Speed up processing large error counts and improve error filtering (Hugues, PR 12631)

Experimental Fast Module Lookup

Use the new --fast-module-lookup to switch to an alternative import resolution implementation that is faster when a large number of folders share a top-level namespace. We’d like to hear if you notice an improvement when using this flag, so that we can potentially prioritize work to enable this by default.

This feature was contributed by Hugues (PR 12616).

Documentation Updates

  • Add information about classes and types to “Getting started” (Michael Lee, PR 6557)
  • Mention no_type_check decorator in documentation (Shantanu, PR 12713)
  • Remove most mentions of type comments from docs (Shantanu, PR 12683)
  • Use PEP 585 syntax in "The type of class objects" (Alex Waygood, PR 12516)

Improvements to Plugin System

  • Add a class attribute hook to the plugin system (Danny Weinberg, PR 9881)
  • Add an alternative class decorator hook that is less error-prone than the old one (Jukka Lehtosalo, PR 12762)

ParamSpec Improvements

  • Friendlier errors for ParamSpec (PEP 612) (Shantanu, PR 12832)
  • Fix ParamSpec crash related to Any types (EXPLOSION, PR 12548)
  • Use tuple[object, ...] and dict[str, object] as upper bounds for ParamSpec.args and ParamSpec.kwargs (Alex Waygood, PR 12668)

Fixes to Crashes

  • Fix crash on invalid Python executable (Pranav Rajpal, PR 12812)
  • Fix crash on type alias definition inside dataclass declaration (Alex Waygood, PR 12792)
  • Fix crash related to namedtuple in unannotated function (Jukka Lehtosalo, PR 12804)
  • Fix nested namedtuple crash in incremental mode (Jukka Lehtosalo, PR 12803)
  • Fix forward references and generic inheritance in attrs classes (Jukka Lehtosalo, PR 12772)
  • mypyc: Fix TypeError in lambda argument to overloaded function (Jukka Lehtosalo, PR 12780)
  • Fix crashes related to functools.total_ordering and forward references (Jukka Lehtosalo, PR 12767)
  • Fix crashes related to dataclasses and forward references (Jukka Lehtosalo, PR 12762)
  • Fix crash on invalid TypedDict definition (Alex Waygood, PR 12741)
  • Fix crash when using decorator in class scope (dzcode, PR 12724)

Other Notable Fixes and Improvements

  • Fix type annotation support of dunder methods in stubgen (Fabian Keller, PR 12828)
  • Fix some value patterns in match statements to be non-exhaustive (Štěpán Horáček, PR 12751)
  • Generate error when using both abstractmethod and final (Tomoki Nakagawa, PR 12743)
  • Add more precise error message for Callable annotation (frerikandriessen, PR 12518)
  • Fix generic inference in functions with TypeGuard (Nikita Sobolev, PR 11797)
  • Add check if python_version was parsed as float in pyproject.toml (Marcel Otoboni, PR 12558)
  • Fix nested overload merging (Marc Mueller, PR 12607)
  • stubtest: Generate error if type alias doesn't exist at runtime (Alex Waygood, PR 12608)
  • Support typing_extensions.overload (Jelle Zijlstra, PR 12602)

Typeshed Updates

Typeshed is now modular and distributed as separate PyPI packages for everything except the standard library stubs. Please see git log for full list of typeshed changes.

Acknowledgements

Thanks to all mypy contributors who contributed to this release:

  • 97littleleaf11
  • Alex Waygood
  • Danny Weinberg
  • EXPLOSION
  • Ethan Smith
  • Fabian Keller
  • Hugues
  • Ikko Ashimine
  • Jelle Zijlstra
  • Marc Mueller
  • Marcel Otoboni
  • Max Jones
  • Michael Lee
  • Nikita Sobolev
  • Shantanu
  • Tomoki Nakagawa
  • Vincent Vanlaer
  • dzcode
  • eggplants
  • frerikandriessen
  • Jared Hance
  • Pranav Rajpal
  • Štěpán Horáček

I’d also like to thank my employer, Dropbox, for funding the mypy core team.

Wednesday, 27 April 2022

Mypy 0.950 Released

We’ve just uploaded mypy 0.950 to the Python Package Index (PyPI). Mypy is a static type checker for Python. This release includes new features 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.

Pinning Third-Party Library Stub Versions

Recent third-party library stubs available via types-* packages (e.g. types-requests) are actively using recent typing features that may not be supported by older mypy releases. We recommend that if you pin mypy to a specific version, you should also pin any stub packages to a version no more recent than the mypy release. Otherwise the mypy version you use may silently fall back to Any types if it encounters annotation syntax that it can’t process. It’s fine to continue using older versions of stubs when you upgrade mypy.

Note also that recent versions of many third-party stub packages don’t support Python 2 any more. If you are using mypy to type check Python 2 code, it’s important to pin all stub packages to versions that still support Python 2. Generally stub package versions released in Feb 2022 or earlier still support Python 2 (assuming that they supported Python 2 at all).

New Features: Concatenate and Literals with ParamSpec

It’s now possible to precisely annotate decorators that add/remove arguments, using ParamSpec together with typing.Concatenate (Python 3.10 or later) or typing_extensions.Concatenate. The decorator in this example provides an implicit Request argument to the decorated function:

    from typing import ParamSpec, TypeVar, Callable, Concatenate

    P = ParamSpec("P")
    T = TypeVar(T")

    def my_decorator(f: Callable[Concatenate[Request, P], T]
                    ) -> Callable[P, T]:
        def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
            r = current_request()
            return f(r, *args, **kwargs)
        return wrapper

    @my_decorator
    def my_func(request: Request, x: int) -> str:
        # do something ...
        return ...

    def func2() -> str:
        return my_func(x=2)  # OK, the request argument is implicit

You can provide the value of a ParamSpec explicitly using the [T1, …, Tn] syntax. This example illustrates the use case:

    from typing import ParamSpec, TypeVar, Generic, Callable

    P = ParamSpec("P")
    T = TypeVar("T")

    class CallCounter(Generic[P, T]):
        def __init__(self, fn: Callable[P, T]):
            self.fn = fn
            self.count = 0

        def invoke(self, *args: P.args, **kwargs: P.kwargs) -> T:
            self.count += 1
            return self.fn(*args, **kwargs)

    # The [str] below specifies the value of P (one positional 
    # argument of type str)
    def ensure_n_calls(cc: CallCounter[[str], None], 
                       n: int, arg: str) -> None:
        while cc.count < n:
            cc.invoke(arg)

This experimental support for ParamSpec Concatenate and literals was contributed by EXPLOSION (PR 11847).

New Feature: Detect Unused Coroutines and Awaitables

Now mypy will give an error if you forget to await a coroutine:

    async def log(message: str) -> None:
        ...

    async def do_stuff() -> None:
        # Error: Value of type "Coroutine[Any, Any, None]" 
        #        must be used
        log("doing stuff")  # Oops, no "await"
        ...

If you enable the unused-awaitable error code, mypy will also complain about any unused value that supports __await__. This is not enabled by default, since this can cause false positives.

This feature was contributed by Jared Hance (PR 12279).

New Feature: assert_type

You can now use typing_extensions.assert_type to ask mypy to validate that an expression has a specific static type. Mypy will report an error if the inferred type is not as expected:

    from typing_extensions import assert_type

    assert_type([1], list[int])  # OK

    # Error: Expression is of type "List[int]", not "List[str]"
    assert_type([1], list[str])

This can be used to validate that the expected type is inferred by mypy when calling a complex overloaded function, for example. At runtime assert_type just returns the first argument and doesn’t perform a runtime type check.

This was contributed by Jelle Zijlstra (PR 12612, PR 12584).

Mypyc Fixes and Improvements

  • Fix overflow in id built-in (Ekin Dursun, PR 12332)
  • Simplify generated code for native attribute get (Jukka Lehtosalo, PR 11978)
  • Implement close method for generators (Max Shvets, PR 12042)
  • Use more accurate flags with msvc (KotlinIsland, PR 12468)
  • Fix potential memory leak with setdefault() (Jukka Lehtosalo, PR 12514)
  • Make boxed integer constants/literals faster (Jukka Lehtosalo, PR 12507)

Performance Improvements

Mypy now type checks somewhat faster, in particular when dealing with enums and unions with many items.

  • Speed up union types (Jukka Lehtosalo, PR 12541, PR 12519)
  • Speed up subtype checks (Jukka Lehtosalo, PR 12540, PR 12538, PR 12536, PR 12539)
  • Speed up type checking enums (Hugues, PR 12032)
  • Speed up union types further (Hugues, PR 12630)

Documentation Improvements

  • Use Furo theme for documentation (97littleleaf11, PR 12348)
  • Add missing enable_error_code to config documentation (Mathieu Kniewallner, PR 12346)
  • Correct example in “Annotation issues at runtime” (Alex Waygood, PR 12356)
  • Fix inaccuracy: NoneType is exposed in the types module on Python 3.10+ (Alex Waygood, PR 12515)

Stubgen Improvements

  • Fix handling of Protocol (citruz, PR 12129)
  • Use _typeshed.Incomplete instead of typing.Any (Sebastian Rittau, PR 12449)
  • Do not consider nested generators (Štěpán Horáček, PR 12463)
  • Fix behavior for instance variables in C extensions (Shubham SInghal, PR 12524)

Stubtest Improvements

  • Generate error for read-only property at runtime, but not in stub (Alex Waygood, PR 12291)
  • Enable verification of __match_args__ attributes (Alex Waygood, PR 12465)

Other Notable Fixes and Improvements

  • Use tomllib on Python 3.11 (Shantanu, PR 12305)
  • Print compilation status with --version (Shantanu, PR 12318)
  • Fix __annotations__ being undefined (Niklas Gustafsson, PR 10969)
  • Add success message for notes-only output (97littleleaf11, PR 12306)
  • dmypy: Warn instead of failing if report generation is configured (Nate McMaster, PR 10181)
  • Fix caching of PEP 561 namespace packages with missing submodules (Shantanu, PR 12250)
  • Fix empty reveal_locals output (Cibin Mathew, PR 12400)
  • Check that async for/with is inside an async function (Štěpán Horáček, PR 12418)
  • Recognize Hashable as a real protocol (Nikita Sobolev, PR 11802)
  • Remove the * for inferred types from reveal_type output (Stanislav K, PR 12459)
  • Unify a codepath in typevarlike semanal (Jared Hance, PR 12480)
  • Recognise both attrs and attr package names (Spencer Brown, PR 12469)
  • Fix Callable attributes in frozen dataclasses (Jordan Speicher, PR 12383)
  • Improve checking of __slots__ (Jukka Lehtosalo, PR 12531)
  • Avoid conflicts between type variables defined in different classes (Jukka Lehtosalo, PR 12590)
  • Fix __slots__ and __deletable__ in incremental mode (Jukka Lehtosalo, PR 12645)
  • Fix issue with ParamSpec serialization (Jukka Lehtosalo, PR 12654)
  • Fix types of inherited attributes in generic dataclasses (Jukka Lehtosalo, PR 12656)

Typeshed Updates

Typeshed is now modular and distributed as separate PyPI packages for everything except the standard library stubs. Please see git log for full list of typeshed changes.

Acknowledgements

Thanks to all mypy contributors who contributed to this release:

  • 97littleleaf11
  • Akuli
  • Alex Waygood
  • Chris Rose
  • Cibin Mathew
  • citruz
  • EXPLOSION
  • Ekin Dursun
  • Géry Ogam
  • gresm
  • Hugues
  • Ikko Ashimine
  • Jared Hance
  • Jelle Zijlstra
  • Jordan Speicher
  • Kevin Mai-Husan Chia
  • KotlinIsland
  • luzpaz
  • Marc Mueller
  • Mathieu Kniewallner
  • Max Shvets
  • mixed-source
  • Nate McMaster
  • Nikita Sobolev
  • Niklas Gustafsson
  • Petter Friberg
  • Sebastian Rittau
  • Shantanu
  • Shubham SInghal
  • Spencer Brown
  • Stanislav K
  • Stanislav Levin
  • Štěpán Horáček

I’d also like to thank my employer, Dropbox, for funding the mypy core team.

Thursday, 24 March 2022

Mypy 0.942 Released

We’ve just uploaded mypy 0.942 to the Python Package Index (PyPI). Mypy is a static type checker for Python. This release includes bug fixes only. 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.

Fixes to Regressions

  • Let overload item have a more general return type than the implementation (Jukka Lehtosalo, PR 12435)
  • Fix inheritance false positives with dataclasses/attrs (Jukka Lehtosalo, PR 12411)
  • Support overriding dunder attributes in Enum subclass (Petter Friberg, PR 12138)
  • Fix small conditional overload regression (Marc Mueller, PR 12336)

Other Fixes

  • Fix issues related to the order of processing in the builtins import cycle (Jukka Lehtosalo, PR 12431)
  • Fix crash in match statement if class name is undefined (Jukka Lehtosalo, PR 12417)
  • Allow non-final __match_args__ and overriding (Jukka Lehtosalo, PR 12415)

I’d like to thank my employer, Dropbox, for funding the mypy core team.

Friday, 11 March 2022

Mypy 0.940 Released

We’ve just uploaded mypy 0.940 to the Python Package Index (PyPI). Mypy is a static type checker for Python. This release includes new features 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.

Match Statement

Mypy now has experimental support for type checking match statements introduced in Python 3.10.

Mypy can perform exhaustiveness checking to detect whether a match statement covers all possible values, if the target value has a union type or an enum type:

    def empty_value(x: int | str) -> str:
        match x:
            case str():
                # Type of "x" is "str" here
                return '""'
            case int():
                # Type of "x" is "int" here
                return "0"
        # No error about missing return statement (unreachable)

Note that exhaustiveness checking is still not generally supported across class hierarchies, since mypy doesn’t support sealed classes with a fixed set of subclasses. You can use an union type or assert False as a workaround:

    class Base(metaclass=ABCMeta): ...

    class A(Base): ...
    class B(Base): ...

    def process(x: A | B) -> bool:
        match x:
            case A():
                ...
            case B():
                ...
        # Mypy knows that this is unrachable.

    def process2(x: Base) -> bool:
        match x:
            case A():
                ...
            case B():
                ...
        # Use "assert False" to silence error about missing import,
        # since mypy can't prove that code is unreachable.
        assert False

You can also use an “assert never” function for more explicit exhaustiveness checks with match statements, as discussed in the documentation.

This feature was contributed by Adrian Freund (PR 12267, PR 10191), with additional updates by Jukka Lehtosalo.

Python 2 End-of-Life Schedule

After this release, Python 2 support is in feature freeze. Mypy won’t add new features or fixes specific to type checking Python 2 code, expect for fixes of significant regressions.

Mypy will drop Python 2 support in the second half of 2022.

Important note: Since typeshed is in the process of removing Python 2 specific stubs, you should pin all installed typeshed stub packages for third-party libraries to a version from Feb 2022 or earlier if you want to type check Python 2 code.

Miscellaneous New Features

  • Add support for conditionally defined overloads (Marc Mueller, PR 10712)
  • Give "as" variables in with statements separate scopes when it is safe to do so (Jukka Lehtosalo, PR 12254)
  • Add an optional error code ignore-without-code to require ignore comments to have error codes (Peter Law, PR 11633)
  • Add support for typing.Never and typing_extensions.Never as alternative spellings of NoReturn (Jelle Zijlstra, PR 12153)
  • Add support for typing.reveal_type (Jelle Zijlstra, PR 12117)
  • Support universal2 macOS wheels (97littleleaf11, PR 10651)
  • Add match_args support to attr.s() (Nikita Sobolev, PR 12111)

Enum Improvements

  • Check Enum definition for invalid base classes (Nikita Sobolev, PR 12026)
  • Understand the self-destructing nature of Enum._ignore_ (Kenny Stauffer, PR 12128)
  • Add StrEnum support for Python 3.11 (Nikita Sobolev, PR 12035)
  • Make enum values final (joey-laminar, PR 11962)
  • Improve final detection for Enum (Nikita Sobolev, PR 11984)
  • Fix Enum final properties and writable special members (Nikita Sobolev, PR 11945)
  • Enum now accepts String literals and final values as 2nd argument (Vincent Perez, PR 8664)
  • Fix false positive about member name reuse in enum (Max Rossmannek, PR 11972)
  • Fix enum inheritance regression (Nikita Sobolev, PR 12260)

Mypyc Fixes and Improvements

  • Use Py_TYPE and Py_IsNone (97littleleaf11, PR 12233)
  • Implement additional internal consistency checks (Jared Hance, PR 12191)
  • Raise AttributeError also for non-refcounted types (Jukka Lehtosalo, PR 11940)
  • Fix invalid unlikely() in certain rare branches (Jukka Lehtosalo, PR 11939)
  • Skip no-op super calls to object.__init__() (Jukka Lehtosalo, PR 11938)
  • Use latest pythoncapi_compat (97littleleaf11, PR 12188)
  • Add helpful message to assert (Joshua Cannon, PR 12119)

Documentation Updates

  • Add documentations about Enum types (Nikita Sobolev, PR 11805)
  • Update Enum documentation (Nikita Sobolev, PR 12238)
  • Improve documentation of allow_redefinition (KotlinIsland, PR 11951)
  • Fix intelligent indexing example (Chris Keefe, PR 11973)
  • Explain generic Protocol[T1, T2, ...] shorthand (Matt Bogosian, PR 12047)
  • Clarify that stub-only packages need to be installed (Gustav Gränsbo, PR 9958)
  • Small documentation improvements for conditional overloads (Marc Mueller, PR 12283)

Improved Error Messages

  • Improve the "Argument must be a mapping" error message (Purna Chandra Mansingh, PR 12222)
  • Coalesce Literals when printing unions (Marti Raudsepp, PR 12205)
  • Suggest typing.Callable when using callable as type (Tuomas Siipola, PR 12204)
  • Suggest typing.Any when using any as type (Tuomas Siipola, PR 12185)
  • Add note about wrong error code in type: ignore (Jukka Lehtosalo, PR 12067)
  • Add no-overload-impl error code (Brian Phillips, PR 11944)
  • Display ellipsis when formatting variadic tuple[T, ...] (Marti Raudsepp, PR 11857)
  • Deduplicate error codes for ignore-without-code (Marc Mueller, PR 12194)
  • Tweak ignore-without-code error message (Marc Mueller, PR 12216)
  • Mention common resolutions for build errors (Shantanu, PR 12154)

Stubtest Improvements

  • Ignore more dunder positional-only errors (Shantanu, PR 12294)
  • Fix wrong assumption about relative path (Stanislav Levin, PR 12282)
  • Catch more getattr errors (Shantanu, PR 12219)
  • Error if module level dunder is missing, housekeeping (Shantanu, PR 12217)
  • Ignore __main__ module (Shantanu, PR 12218)
  • Error if a dunder method is missing from a stub (Alex Waygood, PR 12203)
  • Error if a function is async at runtime but not in the stub (and vice versa) (Alex Waygood, PR 12212)
  • Do not error if a stub is async, but runtime is not (Alex Waygood, PR 12234)
  • Error if a class should be decorated with @final (Akuli, PR 12091)
  • Use VERSIONS for submodules (Shantanu, PR 12083)
  • Treat dicts as a subtype of typeddict (Shantanu, PR 12040)
  • Ignore more exceptions in stubtest (Jelle Zijlstra, PR 11946)

Other Notable Fixes and Improvements

  • Fix non-default keyword-only argument positioning in stubgen (Štěpán Horáček, PR 12303)
  • Remove orjson stubs from default list (Shantanu, PR 12264)
  • Use __truediv__ for Python 2 with __future__ import (Nikita Sobolev, PR 11787)
  • Fix Python 2 compatibility issue (Shantanu, PR 12244)
  • Use type variable bound to infer constraints (Jukka Lehtosalo, PR 12230)
  • Handle raise Exception(), None on Python 2.7 (Nikita Sobolev, PR 11786)
  • Fix inference of protocol against overloaded function (Jukka Lehtosalo, PR 12227)
  • Fix an issubclass failure for protocols with overloaded methods (Bas van Beek, PR 9904)
  • Fix crashes in class scoped imports (PR 12199, PR 12023) (Shantanu)
  • Fix use of TypeAlias from aliased imports (Shantanu, PR 12180)
  • Delete open plugin (Shantanu, PR 9275)
  • Read pyproject.toml with correct encoding on Windows (Dominic Davis-Foster, PR 12105)
  • Fix issue with implicit type aliases in import cycles (but only for stubs) (Alex Waygood, PR 11915)
  • Forbid extra ParamSpec arguments (Nikita Sobolev, PR 12024)
  • Fix crash involving explicit any flag and Required (Mehdi Drissi, PR 12039)
  • Fix join of Any against a union type (Jukka Lehtosalo, PR 12068)
  • Simplify unions when erasing last known values (Jukka Lehtosalo, PR 12064)
  • Fix crash with yield in comprehension (Alexandre Bouayad, PR 12048)
  • Fix handling of NoReturn in union return types (Jannic Warken, PR 11996)
  • Fix __init__ in dataclasses inheriting from Any (joey-laminar, PR 11966)
  • Narrow NamedTuple to bool correctly when __bool__ is defined (Nikita Sobolev, PR 11822)
  • Improve type of __attrs_attrs__ in attrs classes (Tin Tvrtković, PR 11794)
  • Install dependencies needed for reports via pip install mypy[reports] (James Braza, PR 11777)
  • Consider import * to be an explicit re-export (Shantanu, PR 11867)
  • Fix --no-implicit-reexport inconsistency (Shantanu, PR 11707)
  • Fix crash if "_" is in builtins (StefanM-TT, PR 11811)
  • Fixes crash on subclassing Annotated without args (Nikita Sobolev, PR 11814)

Typeshed Updates

Typeshed is now modular and distributed as separate PyPI packages for everything except the standard library stubs. Please see git log for full list of typeshed changes.

Acknowledgements

Thanks to all mypy contributors who contributed to this release:

  • 97littleleaf11
  • Adrian Freund
  • Akuli
  • Alex Waygood
  • Alexandre Bouayad
  • Anthony Sottile
  • Bas van Beek
  • Brian Phillips
  • Chris Keefe
  • Dominic Davis-Foster
  • Gustav Gränsbo
  • James Braza
  • Jannic Warken
  • Jared Hance
  • Jelle Zijlstra
  • joey-laminar
  • Joshua Cannon
  • Kenny Stauffer
  • KotlinIsland
  • Marc Mueller
  • Mark Bell
  • Marti Raudsepp
  • Matt Bogosian
  • Max Rossmannek
  • Mehdi Drissi
  • Michael R. Crusoe
  • Nikita Sobolev
  • Oliver Newman
  • Peter Law
  • Purna Chandra Mansingh
  • Shantanu
  • Stanislav Levin
  • StefanM-TT
  • Tin Tvrtković
  • Tuomas Siipola
  • Vincent Perez
  • Štěpán Horáček

I’d also like to thank my employer, Dropbox, for funding the mypy core team.