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.
