diff --git a/resources/test/fixtures/U005.py b/resources/test/fixtures/U005.py index 5812f93e31..2f99802af4 100644 --- a/resources/test/fixtures/U005.py +++ b/resources/test/fixtures/U005.py @@ -6,3 +6,5 @@ class Suite(unittest.TestCase): self.assertEquals (1, 2) self.assertEquals(1, 2) self.assertEqual(3, 4) + self.failUnlessAlmostEqual(1, 1.1) + self.assertNotRegexpMatches("a", "b") diff --git a/src/ast/checks.rs b/src/ast/checks.rs index 4cc594db85..424967c1fc 100644 --- a/src/ast/checks.rs +++ b/src/ast/checks.rs @@ -361,23 +361,6 @@ pub fn check_duplicate_arguments(arguments: &Arguments) -> Vec { checks } -/// Check AssertEquals compliance. -pub fn check_assert_equals(expr: &Expr) -> Option { - if let ExprKind::Attribute { value, attr, .. } = &expr.node { - if attr == "assertEquals" { - if let ExprKind::Name { id, .. } = &value.node { - if id == "self" { - return Some(Check::new( - CheckKind::NoAssertEquals, - Range::from_located(expr), - )); - } - } - } - } - None -} - #[derive(Debug, PartialEq)] enum DictionaryKey<'a> { Constant(&'a Constant), diff --git a/src/check_ast.rs b/src/check_ast.rs index fb4f5d67a1..2e58939c2c 100644 --- a/src/check_ast.rs +++ b/src/check_ast.rs @@ -726,7 +726,7 @@ where .. } => { if self.settings.enabled.contains(&CheckCode::U005) { - plugins::assert_equals(self, func); + plugins::deprecated_unittest_alias(self, func); } // flake8-super diff --git a/src/checks.rs b/src/checks.rs index 3c8a678a50..7ee06e386b 100644 --- a/src/checks.rs +++ b/src/checks.rs @@ -227,7 +227,7 @@ pub enum CheckKind { TypeOfPrimitive(Primitive), UnnecessaryAbspath, UselessMetaclassType, - NoAssertEquals, + DeprecatedUnittestAlias(String, String), UselessObjectInheritance(String), UsePEP585Annotation(String), UsePEP604Annotation, @@ -323,7 +323,10 @@ impl CheckCode { CheckCode::U002 => CheckKind::UnnecessaryAbspath, CheckCode::U003 => CheckKind::TypeOfPrimitive(Primitive::Str), CheckCode::U004 => CheckKind::UselessObjectInheritance("...".to_string()), - CheckCode::U005 => CheckKind::NoAssertEquals, + CheckCode::U005 => CheckKind::DeprecatedUnittestAlias( + "assertEquals".to_string(), + "assertEqual".to_string(), + ), CheckCode::U006 => CheckKind::UsePEP585Annotation("List".to_string()), CheckCode::U007 => CheckKind::UsePEP604Annotation, CheckCode::U008 => CheckKind::SuperCallWithParameters, @@ -403,7 +406,7 @@ impl CheckKind { CheckKind::TypeOfPrimitive(_) => &CheckCode::U003, CheckKind::UnnecessaryAbspath => &CheckCode::U002, CheckKind::UselessMetaclassType => &CheckCode::U001, - CheckKind::NoAssertEquals => &CheckCode::U005, + CheckKind::DeprecatedUnittestAlias(_, _) => &CheckCode::U005, CheckKind::UsePEP585Annotation(_) => &CheckCode::U006, CheckKind::UsePEP604Annotation => &CheckCode::U007, CheckKind::UselessObjectInheritance(_) => &CheckCode::U004, @@ -595,8 +598,8 @@ impl CheckKind { "`abspath(__file__)` is unnecessary in Python 3.9 and later".to_string() } CheckKind::UselessMetaclassType => "`__metaclass__ = type` is implied".to_string(), - CheckKind::NoAssertEquals => { - "`assertEquals` is deprecated, use `assertEqual` instead".to_string() + CheckKind::DeprecatedUnittestAlias(alias, target) => { + format!("`{}` is deprecated, use `{}` instead", alias, target) } CheckKind::UselessObjectInheritance(name) => { format!("Class `{name}` inherits from object") @@ -624,7 +627,7 @@ impl CheckKind { pub fn fixable(&self) -> bool { matches!( self, - CheckKind::NoAssertEquals + CheckKind::DeprecatedUnittestAlias(_, _) | CheckKind::PPrintFound | CheckKind::PrintFound | CheckKind::SuperCallWithParameters diff --git a/src/plugins.rs b/src/plugins.rs index d7641c780a..cf34eef8b1 100644 --- a/src/plugins.rs +++ b/src/plugins.rs @@ -1,5 +1,5 @@ -pub use assert_equals::assert_equals; pub use assert_tuple::assert_tuple; +pub use deprecated_unittest_alias::deprecated_unittest_alias; pub use if_tuple::if_tuple; pub use invalid_print_syntax::invalid_print_syntax; pub use print_call::print_call; @@ -11,8 +11,8 @@ pub use use_pep604_annotation::use_pep604_annotation; pub use useless_metaclass_type::useless_metaclass_type; pub use useless_object_inheritance::useless_object_inheritance; -mod assert_equals; mod assert_tuple; +mod deprecated_unittest_alias; mod if_tuple; mod invalid_print_syntax; mod print_call; diff --git a/src/plugins/assert_equals.rs b/src/plugins/assert_equals.rs deleted file mode 100644 index 39dd0bdb66..0000000000 --- a/src/plugins/assert_equals.rs +++ /dev/null @@ -1,20 +0,0 @@ -use rustpython_ast::{Expr, Location}; - -use crate::ast::checks; -use crate::autofix::fixer; -use crate::check_ast::Checker; -use crate::checks::Fix; - -pub fn assert_equals(checker: &mut Checker, expr: &Expr) { - if let Some(mut check) = checks::check_assert_equals(expr) { - if matches!(checker.autofix, fixer::Mode::Generate | fixer::Mode::Apply) { - check.amend(Fix { - content: "self.assertEqual".to_string(), - location: Location::new(expr.location.row(), expr.location.column()), - end_location: Location::new(expr.end_location.row(), expr.end_location.column()), - applied: false, - }); - } - checker.add_check(check); - } -} diff --git a/src/plugins/deprecated_unittest_alias.rs b/src/plugins/deprecated_unittest_alias.rs new file mode 100644 index 0000000000..28b4fb8a5f --- /dev/null +++ b/src/plugins/deprecated_unittest_alias.rs @@ -0,0 +1,56 @@ +use std::collections::BTreeMap; + +use once_cell::sync::Lazy; +use rustpython_ast::{Expr, ExprKind, Location}; + +use crate::ast::types::Range; +use crate::autofix::fixer; +use crate::check_ast::Checker; +use crate::checks::{Check, CheckKind, Fix}; + +static DEPRECATED_ALIASES: Lazy> = Lazy::new(|| { + BTreeMap::from([ + ("failUnlessEqual", "assertEqual"), + ("assertEquals", "assertEqual"), + ("failIfEqual", "assertNotEqual"), + ("assertNotEquals", "assertNotEqual"), + ("failUnless", "assertTrue"), + ("assert_", "assertTrue"), + ("failIf", "assertFalse"), + ("failUnlessRaises", "assertRaises"), + ("failUnlessAlmostEqual", "assertAlmostEqual"), + ("assertAlmostEquals", "assertAlmostEqual"), + ("failIfAlmostEqual", "assertNotAlmostEqual"), + ("assertNotAlmostEquals", "assertNotAlmostEqual"), + ("assertRegexpMatches", "assertRegex"), + ("assertNotRegexpMatches", "assertNotRegex"), + ("assertRaisesRegexp", "assertRaisesRegex"), + ]) +}); + +pub fn deprecated_unittest_alias(checker: &mut Checker, expr: &Expr) { + if let ExprKind::Attribute { value, attr, .. } = &expr.node { + if let Some(target) = DEPRECATED_ALIASES.get(attr.as_str()) { + if let ExprKind::Name { id, .. } = &value.node { + if id == "self" { + let mut check = Check::new( + CheckKind::DeprecatedUnittestAlias(attr.to_string(), target.to_string()), + Range::from_located(expr), + ); + if matches!(checker.autofix, fixer::Mode::Generate | fixer::Mode::Apply) { + check.amend(Fix { + content: format!("self.{}", target), + location: Location::new(expr.location.row(), expr.location.column()), + end_location: Location::new( + expr.end_location.row(), + expr.end_location.column(), + ), + applied: false, + }); + } + checker.add_check(check); + } + } + } + } +} diff --git a/src/snapshots/ruff__linter__tests__u005.snap b/src/snapshots/ruff__linter__tests__u005.snap index cace578e1b..3f60e61dfb 100644 --- a/src/snapshots/ruff__linter__tests__u005.snap +++ b/src/snapshots/ruff__linter__tests__u005.snap @@ -2,7 +2,10 @@ source: src/linter.rs expression: checks --- -- kind: NoAssertEquals +- kind: + DeprecatedUnittestAlias: + - assertEquals + - assertEqual location: row: 6 column: 9 @@ -18,7 +21,10 @@ expression: checks row: 6 column: 26 applied: false -- kind: NoAssertEquals +- kind: + DeprecatedUnittestAlias: + - assertEquals + - assertEqual location: row: 7 column: 9 @@ -34,4 +40,42 @@ expression: checks row: 7 column: 26 applied: false +- kind: + DeprecatedUnittestAlias: + - failUnlessAlmostEqual + - assertAlmostEqual + location: + row: 9 + column: 9 + end_location: + row: 9 + column: 35 + fix: + content: self.assertAlmostEqual + location: + row: 9 + column: 9 + end_location: + row: 9 + column: 35 + applied: false +- kind: + DeprecatedUnittestAlias: + - assertNotRegexpMatches + - assertNotRegex + location: + row: 10 + column: 9 + end_location: + row: 10 + column: 36 + fix: + content: self.assertNotRegex + location: + row: 10 + column: 9 + end_location: + row: 10 + column: 36 + applied: false