-
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.
Implement
shallow-copy-environ / W1507
(#14241)
<!-- Thank you for contributing to Ruff! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? - Does this pull request include references to any relevant issues? --> ## Summary <!-- What's the purpose of the change? What does it do, and why? --> Related to #970. Implement [`shallow-copy-environ / W1507`](https://pylint.readthedocs.io/en/stable/user_guide/messages/warning/shallow-copy-environ.html). ## Test Plan <!-- How was it tested? --> Unit test --------- Co-authored-by: Simon Brugman <[email protected]> Co-authored-by: Charlie Marsh <[email protected]>
- Loading branch information
1 parent
5d91ba0
commit d4cf61d
Showing
9 changed files
with
122 additions
and
0 deletions.
There are no files selected for viewing
4 changes: 4 additions & 0 deletions
4
crates/ruff_linter/resources/test/fixtures/pylint/shallow_copy_environ.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,4 @@ | ||
import copy | ||
import os | ||
|
||
copied_env = copy.copy(os.environ) # [shallow-copy-environ] |
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
90 changes: 90 additions & 0 deletions
90
crates/ruff_linter/src/rules/pylint/rules/shallow_copy_environ.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,90 @@ | ||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; | ||
use ruff_macros::{derive_message_formats, violation}; | ||
use ruff_python_ast::{self as ast}; | ||
use ruff_python_semantic::Modules; | ||
use ruff_text_size::Ranged; | ||
|
||
use crate::checkers::ast::Checker; | ||
|
||
/// ## What it does | ||
/// Check for shallow `os.environ` copies. | ||
/// | ||
/// ## Why is this bad? | ||
/// `os.environ` is not a `dict` object, but rather, a proxy object. As such, mutating a shallow | ||
/// copy of `os.environ` will also mutate the original object. | ||
/// | ||
/// See: [#15373] for more information. | ||
/// | ||
/// ## Example | ||
/// ```python | ||
/// import copy | ||
/// import os | ||
/// | ||
/// env = copy.copy(os.environ) | ||
/// ``` | ||
/// | ||
/// Use instead: | ||
/// ```python | ||
/// import os | ||
/// | ||
/// env = os.environ.copy() | ||
/// ``` | ||
/// | ||
/// ## References | ||
/// - [Python documentation: `copy` — Shallow and deep copy operations](https://docs.python.org/3/library/copy.html) | ||
/// - [Python documentation: `os.environ`](https://docs.python.org/3/library/os.html#os.environ) | ||
/// | ||
/// [#15373]: https://bugs.python.org/issue15373 | ||
#[violation] | ||
pub struct ShallowCopyEnviron; | ||
|
||
impl AlwaysFixableViolation for ShallowCopyEnviron { | ||
#[derive_message_formats] | ||
fn message(&self) -> String { | ||
"Shallow copy of `os.environ` via `copy.copy(os.environ)`".to_string() | ||
} | ||
|
||
fn fix_title(&self) -> String { | ||
"Replace with `os.environ.copy()`".to_string() | ||
} | ||
} | ||
|
||
/// PLW1507 | ||
pub(crate) fn shallow_copy_environ(checker: &mut Checker, call: &ast::ExprCall) { | ||
if !(checker.semantic().seen_module(Modules::OS) | ||
&& checker.semantic().seen_module(Modules::COPY)) | ||
{ | ||
return; | ||
} | ||
|
||
if !checker | ||
.semantic() | ||
.resolve_qualified_name(&call.func) | ||
.is_some_and(|qualified_name| matches!(qualified_name.segments(), ["copy", "copy"])) | ||
{ | ||
return; | ||
} | ||
|
||
if !call.arguments.keywords.is_empty() { | ||
return; | ||
} | ||
|
||
let [arg] = call.arguments.args.as_ref() else { | ||
return; | ||
}; | ||
|
||
if !checker | ||
.semantic() | ||
.resolve_qualified_name(arg) | ||
.is_some_and(|qualified_name| matches!(qualified_name.segments(), ["os", "environ"])) | ||
{ | ||
return; | ||
} | ||
|
||
let mut diagnostic = Diagnostic::new(ShallowCopyEnviron, call.range()); | ||
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( | ||
format!("{}.copy()", checker.locator().slice(arg)), | ||
call.range(), | ||
))); | ||
checker.diagnostics.push(diagnostic); | ||
} |
18 changes: 18 additions & 0 deletions
18
.../pylint/snapshots/ruff_linter__rules__pylint__tests__PLW1507_shallow_copy_environ.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,18 @@ | ||
--- | ||
source: crates/ruff_linter/src/rules/pylint/mod.rs | ||
--- | ||
shallow_copy_environ.py:4:14: PLW1507 [*] Shallow copy of `os.environ` via `copy.copy(os.environ)` | ||
| | ||
2 | import os | ||
3 | | ||
4 | copied_env = copy.copy(os.environ) # [shallow-copy-environ] | ||
| ^^^^^^^^^^^^^^^^^^^^^ PLW1507 | ||
| | ||
= help: Replace with `os.environ.copy()` | ||
|
||
ℹ Safe fix | ||
1 1 | import copy | ||
2 2 | import os | ||
3 3 | | ||
4 |-copied_env = copy.copy(os.environ) # [shallow-copy-environ] | ||
4 |+copied_env = os.environ.copy() # [shallow-copy-environ] |
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.