Properly annotate run functions #997
Open
+136
−46
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I'd like to run a type checker against the code in
tasks.py
however the fact thatContext.run
returnsResult | None
instead of just aResult
makes it rather annoying to deal with. I constantly have toassert result is not None
in order to access attributes likeResult.stdout
.Given the underlying implementation, the solution is to describe
run()
with overloads. Further, since there a number of public interfaces that look likeContext.run
, in this PR I've devised anannotate_run_function
decorator that makes it easy to declare a function as having arun
-like interface. Beyond just properly describing the return type ofrun
-like methods, this PR also annotates all the valid options that can be passed torun
as well. I also find this quite useful since I always have to dive into the docs forRunner.run
to figure out what parameters are available instead of just being able to refer toContext.run
.In order to make all this happen I've had to do a couple things...
First, I had to upgrade MyPy for it to understand the most recent type tooling (e.g.
Unpack
). This allowed me to remove a coupletype: ignore
comments. However, the latest version of MyPy only supports Python>=3.8 so it looks like there will need to be a change toorb/invocations
so that it runs under Python 3.8 by default. Dropping support for Python<3.8 seems fairly reasonable - for example, Numpy's policy is that it's newest releases will only support the last three Python versions (3.10+ as of writing).Second, I needed to use
typing_extensions
in order to get access to back-ported implementations of newer typing features. Sinceinvoke
doesn't seem to have dependencies I've defined most of the type annotations inif TYPE_CHECKING
to avoid any issues at runtime.