-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Implementation Overview
This is a general introduction to the mypy implementation. The linked subpages have more detailed information. The file links point to the mypy git repository.
The main entry point of mypy is mypy/main.py. This file is responsible for parsing the config file, parsing command line options, and handling other related boilerplate.
The flow of execution is then passed off to the Build Manager (mypy/build.py), which is responsible for coordinating a build, managing dependencies between modules, and performing compilation passes in the correct order.
The build manager will then perform several passes over each module to typecheck them (see the process_graph
function for more details).
Common passes:
-
Python Parser (mypy/parse.py, mypy/fastparse.py, mypy/fastparse2.py)
- Uses the typed_ast to build an abstract syntax tree (AST). The typed_ast library is nearly identical to CPython's "ast" module except that it has better support for parsing things like type comments.
- This AST is then converted into mypy-specific parse tree, which is defined in the files mypy/nodes.py and mypy/types.py
-
Semantic Analyzer (mypy/semanal.py, mypy/semanal_*.py, mypy/typeanal.py)
- Binds names to definitions
- Performs various consistency checks
-
Type Checker (mypy/checker.py, mypy/checkexpr.py, mypy/checkmember.py)
- Type checks the program
- Performs type inference
NOTE: We're moving away from runtests.py and towards pytest. But the migration isn't finished yet. Up to date docs for tests are in the repo at test-data/unit/README.md. The docs below are out of date and unmaintained.
The file runtests.py
runs all the tests. Test suites for individual components are in the files mypy/test/test*.py
. You can run many of these individually by doing runtests.py testfoobar
. Type checker test cases (testcheck.py
) have been migrated to pytest and you can run them using py.test mypy
. (We are planning to migrate all test cases to pytest eventually -- any help is appreciated here.)
Many test suites store test case descriptions in text files (test-data/unit/*.test
). The module mypy.test.data
parses these descriptions. The package mypy.myunit
contains the test framework used for the non-checker test cases. The unit tests use minimal stubs for builtins, so a lot of operations are not possible. You should generally define any needed classes within the test case instead of relying on builtins, though clearly this is not always an option (see below for more about stubs in test cases). This
way tests run much faster and don't break if the stubs change. If your test crashes mysteriously even though the code works when run manually, you should make sure you have all the stubs you need for your test case, including built-in classes such as list
or dict
, as these are not included by default.
Notes about test cases:
- Python evaluation test cases are a little different from unit tests (
mypy/test/testpythoneval.py
,test-data/unit/pythoneval.test
). These type check programs and run them. Unlike the unit tests, these use the full builtins and library stubs instead of minimal ones. Run them usingruntests.py testpythoneval
.
More things (this should be expanded):
- You can run just a subset of tests by giving a wildcard argument, e.g.
runtests.py unit-test -a "*Overload*"
to run all unit tests withOverload
as a substring. - The builtins used by default in unit tests live in
test-data/unit/lib-stub
. Individual tests cases can override the stubs by using[builtins fixtures/foo.py]
; this targets files intest-data/unit/fixtures
. You are free add additional stubs to this directory, but generally don't update files inlib-stub
without first discussing the addition with other mypy developers, as additions could slow down the test suite.