For the last few days, I have been adding type annotations 
<https://mypy.readthedocs.io/en/latest/#overview-type-system-reference> for 
mypy <https://mypy.readthedocs.io/en/latest/>. mypy has gone from being 
mysterious to just another tool.

This Engineering Notebook post discusses what I have learned and what 
remains to do.

*tl;dr:* Read the summary

*Settings*

At first, mypy's operation seemed mysterious to me. Using the proper 
settings helped a lot.

The following settings appear in .mypy.ini 
<https://mypy.readthedocs.io/en/latest/config_file.html#the-mypy-configuration-file>
 
in the ekr-annotate branch. They will eventually migrate into devel:

check_untyped_defs = True 

By default, this setting is False, which means that mypy only checks 
functions and methods that contain type annotations. No wonder it didn't 
seem like mypy was doing anything :-)

strict_optional = False 

If False, mypy treats None as compatible with every type. False by default 
in mypy versions earlier than 0.600. This option eliminates a lot of 
spurious warnings.

incremental = True
True is the default, and there seems no reason to change it.  When True, 
mypy caches type data.

cache_dir = mypy_stubs

Leo's .gitignore file contains mypy_stubs/, so git will never this 
directory. Imo, this is as it should be.

show_error_codes = True

This setting shows the error codes in mypy complaints. You can suppress 
only a particular error code by adding the # type:ignore[some-error-code].

follow_imports = skip

By default (in .mypy.ini) this setting is True. However, setting this to 
skip is useful for Qt wrapper files.

*Using mypy*

Using mypy is straightforward, provided check_untyped_defs is True and 
strict_optional is False :-)  With these settings, mypy works much like 
pylint.

To check all of Leo, it suffices to do:

mypy launchLeo.py

To limit checking to a particular file, say leoAst.py, do:

mypy leo\core\leoApp.py --follow-imports=skip

As you will soon learn, mypy requires annotations for many dicts and lists. 
mypy typically does *not* need help inferring the types of other local vars 
in functions and methods.

To increase the strength of type checking, one should add annotations for 
signatures.  

To annotate p, do something this:

from leo.core import leoNodes
Pos = "leoNodes.Position"
...
def f1(self, p: Pos):

To annotate c, do something like this:

from leo.core.leoCommands import Commands as Cmdr
...
def f2(self, c: Cmdr):

It's easy to annotate Leo's convention for s, i, etc.

def f3(self, s: str, i: int):

*Stub files*

Imo, stub files have outlived their usefulness. It's simpler and more 
explicit to use annotations in Leo. For this reason, I plan to wind down my 
make_stub_files project.

I have abandoned the effort to create a mypy plugin to make Leo's 
conventions available directly to mypy. I have updated #1944 
<https://github.com/leo-editor/leo-editor/issues/1944> accordingly.

*Summary*

*.mypy.ini* contains default settings. Learning which defaults to use made 
mypy much less mysterious. Type annotations allow mypy to find errors that 
pylint can't find. 

After an initial learning period, mypy is about as easy to use as pylint:

- mypy supports gradual type checking. We can add annotations gradually.
- It's easy to make Leo's naming conventions available to mypy. 
- Imo, stub files are no longer useful in the python 3 world. I shall wind 
down my make_stub_files <https://github.com/edreamleo/make-stub-files> 
project.

All comments and questions are welcome.

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/leo-editor/cbd7bfe7-17e7-4a5b-a9d7-6e68515fb9cdn%40googlegroups.com.

Reply via email to