Skip to content

Commit

Permalink
Tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Nov 7, 2023
1 parent f1e0d9e commit cdd9910
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 53 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import trio

async def foo():

async def func():
while True:
await trio.sleep(10)

async def foo():

async def func():
while True:
await trio.sleep_until(10)

async def foo():

async def func():
while True:
trio.sleep(10)
7 changes: 2 additions & 5 deletions crates/ruff_linter/src/checkers/ast/analyze/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1206,7 +1206,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
flake8_trio::rules::timeout_without_await(checker, with_stmt, items);
}
}
Stmt::While(ast::StmtWhile { body, orelse, .. }) => {
Stmt::While(while_stmt @ ast::StmtWhile { body, orelse, .. }) => {
if checker.enabled(Rule::FunctionUsesLoopVariable) {
flake8_bugbear::rules::function_uses_loop_variable(checker, &Node::Stmt(stmt));
}
Expand All @@ -1216,11 +1216,8 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
if checker.enabled(Rule::TryExceptInLoop) {
perflint::rules::try_except_in_loop(checker, body);
}
if checker.enabled(Rule::TryExceptInLoop) {
perflint::rules::try_except_in_loop(checker, body);
}
if checker.enabled(Rule::TrioUnneededSleep) {
flake8_trio::rules::unneeded_sleep(checker, stmt, body);
flake8_trio::rules::unneeded_sleep(checker, while_stmt);
}
}
Stmt::For(
Expand Down
60 changes: 27 additions & 33 deletions crates/ruff_linter/src/rules/flake8_trio/rules/unneeded_sleep.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::{Expr, ExprAwait, ExprCall, Stmt, StmtExpr};
use ruff_python_ast::{self as ast, Expr, Stmt};
use ruff_text_size::Ranged;

use crate::checkers::ast::Checker;

/// ## What it does
/// Checks for the while loop, which waits for the event.
/// Checks for the use of `trio.sleep` in a `while` loop.
///
/// ## Why is this bad?
/// Instead of sleeping in a loop waiting for a condition to be true,
/// it's preferable to use a `trio.Event`.
/// Instead of sleeping in a `while` loop, and waiting for a condition
/// to become true, it's preferable to `wait()` on a `trio.Event`.
///
/// ## Example
/// ```python
/// DONE = False
///
///
/// async def func():
/// while not DONE:
/// await trio.sleep(1)
Expand All @@ -25,6 +26,7 @@ use crate::checkers::ast::Checker;
/// ```python
/// DONE = trio.Event()
///
///
/// async def func():
/// await DONE.wait()
/// ```
Expand All @@ -34,41 +36,33 @@ pub struct TrioUnneededSleep;
impl Violation for TrioUnneededSleep {
#[derive_message_formats]
fn message(&self) -> String {
format!("Use event instead of `while <condition>: await trio.sleep()`")
format!("Use `trio.Event` instead of awaiting `trio.sleep` in a `while` loop")
}
}

pub(crate) fn unneeded_sleep(checker: &mut Checker, stmt: &Stmt, body: &[Stmt]) {
if body.len() != 1 {
/// TRIO110
pub(crate) fn unneeded_sleep(checker: &mut Checker, while_stmt: &ast::StmtWhile) {
// The body should be a single `await` call.
let [stmt] = while_stmt.body.as_slice() else {
return;
};
let Stmt::Expr(ast::StmtExpr { value, .. }) = stmt else {
return;
};
let Expr::Await(ast::ExprAwait { value, .. }) = value.as_ref() else {
return;
};
let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() else {
return;
}

let awaitable = {
if let Stmt::Expr(StmtExpr { range: _, value }) = &body[0] {
if let Expr::Await(ExprAwait { range: _, value }) = value.as_ref() {
Some(value.as_ref())
} else {
None
}
} else {
None
}
};

if let Some(Expr::Call(ExprCall {
range: _,
func,
arguments: _,
})) = awaitable
if checker
.semantic()
.resolve_call_path(func.as_ref())
.is_some_and(|path| matches!(path.as_slice(), ["trio", "sleep" | "sleep_until"]))
{
if checker
.semantic()
.resolve_call_path(func.as_ref())
.is_some_and(|path| matches!(path.as_slice(), ["trio", "sleep" | "sleep_until"]))
{
checker
.diagnostics
.push(Diagnostic::new(TrioUnneededSleep, stmt.range()));
}
checker
.diagnostics
.push(Diagnostic::new(TrioUnneededSleep, while_stmt.range()));
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
---
source: crates/ruff_linter/src/rules/flake8_trio/mod.rs
---
TRIO110.py:4:5: TRIO110 Use event instead of `while <condition>: await trio.sleep()`
TRIO110.py:5:5: TRIO110 Use `trio.Event` instead of awaiting `trio.sleep` in a `while` loop
|
3 | async def foo():
4 | while True:
4 | async def func():
5 | while True:
| _____^
5 | | await trio.sleep(10)
6 | | await trio.sleep(10)
| |____________________________^ TRIO110
6 |
7 | async def foo():
|

TRIO110.py:8:5: TRIO110 Use event instead of `while <condition>: await trio.sleep()`
TRIO110.py:10:5: TRIO110 Use `trio.Event` instead of awaiting `trio.sleep` in a `while` loop
|
7 | async def foo():
8 | while True:
9 | async def func():
10 | while True:
| _____^
9 | | await trio.sleep_until(10)
11 | | await trio.sleep_until(10)
| |__________________________________^ TRIO110
10 |
11 | async def foo():
|


0 comments on commit cdd9910

Please sign in to comment.