-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
There are a few use cases when stubs may be compelling over type annotations or type comments:
- annotate code that needs to be Python 2 compatible, ideally by using type annotations (so no type comments),
- often times users prefer to have type information outside of the source code (this is to avoid modifying legacy code change - and in practice lowers resistance from maintainers),
- the maintainer of the library does not want to take on the in-line type annotations, someone else trying to provide it as a separate package.
However at the moment this has some limitations: stub files are used only to check clients of the stub, not the code itself.
# a.py
def add_int(a, b):
return a + b
add_int("a", "b") # mypy does not complain, actually ignores the entire file# a.pyi
def add_int(a:int, b:int) -> int: ...# client.py
from a import add_int
add_int(1, 2)
add_int(1, "2") # here mypy is going to complainIn case of the above files mypy will warn about bad usage of inside client.py, but not in a.py (that is, mypy does not validate against the source files being annotated by the stub). This has serious drawbacks:
- maintaining the stub files is hard, now users need to manually make sure whatever is in the stub file is an accurate representation of the matching source files (both interface - aka number of arguments, names - and type wise),
- the stub creator does not know if the source code itself is type correct or not.
Here I propose to implement a way to support testing stub files against the real code:
- build the syntax tree for the source file,
- build the syntax tree for the stub file,
- merge stub tree into the source tree
- source file only tree available: dynamically typed - noop
- abstract syntax tree only: raise error - missing annotated sources
- both stub and source AST exists:
- for all source elements for what there is a matching stub element
- copy inject over type annotations
- complain if function interface missmatch
- for all source elements for what there is a matching stub element
- now just run the existing type checking mechanism on the enriched source code ast
Merging the AST definitely is not trivial. The plan is to start with a POC implementation, that works for the most cases, and then see the viability of this approach. Note this would help a lot both stub maintainers I think (typeshed) and projects that need Python 2 support.