Add scripts for generating type stubs reflecting runtime module layout#1519
Add scripts for generating type stubs reflecting runtime module layout#1519matejmatuska wants to merge 6 commits into
Conversation
Thank you for contributing to the Leapp project!Please note that every PR needs to comply with the leapp-repository contribution and development guidelines and must pass all tests in order to be mergeable.
Packit will automatically schedule regression tests for this PR's build and latest upstream leapp build.
Note that first time contributors cannot run tests automatically - they need to be started by a reviewer. It is possible to schedule specific on-demand tests as well. Currently 2 test sets are supported,
See other labels for particular jobs defined in the Please open ticket in case you experience technical problem with the CI. (RH internal only) Note: In case there are problems with tests not being triggered automatically on new PR/commit or pending for a long time, please contact leapp-infra. |
3fc12c8 to
18aa233
Compare
pirat89
left a comment
There was a problem hiding this comment.
just preventive block - to no forget to fix commits before the merge :-D
|
Just to clarify, this doesn't make mypy work very good. mypy is not very good at merging definitions from the source file with definitions in the type stub file (pyright is quite good at that). Furthermore the leapp-repository codebase as well as the leapp framework codebase have almost no type annotations. It is possible to make it work relatively OK, however there is a lot of noise. That said it works quite nice with pyright, which was the primary goal of the work. We can expand in the future. |
| :glob: | ||
|
|
||
| setup-devel-env | ||
| setup-devel-tools |
There was a problem hiding this comment.
@matejmatuska thematically it should be be part of setup-devel-env
There was a problem hiding this comment.
Yeah I was thinking about that, but I am not sure if it fits there, the dev env is means something a little different there.
| @@ -0,0 +1,19 @@ | |||
| # Making development tools work | |||
There was a problem hiding this comment.
We should use a different title. What about something like: Tweaks for type checking and editors?
There was a problem hiding this comment.
Yeah could be that.
good to know! |
Enum fields where the choices are defined via constants rather than literals are now handled as Incomplete, rather than Literal[] which is invalid. Also, contants defined in a model, such as enum members now have type Literal[<the literal value>] rather than Any.
21d76d2 to
bdd48fc
Compare
Due to the various dynamic import mechanism that the leapp framework uses to import leapp entities, development tools such as language servers or type checkers work very unreliably if at all.
This PR adds scripts for generation of type stubs for leapp framework components, namely: actor libs, common libs, models, tags, topics (no actors, they are never imported). These generated type stub files are stored in a
typingsdirectory in a layout which simulates the import hierarchy at runtime, i.e. a common library defined atrepos/system_upgrade/common/libraries/grub.pyhas a type stub attypings/leapp/libraries/common/grub.pyi.When tools such as the Pylance language server (the VS code extension for Python) or pyright (upstream of Pylance) are pointed at the type stub directory, they prefer it over the real source code. These stubs are then used as a source of information which brings (more like fixes) several features:
There are also some limitations, however no regressions, I believe:
Usage
typingsdirectory will be used automatically. If you use anything else e.g. jedi, mypy, etc. You might need to point to thetypingsdirectory, but seems like the name is standard.make stubgento generate.Technical notes
All of the stubs are generated using
mypy.stubgen, except for the model ones. Those are generated using a custom script with the ast module, because of how models are implemented (metaclasses and class properties). This allows offering much better type information because the scripts converts the leapp field types to actual standard python type hints (whereas mypy only generates_typeshed.Incomplete). Also, docstrings for the fields are preserved (though due to them not being standardized the tools might not show them).There is also a
.stub_tmpdirectory which is a temporary dictionary to where the direct outputs of the generators are put before they are assembled. The assembly is a process in which multiple stubs are combined to a single__init__.pyfor a flat module hierarchy and import statements are inserted, this applies to models, tags and topics. Then all the stubs are moved to the correct places.Other solutions considered
I tried to run the stub generation tool (
mypy.stubgen) after actually loading the upgrade leapp repositories via leapp, however due to how the imports work and the different dynamic import schemes used for models, libraries and tags and topics, this requires a lot of workarounds and usage of the lower level stubgen apis such asInspectionStubGenerator.It is also slower due to the loading of repositories.
Examples