Skip to content

Commit 494802f

Browse files
authored
Add a separate error code for top level await (#14801)
Now users can disable the first kind of error, but not the second kind (which is always a syntax error). Refs #14486 Closes #14763
1 parent 243f584 commit 494802f

File tree

3 files changed

+11
-2
lines changed

3 files changed

+11
-2
lines changed

mypy/errorcodes.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ def __str__(self) -> str:
132132
SAFE_SUPER: Final = ErrorCode(
133133
"safe-super", "Warn about calls to abstract methods with empty/trivial bodies", "General"
134134
)
135+
TOP_LEVEL_AWAIT: Final = ErrorCode(
136+
"top-level-await", "Warn about top level await experessions", "General"
137+
)
135138

136139
# These error codes aren't enabled by default.
137140
NO_UNTYPED_DEF: Final[ErrorCode] = ErrorCode(

mypy/semanal.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5249,7 +5249,9 @@ def visit_yield_expr(self, e: YieldExpr) -> None:
52495249
def visit_await_expr(self, expr: AwaitExpr) -> None:
52505250
if not self.is_func_scope() or not self.function_stack:
52515251
# We check both because is_function_scope() returns True inside comprehensions.
5252-
self.fail('"await" outside function', expr, serious=True, blocker=True)
5252+
# This is not a blocker, because some enviroments (like ipython)
5253+
# support top level awaits.
5254+
self.fail('"await" outside function', expr, serious=True, code=codes.TOP_LEVEL_AWAIT)
52535255
elif not self.function_stack[-1].is_coroutine:
52545256
self.fail('"await" outside coroutine ("async def")', expr, serious=True, blocker=True)
52555257
expr.expr.accept(self)

test-data/unit/check-async-await.test

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -945,11 +945,15 @@ async def bar(x: Union[A, B]) -> None:
945945
[typing fixtures/typing-async.pyi]
946946

947947
[case testInvalidComprehensionNoCrash]
948+
# flags: --show-error-codes
948949
async def foo(x: int) -> int: ...
949950

950-
crasher = [await foo(x) for x in [1, 2, 3]] # E: "await" outside function
951+
# These are allowed in some cases:
952+
top_level = await foo(1) # E: "await" outside function [top-level-await]
953+
crasher = [await foo(x) for x in [1, 2, 3]] # E: "await" outside function [top-level-await]
951954

952955
def bad() -> None:
956+
# These are always critical / syntax issues:
953957
y = [await foo(x) for x in [1, 2, 3]] # E: "await" outside coroutine ("async def")
954958
async def good() -> None:
955959
y = [await foo(x) for x in [1, 2, 3]] # OK

0 commit comments

Comments
 (0)