app/notes/20171103-0656.md
MyPy Review
mypy-review
1509692197
I recently added type annotations to two of my projects [git-browse](https://github.com/albertyw/git-browse)
and [git-reviewers](https://github.com/albertyw/git-reviewers) using
[mypy](https://github.com/python/mypy) and found it to
be relatively enjoyable. Adding types to python definitely helps to make code
self-documenting and effectively increases the number of tests in your code.
There are a few large issues though for anyone trying to add type annotations:
1. In order to use python's type annotation syntax (rather than type comments),
your code must be Python 3 only. (Yes, you should use python 3 regardless of whether
you're adding type annotations)
2. You must have library stubs of your imports so that MyPy can infer types.
So far, there are very few library stubs available and even some extremely
popular packages like Flask aren't covered. This limits type checking to
packages with few if any external dependencies.
Adding in type annotations, I also ran into a few issues:
1. The [docs](http://mypy.readthedocs.io/en/stable/index.html) are quite good
but given python typing's obscurity, it's still hard to find answers for more
esoteric features.
2. The syntax for default values, e.g. (from the mypy docs):
```python
def greeting(name: str, prefix: str = 'Mr.') -> str:
return 'Hello, {} {}'.format(name, prefix)
```
puts the default value after the type annotation. For a person who hasn't
worked with the type syntax before, at first glance it looks like a string
value is being assigned to `str` within a dictionary.
3. MyPy requires newly instantiated empty iterables (lists, sets, dictionaries)
to include annotations so it can type check elements. However, the native
python syntax has no support for it which requires adding type comments,
resulting in:
```python
data = [] # type: List[int]
```
4. The comment syntax has a bug where its types require imports which
set off linters like Flake8 as an unused import. From the above example, this
ends up requiring odd code to pass both the flake8 linter and mypy:
```python
from types import List # NOQA
data = [] # type: List[int]
```
MyPy is still under heavy development with significant hands-on support from
[Guido van Rossum](https://github.com/gvanrossum) himself. Overall though,
adding in types was still a relatively easy and useful exercise
and helped prompt some refactorings.
PS - Turns out that python-markdown2 has a [bug when rendering code fences
inside of lists](https://github.com/trentm/python-markdown2/issues/276).