Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[flake8-pytest-style] Implement pytest.warns diagnostics (PT029, PT030, PT031) #15444

Merged
merged 4 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/ruff/tests/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,8 @@ fn value_given_to_table_key_is_not_inline_table_1() {
- `lint.flake8-pytest-style.raises-require-match-for`
- `lint.flake8-pytest-style.raises-extend-require-match-for`
- `lint.flake8-pytest-style.mark-parentheses`
- `lint.flake8-pytest-style.warns-require-match-for`
- `lint.flake8-pytest-style.warns-extend-require-match-for`

For more information, try '--help'.
"#);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import pytest


def test_ok():
with pytest.warns():
pass


def test_error():
with pytest.warns(UserWarning):
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import pytest
from foo import FooWarning


def test_ok():
with pytest.warns(UserWarning, match="Can't divide by 0"):
pass


def test_ok_different_error_from_config():
with pytest.warns(EncodingWarning):
pass


def test_error_no_argument_given():
with pytest.warns(UserWarning):
pass

with pytest.warns(expected_warning=UserWarning):
pass

with pytest.warns(FooWarning):
pass


def test_error_match_is_empty():
with pytest.warns(UserWarning, match=None):
pass

with pytest.warns(UserWarning, match=""):
pass

with pytest.warns(UserWarning, match=f""):
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import pytest


def test_ok():
with pytest.warns(UserWarning):
...


async def test_ok_trivial_with():
with pytest.warns(UserWarning):
with context_manager_under_test():
pass

with pytest.warns(UserWarning):
with context_manager_under_test():
foo()

with pytest.warns(UserWarning):
async with context_manager_under_test():
pass


def test_ok_complex_single_call():
with pytest.warns(UserWarning):
foo(
"",
0,
)


def test_ok_func_and_class():
with pytest.warns(UserWarning):
class Foo:
pass

with pytest.warns(UserWarning):
def foo():
pass


def test_error_multiple_statements():
with pytest.warns(UserWarning):
foo()
bar()


async def test_error_complex_statement():
with pytest.warns(UserWarning):
if True:
foo()

with pytest.warns(UserWarning):
for i in []:
foo()

with pytest.warns(UserWarning):
async for i in []:
foo()

with pytest.warns(UserWarning):
while True:
foo()

with pytest.warns(UserWarning):
async with context_manager_under_test():
if True:
foo()


def test_error_try():
with pytest.warns(UserWarning):
try:
foo()
except:
raise
3 changes: 3 additions & 0 deletions crates/ruff_linter/src/checkers/ast/analyze/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,9 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
]) {
flake8_pytest_style::rules::raises_call(checker, call);
}
if checker.any_enabled(&[Rule::PytestWarnsWithoutWarning, Rule::PytestWarnsTooBroad]) {
flake8_pytest_style::rules::warns_call(checker, call);
}
if checker.enabled(Rule::PytestFailWithoutMessage) {
flake8_pytest_style::rules::fail_call(checker, call);
}
Expand Down
3 changes: 3 additions & 0 deletions crates/ruff_linter/src/checkers/ast/analyze/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1296,6 +1296,9 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
if checker.enabled(Rule::PytestRaisesWithMultipleStatements) {
flake8_pytest_style::rules::complex_raises(checker, stmt, items, body);
}
if checker.enabled(Rule::PytestWarnsWithMultipleStatements) {
flake8_pytest_style::rules::complex_warns(checker, stmt, items, body);
}
if checker.enabled(Rule::MultipleWithStatements) {
flake8_simplify::rules::multiple_with_statements(
checker,
Expand Down
3 changes: 3 additions & 0 deletions crates/ruff_linter/src/codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,9 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
(Flake8PytestStyle, "025") => (RuleGroup::Stable, rules::flake8_pytest_style::rules::PytestErroneousUseFixturesOnFixture),
(Flake8PytestStyle, "026") => (RuleGroup::Stable, rules::flake8_pytest_style::rules::PytestUseFixturesWithoutParameters),
(Flake8PytestStyle, "027") => (RuleGroup::Stable, rules::flake8_pytest_style::rules::PytestUnittestRaisesAssertion),
(Flake8PytestStyle, "029") => (RuleGroup::Preview, rules::flake8_pytest_style::rules::PytestWarnsWithoutWarning),
(Flake8PytestStyle, "030") => (RuleGroup::Preview, rules::flake8_pytest_style::rules::PytestWarnsTooBroad),
(Flake8PytestStyle, "031") => (RuleGroup::Preview, rules::flake8_pytest_style::rules::PytestWarnsWithMultipleStatements),

// flake8-pie
(Flake8Pie, "790") => (RuleGroup::Stable, rules::flake8_pie::rules::UnnecessaryPlaceholder),
Expand Down
54 changes: 54 additions & 0 deletions crates/ruff_linter/src/rules/flake8_pytest_style/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,60 @@ mod tests {
Settings::default(),
"PT027_1"
)]
#[test_case(
Rule::PytestWarnsWithoutWarning,
Path::new("PT029.py"),
Settings::default(),
"PT029"
)]
#[test_case(
Rule::PytestWarnsTooBroad,
Path::new("PT030.py"),
Settings::default(),
"PT030_default"
)]
#[test_case(
Rule::PytestWarnsTooBroad,
Path::new("PT030.py"),
Settings {
warns_extend_require_match_for: vec![IdentifierPattern::new("EncodingWarning").unwrap()],
..Settings::default()
},
"PT030_extend_broad_exceptions"
)]
#[test_case(
Rule::PytestWarnsTooBroad,
Path::new("PT030.py"),
Settings {
warns_require_match_for: vec![IdentifierPattern::new("EncodingWarning").unwrap()],
..Settings::default()
},
"PT030_replace_broad_exceptions"
)]
#[test_case(
Rule::PytestWarnsTooBroad,
Path::new("PT030.py"),
Settings {
warns_require_match_for: vec![IdentifierPattern::new("*").unwrap()],
..Settings::default()
},
"PT030_glob_all"
)]
#[test_case(
Rule::PytestWarnsTooBroad,
Path::new("PT030.py"),
Settings {
warns_require_match_for: vec![IdentifierPattern::new("foo.*").unwrap()],
..Settings::default()
},
"PT030_glob_prefix"
)]
#[test_case(
Rule::PytestWarnsWithMultipleStatements,
Path::new("PT031.py"),
Settings::default(),
"PT031"
)]
fn test_pytest_style(
rule_code: Rule,
path: &Path,
Expand Down
2 changes: 2 additions & 0 deletions crates/ruff_linter/src/rules/flake8_pytest_style/rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub(crate) use marks::*;
pub(crate) use parametrize::*;
pub(crate) use patch::*;
pub(crate) use raises::*;
pub(crate) use warns::*;

mod assertion;
mod fail;
Expand All @@ -17,3 +18,4 @@ mod parametrize;
mod patch;
mod raises;
mod unittest_assert;
mod warns;
Loading
Loading