Making PEP 561 compatible packages

PEP 561 notes three main ways to distribute type information. The first is apackage that has only inline type annotations in the code itself. The second isa package that ships stub files with type informationalongside the runtime code. The third method, also known as a “stub onlypackage” is a package that ships type information for a package separately asstub files.

If you would like to publish a library package to a package repository (e.g.PyPI) for either internal or external use in type checking, packages thatsupply type information via type comments or annotations in the code should puta py.typed file in their package directory. For example, with a directorystructure as follows

  1. setup.py
  2. package_a/
  3. __init__.py
  4. lib.py
  5. py.typed

the setup.py might look like

  1. from distutils.core import setup
  2.  
  3. setup(
  4. name="SuperPackageA",
  5. author="Me",
  6. version="0.1",
  7. package_data={"package_a": ["py.typed"]},
  8. packages=["package_a"]
  9. )

Note

If you use setuptools, you must pass the option zip_safe=False tosetup(), or mypy will not be able to find the installed package.

Some packages have a mix of stub files and runtime files. These packages alsorequire a py.typed file. An example can be seen below

  1. setup.py
  2. package_b/
  3. __init__.py
  4. lib.py
  5. lib.pyi
  6. py.typed

the setup.py might look like:

  1. from distutils.core import setup
  2.  
  3. setup(
  4. name="SuperPackageB",
  5. author="Me",
  6. version="0.1",
  7. package_data={"package_b": ["py.typed", "lib.pyi"]},
  8. packages=["package_b"]
  9. )

In this example, both lib.py and the lib.pyi stub file exist. Atruntime, the Python interpreter will use lib.py, but mypy will uselib.pyi instead.

If the package is stub-only (not imported at runtime), the package should havea prefix of the runtime package name and a suffix of -stubs.A py.typed file is not needed for stub-only packages. For example, if wehad stubs for package_c, we might do the following:

  1. setup.py
  2. package_c-stubs/
  3. __init__.pyi
  4. lib.pyi

the setup.py might look like:

  1. from distutils.core import setup
  2.  
  3. setup(
  4. name="SuperPackageC",
  5. author="Me",
  6. version="0.1",
  7. package_data={"package_c-stubs": ["__init__.pyi", "lib.pyi"]},
  8. packages=["package_c-stubs"]
  9. )