mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 22:54:42 +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))
|
||||
else:
|
||||
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 ruff_diagnostics::{Diagnostic, 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_semantic::{analyze::typing, Scope, SemanticModel};
|
||||
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)
|
||||
#[violation]
|
||||
pub struct AsyncioDanglingTask {
|
||||
expr: String,
|
||||
method: Method,
|
||||
}
|
||||
|
||||
impl Violation for AsyncioDanglingTask {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let AsyncioDanglingTask { method } = self;
|
||||
format!("Store a reference to the return value of `asyncio.{method}`")
|
||||
let AsyncioDanglingTask { expr, method } = self;
|
||||
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(
|
||||
AsyncioDanglingTask { method },
|
||||
AsyncioDanglingTask {
|
||||
expr: "asyncio".to_string(),
|
||||
method,
|
||||
},
|
||||
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 attr == "create_task" {
|
||||
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(
|
||||
AsyncioDanglingTask {
|
||||
expr: compose_call_path(value).unwrap_or_else(|| "asyncio".to_string()),
|
||||
method: Method::CreateTask,
|
||||
},
|
||||
expr.range(),
|
||||
|
|
|
@ -25,7 +25,7 @@ RUF006.py:68:12: RUF006 Store a reference to the return value of `asyncio.create
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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():
|
||||
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.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():
|
||||
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.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