First steps
Type system reference
Configuring and running mypy
Miscellaneous
Project Links
Astub file is a file containing a skeleton of the public interfaceof that Python module, including classes, variables, functions – andmost importantly, their types.
Mypy uses stub files stored in thetypeshed repository to determinethe types of standard library and third-party library functions, classes,and other definitions. You can also create your own stubs that will beused to type check your code.
Here is an overview of how to create a stub file:
Write a stub file for the library (or an arbitrary module) and store it asa.pyi file in the same directory as the library module.
Alternatively, put your stubs (.pyi files) in a directoryreserved for stubs (e.g.,myproject/stubs). In this case youhave to set the environment variableMYPYPATH to refer to thedirectory. For example:
$ export MYPYPATH=~/work/myproject/stubs
Use the normal Python file name conventions for modules, e.g.csv.pyifor modulecsv. Use a subdirectory with__init__.pyi for packages. NotethatPEP 561 stub-only packages must be installed, and may not be pointedat through theMYPYPATH (seePEP 561 support).
If a directory contains both a.py and a.pyi file for thesame module, the.pyi file takes precedence. This way you caneasily add annotations for a module even if you don’t want to modifythe source code. This can be useful, for example, if you use 3rd partyopen source libraries in your program (and there are no stubs intypeshed yet).
That’s it!
Now you can access the module in mypy programs and type checkcode that uses the library. If you write a stub for a library module,consider making it available for other programmers that use mypyby contributing it back to the typeshed repo.
Mypy also ships with two tools for making it easier to create and maintainstubs:Automatic stub generation (stubgen) andAutomatic stub testing (stubtest).
The following sections explain the kinds of type annotations you can usein your programs and stub files.
Note
You may be tempted to pointMYPYPATH to the standard library orto thesite-packages directory where your 3rd party packagesare installed. This is almost always a bad idea – you will likelyget tons of error messages about code you didn’t write and thatmypy can’t analyze all that well yet, and in the worst casescenario mypy may crash due to some construct in a 3rd partypackage that it didn’t expect.
Stub files are written in normal Python syntax, but generallyleaving out runtime logic like variable initializers, function bodies,and default arguments.
If it is not possible to completely leave out some piece of runtimelogic, the recommended convention is to replace or elide them with ellipsisexpressions (...). Each ellipsis below is literally written in thestub file as three dots:
# Variables with annotations do not need to be assigned a value.# So by convention, we omit them in the stub file.x:int# Function bodies cannot be completely removed. By convention,# we replace them with `...` instead of the `pass` statement.deffunc_1(code:str)->int:...# We can do the same with default arguments.deffunc_2(a:int,b:int=...)->int:...
Note
The ellipsis... is also used with a different meaning incallable types andtuple types.
You may also occasionally need to elide actual logic in regularPython code – for example, when writing methods inoverload variants orcustom protocols.
The recommended style is to use ellipses to do so, just like instub files. It is also considered stylistically acceptable tothrow aNotImplementedError in cases where the user of thecode may accidentally call functions with no actual logic.
You can also elide default arguments as long as the function bodyalso contains no runtime logic: the function body only containsa single ellipsis, the pass statement, or araiseNotImplementedError().It is also acceptable for the function body to contain a docstring.For example:
fromtypingimportProtocolclassResource(Protocol):defok_1(self,foo:list[str]=...)->None:...defok_2(self,foo:list[str]=...)->None:raiseNotImplementedError()defok_3(self,foo:list[str]=...)->None:"""Some docstring"""pass# Error: Incompatible default for argument "foo" (default has# type "ellipsis", argument has type "list[str]")defnot_ok(self,foo:list[str]=...)->None:print(foo)