Skip to content

Commit

Permalink
[pygrep_hooks] Add fix for deprecated-log-warn (PGH002) (#9519)
Browse files Browse the repository at this point in the history
## Summary

add autofix for `deprecated_log_warn` (`PGH002`)

## Test Plan

`cargo test`

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
  • Loading branch information
diceroll123 and charliermarsh authored Jan 16, 2024
1 parent 9a2f3e2 commit 2bddde2
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 8 deletions.
20 changes: 20 additions & 0 deletions crates/ruff_linter/src/rules/pygrep_hooks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ mod tests {
use test_case::test_case;

use crate::registry::Rule;
use crate::settings::types::PreviewMode;
use crate::settings::LinterSettings;
use crate::test::test_path;
use crate::{assert_messages, settings};

Expand All @@ -29,4 +31,22 @@ mod tests {
assert_messages!(snapshot, diagnostics);
Ok(())
}

#[test_case(Rule::DeprecatedLogWarn, Path::new("PGH002_1.py"))]
fn preview_rules(rule_code: Rule, path: &Path) -> Result<()> {
let snapshot = format!(
"preview__{}_{}",
rule_code.noqa_code(),
path.to_string_lossy()
);
let diagnostics = test_path(
Path::new("pygrep_hooks").join(path).as_path(),
&LinterSettings {
preview: PreviewMode::Enabled,
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
Ok(())
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use ruff_python_ast::{self as ast, Expr, ExprCall};
use ruff_python_semantic::analyze::logging;

use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::{self as ast, Expr};
use ruff_python_semantic::analyze::logging;
use ruff_python_stdlib::logging::LoggingLevel;
use ruff_text_size::Ranged;

use crate::checkers::ast::Checker;
use crate::importer::ImportRequest;

/// ## What it does
/// Check for usages of the deprecated `warn` method from the `logging` module.
Expand Down Expand Up @@ -38,14 +38,20 @@ use crate::checkers::ast::Checker;
pub struct DeprecatedLogWarn;

impl Violation for DeprecatedLogWarn {
const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes;

#[derive_message_formats]
fn message(&self) -> String {
format!("`warn` is deprecated in favor of `warning`")
}

fn fix_title(&self) -> Option<String> {
Some(format!("Replace with `warning`"))
}
}

/// PGH002
pub(crate) fn deprecated_log_warn(checker: &mut Checker, call: &ExprCall) {
pub(crate) fn deprecated_log_warn(checker: &mut Checker, call: &ast::ExprCall) {
match call.func.as_ref() {
Expr::Attribute(ast::ExprAttribute { attr, .. }) => {
if !logging::is_logger_candidate(
Expand Down Expand Up @@ -74,7 +80,28 @@ pub(crate) fn deprecated_log_warn(checker: &mut Checker, call: &ExprCall) {
_ => return,
}

checker
.diagnostics
.push(Diagnostic::new(DeprecatedLogWarn, call.func.range()));
let mut diagnostic = Diagnostic::new(DeprecatedLogWarn, call.func.range());
if checker.settings.preview.is_enabled() {
match call.func.as_ref() {
Expr::Attribute(ast::ExprAttribute { attr, .. }) => {
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
"warning".to_string(),
attr.range(),
)));
}
Expr::Name(_) => {
diagnostic.try_set_fix(|| {
let (import_edit, binding) = checker.importer().get_or_import_symbol(
&ImportRequest::import("logging", "warning"),
call.start(),
checker.semantic(),
)?;
let name_edit = Edit::range_replacement(binding, call.func.range());
Ok(Fix::safe_edits(import_edit, [name_edit]))
});
}
_ => {}
}
}
checker.diagnostics.push(diagnostic);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ PGH002_1.py:4:1: PGH002 `warn` is deprecated in favor of `warning`
| ^^^^^^^^^^^^ PGH002
5 | warn("not ok")
|
= help: Replace with `warning`

PGH002_1.py:5:1: PGH002 `warn` is deprecated in favor of `warning`
|
Expand All @@ -18,12 +19,14 @@ PGH002_1.py:5:1: PGH002 `warn` is deprecated in favor of `warning`
6 |
7 | logger = logging.getLogger(__name__)
|
= help: Replace with `warning`

PGH002_1.py:8:1: PGH002 `warn` is deprecated in favor of `warning`
|
7 | logger = logging.getLogger(__name__)
8 | logger.warn("this is not ok")
| ^^^^^^^^^^^ PGH002
|
= help: Replace with `warning`


Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
source: crates/ruff_linter/src/rules/pygrep_hooks/mod.rs
---
PGH002_1.py:4:1: PGH002 [*] `warn` is deprecated in favor of `warning`
|
2 | from logging import warn
3 |
4 | logging.warn("this is not ok")
| ^^^^^^^^^^^^ PGH002
5 | warn("not ok")
|
= help: Replace with `warning`

Safe fix
1 1 | import logging
2 2 | from logging import warn
3 3 |
4 |-logging.warn("this is not ok")
4 |+logging.warning("this is not ok")
5 5 | warn("not ok")
6 6 |
7 7 | logger = logging.getLogger(__name__)

PGH002_1.py:5:1: PGH002 [*] `warn` is deprecated in favor of `warning`
|
4 | logging.warn("this is not ok")
5 | warn("not ok")
| ^^^^ PGH002
6 |
7 | logger = logging.getLogger(__name__)
|
= help: Replace with `warning`

Safe fix
2 2 | from logging import warn
3 3 |
4 4 | logging.warn("this is not ok")
5 |-warn("not ok")
5 |+logging.warning("not ok")
6 6 |
7 7 | logger = logging.getLogger(__name__)
8 8 | logger.warn("this is not ok")

PGH002_1.py:8:1: PGH002 [*] `warn` is deprecated in favor of `warning`
|
7 | logger = logging.getLogger(__name__)
8 | logger.warn("this is not ok")
| ^^^^^^^^^^^ PGH002
|
= help: Replace with `warning`

Safe fix
5 5 | warn("not ok")
6 6 |
7 7 | logger = logging.getLogger(__name__)
8 |-logger.warn("this is not ok")
8 |+logger.warning("this is not ok")


0 comments on commit 2bddde2

Please sign in to comment.