Skip to content

Commit 8817cb3

Browse files
authored
Advice for writing and maintaining stub files (#1167)
1 parent 11cf5d6 commit 8817cb3

File tree

4 files changed

+112
-5
lines changed

4 files changed

+112
-5
lines changed

docs/source/guides.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ Type System Guides
77
:caption: Contents:
88

99
libraries
10+
writing_stubs
1011
unreachable

docs/source/libraries.rst

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,8 @@ library:
4141

4242
Inline type annotations simply refers to the use of annotations within your
4343
``.py`` files. In contrast, with type stub files, type information lives in
44-
separate ``.pyi`` files; see :ref:`stubs` for more details.
45-
46-
..
47-
TODO: link to a guide for writing stubs above
44+
separate ``.pyi`` files; see :ref:`stubs` and :ref:`writing_stubs` for more
45+
details.
4846

4947
We recommend using the inline type annotations approach, since it has the
5048
following benefits:

docs/source/quality.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.. _tools:
1+
.. _testing:
22

33
********************************************
44
Testing and Ensuring Type Annotation Quality

docs/source/writing_stubs.rst

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
.. _writing_stubs:
2+
3+
**********************************
4+
Writing and Maintaining Stub Files
5+
**********************************
6+
7+
Stub files are a means of providing type information for Python modules.
8+
For a full reference, refer to :ref:`stubs`.
9+
10+
Maintaining stubs can be a little cumbersome because they are separated from the
11+
implementation. This page lists some tools that make writing and maintaining
12+
stubs less painful.
13+
14+
Tools for generating stubs
15+
==========================
16+
17+
stubgen
18+
-------
19+
20+
stubgen is a tool bundled with `mypy <https://github.com/python/mypy>`__
21+
that can be used to generate basic stubs. These stubs serve as a
22+
basic starting point; most types will default to ``Any``.
23+
24+
.. code-block:: console
25+
26+
stubgen -p my_great_package
27+
28+
For more details, see `stubgen docs <https://mypy.readthedocs.io/en/stable/stubgen.html>`__.
29+
30+
pyright
31+
-------
32+
33+
pyright contains a tool that generates basic stubs. Like stubgen, these generated
34+
stubs serve more as a starting point.
35+
36+
.. code-block:: console
37+
38+
pyright --createstub my_great_package
39+
40+
For more details, see `pyright docs <https://github.com/microsoft/pyright/blob/main/docs/type-stubs.md#generating-type-stubs-from-command-line>`__.
41+
42+
monkeytype
43+
----------
44+
45+
monkeytype takes a slightly different approach — you run your code (perhaps via
46+
your tests) and monkeytype collects the types it observes at runtime to generate
47+
stubs.
48+
49+
.. code-block:: console
50+
51+
monkeytype run script.py
52+
monkeytype stub my_great_package
53+
54+
For more details, see `monkeytype docs <https://monkeytype.readthedocs.io/en/latest/>`__.
55+
56+
Tools for maintaining stubs
57+
===========================
58+
59+
stubtest
60+
--------
61+
62+
stubtest is a tool bundled with `mypy <https://github.com/python/mypy>`__.
63+
64+
stubtest finds inconsistencies between stub files and the implementation. It
65+
does this by comparing stub definitions to what it finds from importing your
66+
code and using runtime introspection (via the ``inspect`` module).
67+
68+
.. code-block:: console
69+
70+
stubtest my_great_package
71+
72+
For more details, see `stubtest docs <https://mypy.readthedocs.io/en/stable/stubtest.html>`__.
73+
74+
flake8-pyi
75+
----------
76+
77+
flake8-pyi is a `flake8 <https://flake8.pycqa.org/en/latest/>`__ plugin that
78+
lints common issues in stub files.
79+
80+
.. code-block:: console
81+
82+
flake8 my_great_package
83+
84+
For more details, see `flake8-pyi docs <https://github.com/PyCQA/flake8-pyi>`__.
85+
86+
Running a type checker on the stubs
87+
-----------------------------------
88+
89+
Simply running a type checker on the stubs can catch several issues, from simple
90+
things like detecting missing annotations to more complex things like ensuring
91+
Liskov substitutability or detecting problematic overloads.
92+
93+
It may be instructive to examine `typeshed <https://github.com/python/typeshed/>`__'s
94+
`setup for testing stubs <https://github.com/python/typeshed/blob/master/tests/README.md>`__.
95+
96+
..
97+
TODO: consider adding examples and configurations for specific type checkers
98+
99+
Type checking usage of your package
100+
-----------------------------------
101+
102+
If you have access to a codebase that uses your package — perhaps tests for your
103+
package — running a type checker against it can help you detect issues,
104+
particularly with false positives.
105+
106+
If your package has some particularly complex aspects, you could even consider
107+
writing dedicated typing tests for tricky definitions. For more details, see
108+
:ref:`testing`.

0 commit comments

Comments
 (0)