Issue
Consider the following code:
import asyncio
def a():
print("whatever")
async def b():
await a()
asyncio.run(b())
It does not run: TypeError: object NoneType can't be used in 'await' expression
However it passes mypy (v1.2.0): Success: no issues found in 1 source file
.
Is there a setting for mypy, or a way to annotate a()
so that mypy detects this type of errors? I tried to annotate the return type of a with def a() -> None:
, but it does not help. Am doing something wrong? Is this a known limitation of mypy?
Solution
The reason why this does not cause Mypy to report an error is that you did not annotate your functions. Specifically, there is no return type annotation for a
. Mypy has no choice but to fall back to Any
as the return type. And Any
is compatible with, well, anything. This includes await
expressions.
If you run mypy --strict
, you'll actually get the following output for your code:
...:4: error: Function is missing a return type annotation [no-untyped-def]
...:4: note: Use "-> None" if function does not return a value
...:8: error: Function is missing a return type annotation [no-untyped-def]
...:8: note: Use "-> None" if function does not return a value
...:9: error: Call to untyped function "a" in typed context [no-untyped-call]
...:12: error: Call to untyped function "b" in typed context [no-untyped-call]
And if you modify b
slightly to reveal the types involved, you'll see what I mean:
...
async def b():
supposed_awaitable = a()
reveal_type(supposed_awaitable)
await supposed_awaitable
Mypy will tell you Revealed type is "Any"
even though you and me know it is None
.
By contrast, if you just add -> None
to your a
function, you will at least get an error:
def a() -> None:
print("whatever")
async def b():
await a() # error: "a" does not return a value [func-returns-value]
While this is not ideal IMO because it is not very precise and to be honest actually incorrect since None
is of course a value, that is still enough to point you to the error you made because if something is None
(or "not a value" as Mypy calls it here), you obviously cannot use it in an await expression.
As a side note, I appreciate that PyCharm at least tells me Cannot find reference 'await' in 'None'
, which I find a bit clearer.
Answered By - Daniil Fajnberg
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.