mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-19 01:51:30 +00:00
[TRIO
] Add TRIO105
: SyncTrioCall
(#8490)
## Summary Adds `TRIO105` from the [flake8-trio plugin](https://github.com/Zac-HD/flake8-trio). The `MethodName` logic mirrors that of `TRIO100` to stay consistent within the plugin. It is at 95% parity with the exception of upstream also checking for a slightly more complex scenario where a call to `start()` on a `trio.Nursery` context should also be immediately awaited. Upstream plugin appears to just check for anything named `nursery` judging from [the relevant issue](https://github.com/Zac-HD/flake8-trio/issues/56). Unsure if we want to do so something similar or, alternatively, if there is some capability in ruff to check for calls made on this context some other way ## Test Plan Added a new fixture, based on [the one from upstream plugin](https://github.com/Zac-HD/flake8-trio/blob/main/tests/eval_files/trio105.py) ## Issue link Refers: https://github.com/astral-sh/ruff/issues/8451
This commit is contained in:
parent
72ebde8d38
commit
4170ef0508
11 changed files with 872 additions and 61 deletions
64
crates/ruff_linter/resources/test/fixtures/flake8_trio/TRIO105.py
vendored
Normal file
64
crates/ruff_linter/resources/test/fixtures/flake8_trio/TRIO105.py
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
import trio
|
||||
|
||||
|
||||
async def func() -> None:
|
||||
trio.run(foo) # OK, not async
|
||||
|
||||
# OK
|
||||
await trio.aclose_forcefully(foo)
|
||||
await trio.open_file(foo)
|
||||
await trio.open_ssl_over_tcp_listeners(foo, foo)
|
||||
await trio.open_ssl_over_tcp_stream(foo, foo)
|
||||
await trio.open_tcp_listeners(foo)
|
||||
await trio.open_tcp_stream(foo, foo)
|
||||
await trio.open_unix_socket(foo)
|
||||
await trio.run_process(foo)
|
||||
await trio.sleep(5)
|
||||
await trio.sleep_until(5)
|
||||
await trio.lowlevel.cancel_shielded_checkpoint()
|
||||
await trio.lowlevel.checkpoint()
|
||||
await trio.lowlevel.checkpoint_if_cancelled()
|
||||
await trio.lowlevel.open_process(foo)
|
||||
await trio.lowlevel.permanently_detach_coroutine_object(foo)
|
||||
await trio.lowlevel.reattach_detached_coroutine_object(foo, foo)
|
||||
await trio.lowlevel.temporarily_detach_coroutine_object(foo)
|
||||
await trio.lowlevel.wait_readable(foo)
|
||||
await trio.lowlevel.wait_task_rescheduled(foo)
|
||||
await trio.lowlevel.wait_writable(foo)
|
||||
|
||||
# TRIO105
|
||||
trio.aclose_forcefully(foo)
|
||||
trio.open_file(foo)
|
||||
trio.open_ssl_over_tcp_listeners(foo, foo)
|
||||
trio.open_ssl_over_tcp_stream(foo, foo)
|
||||
trio.open_tcp_listeners(foo)
|
||||
trio.open_tcp_stream(foo, foo)
|
||||
trio.open_unix_socket(foo)
|
||||
trio.run_process(foo)
|
||||
trio.serve_listeners(foo, foo)
|
||||
trio.serve_ssl_over_tcp(foo, foo, foo)
|
||||
trio.serve_tcp(foo, foo)
|
||||
trio.sleep(foo)
|
||||
trio.sleep_forever()
|
||||
trio.sleep_until(foo)
|
||||
trio.lowlevel.cancel_shielded_checkpoint()
|
||||
trio.lowlevel.checkpoint()
|
||||
trio.lowlevel.checkpoint_if_cancelled()
|
||||
trio.lowlevel.open_process()
|
||||
trio.lowlevel.permanently_detach_coroutine_object(foo)
|
||||
trio.lowlevel.reattach_detached_coroutine_object(foo, foo)
|
||||
trio.lowlevel.temporarily_detach_coroutine_object(foo)
|
||||
trio.lowlevel.wait_readable(foo)
|
||||
trio.lowlevel.wait_task_rescheduled(foo)
|
||||
trio.lowlevel.wait_writable(foo)
|
||||
|
||||
async with await trio.open_file(foo): # Ok
|
||||
pass
|
||||
|
||||
async with trio.open_file(foo): # TRIO105
|
||||
pass
|
||||
|
||||
|
||||
def func() -> None:
|
||||
# TRIO105 (without fix)
|
||||
trio.open_file(foo)
|
|
@ -15,8 +15,8 @@ use crate::rules::{
|
|||
flake8_comprehensions, flake8_datetimez, flake8_debugger, flake8_django,
|
||||
flake8_future_annotations, flake8_gettext, flake8_implicit_str_concat, flake8_logging,
|
||||
flake8_logging_format, flake8_pie, flake8_print, flake8_pyi, flake8_pytest_style, flake8_self,
|
||||
flake8_simplify, flake8_tidy_imports, flake8_use_pathlib, flynt, numpy, pandas_vet,
|
||||
pep8_naming, pycodestyle, pyflakes, pygrep_hooks, pylint, pyupgrade, refurb, ruff,
|
||||
flake8_simplify, flake8_tidy_imports, flake8_trio, flake8_use_pathlib, flynt, numpy,
|
||||
pandas_vet, pep8_naming, pycodestyle, pyflakes, pygrep_hooks, pylint, pyupgrade, refurb, ruff,
|
||||
};
|
||||
use crate::settings::types::PythonVersion;
|
||||
|
||||
|
@ -926,6 +926,9 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
|||
if checker.enabled(Rule::ImplicitCwd) {
|
||||
refurb::rules::no_implicit_cwd(checker, call);
|
||||
}
|
||||
if checker.enabled(Rule::TrioSyncCall) {
|
||||
flake8_trio::rules::sync_call(checker, call);
|
||||
}
|
||||
}
|
||||
Expr::Dict(
|
||||
dict @ ast::ExprDict {
|
||||
|
|
|
@ -292,6 +292,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
|||
|
||||
// flake8-trio
|
||||
(Flake8Trio, "100") => (RuleGroup::Preview, rules::flake8_trio::rules::TrioTimeoutWithoutAwait),
|
||||
(Flake8Trio, "105") => (RuleGroup::Preview, rules::flake8_trio::rules::TrioSyncCall),
|
||||
|
||||
// flake8-builtins
|
||||
(Flake8Builtins, "001") => (RuleGroup::Stable, rules::flake8_builtins::rules::BuiltinVariableShadowing),
|
||||
|
|
157
crates/ruff_linter/src/rules/flake8_trio/method_name.rs
Normal file
157
crates/ruff_linter/src/rules/flake8_trio/method_name.rs
Normal file
|
@ -0,0 +1,157 @@
|
|||
use ruff_python_ast::call_path::CallPath;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub(super) enum MethodName {
|
||||
AcloseForcefully,
|
||||
CancelScope,
|
||||
CancelShieldedCheckpoint,
|
||||
Checkpoint,
|
||||
CheckpointIfCancelled,
|
||||
FailAfter,
|
||||
FailAt,
|
||||
MoveOnAfter,
|
||||
MoveOnAt,
|
||||
OpenFile,
|
||||
OpenProcess,
|
||||
OpenSslOverTcpListeners,
|
||||
OpenSslOverTcpStream,
|
||||
OpenTcpListeners,
|
||||
OpenTcpStream,
|
||||
OpenUnixSocket,
|
||||
PermanentlyDetachCoroutineObject,
|
||||
ReattachDetachedCoroutineObject,
|
||||
RunProcess,
|
||||
ServeListeners,
|
||||
ServeSslOverTcp,
|
||||
ServeTcp,
|
||||
Sleep,
|
||||
SleepForever,
|
||||
TemporarilyDetachCoroutineObject,
|
||||
WaitReadable,
|
||||
WaitTaskRescheduled,
|
||||
WaitWritable,
|
||||
}
|
||||
|
||||
impl MethodName {
|
||||
/// Returns `true` if the method is async, `false` if it is sync.
|
||||
pub(super) fn is_async(self) -> bool {
|
||||
match self {
|
||||
MethodName::AcloseForcefully
|
||||
| MethodName::CancelShieldedCheckpoint
|
||||
| MethodName::Checkpoint
|
||||
| MethodName::CheckpointIfCancelled
|
||||
| MethodName::OpenFile
|
||||
| MethodName::OpenProcess
|
||||
| MethodName::OpenSslOverTcpListeners
|
||||
| MethodName::OpenSslOverTcpStream
|
||||
| MethodName::OpenTcpListeners
|
||||
| MethodName::OpenTcpStream
|
||||
| MethodName::OpenUnixSocket
|
||||
| MethodName::PermanentlyDetachCoroutineObject
|
||||
| MethodName::ReattachDetachedCoroutineObject
|
||||
| MethodName::RunProcess
|
||||
| MethodName::ServeListeners
|
||||
| MethodName::ServeSslOverTcp
|
||||
| MethodName::ServeTcp
|
||||
| MethodName::Sleep
|
||||
| MethodName::SleepForever
|
||||
| MethodName::TemporarilyDetachCoroutineObject
|
||||
| MethodName::WaitReadable
|
||||
| MethodName::WaitTaskRescheduled
|
||||
| MethodName::WaitWritable => true,
|
||||
|
||||
MethodName::MoveOnAfter
|
||||
| MethodName::MoveOnAt
|
||||
| MethodName::FailAfter
|
||||
| MethodName::FailAt
|
||||
| MethodName::CancelScope => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MethodName {
|
||||
pub(super) fn try_from(call_path: &CallPath<'_>) -> Option<Self> {
|
||||
match call_path.as_slice() {
|
||||
["trio", "CancelScope"] => Some(Self::CancelScope),
|
||||
["trio", "aclose_forcefully"] => Some(Self::AcloseForcefully),
|
||||
["trio", "fail_after"] => Some(Self::FailAfter),
|
||||
["trio", "fail_at"] => Some(Self::FailAt),
|
||||
["trio", "lowlevel", "cancel_shielded_checkpoint"] => {
|
||||
Some(Self::CancelShieldedCheckpoint)
|
||||
}
|
||||
["trio", "lowlevel", "checkpoint"] => Some(Self::Checkpoint),
|
||||
["trio", "lowlevel", "checkpoint_if_cancelled"] => Some(Self::CheckpointIfCancelled),
|
||||
["trio", "lowlevel", "open_process"] => Some(Self::OpenProcess),
|
||||
["trio", "lowlevel", "permanently_detach_coroutine_object"] => {
|
||||
Some(Self::PermanentlyDetachCoroutineObject)
|
||||
}
|
||||
["trio", "lowlevel", "reattach_detached_coroutine_object"] => {
|
||||
Some(Self::ReattachDetachedCoroutineObject)
|
||||
}
|
||||
["trio", "lowlevel", "temporarily_detach_coroutine_object"] => {
|
||||
Some(Self::TemporarilyDetachCoroutineObject)
|
||||
}
|
||||
["trio", "lowlevel", "wait_readable"] => Some(Self::WaitReadable),
|
||||
["trio", "lowlevel", "wait_task_rescheduled"] => Some(Self::WaitTaskRescheduled),
|
||||
["trio", "lowlevel", "wait_writable"] => Some(Self::WaitWritable),
|
||||
["trio", "move_on_after"] => Some(Self::MoveOnAfter),
|
||||
["trio", "move_on_at"] => Some(Self::MoveOnAt),
|
||||
["trio", "open_file"] => Some(Self::OpenFile),
|
||||
["trio", "open_ssl_over_tcp_listeners"] => Some(Self::OpenSslOverTcpListeners),
|
||||
["trio", "open_ssl_over_tcp_stream"] => Some(Self::OpenSslOverTcpStream),
|
||||
["trio", "open_tcp_listeners"] => Some(Self::OpenTcpListeners),
|
||||
["trio", "open_tcp_stream"] => Some(Self::OpenTcpStream),
|
||||
["trio", "open_unix_socket"] => Some(Self::OpenUnixSocket),
|
||||
["trio", "run_process"] => Some(Self::RunProcess),
|
||||
["trio", "serve_listeners"] => Some(Self::ServeListeners),
|
||||
["trio", "serve_ssl_over_tcp"] => Some(Self::ServeSslOverTcp),
|
||||
["trio", "serve_tcp"] => Some(Self::ServeTcp),
|
||||
["trio", "sleep"] => Some(Self::Sleep),
|
||||
["trio", "sleep_forever"] => Some(Self::SleepForever),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for MethodName {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
MethodName::AcloseForcefully => write!(f, "trio.aclose_forcefully"),
|
||||
MethodName::CancelScope => write!(f, "trio.CancelScope"),
|
||||
MethodName::CancelShieldedCheckpoint => {
|
||||
write!(f, "trio.lowlevel.cancel_shielded_checkpoint")
|
||||
}
|
||||
MethodName::Checkpoint => write!(f, "trio.lowlevel.checkpoint"),
|
||||
MethodName::CheckpointIfCancelled => write!(f, "trio.lowlevel.checkpoint_if_cancelled"),
|
||||
MethodName::FailAfter => write!(f, "trio.fail_after"),
|
||||
MethodName::FailAt => write!(f, "trio.fail_at"),
|
||||
MethodName::MoveOnAfter => write!(f, "trio.move_on_after"),
|
||||
MethodName::MoveOnAt => write!(f, "trio.move_on_at"),
|
||||
MethodName::OpenFile => write!(f, "trio.open_file"),
|
||||
MethodName::OpenProcess => write!(f, "trio.lowlevel.open_process"),
|
||||
MethodName::OpenSslOverTcpListeners => write!(f, "trio.open_ssl_over_tcp_listeners"),
|
||||
MethodName::OpenSslOverTcpStream => write!(f, "trio.open_ssl_over_tcp_stream"),
|
||||
MethodName::OpenTcpListeners => write!(f, "trio.open_tcp_listeners"),
|
||||
MethodName::OpenTcpStream => write!(f, "trio.open_tcp_stream"),
|
||||
MethodName::OpenUnixSocket => write!(f, "trio.open_unix_socket"),
|
||||
MethodName::PermanentlyDetachCoroutineObject => {
|
||||
write!(f, "trio.lowlevel.permanently_detach_coroutine_object")
|
||||
}
|
||||
MethodName::ReattachDetachedCoroutineObject => {
|
||||
write!(f, "trio.lowlevel.reattach_detached_coroutine_object")
|
||||
}
|
||||
MethodName::RunProcess => write!(f, "trio.run_process"),
|
||||
MethodName::ServeListeners => write!(f, "trio.serve_listeners"),
|
||||
MethodName::ServeSslOverTcp => write!(f, "trio.serve_ssl_over_tcp"),
|
||||
MethodName::ServeTcp => write!(f, "trio.serve_tcp"),
|
||||
MethodName::Sleep => write!(f, "trio.sleep"),
|
||||
MethodName::SleepForever => write!(f, "trio.sleep_forever"),
|
||||
MethodName::TemporarilyDetachCoroutineObject => {
|
||||
write!(f, "trio.lowlevel.temporarily_detach_coroutine_object")
|
||||
}
|
||||
MethodName::WaitReadable => write!(f, "trio.lowlevel.wait_readable"),
|
||||
MethodName::WaitTaskRescheduled => write!(f, "trio.lowlevel.wait_task_rescheduled"),
|
||||
MethodName::WaitWritable => write!(f, "trio.lowlevel.wait_writable"),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
//! Rules from [flake8-trio](https://pypi.org/project/flake8-trio/).
|
||||
pub(super) mod method_name;
|
||||
pub(crate) mod rules;
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -14,6 +15,7 @@ mod tests {
|
|||
use crate::test::test_path;
|
||||
|
||||
#[test_case(Rule::TrioTimeoutWithoutAwait, Path::new("TRIO100.py"))]
|
||||
#[test_case(Rule::TrioSyncCall, Path::new("TRIO105.py"))]
|
||||
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy());
|
||||
let diagnostics = test_path(
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
pub(crate) use sync_call::*;
|
||||
pub(crate) use timeout_without_await::*;
|
||||
|
||||
mod sync_call;
|
||||
mod timeout_without_await;
|
||||
|
|
87
crates/ruff_linter/src/rules/flake8_trio/rules/sync_call.rs
Normal file
87
crates/ruff_linter/src/rules/flake8_trio/rules/sync_call.rs
Normal file
|
@ -0,0 +1,87 @@
|
|||
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::{Expr, ExprCall};
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::fix::edits::pad;
|
||||
use crate::rules::flake8_trio::method_name::MethodName;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for calls to trio functions that are not immediately awaited.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Many of the functions exposed by trio are asynchronous, and must be awaited
|
||||
/// to take effect. Calling a trio function without an `await` can lead to
|
||||
/// `RuntimeWarning` diagnostics and unexpected behaviour.
|
||||
///
|
||||
/// ## Fix safety
|
||||
/// This rule's fix is marked as unsafe, as adding an `await` to a function
|
||||
/// call changes its semantics and runtime behavior.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// async def double_sleep(x):
|
||||
/// trio.sleep(2 * x)
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// async def double_sleep(x):
|
||||
/// await trio.sleep(2 * x)
|
||||
/// ```
|
||||
#[violation]
|
||||
pub struct TrioSyncCall {
|
||||
method_name: MethodName,
|
||||
}
|
||||
|
||||
impl Violation for TrioSyncCall {
|
||||
const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes;
|
||||
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let Self { method_name } = self;
|
||||
format!("Call to `{method_name}` is not immediately awaited")
|
||||
}
|
||||
|
||||
fn fix_title(&self) -> Option<String> {
|
||||
Some(format!("Add `await`"))
|
||||
}
|
||||
}
|
||||
|
||||
/// TRIO105
|
||||
pub(crate) fn sync_call(checker: &mut Checker, call: &ExprCall) {
|
||||
let Some(method_name) = ({
|
||||
let Some(call_path) = checker.semantic().resolve_call_path(call.func.as_ref()) else {
|
||||
return;
|
||||
};
|
||||
MethodName::try_from(&call_path)
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
|
||||
if !method_name.is_async() {
|
||||
return;
|
||||
}
|
||||
|
||||
if checker
|
||||
.semantic()
|
||||
.current_expression_parent()
|
||||
.is_some_and(Expr::is_await_expr)
|
||||
{
|
||||
return;
|
||||
};
|
||||
|
||||
let mut diagnostic = Diagnostic::new(TrioSyncCall { method_name }, call.range);
|
||||
if checker.semantic().in_async_context() {
|
||||
diagnostic.set_fix(Fix::unsafe_edit(Edit::insertion(
|
||||
pad(
|
||||
"await".to_string(),
|
||||
TextRange::new(call.func.start(), call.func.start()),
|
||||
checker.locator(),
|
||||
),
|
||||
call.func.start(),
|
||||
)));
|
||||
}
|
||||
checker.diagnostics.push(diagnostic);
|
||||
}
|
|
@ -1,10 +1,11 @@
|
|||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::call_path::CallPath;
|
||||
use ruff_python_ast::visitor::{walk_expr, walk_stmt, Visitor};
|
||||
use ruff_python_ast::{Expr, ExprAwait, Stmt, StmtWith, WithItem};
|
||||
use ruff_python_ast::helpers::AwaitVisitor;
|
||||
use ruff_python_ast::visitor::Visitor;
|
||||
use ruff_python_ast::{StmtWith, WithItem};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::rules::flake8_trio::method_name::MethodName;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for trio functions that should contain await but don't.
|
||||
|
@ -56,6 +57,17 @@ pub(crate) fn timeout_without_await(
|
|||
return;
|
||||
};
|
||||
|
||||
if !matches!(
|
||||
method_name,
|
||||
MethodName::MoveOnAfter
|
||||
| MethodName::MoveOnAt
|
||||
| MethodName::FailAfter
|
||||
| MethodName::FailAt
|
||||
| MethodName::CancelScope
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut visitor = AwaitVisitor::default();
|
||||
visitor.visit_body(&with_stmt.body);
|
||||
if visitor.seen_await {
|
||||
|
@ -67,59 +79,3 @@ pub(crate) fn timeout_without_await(
|
|||
with_stmt.range,
|
||||
));
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
enum MethodName {
|
||||
MoveOnAfter,
|
||||
MoveOnAt,
|
||||
FailAfter,
|
||||
FailAt,
|
||||
CancelScope,
|
||||
}
|
||||
|
||||
impl MethodName {
|
||||
fn try_from(call_path: &CallPath<'_>) -> Option<Self> {
|
||||
match call_path.as_slice() {
|
||||
["trio", "move_on_after"] => Some(Self::MoveOnAfter),
|
||||
["trio", "move_on_at"] => Some(Self::MoveOnAt),
|
||||
["trio", "fail_after"] => Some(Self::FailAfter),
|
||||
["trio", "fail_at"] => Some(Self::FailAt),
|
||||
["trio", "CancelScope"] => Some(Self::CancelScope),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for MethodName {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
MethodName::MoveOnAfter => write!(f, "trio.move_on_after"),
|
||||
MethodName::MoveOnAt => write!(f, "trio.move_on_at"),
|
||||
MethodName::FailAfter => write!(f, "trio.fail_after"),
|
||||
MethodName::FailAt => write!(f, "trio.fail_at"),
|
||||
MethodName::CancelScope => write!(f, "trio.CancelScope"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct AwaitVisitor {
|
||||
seen_await: bool,
|
||||
}
|
||||
|
||||
impl Visitor<'_> for AwaitVisitor {
|
||||
fn visit_stmt(&mut self, stmt: &Stmt) {
|
||||
match stmt {
|
||||
Stmt::FunctionDef(_) | Stmt::ClassDef(_) => (),
|
||||
_ => walk_stmt(self, stmt),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &Expr) {
|
||||
if let Expr::Await(ExprAwait { .. }) = expr {
|
||||
self.seen_await = true;
|
||||
} else {
|
||||
walk_expr(self, expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,514 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_trio/mod.rs
|
||||
---
|
||||
TRIO105.py:30:5: TRIO105 [*] Call to `trio.aclose_forcefully` is not immediately awaited
|
||||
|
|
||||
29 | # TRIO105
|
||||
30 | trio.aclose_forcefully(foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
31 | trio.open_file(foo)
|
||||
32 | trio.open_ssl_over_tcp_listeners(foo, foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
27 27 | await trio.lowlevel.wait_writable(foo)
|
||||
28 28 |
|
||||
29 29 | # TRIO105
|
||||
30 |- trio.aclose_forcefully(foo)
|
||||
30 |+ await trio.aclose_forcefully(foo)
|
||||
31 31 | trio.open_file(foo)
|
||||
32 32 | trio.open_ssl_over_tcp_listeners(foo, foo)
|
||||
33 33 | trio.open_ssl_over_tcp_stream(foo, foo)
|
||||
|
||||
TRIO105.py:31:5: TRIO105 [*] Call to `trio.open_file` is not immediately awaited
|
||||
|
|
||||
29 | # TRIO105
|
||||
30 | trio.aclose_forcefully(foo)
|
||||
31 | trio.open_file(foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
32 | trio.open_ssl_over_tcp_listeners(foo, foo)
|
||||
33 | trio.open_ssl_over_tcp_stream(foo, foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
28 28 |
|
||||
29 29 | # TRIO105
|
||||
30 30 | trio.aclose_forcefully(foo)
|
||||
31 |- trio.open_file(foo)
|
||||
31 |+ await trio.open_file(foo)
|
||||
32 32 | trio.open_ssl_over_tcp_listeners(foo, foo)
|
||||
33 33 | trio.open_ssl_over_tcp_stream(foo, foo)
|
||||
34 34 | trio.open_tcp_listeners(foo)
|
||||
|
||||
TRIO105.py:32:5: TRIO105 [*] Call to `trio.open_ssl_over_tcp_listeners` is not immediately awaited
|
||||
|
|
||||
30 | trio.aclose_forcefully(foo)
|
||||
31 | trio.open_file(foo)
|
||||
32 | trio.open_ssl_over_tcp_listeners(foo, foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
33 | trio.open_ssl_over_tcp_stream(foo, foo)
|
||||
34 | trio.open_tcp_listeners(foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
29 29 | # TRIO105
|
||||
30 30 | trio.aclose_forcefully(foo)
|
||||
31 31 | trio.open_file(foo)
|
||||
32 |- trio.open_ssl_over_tcp_listeners(foo, foo)
|
||||
32 |+ await trio.open_ssl_over_tcp_listeners(foo, foo)
|
||||
33 33 | trio.open_ssl_over_tcp_stream(foo, foo)
|
||||
34 34 | trio.open_tcp_listeners(foo)
|
||||
35 35 | trio.open_tcp_stream(foo, foo)
|
||||
|
||||
TRIO105.py:33:5: TRIO105 [*] Call to `trio.open_ssl_over_tcp_stream` is not immediately awaited
|
||||
|
|
||||
31 | trio.open_file(foo)
|
||||
32 | trio.open_ssl_over_tcp_listeners(foo, foo)
|
||||
33 | trio.open_ssl_over_tcp_stream(foo, foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
34 | trio.open_tcp_listeners(foo)
|
||||
35 | trio.open_tcp_stream(foo, foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
30 30 | trio.aclose_forcefully(foo)
|
||||
31 31 | trio.open_file(foo)
|
||||
32 32 | trio.open_ssl_over_tcp_listeners(foo, foo)
|
||||
33 |- trio.open_ssl_over_tcp_stream(foo, foo)
|
||||
33 |+ await trio.open_ssl_over_tcp_stream(foo, foo)
|
||||
34 34 | trio.open_tcp_listeners(foo)
|
||||
35 35 | trio.open_tcp_stream(foo, foo)
|
||||
36 36 | trio.open_unix_socket(foo)
|
||||
|
||||
TRIO105.py:34:5: TRIO105 [*] Call to `trio.open_tcp_listeners` is not immediately awaited
|
||||
|
|
||||
32 | trio.open_ssl_over_tcp_listeners(foo, foo)
|
||||
33 | trio.open_ssl_over_tcp_stream(foo, foo)
|
||||
34 | trio.open_tcp_listeners(foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
35 | trio.open_tcp_stream(foo, foo)
|
||||
36 | trio.open_unix_socket(foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
31 31 | trio.open_file(foo)
|
||||
32 32 | trio.open_ssl_over_tcp_listeners(foo, foo)
|
||||
33 33 | trio.open_ssl_over_tcp_stream(foo, foo)
|
||||
34 |- trio.open_tcp_listeners(foo)
|
||||
34 |+ await trio.open_tcp_listeners(foo)
|
||||
35 35 | trio.open_tcp_stream(foo, foo)
|
||||
36 36 | trio.open_unix_socket(foo)
|
||||
37 37 | trio.run_process(foo)
|
||||
|
||||
TRIO105.py:35:5: TRIO105 [*] Call to `trio.open_tcp_stream` is not immediately awaited
|
||||
|
|
||||
33 | trio.open_ssl_over_tcp_stream(foo, foo)
|
||||
34 | trio.open_tcp_listeners(foo)
|
||||
35 | trio.open_tcp_stream(foo, foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
36 | trio.open_unix_socket(foo)
|
||||
37 | trio.run_process(foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
32 32 | trio.open_ssl_over_tcp_listeners(foo, foo)
|
||||
33 33 | trio.open_ssl_over_tcp_stream(foo, foo)
|
||||
34 34 | trio.open_tcp_listeners(foo)
|
||||
35 |- trio.open_tcp_stream(foo, foo)
|
||||
35 |+ await trio.open_tcp_stream(foo, foo)
|
||||
36 36 | trio.open_unix_socket(foo)
|
||||
37 37 | trio.run_process(foo)
|
||||
38 38 | trio.serve_listeners(foo, foo)
|
||||
|
||||
TRIO105.py:36:5: TRIO105 [*] Call to `trio.open_unix_socket` is not immediately awaited
|
||||
|
|
||||
34 | trio.open_tcp_listeners(foo)
|
||||
35 | trio.open_tcp_stream(foo, foo)
|
||||
36 | trio.open_unix_socket(foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
37 | trio.run_process(foo)
|
||||
38 | trio.serve_listeners(foo, foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
33 33 | trio.open_ssl_over_tcp_stream(foo, foo)
|
||||
34 34 | trio.open_tcp_listeners(foo)
|
||||
35 35 | trio.open_tcp_stream(foo, foo)
|
||||
36 |- trio.open_unix_socket(foo)
|
||||
36 |+ await trio.open_unix_socket(foo)
|
||||
37 37 | trio.run_process(foo)
|
||||
38 38 | trio.serve_listeners(foo, foo)
|
||||
39 39 | trio.serve_ssl_over_tcp(foo, foo, foo)
|
||||
|
||||
TRIO105.py:37:5: TRIO105 [*] Call to `trio.run_process` is not immediately awaited
|
||||
|
|
||||
35 | trio.open_tcp_stream(foo, foo)
|
||||
36 | trio.open_unix_socket(foo)
|
||||
37 | trio.run_process(foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
38 | trio.serve_listeners(foo, foo)
|
||||
39 | trio.serve_ssl_over_tcp(foo, foo, foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
34 34 | trio.open_tcp_listeners(foo)
|
||||
35 35 | trio.open_tcp_stream(foo, foo)
|
||||
36 36 | trio.open_unix_socket(foo)
|
||||
37 |- trio.run_process(foo)
|
||||
37 |+ await trio.run_process(foo)
|
||||
38 38 | trio.serve_listeners(foo, foo)
|
||||
39 39 | trio.serve_ssl_over_tcp(foo, foo, foo)
|
||||
40 40 | trio.serve_tcp(foo, foo)
|
||||
|
||||
TRIO105.py:38:5: TRIO105 [*] Call to `trio.serve_listeners` is not immediately awaited
|
||||
|
|
||||
36 | trio.open_unix_socket(foo)
|
||||
37 | trio.run_process(foo)
|
||||
38 | trio.serve_listeners(foo, foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
39 | trio.serve_ssl_over_tcp(foo, foo, foo)
|
||||
40 | trio.serve_tcp(foo, foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
35 35 | trio.open_tcp_stream(foo, foo)
|
||||
36 36 | trio.open_unix_socket(foo)
|
||||
37 37 | trio.run_process(foo)
|
||||
38 |- trio.serve_listeners(foo, foo)
|
||||
38 |+ await trio.serve_listeners(foo, foo)
|
||||
39 39 | trio.serve_ssl_over_tcp(foo, foo, foo)
|
||||
40 40 | trio.serve_tcp(foo, foo)
|
||||
41 41 | trio.sleep(foo)
|
||||
|
||||
TRIO105.py:39:5: TRIO105 [*] Call to `trio.serve_ssl_over_tcp` is not immediately awaited
|
||||
|
|
||||
37 | trio.run_process(foo)
|
||||
38 | trio.serve_listeners(foo, foo)
|
||||
39 | trio.serve_ssl_over_tcp(foo, foo, foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
40 | trio.serve_tcp(foo, foo)
|
||||
41 | trio.sleep(foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
36 36 | trio.open_unix_socket(foo)
|
||||
37 37 | trio.run_process(foo)
|
||||
38 38 | trio.serve_listeners(foo, foo)
|
||||
39 |- trio.serve_ssl_over_tcp(foo, foo, foo)
|
||||
39 |+ await trio.serve_ssl_over_tcp(foo, foo, foo)
|
||||
40 40 | trio.serve_tcp(foo, foo)
|
||||
41 41 | trio.sleep(foo)
|
||||
42 42 | trio.sleep_forever()
|
||||
|
||||
TRIO105.py:40:5: TRIO105 [*] Call to `trio.serve_tcp` is not immediately awaited
|
||||
|
|
||||
38 | trio.serve_listeners(foo, foo)
|
||||
39 | trio.serve_ssl_over_tcp(foo, foo, foo)
|
||||
40 | trio.serve_tcp(foo, foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
41 | trio.sleep(foo)
|
||||
42 | trio.sleep_forever()
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
37 37 | trio.run_process(foo)
|
||||
38 38 | trio.serve_listeners(foo, foo)
|
||||
39 39 | trio.serve_ssl_over_tcp(foo, foo, foo)
|
||||
40 |- trio.serve_tcp(foo, foo)
|
||||
40 |+ await trio.serve_tcp(foo, foo)
|
||||
41 41 | trio.sleep(foo)
|
||||
42 42 | trio.sleep_forever()
|
||||
43 43 | trio.sleep_until(foo)
|
||||
|
||||
TRIO105.py:41:5: TRIO105 [*] Call to `trio.sleep` is not immediately awaited
|
||||
|
|
||||
39 | trio.serve_ssl_over_tcp(foo, foo, foo)
|
||||
40 | trio.serve_tcp(foo, foo)
|
||||
41 | trio.sleep(foo)
|
||||
| ^^^^^^^^^^^^^^^ TRIO105
|
||||
42 | trio.sleep_forever()
|
||||
43 | trio.sleep_until(foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
38 38 | trio.serve_listeners(foo, foo)
|
||||
39 39 | trio.serve_ssl_over_tcp(foo, foo, foo)
|
||||
40 40 | trio.serve_tcp(foo, foo)
|
||||
41 |- trio.sleep(foo)
|
||||
41 |+ await trio.sleep(foo)
|
||||
42 42 | trio.sleep_forever()
|
||||
43 43 | trio.sleep_until(foo)
|
||||
44 44 | trio.lowlevel.cancel_shielded_checkpoint()
|
||||
|
||||
TRIO105.py:42:5: TRIO105 [*] Call to `trio.sleep_forever` is not immediately awaited
|
||||
|
|
||||
40 | trio.serve_tcp(foo, foo)
|
||||
41 | trio.sleep(foo)
|
||||
42 | trio.sleep_forever()
|
||||
| ^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
43 | trio.sleep_until(foo)
|
||||
44 | trio.lowlevel.cancel_shielded_checkpoint()
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
39 39 | trio.serve_ssl_over_tcp(foo, foo, foo)
|
||||
40 40 | trio.serve_tcp(foo, foo)
|
||||
41 41 | trio.sleep(foo)
|
||||
42 |- trio.sleep_forever()
|
||||
42 |+ await trio.sleep_forever()
|
||||
43 43 | trio.sleep_until(foo)
|
||||
44 44 | trio.lowlevel.cancel_shielded_checkpoint()
|
||||
45 45 | trio.lowlevel.checkpoint()
|
||||
|
||||
TRIO105.py:44:5: TRIO105 [*] Call to `trio.lowlevel.cancel_shielded_checkpoint` is not immediately awaited
|
||||
|
|
||||
42 | trio.sleep_forever()
|
||||
43 | trio.sleep_until(foo)
|
||||
44 | trio.lowlevel.cancel_shielded_checkpoint()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
45 | trio.lowlevel.checkpoint()
|
||||
46 | trio.lowlevel.checkpoint_if_cancelled()
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
41 41 | trio.sleep(foo)
|
||||
42 42 | trio.sleep_forever()
|
||||
43 43 | trio.sleep_until(foo)
|
||||
44 |- trio.lowlevel.cancel_shielded_checkpoint()
|
||||
44 |+ await trio.lowlevel.cancel_shielded_checkpoint()
|
||||
45 45 | trio.lowlevel.checkpoint()
|
||||
46 46 | trio.lowlevel.checkpoint_if_cancelled()
|
||||
47 47 | trio.lowlevel.open_process()
|
||||
|
||||
TRIO105.py:45:5: TRIO105 [*] Call to `trio.lowlevel.checkpoint` is not immediately awaited
|
||||
|
|
||||
43 | trio.sleep_until(foo)
|
||||
44 | trio.lowlevel.cancel_shielded_checkpoint()
|
||||
45 | trio.lowlevel.checkpoint()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
46 | trio.lowlevel.checkpoint_if_cancelled()
|
||||
47 | trio.lowlevel.open_process()
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
42 42 | trio.sleep_forever()
|
||||
43 43 | trio.sleep_until(foo)
|
||||
44 44 | trio.lowlevel.cancel_shielded_checkpoint()
|
||||
45 |- trio.lowlevel.checkpoint()
|
||||
45 |+ await trio.lowlevel.checkpoint()
|
||||
46 46 | trio.lowlevel.checkpoint_if_cancelled()
|
||||
47 47 | trio.lowlevel.open_process()
|
||||
48 48 | trio.lowlevel.permanently_detach_coroutine_object(foo)
|
||||
|
||||
TRIO105.py:46:5: TRIO105 [*] Call to `trio.lowlevel.checkpoint_if_cancelled` is not immediately awaited
|
||||
|
|
||||
44 | trio.lowlevel.cancel_shielded_checkpoint()
|
||||
45 | trio.lowlevel.checkpoint()
|
||||
46 | trio.lowlevel.checkpoint_if_cancelled()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
47 | trio.lowlevel.open_process()
|
||||
48 | trio.lowlevel.permanently_detach_coroutine_object(foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
43 43 | trio.sleep_until(foo)
|
||||
44 44 | trio.lowlevel.cancel_shielded_checkpoint()
|
||||
45 45 | trio.lowlevel.checkpoint()
|
||||
46 |- trio.lowlevel.checkpoint_if_cancelled()
|
||||
46 |+ await trio.lowlevel.checkpoint_if_cancelled()
|
||||
47 47 | trio.lowlevel.open_process()
|
||||
48 48 | trio.lowlevel.permanently_detach_coroutine_object(foo)
|
||||
49 49 | trio.lowlevel.reattach_detached_coroutine_object(foo, foo)
|
||||
|
||||
TRIO105.py:47:5: TRIO105 [*] Call to `trio.lowlevel.open_process` is not immediately awaited
|
||||
|
|
||||
45 | trio.lowlevel.checkpoint()
|
||||
46 | trio.lowlevel.checkpoint_if_cancelled()
|
||||
47 | trio.lowlevel.open_process()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
48 | trio.lowlevel.permanently_detach_coroutine_object(foo)
|
||||
49 | trio.lowlevel.reattach_detached_coroutine_object(foo, foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
44 44 | trio.lowlevel.cancel_shielded_checkpoint()
|
||||
45 45 | trio.lowlevel.checkpoint()
|
||||
46 46 | trio.lowlevel.checkpoint_if_cancelled()
|
||||
47 |- trio.lowlevel.open_process()
|
||||
47 |+ await trio.lowlevel.open_process()
|
||||
48 48 | trio.lowlevel.permanently_detach_coroutine_object(foo)
|
||||
49 49 | trio.lowlevel.reattach_detached_coroutine_object(foo, foo)
|
||||
50 50 | trio.lowlevel.temporarily_detach_coroutine_object(foo)
|
||||
|
||||
TRIO105.py:48:5: TRIO105 [*] Call to `trio.lowlevel.permanently_detach_coroutine_object` is not immediately awaited
|
||||
|
|
||||
46 | trio.lowlevel.checkpoint_if_cancelled()
|
||||
47 | trio.lowlevel.open_process()
|
||||
48 | trio.lowlevel.permanently_detach_coroutine_object(foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
49 | trio.lowlevel.reattach_detached_coroutine_object(foo, foo)
|
||||
50 | trio.lowlevel.temporarily_detach_coroutine_object(foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
45 45 | trio.lowlevel.checkpoint()
|
||||
46 46 | trio.lowlevel.checkpoint_if_cancelled()
|
||||
47 47 | trio.lowlevel.open_process()
|
||||
48 |- trio.lowlevel.permanently_detach_coroutine_object(foo)
|
||||
48 |+ await trio.lowlevel.permanently_detach_coroutine_object(foo)
|
||||
49 49 | trio.lowlevel.reattach_detached_coroutine_object(foo, foo)
|
||||
50 50 | trio.lowlevel.temporarily_detach_coroutine_object(foo)
|
||||
51 51 | trio.lowlevel.wait_readable(foo)
|
||||
|
||||
TRIO105.py:49:5: TRIO105 [*] Call to `trio.lowlevel.reattach_detached_coroutine_object` is not immediately awaited
|
||||
|
|
||||
47 | trio.lowlevel.open_process()
|
||||
48 | trio.lowlevel.permanently_detach_coroutine_object(foo)
|
||||
49 | trio.lowlevel.reattach_detached_coroutine_object(foo, foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
50 | trio.lowlevel.temporarily_detach_coroutine_object(foo)
|
||||
51 | trio.lowlevel.wait_readable(foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
46 46 | trio.lowlevel.checkpoint_if_cancelled()
|
||||
47 47 | trio.lowlevel.open_process()
|
||||
48 48 | trio.lowlevel.permanently_detach_coroutine_object(foo)
|
||||
49 |- trio.lowlevel.reattach_detached_coroutine_object(foo, foo)
|
||||
49 |+ await trio.lowlevel.reattach_detached_coroutine_object(foo, foo)
|
||||
50 50 | trio.lowlevel.temporarily_detach_coroutine_object(foo)
|
||||
51 51 | trio.lowlevel.wait_readable(foo)
|
||||
52 52 | trio.lowlevel.wait_task_rescheduled(foo)
|
||||
|
||||
TRIO105.py:50:5: TRIO105 [*] Call to `trio.lowlevel.temporarily_detach_coroutine_object` is not immediately awaited
|
||||
|
|
||||
48 | trio.lowlevel.permanently_detach_coroutine_object(foo)
|
||||
49 | trio.lowlevel.reattach_detached_coroutine_object(foo, foo)
|
||||
50 | trio.lowlevel.temporarily_detach_coroutine_object(foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
51 | trio.lowlevel.wait_readable(foo)
|
||||
52 | trio.lowlevel.wait_task_rescheduled(foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
47 47 | trio.lowlevel.open_process()
|
||||
48 48 | trio.lowlevel.permanently_detach_coroutine_object(foo)
|
||||
49 49 | trio.lowlevel.reattach_detached_coroutine_object(foo, foo)
|
||||
50 |- trio.lowlevel.temporarily_detach_coroutine_object(foo)
|
||||
50 |+ await trio.lowlevel.temporarily_detach_coroutine_object(foo)
|
||||
51 51 | trio.lowlevel.wait_readable(foo)
|
||||
52 52 | trio.lowlevel.wait_task_rescheduled(foo)
|
||||
53 53 | trio.lowlevel.wait_writable(foo)
|
||||
|
||||
TRIO105.py:51:5: TRIO105 [*] Call to `trio.lowlevel.wait_readable` is not immediately awaited
|
||||
|
|
||||
49 | trio.lowlevel.reattach_detached_coroutine_object(foo, foo)
|
||||
50 | trio.lowlevel.temporarily_detach_coroutine_object(foo)
|
||||
51 | trio.lowlevel.wait_readable(foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
52 | trio.lowlevel.wait_task_rescheduled(foo)
|
||||
53 | trio.lowlevel.wait_writable(foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
48 48 | trio.lowlevel.permanently_detach_coroutine_object(foo)
|
||||
49 49 | trio.lowlevel.reattach_detached_coroutine_object(foo, foo)
|
||||
50 50 | trio.lowlevel.temporarily_detach_coroutine_object(foo)
|
||||
51 |- trio.lowlevel.wait_readable(foo)
|
||||
51 |+ await trio.lowlevel.wait_readable(foo)
|
||||
52 52 | trio.lowlevel.wait_task_rescheduled(foo)
|
||||
53 53 | trio.lowlevel.wait_writable(foo)
|
||||
54 54 |
|
||||
|
||||
TRIO105.py:52:5: TRIO105 [*] Call to `trio.lowlevel.wait_task_rescheduled` is not immediately awaited
|
||||
|
|
||||
50 | trio.lowlevel.temporarily_detach_coroutine_object(foo)
|
||||
51 | trio.lowlevel.wait_readable(foo)
|
||||
52 | trio.lowlevel.wait_task_rescheduled(foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
53 | trio.lowlevel.wait_writable(foo)
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
49 49 | trio.lowlevel.reattach_detached_coroutine_object(foo, foo)
|
||||
50 50 | trio.lowlevel.temporarily_detach_coroutine_object(foo)
|
||||
51 51 | trio.lowlevel.wait_readable(foo)
|
||||
52 |- trio.lowlevel.wait_task_rescheduled(foo)
|
||||
52 |+ await trio.lowlevel.wait_task_rescheduled(foo)
|
||||
53 53 | trio.lowlevel.wait_writable(foo)
|
||||
54 54 |
|
||||
55 55 | async with await trio.open_file(foo): # Ok
|
||||
|
||||
TRIO105.py:53:5: TRIO105 [*] Call to `trio.lowlevel.wait_writable` is not immediately awaited
|
||||
|
|
||||
51 | trio.lowlevel.wait_readable(foo)
|
||||
52 | trio.lowlevel.wait_task_rescheduled(foo)
|
||||
53 | trio.lowlevel.wait_writable(foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
54 |
|
||||
55 | async with await trio.open_file(foo): # Ok
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
50 50 | trio.lowlevel.temporarily_detach_coroutine_object(foo)
|
||||
51 51 | trio.lowlevel.wait_readable(foo)
|
||||
52 52 | trio.lowlevel.wait_task_rescheduled(foo)
|
||||
53 |- trio.lowlevel.wait_writable(foo)
|
||||
53 |+ await trio.lowlevel.wait_writable(foo)
|
||||
54 54 |
|
||||
55 55 | async with await trio.open_file(foo): # Ok
|
||||
56 56 | pass
|
||||
|
||||
TRIO105.py:58:16: TRIO105 [*] Call to `trio.open_file` is not immediately awaited
|
||||
|
|
||||
56 | pass
|
||||
57 |
|
||||
58 | async with trio.open_file(foo): # TRIO105
|
||||
| ^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
59 | pass
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
ℹ Suggested fix
|
||||
55 55 | async with await trio.open_file(foo): # Ok
|
||||
56 56 | pass
|
||||
57 57 |
|
||||
58 |- async with trio.open_file(foo): # TRIO105
|
||||
58 |+ async with await trio.open_file(foo): # TRIO105
|
||||
59 59 | pass
|
||||
60 60 |
|
||||
61 61 |
|
||||
|
||||
TRIO105.py:64:5: TRIO105 Call to `trio.open_file` is not immediately awaited
|
||||
|
|
||||
62 | def func() -> None:
|
||||
63 | # TRIO105 (without fix)
|
||||
64 | trio.open_file(foo)
|
||||
| ^^^^^^^^^^^^^^^^^^^ TRIO105
|
||||
|
|
||||
= help: Add `await`
|
||||
|
||||
|
|
@ -10,6 +10,7 @@ use ruff_text_size::{Ranged, TextRange};
|
|||
use crate::call_path::CallPath;
|
||||
use crate::parenthesize::parenthesized_range;
|
||||
use crate::statement_visitor::{walk_body, walk_stmt, StatementVisitor};
|
||||
use crate::visitor::Visitor;
|
||||
use crate::AnyNodeRef;
|
||||
use crate::{
|
||||
self as ast, Arguments, CmpOp, ExceptHandler, Expr, MatchCase, Pattern, Stmt, TypeParam,
|
||||
|
@ -931,6 +932,29 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// A [`Visitor`] that detects the presence of `await` expressions in the current scope.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct AwaitVisitor {
|
||||
pub seen_await: bool,
|
||||
}
|
||||
|
||||
impl Visitor<'_> for AwaitVisitor {
|
||||
fn visit_stmt(&mut self, stmt: &Stmt) {
|
||||
match stmt {
|
||||
Stmt::FunctionDef(_) | Stmt::ClassDef(_) => (),
|
||||
_ => crate::visitor::walk_stmt(self, stmt),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &Expr) {
|
||||
if let Expr::Await(ast::ExprAwait { .. }) = expr {
|
||||
self.seen_await = true;
|
||||
} else {
|
||||
crate::visitor::walk_expr(self, expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return `true` if a `Stmt` is a docstring.
|
||||
pub fn is_docstring_stmt(stmt: &Stmt) -> bool {
|
||||
if let Stmt::Expr(ast::StmtExpr { value, range: _ }) = stmt {
|
||||
|
|
1
ruff.schema.json
generated
1
ruff.schema.json
generated
|
@ -3472,6 +3472,7 @@
|
|||
"TRIO1",
|
||||
"TRIO10",
|
||||
"TRIO100",
|
||||
"TRIO105",
|
||||
"TRY",
|
||||
"TRY0",
|
||||
"TRY00",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue