mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 06:41:23 +00:00
Expand asyncio-dangling-task
(RUF006
) to include new_event_loop
(#9976)
## Summary Fixes #9974 ## Test Plan I added some new test cases.
This commit is contained in:
parent
46db3f96ac
commit
3e9d761b13
3 changed files with 62 additions and 7 deletions
|
@ -162,3 +162,26 @@ async def f(x: bool):
|
||||||
T = asyncio.create_task(asyncio.sleep(1))
|
T = asyncio.create_task(asyncio.sleep(1))
|
||||||
else:
|
else:
|
||||||
T = None
|
T = None
|
||||||
|
|
||||||
|
|
||||||
|
# Error
|
||||||
|
def f():
|
||||||
|
loop = asyncio.new_event_loop()
|
||||||
|
loop.create_task(main()) # Error
|
||||||
|
|
||||||
|
# Error
|
||||||
|
def f():
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
loop.create_task(main()) # Error
|
||||||
|
|
||||||
|
# OK
|
||||||
|
def f():
|
||||||
|
global task
|
||||||
|
loop = asyncio.new_event_loop()
|
||||||
|
task = loop.create_task(main()) # Error
|
||||||
|
|
||||||
|
# OK
|
||||||
|
def f():
|
||||||
|
global task
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
task = loop.create_task(main()) # Error
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::fmt;
|
||||||
use ast::Stmt;
|
use ast::Stmt;
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
use ruff_python_ast::call_path::compose_call_path;
|
||||||
use ruff_python_ast::{self as ast, Expr};
|
use ruff_python_ast::{self as ast, Expr};
|
||||||
use ruff_python_semantic::{analyze::typing, Scope, SemanticModel};
|
use ruff_python_semantic::{analyze::typing, Scope, SemanticModel};
|
||||||
use ruff_text_size::Ranged;
|
use ruff_text_size::Ranged;
|
||||||
|
@ -52,14 +53,15 @@ use ruff_text_size::Ranged;
|
||||||
/// - [The Python Standard Library](https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task)
|
/// - [The Python Standard Library](https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task)
|
||||||
#[violation]
|
#[violation]
|
||||||
pub struct AsyncioDanglingTask {
|
pub struct AsyncioDanglingTask {
|
||||||
|
expr: String,
|
||||||
method: Method,
|
method: Method,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Violation for AsyncioDanglingTask {
|
impl Violation for AsyncioDanglingTask {
|
||||||
#[derive_message_formats]
|
#[derive_message_formats]
|
||||||
fn message(&self) -> String {
|
fn message(&self) -> String {
|
||||||
let AsyncioDanglingTask { method } = self;
|
let AsyncioDanglingTask { expr, method } = self;
|
||||||
format!("Store a reference to the return value of `asyncio.{method}`")
|
format!("Store a reference to the return value of `{expr}.{method}`")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,19 +82,29 @@ pub(crate) fn asyncio_dangling_task(expr: &Expr, semantic: &SemanticModel) -> Op
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
return Some(Diagnostic::new(
|
return Some(Diagnostic::new(
|
||||||
AsyncioDanglingTask { method },
|
AsyncioDanglingTask {
|
||||||
|
expr: "asyncio".to_string(),
|
||||||
|
method,
|
||||||
|
},
|
||||||
expr.range(),
|
expr.range(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ex) `loop = asyncio.get_running_loop(); loop.create_task(...)`
|
// Ex) `loop = ...; loop.create_task(...)`
|
||||||
if let Expr::Attribute(ast::ExprAttribute { attr, value, .. }) = func.as_ref() {
|
if let Expr::Attribute(ast::ExprAttribute { attr, value, .. }) = func.as_ref() {
|
||||||
if attr == "create_task" {
|
if attr == "create_task" {
|
||||||
if typing::resolve_assignment(value, semantic).is_some_and(|call_path| {
|
if typing::resolve_assignment(value, semantic).is_some_and(|call_path| {
|
||||||
matches!(call_path.as_slice(), ["asyncio", "get_running_loop"])
|
matches!(
|
||||||
|
call_path.as_slice(),
|
||||||
|
[
|
||||||
|
"asyncio",
|
||||||
|
"get_event_loop" | "get_running_loop" | "new_event_loop"
|
||||||
|
]
|
||||||
|
)
|
||||||
}) {
|
}) {
|
||||||
return Some(Diagnostic::new(
|
return Some(Diagnostic::new(
|
||||||
AsyncioDanglingTask {
|
AsyncioDanglingTask {
|
||||||
|
expr: compose_call_path(value).unwrap_or_else(|| "asyncio".to_string()),
|
||||||
method: Method::CreateTask,
|
method: Method::CreateTask,
|
||||||
},
|
},
|
||||||
expr.range(),
|
expr.range(),
|
||||||
|
|
|
@ -25,7 +25,7 @@ RUF006.py:68:12: RUF006 Store a reference to the return value of `asyncio.create
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF006
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF006
|
||||||
|
|
|
|
||||||
|
|
||||||
RUF006.py:74:26: RUF006 Store a reference to the return value of `asyncio.create_task`
|
RUF006.py:74:26: RUF006 Store a reference to the return value of `loop.create_task`
|
||||||
|
|
|
|
||||||
72 | def f():
|
72 | def f():
|
||||||
73 | loop = asyncio.get_running_loop()
|
73 | loop = asyncio.get_running_loop()
|
||||||
|
@ -33,7 +33,7 @@ RUF006.py:74:26: RUF006 Store a reference to the return value of `asyncio.create
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF006
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF006
|
||||||
|
|
|
|
||||||
|
|
||||||
RUF006.py:97:5: RUF006 Store a reference to the return value of `asyncio.create_task`
|
RUF006.py:97:5: RUF006 Store a reference to the return value of `loop.create_task`
|
||||||
|
|
|
|
||||||
95 | def f():
|
95 | def f():
|
||||||
96 | loop = asyncio.get_running_loop()
|
96 | loop = asyncio.get_running_loop()
|
||||||
|
@ -41,4 +41,24 @@ RUF006.py:97:5: RUF006 Store a reference to the return value of `asyncio.create_
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF006
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF006
|
||||||
|
|
|
|
||||||
|
|
||||||
|
RUF006.py:170:5: RUF006 Store a reference to the return value of `loop.create_task`
|
||||||
|
|
|
||||||
|
168 | def f():
|
||||||
|
169 | loop = asyncio.new_event_loop()
|
||||||
|
170 | loop.create_task(main()) # Error
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ RUF006
|
||||||
|
171 |
|
||||||
|
172 | # Error
|
||||||
|
|
|
||||||
|
|
||||||
|
RUF006.py:175:5: RUF006 Store a reference to the return value of `loop.create_task`
|
||||||
|
|
|
||||||
|
173 | def f():
|
||||||
|
174 | loop = asyncio.get_event_loop()
|
||||||
|
175 | loop.create_task(main()) # Error
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ RUF006
|
||||||
|
176 |
|
||||||
|
177 | # OK
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue