Skip to content

Commit 71e93a9

Browse files
Only flag flake8-trio rule when trio is present (#8550)
## Summary Hoping to avoid some false positives by narrowing the scope of #8534.
1 parent e2c7b1e commit 71e93a9

File tree

4 files changed

+30
-6
lines changed

4 files changed

+30
-6
lines changed

crates/ruff_linter/resources/test/fixtures/flake8_trio/TRIO109.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import trio
2+
3+
14
async def func():
25
...
36

crates/ruff_linter/src/rules/flake8_trio/rules/async_function_with_timeout.rs

+11
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ use crate::checkers::ast::Checker;
1313
/// trio's built-in timeout functionality, available as `trio.fail_after`,
1414
/// `trio.move_on_after`, `trio.fail_at`, and `trio.move_on_at`.
1515
///
16+
/// ## Known problems
17+
/// To avoid false positives, this rule is only enabled if `trio` is imported
18+
/// in the module.
19+
///
1620
/// ## Example
1721
/// ```python
1822
/// async def func():
@@ -40,12 +44,19 @@ pub(crate) fn async_function_with_timeout(
4044
checker: &mut Checker,
4145
function_def: &ast::StmtFunctionDef,
4246
) {
47+
// Detect `async` calls with a `timeout` argument.
4348
if !function_def.is_async {
4449
return;
4550
}
4651
let Some(timeout) = function_def.parameters.find("timeout") else {
4752
return;
4853
};
54+
55+
// If `trio` isn't in scope, avoid raising the diagnostic.
56+
if !checker.semantic().seen(&["trio"]) {
57+
return;
58+
}
59+
4960
checker.diagnostics.push(Diagnostic::new(
5061
TrioAsyncFunctionWithTimeout,
5162
timeout.range(),
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
---
22
source: crates/ruff_linter/src/rules/flake8_trio/mod.rs
33
---
4-
TRIO109.py:5:16: TRIO109 Prefer `trio.fail_after` and `trio.move_on_after` over manual `async` timeout behavior
4+
TRIO109.py:8:16: TRIO109 Prefer `trio.fail_after` and `trio.move_on_after` over manual `async` timeout behavior
55
|
6-
5 | async def func(timeout):
6+
8 | async def func(timeout):
77
| ^^^^^^^ TRIO109
8-
6 | ...
8+
9 | ...
99
|
1010

11-
TRIO109.py:9:16: TRIO109 Prefer `trio.fail_after` and `trio.move_on_after` over manual `async` timeout behavior
11+
TRIO109.py:12:16: TRIO109 Prefer `trio.fail_after` and `trio.move_on_after` over manual `async` timeout behavior
1212
|
13-
9 | async def func(timeout=10):
13+
12 | async def func(timeout=10):
1414
| ^^^^^^^^^^ TRIO109
15-
10 | ...
15+
13 | ...
1616
|
1717

1818

crates/ruff_python_semantic/src/model.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1207,6 +1207,16 @@ impl<'a> SemanticModel<'a> {
12071207
exceptions
12081208
}
12091209

1210+
/// Return `true` if the module at the given path was seen anywhere in the semantic model.
1211+
/// This includes both direct imports (`import trio`) and member imports (`from trio import
1212+
/// TrioTask`).
1213+
pub fn seen(&self, module: &[&str]) -> bool {
1214+
self.bindings
1215+
.iter()
1216+
.filter_map(Binding::as_any_import)
1217+
.any(|import| import.call_path().starts_with(module))
1218+
}
1219+
12101220
/// Generate a [`Snapshot`] of the current semantic model.
12111221
pub fn snapshot(&self) -> Snapshot {
12121222
Snapshot {

0 commit comments

Comments
 (0)