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
- setup.py
- package_a/
- __init__.py
- lib.py
- py.typed
the setup.py
might look like
- from distutils.core import setup
- setup(
- name="SuperPackageA",
- author="Me",
- version="0.1",
- package_data={"package_a": ["py.typed"]},
- packages=["package_a"]
- )
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
- setup.py
- package_b/
- __init__.py
- lib.py
- lib.pyi
- py.typed
the setup.py
might look like:
- from distutils.core import setup
- setup(
- name="SuperPackageB",
- author="Me",
- version="0.1",
- package_data={"package_b": ["py.typed", "lib.pyi"]},
- packages=["package_b"]
- )
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:
- setup.py
- package_c-stubs/
- __init__.pyi
- lib.pyi
the setup.py
might look like:
- from distutils.core import setup
- setup(
- name="SuperPackageC",
- author="Me",
- version="0.1",
- package_data={"package_c-stubs": ["__init__.pyi", "lib.pyi"]},
- packages=["package_c-stubs"]
- )