mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-24 13:33:50 +00:00
Allow top-level await
in Jupyter notebooks (#6607)
## Summary
Top-level `await` is allowed in Jupyter notebooks (see:
[autoawait](https://ipython.readthedocs.io/en/stable/interactive/autoawait.html)).
Closes https://github.com/astral-sh/ruff/issues/6584.
## Test Plan
Had to test this manually. Created a notebook, verified that the `yield`
was flagged but the `await` was not.
<img width="868" alt="Screen Shot 2023-08-15 at 11 40 19 PM"
src="b2853651
-30a6-4dc6-851c-9fe7f694b8e8">
This commit is contained in:
parent
d9a81f4fbb
commit
2d86e78bfc
1 changed files with 21 additions and 9 deletions
|
@ -1,10 +1,8 @@
|
|||
use std::fmt;
|
||||
|
||||
use ruff_python_ast::{Expr, Ranged};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_semantic::ScopeKind;
|
||||
use ruff_python_ast::{Expr, Ranged};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
|
@ -26,12 +24,15 @@ impl fmt::Display for DeferralKeyword {
|
|||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `yield` and `yield from` statements outside of functions.
|
||||
/// Checks for `yield`, `yield from`, and `await` usages outside of functions.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// The use of a `yield` or `yield from` statement outside of a function will
|
||||
/// The use of `yield`, `yield from`, or `await` outside of a function will
|
||||
/// raise a `SyntaxError`.
|
||||
///
|
||||
/// As an exception, `await` is allowed at the top level of a Jupyter notebook
|
||||
/// (see: [autoawait]).
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// class Foo:
|
||||
|
@ -40,6 +41,8 @@ impl fmt::Display for DeferralKeyword {
|
|||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: `yield`](https://docs.python.org/3/reference/simple_stmts.html#the-yield-statement)
|
||||
///
|
||||
/// [autoawait]: https://ipython.readthedocs.io/en/stable/interactive/autoawait.html
|
||||
#[violation]
|
||||
pub struct YieldOutsideFunction {
|
||||
keyword: DeferralKeyword,
|
||||
|
@ -53,17 +56,26 @@ impl Violation for YieldOutsideFunction {
|
|||
}
|
||||
}
|
||||
|
||||
/// F704
|
||||
pub(crate) fn yield_outside_function(checker: &mut Checker, expr: &Expr) {
|
||||
if matches!(
|
||||
checker.semantic().current_scope().kind,
|
||||
ScopeKind::Class(_) | ScopeKind::Module
|
||||
) {
|
||||
let scope = checker.semantic().current_scope();
|
||||
if scope.kind.is_module() || scope.kind.is_class() {
|
||||
let keyword = match expr {
|
||||
Expr::Yield(_) => DeferralKeyword::Yield,
|
||||
Expr::YieldFrom(_) => DeferralKeyword::YieldFrom,
|
||||
Expr::Await(_) => DeferralKeyword::Await,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
// `await` is allowed at the top level of a Jupyter notebook.
|
||||
// See: https://ipython.readthedocs.io/en/stable/interactive/autoawait.html.
|
||||
if scope.kind.is_module()
|
||||
&& checker.source_type.is_jupyter()
|
||||
&& keyword == DeferralKeyword::Await
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
YieldOutsideFunction { keyword },
|
||||
expr.range(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue