Fix await-outside-async to allow await at the top-level scope of a notebook (#14225)
## Summary <!-- What's the purpose of the change? What does it do, and why? --> Fix `await-outside-async` to allow `await` at the top-level scope of a notebook. ```python # foo.ipynb await asyncio.sleep(1) # should be allowed ``` ## Test Plan <!-- How was it tested? --> A unit test
This commit is contained in:
committed by
GitHub
parent
e598240f04
commit
71da1d6df5
42
crates/ruff_linter/resources/test/fixtures/pylint/await_outside_async.ipynb
vendored
Normal file
42
crates/ruff_linter/resources/test/fixtures/pylint/await_outside_async.ipynb
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import asyncio\n",
|
||||
"\n",
|
||||
"await asyncio.sleep(1) # This is okay\n",
|
||||
"\n",
|
||||
"if True:\n",
|
||||
" await asyncio.sleep(1) # This is okay\n",
|
||||
"\n",
|
||||
"def foo():\n",
|
||||
" await asyncio.sleep(1) # # [await-outside-async]"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "base",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.5"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -27,6 +27,7 @@ mod tests {
|
||||
)]
|
||||
#[test_case(Rule::AssertOnStringLiteral, Path::new("assert_on_string_literal.py"))]
|
||||
#[test_case(Rule::AwaitOutsideAsync, Path::new("await_outside_async.py"))]
|
||||
#[test_case(Rule::AwaitOutsideAsync, Path::new("await_outside_async.ipynb"))]
|
||||
#[test_case(Rule::BadOpenMode, Path::new("bad_open_mode.py"))]
|
||||
#[test_case(
|
||||
Rule::BadStringFormatCharacter,
|
||||
|
||||
@@ -11,6 +11,9 @@ use crate::checkers::ast::Checker;
|
||||
/// ## Why is this bad?
|
||||
/// Using `await` outside an `async` function is a syntax error.
|
||||
///
|
||||
/// As an exception, `await` is allowed at the top level of a Jupyter notebook
|
||||
/// (see: [autoawait]).
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// import asyncio
|
||||
@@ -32,6 +35,8 @@ use crate::checkers::ast::Checker;
|
||||
/// ## References
|
||||
/// - [Python documentation: Await expression](https://docs.python.org/3/reference/expressions.html#await)
|
||||
/// - [PEP 492: Await Expression](https://peps.python.org/pep-0492/#await-expression)
|
||||
///
|
||||
/// [autoawait]: https://ipython.readthedocs.io/en/stable/interactive/autoawait.html
|
||||
#[violation]
|
||||
pub struct AwaitOutsideAsync;
|
||||
|
||||
@@ -49,6 +54,12 @@ pub(crate) fn await_outside_async<T: Ranged>(checker: &mut Checker, node: T) {
|
||||
return;
|
||||
}
|
||||
|
||||
// `await` is allowed at the top level of a Jupyter notebook.
|
||||
// See: https://ipython.readthedocs.io/en/stable/interactive/autoawait.html.
|
||||
if checker.semantic().current_scope().kind.is_module() && checker.source_type.is_ipynb() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Generators are evaluated lazily, so you can use `await` in them. For example:
|
||||
// ```python
|
||||
// # This is valid
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/pylint/mod.rs
|
||||
assertion_line: 236
|
||||
snapshot_kind: text
|
||||
---
|
||||
await_outside_async.ipynb:9:5: PLE1142 `await` should be used within an async function
|
||||
|
|
||||
8 | def foo():
|
||||
9 | await asyncio.sleep(1) # # [await-outside-async]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ PLE1142
|
||||
|
|
||||
Reference in New Issue
Block a user