Use fake rules for testing deprecation and removal infrastructure (#9752)

Updates #9689 and #9691 to use rule testing infrastructure from #9747
This commit is contained in:
Zanie Blue 2024-02-01 10:28:50 -06:00
parent e5008ca714
commit 46c0937bfa
5 changed files with 235 additions and 83 deletions

View file

@ -824,7 +824,9 @@ fn nursery_prefix() {
-:1:1: RUF901 [*] Hey this is a stable test rule with a safe fix.
-:1:1: RUF902 Hey this is a stable test rule with an unsafe fix.
-:1:1: RUF903 Hey this is a stable test rule with a display only fix.
Found 4 errors.
-:1:1: RUF920 Hey this is a deprecated test rule.
-:1:1: RUF921 Hey this is another deprecated test rule.
Found 6 errors.
[*] 1 fixable with the `--fix` option (1 hidden fix can be enabled with the `--unsafe-fixes` option).
----- stderr -----
@ -846,7 +848,9 @@ fn nursery_all() {
-:1:1: RUF901 [*] Hey this is a stable test rule with a safe fix.
-:1:1: RUF902 Hey this is a stable test rule with an unsafe fix.
-:1:1: RUF903 Hey this is a stable test rule with a display only fix.
Found 5 errors.
-:1:1: RUF920 Hey this is a deprecated test rule.
-:1:1: RUF921 Hey this is another deprecated test rule.
Found 7 errors.
[*] 1 fixable with the `--fix` option (1 hidden fix can be enabled with the `--unsafe-fixes` option).
----- stderr -----
@ -1094,7 +1098,7 @@ fn preview_enabled_group_ignore() {
#[test]
fn removed_direct() {
// Selection of a removed rule should fail
let mut cmd = RuffCheck::default().args(["--select", "PLR1706"]).build();
let mut cmd = RuffCheck::default().args(["--select", "RUF931"]).build();
assert_cmd_snapshot!(cmd, @r###"
success: false
exit_code: 2
@ -1102,7 +1106,28 @@ fn removed_direct() {
----- stderr -----
ruff failed
Cause: Rule `PLR1706` was removed and cannot be selected.
Cause: Rule `RUF931` was removed and cannot be selected.
"###);
}
#[test]
fn removed_direct_multiple() {
// Selection of multiple removed rule should fail with a message
// including all the rules
let mut cmd = RuffCheck::default()
.args(["--select", "RUF930", "--select", "RUF931"])
.build();
assert_cmd_snapshot!(cmd, @r###"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
ruff failed
Cause: The following rules have been removed and cannot be selected:
- RUF930
- RUF931
"###);
}
@ -1110,12 +1135,8 @@ fn removed_direct() {
fn removed_indirect() {
// Selection _including_ a removed rule without matching should not fail
// nor should the rule be used
let mut cmd = RuffCheck::default().args(["--select", "PLR"]).build();
assert_cmd_snapshot!(cmd.pass_stdin(r###"
# This would have been a PLR1706 violation
x, y = 1, 2
maximum = x >= y and x or y
"""###), @r###"
let mut cmd = RuffCheck::default().args(["--select", "RUF93"]).build();
assert_cmd_snapshot!(cmd, @r###"
success: true
exit_code: 0
----- stdout -----
@ -1128,74 +1149,49 @@ maximum = x >= y and x or y
fn deprecated_direct() {
// Selection of a deprecated rule without preview enabled should still work
// but a warning should be displayed
let mut cmd = RuffCheck::default().args(["--select", "TRY200"]).build();
assert_cmd_snapshot!(cmd
.pass_stdin(r###"
def reciprocal(n):
try:
return 1 / n
except ZeroDivisionError:
raise ValueError()
"###), @r###"
let mut cmd = RuffCheck::default().args(["--select", "RUF920"]).build();
assert_cmd_snapshot!(cmd, @r###"
success: false
exit_code: 1
----- stdout -----
-:6:9: TRY200 Use `raise from` to specify exception cause
-:1:1: RUF920 Hey this is a deprecated test rule.
Found 1 error.
----- stderr -----
warning: Rule `TRY200` is deprecated and will be removed in a future release.
warning: Rule `RUF920` is deprecated and will be removed in a future release.
"###);
}
#[test]
fn deprecated_multiple_direct() {
let mut cmd = RuffCheck::default()
.args(["--select", "ANN101", "--select", "ANN102"])
.args(["--select", "RUF920", "--select", "RUF921"])
.build();
assert_cmd_snapshot!(cmd
.pass_stdin(r###"
class Foo:
def a(self):
pass
@classmethod
def b(cls):
pass
"###), @r###"
assert_cmd_snapshot!(cmd, @r###"
success: false
exit_code: 1
----- stdout -----
-:3:11: ANN101 Missing type annotation for `self` in method
-:7:11: ANN102 Missing type annotation for `cls` in classmethod
-:1:1: RUF920 Hey this is a deprecated test rule.
-:1:1: RUF921 Hey this is another deprecated test rule.
Found 2 errors.
----- stderr -----
warning: Rule `ANN102` is deprecated and will be removed in a future release.
warning: Rule `ANN101` is deprecated and will be removed in a future release.
warning: Rule `RUF921` is deprecated and will be removed in a future release.
warning: Rule `RUF920` is deprecated and will be removed in a future release.
"###);
}
#[test]
fn deprecated_indirect() {
// `ANN` includes deprecated rules `ANN101` and `ANN102` but should not warn
// `RUF92` includes deprecated rules but should not warn
// since it is not a "direct" selection
let mut cmd = RuffCheck::default().args(["--select", "ANN1"]).build();
assert_cmd_snapshot!(cmd
.pass_stdin(r###"
class Foo:
def a(self):
pass
@classmethod
def b(cls):
pass
"###), @r###"
let mut cmd = RuffCheck::default().args(["--select", "RUF92"]).build();
assert_cmd_snapshot!(cmd, @r###"
success: false
exit_code: 1
----- stdout -----
-:3:11: ANN101 Missing type annotation for `self` in method
-:7:11: ANN102 Missing type annotation for `cls` in classmethod
-:1:1: RUF920 Hey this is a deprecated test rule.
-:1:1: RUF921 Hey this is another deprecated test rule.
Found 2 errors.
----- stderr -----
@ -1206,40 +1202,26 @@ class Foo:
fn deprecated_direct_preview_enabled() {
// Direct selection of a deprecated rule in preview should fail
let mut cmd = RuffCheck::default()
.args(["--select", "TRY200", "--preview"])
.args(["--select", "RUF920", "--preview"])
.build();
assert_cmd_snapshot!(cmd
.pass_stdin(r###"
def reciprocal(n):
try:
return 1 / n
except ZeroDivisionError:
raise ValueError()
"###), @r###"
assert_cmd_snapshot!(cmd, @r###"
success: false
exit_code: 2
----- stdout -----
----- stderr -----
ruff failed
Cause: Selection of deprecated rule `TRY200` is not allowed when preview is enabled.
Cause: Selection of deprecated rule `RUF920` is not allowed when preview is enabled.
"###);
}
#[test]
fn deprecated_indirect_preview_enabled() {
// `TRY200` is deprecated and should be off by default in preview.
// `RUF920` is deprecated and should be off by default in preview.
let mut cmd = RuffCheck::default()
.args(["--select", "TRY", "--preview"])
.args(["--select", "RUF92", "--preview"])
.build();
assert_cmd_snapshot!(cmd
.pass_stdin(r###"
def reciprocal(n):
try:
return 1 / n
except ZeroDivisionError:
raise ValueError()
"###), @r###"
assert_cmd_snapshot!(cmd, @r###"
success: true
exit_code: 0
----- stdout -----
@ -1253,16 +1235,9 @@ fn deprecated_multiple_direct_preview_enabled() {
// Direct selection of the deprecated rules in preview should fail with
// a message listing all of the rule codes
let mut cmd = RuffCheck::default()
.args(["--select", "ANN101", "--select", "ANN102", "--preview"])
.args(["--select", "RUF920", "--select", "RUF921", "--preview"])
.build();
assert_cmd_snapshot!(cmd
.pass_stdin(r###"
def reciprocal(n):
try:
return 1 / n
except ZeroDivisionError:
raise ValueError()
"###), @r###"
assert_cmd_snapshot!(cmd, @r###"
success: false
exit_code: 2
----- stdout -----
@ -1270,8 +1245,8 @@ def reciprocal(n):
----- stderr -----
ruff failed
Cause: Selection of deprecated rules is not allowed when preview is enabled. Remove selection of:
- ANN102
- ANN101
- RUF921
- RUF920
"###);
}
@ -1793,7 +1768,9 @@ extend-safe-fixes = ["RUF9"]
-:1:1: RUF901 Hey this is a stable test rule with a safe fix.
-:1:1: RUF902 [*] Hey this is a stable test rule with an unsafe fix.
-:1:1: RUF903 Hey this is a stable test rule with a display only fix.
Found 4 errors.
-:1:1: RUF920 Hey this is a deprecated test rule.
-:1:1: RUF921 Hey this is another deprecated test rule.
Found 6 errors.
[*] 1 fixable with the `--fix` option (1 hidden fix can be enabled with the `--unsafe-fixes` option).
----- stderr -----

View file

@ -951,6 +951,14 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
#[cfg(feature = "test-rules")]
#[allow(deprecated)]
(Ruff, "912") => (RuleGroup::Nursery, rules::ruff::rules::NurseryTestRule),
#[cfg(feature = "test-rules")]
(Ruff, "920") => (RuleGroup::Deprecated, rules::ruff::rules::DeprecatedTestRule),
#[cfg(feature = "test-rules")]
(Ruff, "921") => (RuleGroup::Deprecated, rules::ruff::rules::AnotherDeprecatedTestRule),
#[cfg(feature = "test-rules")]
(Ruff, "930") => (RuleGroup::Removed, rules::ruff::rules::RemovedTestRule),
#[cfg(feature = "test-rules")]
(Ruff, "931") => (RuleGroup::Removed, rules::ruff::rules::AnotherRemovedTestRule),
// flake8-django

View file

@ -236,6 +236,16 @@ pub fn check_path(
}
Rule::NurseryTestRule => test_rules::NurseryTestRule::diagnostic(locator, indexer),
Rule::PreviewTestRule => test_rules::PreviewTestRule::diagnostic(locator, indexer),
Rule::DeprecatedTestRule => {
test_rules::DeprecatedTestRule::diagnostic(locator, indexer)
}
Rule::AnotherDeprecatedTestRule => {
test_rules::AnotherDeprecatedTestRule::diagnostic(locator, indexer)
}
Rule::RemovedTestRule => test_rules::RemovedTestRule::diagnostic(locator, indexer),
Rule::AnotherRemovedTestRule => {
test_rules::AnotherRemovedTestRule::diagnostic(locator, indexer)
}
_ => unreachable!("All test rules must have an implementation"),
};
if let Some(diagnostic) = diagnostic {

View file

@ -39,6 +39,10 @@ pub(crate) const TEST_RULES: &[Rule] = &[
Rule::StableTestRuleDisplayOnlyFix,
Rule::PreviewTestRule,
Rule::NurseryTestRule,
Rule::DeprecatedTestRule,
Rule::AnotherDeprecatedTestRule,
Rule::RemovedTestRule,
Rule::AnotherRemovedTestRule,
];
pub(crate) trait TestRule {
@ -254,6 +258,7 @@ impl TestRule for PreviewTestRule {
))
}
}
/// ## What it does
/// Fake rule for testing.
///
@ -289,3 +294,147 @@ impl TestRule for NurseryTestRule {
))
}
}
/// ## What it does
/// Fake rule for testing.
///
/// ## Why is this bad?
/// Tests must pass!
///
/// ## Example
/// ```python
/// foo
/// ```
///
/// Use instead:
/// ```python
/// bar
/// ```
#[violation]
pub struct DeprecatedTestRule;
impl Violation for DeprecatedTestRule {
const FIX_AVAILABILITY: FixAvailability = FixAvailability::None;
#[derive_message_formats]
fn message(&self) -> String {
format!("Hey this is a deprecated test rule.")
}
}
impl TestRule for DeprecatedTestRule {
fn diagnostic(_locator: &Locator, _indexer: &Indexer) -> Option<Diagnostic> {
Some(Diagnostic::new(
DeprecatedTestRule,
ruff_text_size::TextRange::default(),
))
}
}
/// ## What it does
/// Fake rule for testing.
///
/// ## Why is this bad?
/// Tests must pass!
///
/// ## Example
/// ```python
/// foo
/// ```
///
/// Use instead:
/// ```python
/// bar
/// ```
#[violation]
pub struct AnotherDeprecatedTestRule;
impl Violation for AnotherDeprecatedTestRule {
const FIX_AVAILABILITY: FixAvailability = FixAvailability::None;
#[derive_message_formats]
fn message(&self) -> String {
format!("Hey this is another deprecated test rule.")
}
}
impl TestRule for AnotherDeprecatedTestRule {
fn diagnostic(_locator: &Locator, _indexer: &Indexer) -> Option<Diagnostic> {
Some(Diagnostic::new(
AnotherDeprecatedTestRule,
ruff_text_size::TextRange::default(),
))
}
}
/// ## What it does
/// Fake rule for testing.
///
/// ## Why is this bad?
/// Tests must pass!
///
/// ## Example
/// ```python
/// foo
/// ```
///
/// Use instead:
/// ```python
/// bar
/// ```
#[violation]
pub struct RemovedTestRule;
impl Violation for RemovedTestRule {
const FIX_AVAILABILITY: FixAvailability = FixAvailability::None;
#[derive_message_formats]
fn message(&self) -> String {
format!("Hey this is a removed test rule.")
}
}
impl TestRule for RemovedTestRule {
fn diagnostic(_locator: &Locator, _indexer: &Indexer) -> Option<Diagnostic> {
Some(Diagnostic::new(
RemovedTestRule,
ruff_text_size::TextRange::default(),
))
}
}
/// ## What it does
/// Fake rule for testing.
///
/// ## Why is this bad?
/// Tests must pass!
///
/// ## Example
/// ```python
/// foo
/// ```
///
/// Use instead:
/// ```python
/// bar
/// ```
#[violation]
pub struct AnotherRemovedTestRule;
impl Violation for AnotherRemovedTestRule {
const FIX_AVAILABILITY: FixAvailability = FixAvailability::None;
#[derive_message_formats]
fn message(&self) -> String {
format!("Hey this is a another removed test rule.")
}
}
impl TestRule for AnotherRemovedTestRule {
fn diagnostic(_locator: &Locator, _indexer: &Indexer) -> Option<Diagnostic> {
Some(Diagnostic::new(
AnotherRemovedTestRule,
ruff_text_size::TextRange::default(),
))
}
}

View file

@ -909,7 +909,15 @@ impl LintConfiguration {
}
// Check if the selector is empty because preview mode is disabled
if selector.rules(&PreviewOptions::default()).next().is_none() {
if selector.rules(&preview).next().is_none()
&& selector
.rules(&PreviewOptions {
mode: PreviewMode::Enabled,
require_explicit: preview.require_explicit,
})
.next()
.is_some()
{
ignored_preview_selectors.insert(selector);
}
}