mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-04 18:58:04 +00:00
[flake8-pytest-style
] Avoid false positive for legacy form of pytest.raises
(PT011
) (#17231)
This fix closes #17026 ## Summary The check for the `PytestRaisesTooBroad` rule is now skipped if there is a second positional argument present, which means `pytest.raises` is used as a function. ## Test Plan Tested on the example from the issue, which now passes the check. ```Python3 pytest.raises(Exception, func, *func_args, **func_kwargs).match("error message") ``` --------- Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
parent
34e06f2d17
commit
97dd6d120c
6 changed files with 131 additions and 111 deletions
|
@ -14,6 +14,13 @@ def test_ok_different_error_from_config():
|
|||
raise ZeroDivisionError("Can't divide by 0")
|
||||
|
||||
|
||||
def test_ok_legacy_form():
|
||||
def func():
|
||||
raise ValueError("Can't divide by 0")
|
||||
|
||||
pytest.raises(ValueError, func).match("Can't divide by 0")
|
||||
|
||||
|
||||
def test_error_no_argument_given():
|
||||
with pytest.raises(ValueError):
|
||||
raise ValueError("Can't divide 1 by 0")
|
||||
|
|
|
@ -173,7 +173,11 @@ const fn is_non_trivial_with_body(body: &[Stmt]) -> bool {
|
|||
pub(crate) fn raises_call(checker: &Checker, call: &ast::ExprCall) {
|
||||
if is_pytest_raises(&call.func, checker.semantic()) {
|
||||
if checker.enabled(Rule::PytestRaisesWithoutException) {
|
||||
if call.arguments.is_empty() {
|
||||
if call
|
||||
.arguments
|
||||
.find_argument("expected_exception", 0)
|
||||
.is_none()
|
||||
{
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
PytestRaisesWithoutException,
|
||||
call.func.range(),
|
||||
|
@ -182,13 +186,22 @@ pub(crate) fn raises_call(checker: &Checker, call: &ast::ExprCall) {
|
|||
}
|
||||
|
||||
if checker.enabled(Rule::PytestRaisesTooBroad) {
|
||||
if let Some(exception) = call.arguments.find_argument_value("expected_exception", 0) {
|
||||
if call
|
||||
.arguments
|
||||
.find_keyword("match")
|
||||
.is_none_or(|k| is_empty_or_null_string(&k.value))
|
||||
// Pytest.raises has two overloads
|
||||
// ```py
|
||||
// with raises(expected_exception: type[E] | tuple[type[E], ...], *, match: str | Pattern[str] | None = ...) → RaisesContext[E] as excinfo
|
||||
// with raises(expected_exception: type[E] | tuple[type[E], ...], func: Callable[[...], Any], *args: Any, **kwargs: Any) → ExceptionInfo[E] as excinfo
|
||||
// ```
|
||||
// Don't raise this diagnostic if the call matches the second overload (has a second positional argument or an argument named `func`)
|
||||
if call.arguments.find_argument("func", 1).is_none() {
|
||||
if let Some(exception) = call.arguments.find_argument_value("expected_exception", 0)
|
||||
{
|
||||
exception_needs_match(checker, exception);
|
||||
if call
|
||||
.arguments
|
||||
.find_keyword("match")
|
||||
.is_none_or(|k| is_empty_or_null_string(&k.value))
|
||||
{
|
||||
exception_needs_match(checker, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,54 +1,54 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_pytest_style/mod.rs
|
||||
---
|
||||
PT011.py:18:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:25:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
17 | def test_error_no_argument_given():
|
||||
18 | with pytest.raises(ValueError):
|
||||
24 | def test_error_no_argument_given():
|
||||
25 | with pytest.raises(ValueError):
|
||||
| ^^^^^^^^^^ PT011
|
||||
19 | raise ValueError("Can't divide 1 by 0")
|
||||
26 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
||||
PT011.py:21:43: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:28:43: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
19 | raise ValueError("Can't divide 1 by 0")
|
||||
20 |
|
||||
21 | with pytest.raises(expected_exception=ValueError):
|
||||
26 | raise ValueError("Can't divide 1 by 0")
|
||||
27 |
|
||||
28 | with pytest.raises(expected_exception=ValueError):
|
||||
| ^^^^^^^^^^ PT011
|
||||
22 | raise ValueError("Can't divide 1 by 0")
|
||||
29 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
||||
PT011.py:24:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:31:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
22 | raise ValueError("Can't divide 1 by 0")
|
||||
23 |
|
||||
24 | with pytest.raises(socket.error):
|
||||
29 | raise ValueError("Can't divide 1 by 0")
|
||||
30 |
|
||||
31 | with pytest.raises(socket.error):
|
||||
| ^^^^^^^^^^^^ PT011
|
||||
25 | raise ValueError("Can't divide 1 by 0")
|
||||
32 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
||||
PT011.py:35:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:42:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
34 | def test_error_match_is_empty():
|
||||
35 | with pytest.raises(ValueError, match=None):
|
||||
41 | def test_error_match_is_empty():
|
||||
42 | with pytest.raises(ValueError, match=None):
|
||||
| ^^^^^^^^^^ PT011
|
||||
36 | raise ValueError("Can't divide 1 by 0")
|
||||
43 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
||||
PT011.py:38:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:45:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
36 | raise ValueError("Can't divide 1 by 0")
|
||||
37 |
|
||||
38 | with pytest.raises(ValueError, match=""):
|
||||
43 | raise ValueError("Can't divide 1 by 0")
|
||||
44 |
|
||||
45 | with pytest.raises(ValueError, match=""):
|
||||
| ^^^^^^^^^^ PT011
|
||||
39 | raise ValueError("Can't divide 1 by 0")
|
||||
46 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
||||
PT011.py:41:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:48:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
39 | raise ValueError("Can't divide 1 by 0")
|
||||
40 |
|
||||
41 | with pytest.raises(ValueError, match=f""):
|
||||
46 | raise ValueError("Can't divide 1 by 0")
|
||||
47 |
|
||||
48 | with pytest.raises(ValueError, match=f""):
|
||||
| ^^^^^^^^^^ PT011
|
||||
42 | raise ValueError("Can't divide 1 by 0")
|
||||
49 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
|
|
@ -9,54 +9,54 @@ PT011.py:13:24: PT011 `pytest.raises(ZeroDivisionError)` is too broad, set the `
|
|||
14 | raise ZeroDivisionError("Can't divide by 0")
|
||||
|
|
||||
|
||||
PT011.py:18:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:25:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
17 | def test_error_no_argument_given():
|
||||
18 | with pytest.raises(ValueError):
|
||||
24 | def test_error_no_argument_given():
|
||||
25 | with pytest.raises(ValueError):
|
||||
| ^^^^^^^^^^ PT011
|
||||
19 | raise ValueError("Can't divide 1 by 0")
|
||||
26 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
||||
PT011.py:21:43: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:28:43: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
19 | raise ValueError("Can't divide 1 by 0")
|
||||
20 |
|
||||
21 | with pytest.raises(expected_exception=ValueError):
|
||||
26 | raise ValueError("Can't divide 1 by 0")
|
||||
27 |
|
||||
28 | with pytest.raises(expected_exception=ValueError):
|
||||
| ^^^^^^^^^^ PT011
|
||||
22 | raise ValueError("Can't divide 1 by 0")
|
||||
29 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
||||
PT011.py:24:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:31:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
22 | raise ValueError("Can't divide 1 by 0")
|
||||
23 |
|
||||
24 | with pytest.raises(socket.error):
|
||||
29 | raise ValueError("Can't divide 1 by 0")
|
||||
30 |
|
||||
31 | with pytest.raises(socket.error):
|
||||
| ^^^^^^^^^^^^ PT011
|
||||
25 | raise ValueError("Can't divide 1 by 0")
|
||||
32 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
||||
PT011.py:35:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:42:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
34 | def test_error_match_is_empty():
|
||||
35 | with pytest.raises(ValueError, match=None):
|
||||
41 | def test_error_match_is_empty():
|
||||
42 | with pytest.raises(ValueError, match=None):
|
||||
| ^^^^^^^^^^ PT011
|
||||
36 | raise ValueError("Can't divide 1 by 0")
|
||||
43 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
||||
PT011.py:38:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:45:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
36 | raise ValueError("Can't divide 1 by 0")
|
||||
37 |
|
||||
38 | with pytest.raises(ValueError, match=""):
|
||||
43 | raise ValueError("Can't divide 1 by 0")
|
||||
44 |
|
||||
45 | with pytest.raises(ValueError, match=""):
|
||||
| ^^^^^^^^^^ PT011
|
||||
39 | raise ValueError("Can't divide 1 by 0")
|
||||
46 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
||||
PT011.py:41:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:48:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
39 | raise ValueError("Can't divide 1 by 0")
|
||||
40 |
|
||||
41 | with pytest.raises(ValueError, match=f""):
|
||||
46 | raise ValueError("Can't divide 1 by 0")
|
||||
47 |
|
||||
48 | with pytest.raises(ValueError, match=f""):
|
||||
| ^^^^^^^^^^ PT011
|
||||
42 | raise ValueError("Can't divide 1 by 0")
|
||||
49 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
|
|
@ -9,72 +9,72 @@ PT011.py:13:24: PT011 `pytest.raises(ZeroDivisionError)` is too broad, set the `
|
|||
14 | raise ZeroDivisionError("Can't divide by 0")
|
||||
|
|
||||
|
||||
PT011.py:18:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:25:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
17 | def test_error_no_argument_given():
|
||||
18 | with pytest.raises(ValueError):
|
||||
24 | def test_error_no_argument_given():
|
||||
25 | with pytest.raises(ValueError):
|
||||
| ^^^^^^^^^^ PT011
|
||||
19 | raise ValueError("Can't divide 1 by 0")
|
||||
26 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
||||
PT011.py:21:43: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:28:43: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
19 | raise ValueError("Can't divide 1 by 0")
|
||||
20 |
|
||||
21 | with pytest.raises(expected_exception=ValueError):
|
||||
26 | raise ValueError("Can't divide 1 by 0")
|
||||
27 |
|
||||
28 | with pytest.raises(expected_exception=ValueError):
|
||||
| ^^^^^^^^^^ PT011
|
||||
22 | raise ValueError("Can't divide 1 by 0")
|
||||
29 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
||||
PT011.py:24:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:31:24: PT011 `pytest.raises(socket.error)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
22 | raise ValueError("Can't divide 1 by 0")
|
||||
23 |
|
||||
24 | with pytest.raises(socket.error):
|
||||
29 | raise ValueError("Can't divide 1 by 0")
|
||||
30 |
|
||||
31 | with pytest.raises(socket.error):
|
||||
| ^^^^^^^^^^^^ PT011
|
||||
25 | raise ValueError("Can't divide 1 by 0")
|
||||
32 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
||||
PT011.py:27:24: PT011 `pytest.raises(pickle.PicklingError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:34:24: PT011 `pytest.raises(pickle.PicklingError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
25 | raise ValueError("Can't divide 1 by 0")
|
||||
26 |
|
||||
27 | with pytest.raises(PicklingError):
|
||||
32 | raise ValueError("Can't divide 1 by 0")
|
||||
33 |
|
||||
34 | with pytest.raises(PicklingError):
|
||||
| ^^^^^^^^^^^^^ PT011
|
||||
28 | raise PicklingError("Can't pickle")
|
||||
35 | raise PicklingError("Can't pickle")
|
||||
|
|
||||
|
||||
PT011.py:30:24: PT011 `pytest.raises(pickle.UnpicklingError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:37:24: PT011 `pytest.raises(pickle.UnpicklingError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
28 | raise PicklingError("Can't pickle")
|
||||
29 |
|
||||
30 | with pytest.raises(UnpicklingError):
|
||||
35 | raise PicklingError("Can't pickle")
|
||||
36 |
|
||||
37 | with pytest.raises(UnpicklingError):
|
||||
| ^^^^^^^^^^^^^^^ PT011
|
||||
31 | raise UnpicklingError("Can't unpickle")
|
||||
38 | raise UnpicklingError("Can't unpickle")
|
||||
|
|
||||
|
||||
PT011.py:35:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:42:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
34 | def test_error_match_is_empty():
|
||||
35 | with pytest.raises(ValueError, match=None):
|
||||
41 | def test_error_match_is_empty():
|
||||
42 | with pytest.raises(ValueError, match=None):
|
||||
| ^^^^^^^^^^ PT011
|
||||
36 | raise ValueError("Can't divide 1 by 0")
|
||||
43 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
||||
PT011.py:38:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:45:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
36 | raise ValueError("Can't divide 1 by 0")
|
||||
37 |
|
||||
38 | with pytest.raises(ValueError, match=""):
|
||||
43 | raise ValueError("Can't divide 1 by 0")
|
||||
44 |
|
||||
45 | with pytest.raises(ValueError, match=""):
|
||||
| ^^^^^^^^^^ PT011
|
||||
39 | raise ValueError("Can't divide 1 by 0")
|
||||
46 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
||||
PT011.py:41:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:48:24: PT011 `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
39 | raise ValueError("Can't divide 1 by 0")
|
||||
40 |
|
||||
41 | with pytest.raises(ValueError, match=f""):
|
||||
46 | raise ValueError("Can't divide 1 by 0")
|
||||
47 |
|
||||
48 | with pytest.raises(ValueError, match=f""):
|
||||
| ^^^^^^^^^^ PT011
|
||||
42 | raise ValueError("Can't divide 1 by 0")
|
||||
49 | raise ValueError("Can't divide 1 by 0")
|
||||
|
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_pytest_style/mod.rs
|
||||
---
|
||||
PT011.py:27:24: PT011 `pytest.raises(pickle.PicklingError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:34:24: PT011 `pytest.raises(pickle.PicklingError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
25 | raise ValueError("Can't divide 1 by 0")
|
||||
26 |
|
||||
27 | with pytest.raises(PicklingError):
|
||||
32 | raise ValueError("Can't divide 1 by 0")
|
||||
33 |
|
||||
34 | with pytest.raises(PicklingError):
|
||||
| ^^^^^^^^^^^^^ PT011
|
||||
28 | raise PicklingError("Can't pickle")
|
||||
35 | raise PicklingError("Can't pickle")
|
||||
|
|
||||
|
||||
PT011.py:30:24: PT011 `pytest.raises(pickle.UnpicklingError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
PT011.py:37:24: PT011 `pytest.raises(pickle.UnpicklingError)` is too broad, set the `match` parameter or use a more specific exception
|
||||
|
|
||||
28 | raise PicklingError("Can't pickle")
|
||||
29 |
|
||||
30 | with pytest.raises(UnpicklingError):
|
||||
35 | raise PicklingError("Can't pickle")
|
||||
36 |
|
||||
37 | with pytest.raises(UnpicklingError):
|
||||
| ^^^^^^^^^^^^^^^ PT011
|
||||
31 | raise UnpicklingError("Can't unpickle")
|
||||
38 | raise UnpicklingError("Can't unpickle")
|
||||
|
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue