-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[flake8-bugbear] Support non-context-manager calls in B017
#19063
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
Changes from 7 commits
3bfae2f
f25dc89
7bbc953
d381956
3dc56dc
fe26add
ba492ef
0545a61
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| """ | ||
| Should emit: | ||
| B017 - on lines 20, 21, 25, and 26 | ||
| """ | ||
| import unittest | ||
| import pytest | ||
|
|
||
|
|
||
| def something_else() -> None: | ||
| for i in (1, 2, 3): | ||
| print(i) | ||
|
|
||
|
|
||
| class Foo: | ||
| pass | ||
|
|
||
|
|
||
| class Foobar(unittest.TestCase): | ||
| def call_form_raises(self) -> None: | ||
| self.assertRaises(Exception, something_else) | ||
| self.assertRaises(BaseException, something_else) | ||
|
|
||
|
|
||
| def test_pytest_call_form() -> None: | ||
| pytest.raises(Exception, something_else) | ||
| pytest.raises(BaseException, something_else) | ||
|
|
||
| pytest.raises(Exception, something_else, match="hello") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| --- | ||
| source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs | ||
| --- | ||
| B017.py:23:14: B017 Do not assert blind exception: `Exception` | ||
| B017_0.py:23:14: B017 Do not assert blind exception: `Exception` | ||
| | | ||
| 21 | class Foobar(unittest.TestCase): | ||
| 22 | def evil_raises(self) -> None: | ||
|
|
@@ -10,23 +10,23 @@ B017.py:23:14: B017 Do not assert blind exception: `Exception` | |
| 24 | raise Exception("Evil I say!") | ||
| | | ||
|
|
||
| B017.py:27:14: B017 Do not assert blind exception: `BaseException` | ||
| B017_0.py:27:14: B017 Do not assert blind exception: `BaseException` | ||
| | | ||
| 26 | def also_evil_raises(self) -> None: | ||
| 27 | with self.assertRaises(BaseException): | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ B017 | ||
| 28 | raise Exception("Evil I say!") | ||
| | | ||
|
|
||
| B017.py:45:10: B017 Do not assert blind exception: `Exception` | ||
| B017_0.py:45:10: B017 Do not assert blind exception: `Exception` | ||
| | | ||
| 44 | def test_pytest_raises(): | ||
| 45 | with pytest.raises(Exception): | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^ B017 | ||
| 46 | raise ValueError("Hello") | ||
| | | ||
|
|
||
| B017.py:48:10: B017 Do not assert blind exception: `Exception` | ||
| B017_0.py:48:10: B017 Do not assert blind exception: `Exception` | ||
| | | ||
| 46 | raise ValueError("Hello") | ||
| 47 | | ||
|
|
@@ -35,7 +35,16 @@ B017.py:48:10: B017 Do not assert blind exception: `Exception` | |
| 49 | raise ValueError("Hello") | ||
| | | ||
|
|
||
| B017.py:57:36: B017 Do not assert blind exception: `Exception` | ||
| B017_0.py:51:10: B017 Do not assert blind exception: `Exception` | ||
| | | ||
| 49 | raise ValueError("Hello") | ||
| 50 | | ||
| 51 | with pytest.raises(Exception, "hello"): | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ B017 | ||
| 52 | raise ValueError("This is fine") | ||
| | | ||
|
|
||
| B017_0.py:57:36: B017 Do not assert blind exception: `Exception` | ||
|
||
| | | ||
| 55 | raise ValueError("This is also fine") | ||
| 56 | | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| --- | ||
| source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs | ||
| --- | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| --- | ||
| source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs | ||
| --- | ||
| B017_0.py:23:14: B017 Do not assert blind exception: `Exception` | ||
| | | ||
| 21 | class Foobar(unittest.TestCase): | ||
| 22 | def evil_raises(self) -> None: | ||
| 23 | with self.assertRaises(Exception): | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ B017 | ||
| 24 | raise Exception("Evil I say!") | ||
| | | ||
|
|
||
| B017_0.py:27:14: B017 Do not assert blind exception: `BaseException` | ||
| | | ||
| 26 | def also_evil_raises(self) -> None: | ||
| 27 | with self.assertRaises(BaseException): | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ B017 | ||
| 28 | raise Exception("Evil I say!") | ||
| | | ||
|
|
||
| B017_0.py:45:10: B017 Do not assert blind exception: `Exception` | ||
| | | ||
| 44 | def test_pytest_raises(): | ||
| 45 | with pytest.raises(Exception): | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^ B017 | ||
| 46 | raise ValueError("Hello") | ||
| | | ||
|
|
||
| B017_0.py:48:10: B017 Do not assert blind exception: `Exception` | ||
| | | ||
| 46 | raise ValueError("Hello") | ||
| 47 | | ||
| 48 | with pytest.raises(Exception), pytest.raises(ValueError): | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^ B017 | ||
| 49 | raise ValueError("Hello") | ||
| | | ||
|
|
||
| B017_0.py:51:10: B017 Do not assert blind exception: `Exception` | ||
| | | ||
| 49 | raise ValueError("Hello") | ||
| 50 | | ||
| 51 | with pytest.raises(Exception, "hello"): | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ B017 | ||
| 52 | raise ValueError("This is fine") | ||
| | | ||
|
|
||
| B017_0.py:51:10: B017 Do not assert blind exception: `Exception` | ||
| | | ||
| 49 | raise ValueError("Hello") | ||
| 50 | | ||
| 51 | with pytest.raises(Exception, "hello"): | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ B017 | ||
| 52 | raise ValueError("This is fine") | ||
| | | ||
|
|
||
| B017_0.py:57:36: B017 Do not assert blind exception: `Exception` | ||
| | | ||
| 55 | raise ValueError("This is also fine") | ||
| 56 | | ||
| 57 | with contextlib.nullcontext(), pytest.raises(Exception): | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^ B017 | ||
| 58 | raise ValueError("Multiple context managers") | ||
| | |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| --- | ||
| source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs | ||
| --- | ||
| B017_1.py:20:9: B017 Do not assert blind exception: `Exception` | ||
| | | ||
| 18 | class Foobar(unittest.TestCase): | ||
| 19 | def call_form_raises(self) -> None: | ||
| 20 | self.assertRaises(Exception, something_else) | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ B017 | ||
| 21 | self.assertRaises(BaseException, something_else) | ||
| | | ||
|
|
||
| B017_1.py:21:9: B017 Do not assert blind exception: `BaseException` | ||
| | | ||
| 19 | def call_form_raises(self) -> None: | ||
| 20 | self.assertRaises(Exception, something_else) | ||
| 21 | self.assertRaises(BaseException, something_else) | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ B017 | ||
| | | ||
|
|
||
| B017_1.py:25:5: B017 Do not assert blind exception: `Exception` | ||
| | | ||
| 24 | def test_pytest_call_form() -> None: | ||
| 25 | pytest.raises(Exception, something_else) | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ B017 | ||
| 26 | pytest.raises(BaseException, something_else) | ||
| | | ||
|
|
||
| B017_1.py:26:5: B017 Do not assert blind exception: `BaseException` | ||
| | | ||
| 24 | def test_pytest_call_form() -> None: | ||
| 25 | pytest.raises(Exception, something_else) | ||
| 26 | pytest.raises(BaseException, something_else) | ||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ B017 | ||
| 27 | | ||
| 28 | pytest.raises(Exception, something_else, match="hello") | ||
| | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is supposed to be
is_nonelike before right?It's a little hard to tell because the diff shifted around, but I'm pretty sure one of the snapshots is showing a different result.
I think this
is_someis actually correct and the existingis_noneis a bug unless I'm misunderstanding something, but I'd rather handle that separately, I guess.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless I'm missing something, I believe
is_some()is the right test here.pytest.raises(..., match="pattern")is a form that already narrows the check to a specific exception message (equivalent to theassertRaisesRegexcase forunittest), so when thatmatch=keyword is present we want to skip B017, because it’s no longer a “blind” exception assertion.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, maybe I got confused by the logic here. The snapshot on
mainlooks correct. Let's regroup the test cases and make sure none of the stable results change, but I think you may be right.is_somedefinitely makes sense intuitively, I guess the condition was negated in the original code.