Thursday, 14 July 2016

Mypy 0.4.3 Released

I just uploaded version 0.4.3 of mypy-lang to PyPI! This release adds several new features (some of which are still experimental), bug fixes and library stub updates.

Run this to upgrade to the new release using pip:

    python3 -m pip install -U mypy-lang

Strict Checking of Optional Types

Mypy now supports strict checking of optional types (enable it through --strict-optional). The option makes mypy check that you don’t try to perform unsupported operations on None values, and that you don’t use None values when a non-Optional value is expected.

This feature is still experimental and has known issues. Our intention is to turn this on by default in a future mypy release, once it works well enough.

Here is an example buggy program that mypy will reject only if you use --strict-optional:

    from typing import Optional, List

    def read_data_file(path: Optional[str]) -> List[str]:
        with open(path) as f:  # Error
            return f.read().split(',')

Mypy will rightly complain about the program, since open() does not accept a None argument — and path may be None. Luckily, it’s easy to fix the program:

    from typing import Optional, List

    DEFAULT_PATH = '...'

    def read_data_file(path: Optional[str]) -> List[str]:
        if not path:
            path = DEFAULT_PATH
        with open(path) as f:  # OK!
            return f.read().split(',')

Mypy recognizes that if the not path condition isn’t true and the if statement body is not executed, path won’t be None. It also knows that after the assignment statement that I added path can’t be None, so now the open(path) call is always safe, no matter which execution path is taken.

The example shows that mypy can do pretty clever reasoning about code. Mypy also knows about other kinds of None checks — go ahead and give it a try.

Multi-line Comment Function Annotation Syntax

You can now use an alternative per-argument comment annotation syntax for code that needs to be Python 2 compatible. Previously, functions with a long argument list resulted in overly long type comments and it was tricky to see which argument type corresponds to which argument.

Note: This only works when using --fast-parser. This isn’t supported on Windows yet. (We intend to use --fast-parser by default in a future release, but only once it works on Windows.)

Here is an example (from PEP 484):

    def send_email(address,     # type: Union[str, List[str]]
                   sender,      # type: str
                   cc,          # type: Optional[List[str]]
                   bcc,         # type: Optional[List[str]]
                   subject='',
                   body=None    # type: List[str]
                   ):
        # type: (...) -> bool
        """Send an email message.  Return True iff successful."""
        <code>

Additional Changes

Here are the remaining notable changes in this release:

  • Improve how mypy deals with module cycles. When adding a new module to a cycle, mypy is less likely to generate unrelated-looking errors from other modules in the cycle.
  • Mypy more aggressively infers types for variables initialized with literals, instead of requiring a dummy annotation. Previously you sometimes had to write code like x = 0 # type: int which was a little silly.
  • Infer types from multiple isinstance checks or’ed together, such as isinstance(x, int) or isinstance(x, str). The inferred type is a union type.
  • Add option --warn-unused-ignores that gives a warning if you use # type: ignore on a line that actually doesn’t generate an error and thus may be redundant.
  • Add option --warn-redundant-casts that gives a warning if you have a cast that is superfluous and can be removed without generating an error.
  • Fixes and improvements to incremental type checking. Add option --cache-dir for specifying a custom custom incremental cache directory. Note that incremental type checking is still experimental.
  • Fixes to Type[C].
  • Other bug fixes.
  • Typeshed stub updates.
  • Python 3.2 is no longer officially supported for running mypy. (This does not affect type checking Python 3.2 programs.)

Acknowledgements

Thanks to all mypy contributors who contributed to this release:

  • Carol Willing
  • Eric Price
  • Herbert Ho
  • Max Wittek
  • Michael Lee
  • Russ Allbery

Additional thanks to typeshed contributors:

  • Alvaro Caceres
  • Amandine Lee
  • Amit Saha
  • Brett Cannon
  • Dakkaron
  • Drew Haven
  • Eklavya Sharma
  • Elazar
  • Fu Yong Quah
  • Herbert Ho
  • Håken Lid
  • Matthias Kramm
  • Michael Lee
  • Mickaël S
  • Oren Leaffer
  • Phil Jones
  • Philip House
  • Russ Allbery
  • Skip Montanaro
  • Valérian Rousset
  • garetht
  • tewe
  • Thomas Cellerier

- Jukka (on behalf of the rest of the mypy team: Guido, David, Greg and Reid)