-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[pylint] Implement
useless-with-lock
(#8321)
- Loading branch information
Showing
8 changed files
with
253 additions
and
0 deletions.
There are no files selected for viewing
56 changes: 56 additions & 0 deletions
56
crates/ruff_linter/resources/test/fixtures/pylint/useless_with_lock.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import threading | ||
from threading import Lock, RLock, Condition, Semaphore, BoundedSemaphore | ||
|
||
|
||
with threading.Lock(): # [useless-with-lock] | ||
... | ||
|
||
with Lock(): # [useless-with-lock] | ||
... | ||
|
||
with threading.Lock() as this_shouldnt_matter: # [useless-with-lock] | ||
... | ||
|
||
with threading.RLock(): # [useless-with-lock] | ||
... | ||
|
||
with RLock(): # [useless-with-lock] | ||
... | ||
|
||
with threading.Condition(): # [useless-with-lock] | ||
... | ||
|
||
with Condition(): # [useless-with-lock] | ||
... | ||
|
||
with threading.Semaphore(): # [useless-with-lock] | ||
... | ||
|
||
with Semaphore(): # [useless-with-lock] | ||
... | ||
|
||
with threading.BoundedSemaphore(): # [useless-with-lock] | ||
... | ||
|
||
with BoundedSemaphore(): # [useless-with-lock] | ||
... | ||
|
||
lock = threading.Lock() | ||
with lock: # this is ok | ||
... | ||
|
||
rlock = threading.RLock() | ||
with rlock: # this is ok | ||
... | ||
|
||
cond = threading.Condition() | ||
with cond: # this is ok | ||
... | ||
|
||
sem = threading.Semaphore() | ||
with sem: # this is ok | ||
... | ||
|
||
b_sem = threading.BoundedSemaphore() | ||
with b_sem: # this is ok | ||
... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
86 changes: 86 additions & 0 deletions
86
crates/ruff_linter/src/rules/pylint/rules/useless_with_lock.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
use ruff_diagnostics::{Diagnostic, Violation}; | ||
use ruff_macros::{derive_message_formats, violation}; | ||
use ruff_python_ast::{self as ast}; | ||
use ruff_text_size::Ranged; | ||
|
||
use crate::checkers::ast::Checker; | ||
|
||
/// ## What it does | ||
/// Checks for direct uses of lock objects in `with` statements. | ||
/// | ||
/// ## Why is this bad? | ||
/// Creating a lock (via `threading.Lock` or similar) in a `with` statement | ||
/// has no effect, as locks are only relevant when shared between threads. | ||
/// | ||
/// Instead, assign the lock to a variable outside the `with` statement, | ||
/// and share that variable between threads. | ||
/// | ||
/// ## Example | ||
/// ```python | ||
/// import threading | ||
/// | ||
/// counter = 0 | ||
/// | ||
/// | ||
/// def increment(): | ||
/// global counter | ||
/// | ||
/// with threading.Lock(): | ||
/// counter += 1 | ||
/// ``` | ||
/// | ||
/// Use instead: | ||
/// ```python | ||
/// import threading | ||
/// | ||
/// counter = 0 | ||
/// lock = threading.Lock() | ||
/// | ||
/// | ||
/// def increment(): | ||
/// global counter | ||
/// | ||
/// with lock: | ||
/// counter += 1 | ||
/// ``` | ||
/// | ||
/// ## References | ||
/// - [Python documentation: `Lock Objects`](https://docs.python.org/3/library/threading.html#lock-objects) | ||
#[violation] | ||
pub struct UselessWithLock; | ||
|
||
impl Violation for UselessWithLock { | ||
#[derive_message_formats] | ||
fn message(&self) -> String { | ||
format!("Threading lock directly created in `with` statement has no effect") | ||
} | ||
} | ||
|
||
/// PLW2101 | ||
pub(crate) fn useless_with_lock(checker: &mut Checker, with: &ast::StmtWith) { | ||
for item in &with.items { | ||
let Some(call) = item.context_expr.as_call_expr() else { | ||
continue; | ||
}; | ||
|
||
if !checker | ||
.semantic() | ||
.resolve_call_path(call.func.as_ref()) | ||
.is_some_and(|call_path| { | ||
matches!( | ||
call_path.as_slice(), | ||
[ | ||
"threading", | ||
"Lock" | "RLock" | "Condition" | "Semaphore" | "BoundedSemaphore" | ||
] | ||
) | ||
}) | ||
{ | ||
return; | ||
} | ||
|
||
checker | ||
.diagnostics | ||
.push(Diagnostic::new(UselessWithLock, call.range())); | ||
} | ||
} |
101 changes: 101 additions & 0 deletions
101
...les/pylint/snapshots/ruff_linter__rules__pylint__tests__PLW2101_useless_with_lock.py.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
--- | ||
source: crates/ruff_linter/src/rules/pylint/mod.rs | ||
--- | ||
useless_with_lock.py:5:6: PLW2101 Threading lock directly created in `with` statement has no effect | ||
| | ||
5 | with threading.Lock(): # [useless-with-lock] | ||
| ^^^^^^^^^^^^^^^^ PLW2101 | ||
6 | ... | ||
| | ||
|
||
useless_with_lock.py:8:6: PLW2101 Threading lock directly created in `with` statement has no effect | ||
| | ||
6 | ... | ||
7 | | ||
8 | with Lock(): # [useless-with-lock] | ||
| ^^^^^^ PLW2101 | ||
9 | ... | ||
| | ||
|
||
useless_with_lock.py:11:6: PLW2101 Threading lock directly created in `with` statement has no effect | ||
| | ||
9 | ... | ||
10 | | ||
11 | with threading.Lock() as this_shouldnt_matter: # [useless-with-lock] | ||
| ^^^^^^^^^^^^^^^^ PLW2101 | ||
12 | ... | ||
| | ||
|
||
useless_with_lock.py:14:6: PLW2101 Threading lock directly created in `with` statement has no effect | ||
| | ||
12 | ... | ||
13 | | ||
14 | with threading.RLock(): # [useless-with-lock] | ||
| ^^^^^^^^^^^^^^^^^ PLW2101 | ||
15 | ... | ||
| | ||
|
||
useless_with_lock.py:17:6: PLW2101 Threading lock directly created in `with` statement has no effect | ||
| | ||
15 | ... | ||
16 | | ||
17 | with RLock(): # [useless-with-lock] | ||
| ^^^^^^^ PLW2101 | ||
18 | ... | ||
| | ||
|
||
useless_with_lock.py:20:6: PLW2101 Threading lock directly created in `with` statement has no effect | ||
| | ||
18 | ... | ||
19 | | ||
20 | with threading.Condition(): # [useless-with-lock] | ||
| ^^^^^^^^^^^^^^^^^^^^^ PLW2101 | ||
21 | ... | ||
| | ||
|
||
useless_with_lock.py:23:6: PLW2101 Threading lock directly created in `with` statement has no effect | ||
| | ||
21 | ... | ||
22 | | ||
23 | with Condition(): # [useless-with-lock] | ||
| ^^^^^^^^^^^ PLW2101 | ||
24 | ... | ||
| | ||
|
||
useless_with_lock.py:26:6: PLW2101 Threading lock directly created in `with` statement has no effect | ||
| | ||
24 | ... | ||
25 | | ||
26 | with threading.Semaphore(): # [useless-with-lock] | ||
| ^^^^^^^^^^^^^^^^^^^^^ PLW2101 | ||
27 | ... | ||
| | ||
|
||
useless_with_lock.py:29:6: PLW2101 Threading lock directly created in `with` statement has no effect | ||
| | ||
27 | ... | ||
28 | | ||
29 | with Semaphore(): # [useless-with-lock] | ||
| ^^^^^^^^^^^ PLW2101 | ||
30 | ... | ||
| | ||
|
||
useless_with_lock.py:32:6: PLW2101 Threading lock directly created in `with` statement has no effect | ||
| | ||
30 | ... | ||
31 | | ||
32 | with threading.BoundedSemaphore(): # [useless-with-lock] | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLW2101 | ||
33 | ... | ||
| | ||
|
||
useless_with_lock.py:35:6: PLW2101 Threading lock directly created in `with` statement has no effect | ||
| | ||
33 | ... | ||
34 | | ||
35 | with BoundedSemaphore(): # [useless-with-lock] | ||
| ^^^^^^^^^^^^^^^^^^ PLW2101 | ||
36 | ... | ||
| | ||
|
||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.