From 2f894e3951d12999e67f79667fcdd4e0ef366aaa Mon Sep 17 00:00:00 2001
From: Jonathan Plasse <13716151+JonathanPlasse@users.noreply.github.com>
Date: Fri, 18 Nov 2022 18:15:10 +0100
Subject: [PATCH] Add flake8-blind-except (#805)
---
LICENSE | 24 ++++++
README.md | 13 +++
flake8_to_ruff/src/plugin.rs | 5 ++
resources/test/fixtures/B902.py | 55 ++++++++++++
src/check_ast.rs | 9 +-
src/checks.rs | 16 ++++
src/checks_gen.rs | 10 +++
src/flake8_blind_except/mod.rs | 1 +
src/flake8_blind_except/plugins.rs | 23 +++++
src/lib.rs | 1 +
src/linter.rs | 1 +
.../ruff__linter__tests__B902_B902.py.snap | 85 +++++++++++++++++++
12 files changed, 240 insertions(+), 3 deletions(-)
create mode 100644 resources/test/fixtures/B902.py
create mode 100644 src/flake8_blind_except/mod.rs
create mode 100644 src/flake8_blind_except/plugins.rs
create mode 100644 src/snapshots/ruff__linter__tests__B902_B902.py.snap
diff --git a/LICENSE b/LICENSE
index d20cfe5133..875fe58626 100644
--- a/LICENSE
+++ b/LICENSE
@@ -168,6 +168,30 @@ are:
THE SOFTWARE.
"""
+- flake8-blind-except, licensed as follows:
+ """
+ The MIT License (MIT)
+
+ Copyright (c) 2014 Elijah Andrews
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
+ this software and associated documentation files (the "Software"), to deal in
+ the Software without restriction, including without limitation the rights to
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ the Software, and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ """
+
- flake8-bugbear, licensed as follows:
"""
The MIT License (MIT)
diff --git a/README.md b/README.md
index 70e2410bc7..b4edd7a05f 100644
--- a/README.md
+++ b/README.md
@@ -61,6 +61,7 @@ Read the [launch blog post](https://notes.crmarsh.com/python-tooling-could-be-mu
1. [flake8-quotes (Q)](#flake8-quotes)
1. [flake8-annotations (ANN)](#flake8-annotations)
1. [flake8-2020 (YTT)](#flake8-2020)
+ 1. [flake8-blind-except](#flake8-blind-except)
1. [mccabe (C90)](#mccabe)
1. [Ruff-specific rules (RUF)](#ruff-specific-rules)
1. [Meta rules (M)](#meta-rules)
@@ -616,6 +617,14 @@ For more, see [flake8-2020](https://pypi.org/project/flake8-2020/1.7.0/) on PyPI
| YTT302 | SysVersionCmpStr10 | `sys.version` compared to string (python10), use `sys.version_info` | |
| YTT303 | SysVersionSlice1Referenced | `sys.version[:1]` referenced (python10), use `sys.version_info` | |
+### flake8-blind-except
+
+For more, see [flake8-blind-except](https://pypi.org/project/flake8-blind-except/0.2.1/) on PyPI.
+
+| Code | Name | Message | Fix |
+| ---- | ---- | ------- | --- |
+| B902 | BlindExcept | Blind except Exception: statement | |
+
### mccabe
For more, see [mccabe](https://pypi.org/project/mccabe/0.7.0/) on PyPI.
@@ -677,6 +686,7 @@ tools:
format-command: 'ruff --stdin-filename ${INPUT} --config ~/myconfigs/linters/ruff.toml --fix --exit-zero --quiet -'
format-stdin: true
```
+
@@ -713,6 +723,7 @@ null_ls.setup({
}
})
```
+
### Language Server Protocol (Unofficial)
@@ -782,6 +793,7 @@ including:
- [`flake8-bandit`](https://pypi.org/project/flake8-bandit/) (6/40)
- [`flake8-bugbear`](https://pypi.org/project/flake8-bugbear/) (25/32)
- [`flake8-2020`](https://pypi.org/project/flake8-2020/)
+- [`flake8-blind-except`](https://pypi.org/project/flake8-blind-except/) (1/2)
- [`mccabe`](https://pypi.org/project/mccabe/)
- [`isort`](https://pypi.org/project/isort/)
- [`pyupgrade`](https://pypi.org/project/pyupgrade/) (14/33)
@@ -811,6 +823,7 @@ Today, Ruff can be used to replace Flake8 when used with any of the following pl
- [`flake8-comprehensions`](https://pypi.org/project/flake8-comprehensions/)
- [`flake8-bugbear`](https://pypi.org/project/flake8-bugbear/) (26/32)
- [`flake8-2020`](https://pypi.org/project/flake8-2020/)
+- [`flake8-blind-except`](https://pypi.org/project/flake8-blind-except/) (1/2)
- [`mccabe`](https://pypi.org/project/mccabe/)
Ruff can also replace [`isort`](https://pypi.org/project/isort/), [`yesqa`](https://github.com/asottile/yesqa),
diff --git a/flake8_to_ruff/src/plugin.rs b/flake8_to_ruff/src/plugin.rs
index 0a7d90033a..6e5111dcbf 100644
--- a/flake8_to_ruff/src/plugin.rs
+++ b/flake8_to_ruff/src/plugin.rs
@@ -16,6 +16,7 @@ pub enum Plugin {
Flake8Quotes,
Flake8Annotations,
McCabe,
+ Flake8BlindExcept,
PEP8Naming,
Pyupgrade,
}
@@ -34,6 +35,7 @@ impl FromStr for Plugin {
"flake8-print" => Ok(Plugin::Flake8Print),
"flake8-quotes" => Ok(Plugin::Flake8Quotes),
"flake8-annotations" => Ok(Plugin::Flake8Annotations),
+ "flake8-blind-except" => Ok(Plugin::Flake8BlindExcept),
"mccabe" => Ok(Plugin::McCabe),
"pep8-naming" => Ok(Plugin::PEP8Naming),
"pyupgrade" => Ok(Plugin::Pyupgrade),
@@ -54,6 +56,7 @@ impl Plugin {
Plugin::Flake8Print => CheckCodePrefix::T,
Plugin::Flake8Quotes => CheckCodePrefix::Q,
Plugin::Flake8Annotations => CheckCodePrefix::ANN,
+ Plugin::Flake8BlindExcept => CheckCodePrefix::B90,
Plugin::McCabe => CheckCodePrefix::C9,
Plugin::PEP8Naming => CheckCodePrefix::N,
Plugin::Pyupgrade => CheckCodePrefix::U,
@@ -86,6 +89,7 @@ impl Plugin {
Plugin::Flake8Print => vec![CheckCodePrefix::T],
Plugin::Flake8Quotes => vec![CheckCodePrefix::Q],
Plugin::Flake8Annotations => vec![CheckCodePrefix::ANN],
+ Plugin::Flake8BlindExcept => vec![CheckCodePrefix::B90],
Plugin::McCabe => vec![CheckCodePrefix::C9],
Plugin::PEP8Naming => vec![CheckCodePrefix::N],
Plugin::Pyupgrade => vec![CheckCodePrefix::U],
@@ -365,6 +369,7 @@ pub fn infer_plugins_from_codes(codes: &BTreeSet) -> Vec {
if self.settings.enabled.contains(&CheckCode::E731) {
diff --git a/src/checks.rs b/src/checks.rs
index 45b756f735..2f51399221 100644
--- a/src/checks.rs
+++ b/src/checks.rs
@@ -103,6 +103,8 @@ pub enum CheckCode {
B025,
B026,
B027,
+ // flake8-blind-except
+ B902,
// flake8-comprehensions
C400,
C401,
@@ -263,6 +265,7 @@ pub enum CheckCategory {
Flake8Quotes,
Flake8Annotations,
Flake82020,
+ Flake8BlindExcept,
McCabe,
Ruff,
Meta,
@@ -283,6 +286,7 @@ impl CheckCategory {
CheckCategory::Flake8Quotes => "flake8-quotes",
CheckCategory::Flake8Annotations => "flake8-annotations",
CheckCategory::Flake82020 => "flake8-2020",
+ CheckCategory::Flake8BlindExcept => "flake8-blind-except",
CheckCategory::Pyupgrade => "pyupgrade",
CheckCategory::Pydocstyle => "pydocstyle",
CheckCategory::PEP8Naming => "pep8-naming",
@@ -319,6 +323,9 @@ impl CheckCategory {
CheckCategory::Pydocstyle => Some("https://pypi.org/project/pydocstyle/6.1.1/"),
CheckCategory::PEP8Naming => Some("https://pypi.org/project/pep8-naming/0.13.2/"),
CheckCategory::Flake8Bandit => Some("https://pypi.org/project/flake8-bandit/4.1.1/"),
+ CheckCategory::Flake8BlindExcept => {
+ Some("https://pypi.org/project/flake8-blind-except/0.2.1/")
+ }
CheckCategory::McCabe => Some("https://pypi.org/project/mccabe/0.7.0/"),
CheckCategory::Ruff => None,
CheckCategory::Meta => None,
@@ -394,6 +401,8 @@ pub enum CheckKind {
BuiltinVariableShadowing(String),
BuiltinArgumentShadowing(String),
BuiltinAttributeShadowing(String),
+ // flake8-blind-except
+ BlindExcept,
// flake8-bugbear
UnaryPrefixIncrement,
AssignmentToOsEnviron,
@@ -734,6 +743,8 @@ impl CheckCode {
CheckCode::YTT301 => CheckKind::SysVersion0Referenced,
CheckCode::YTT302 => CheckKind::SysVersionCmpStr10,
CheckCode::YTT303 => CheckKind::SysVersionSlice1Referenced,
+ // flake8-blind-except
+ CheckCode::B902 => CheckKind::BlindExcept,
// pyupgrade
CheckCode::U001 => CheckKind::UselessMetaclassType,
CheckCode::U003 => CheckKind::TypeOfPrimitive(Primitive::Str),
@@ -920,6 +931,7 @@ impl CheckCode {
CheckCode::B025 => CheckCategory::Flake8Bugbear,
CheckCode::B026 => CheckCategory::Flake8Bugbear,
CheckCode::B027 => CheckCategory::Flake8Bugbear,
+ CheckCode::B902 => CheckCategory::Flake8BlindExcept,
CheckCode::C400 => CheckCategory::Flake8Comprehensions,
CheckCode::C401 => CheckCategory::Flake8Comprehensions,
CheckCode::C402 => CheckCategory::Flake8Comprehensions,
@@ -1131,6 +1143,8 @@ impl CheckKind {
CheckKind::DuplicateTryBlockException(_) => &CheckCode::B025,
CheckKind::StarArgUnpackingAfterKeywordArg => &CheckCode::B026,
CheckKind::EmptyMethodWithoutAbstractDecorator(_) => &CheckCode::B027,
+ // flake8-blind-except
+ CheckKind::BlindExcept => &CheckCode::B902,
// flake8-comprehensions
CheckKind::UnnecessaryGeneratorList => &CheckCode::C400,
CheckKind::UnnecessaryGeneratorSet => &CheckCode::C401,
@@ -1921,6 +1935,8 @@ impl CheckKind {
CheckKind::HardcodedPasswordDefault(string) => {
format!("Possible hardcoded password: `\"{string}\"`")
}
+ // flake8-blind-except
+ CheckKind::BlindExcept => "Blind except Exception: statement".to_string(),
// McCabe
CheckKind::FunctionIsTooComplex(name, complexity) => {
format!("`{name}` is too complex ({complexity})")
diff --git a/src/checks_gen.rs b/src/checks_gen.rs
index c175eb7efc..e69f855293 100644
--- a/src/checks_gen.rs
+++ b/src/checks_gen.rs
@@ -63,6 +63,9 @@ pub enum CheckCodePrefix {
B025,
B026,
B027,
+ B9,
+ B90,
+ B902,
C,
C4,
C40,
@@ -400,6 +403,7 @@ impl CheckCodePrefix {
CheckCode::B025,
CheckCode::B026,
CheckCode::B027,
+ CheckCode::B902,
],
CheckCodePrefix::B0 => vec![
CheckCode::B002,
@@ -484,6 +488,9 @@ impl CheckCodePrefix {
CheckCodePrefix::B025 => vec![CheckCode::B025],
CheckCodePrefix::B026 => vec![CheckCode::B026],
CheckCodePrefix::B027 => vec![CheckCode::B027],
+ CheckCodePrefix::B9 => vec![CheckCode::B902],
+ CheckCodePrefix::B90 => vec![CheckCode::B902],
+ CheckCodePrefix::B902 => vec![CheckCode::B902],
CheckCodePrefix::C => vec![
CheckCode::C400,
CheckCode::C401,
@@ -1242,6 +1249,9 @@ impl CheckCodePrefix {
CheckCodePrefix::B025 => PrefixSpecificity::Explicit,
CheckCodePrefix::B026 => PrefixSpecificity::Explicit,
CheckCodePrefix::B027 => PrefixSpecificity::Explicit,
+ CheckCodePrefix::B9 => PrefixSpecificity::Hundreds,
+ CheckCodePrefix::B90 => PrefixSpecificity::Tens,
+ CheckCodePrefix::B902 => PrefixSpecificity::Explicit,
CheckCodePrefix::C => PrefixSpecificity::Category,
CheckCodePrefix::C4 => PrefixSpecificity::Hundreds,
CheckCodePrefix::C40 => PrefixSpecificity::Tens,
diff --git a/src/flake8_blind_except/mod.rs b/src/flake8_blind_except/mod.rs
new file mode 100644
index 0000000000..25a06164e5
--- /dev/null
+++ b/src/flake8_blind_except/mod.rs
@@ -0,0 +1 @@
+pub mod plugins;
diff --git a/src/flake8_blind_except/plugins.rs b/src/flake8_blind_except/plugins.rs
new file mode 100644
index 0000000000..7804d4e69d
--- /dev/null
+++ b/src/flake8_blind_except/plugins.rs
@@ -0,0 +1,23 @@
+use rustpython_ast::{Excepthandler, ExcepthandlerKind, ExprKind};
+
+use crate::ast::types::Range;
+use crate::check_ast::Checker;
+use crate::checks::{Check, CheckKind};
+
+pub fn blind_except(checker: &mut Checker, handlers: &[Excepthandler]) {
+ for handler in handlers {
+ let ExcepthandlerKind::ExceptHandler { type_, .. } = &handler.node;
+ if let Some(type_) = type_ {
+ if let ExprKind::Name { id, .. } = &type_.node {
+ for exception in ["BaseException", "Exception"] {
+ if id == exception {
+ checker.add_check(Check::new(
+ CheckKind::BlindExcept,
+ Range::from_located(type_),
+ ));
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 349319a090..bdc7f510b1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -30,6 +30,7 @@ mod docstrings;
mod flake8_2020;
pub mod flake8_annotations;
pub mod flake8_bandit;
+mod flake8_blind_except;
pub mod flake8_bugbear;
mod flake8_builtins;
mod flake8_comprehensions;
diff --git a/src/linter.rs b/src/linter.rs
index 7a5a173ec3..a649834e05 100644
--- a/src/linter.rs
+++ b/src/linter.rs
@@ -351,6 +351,7 @@ mod tests {
#[test_case(CheckCode::B025, Path::new("B025.py"); "B025")]
#[test_case(CheckCode::B026, Path::new("B026.py"); "B026")]
#[test_case(CheckCode::B027, Path::new("B027.py"); "B027")]
+ #[test_case(CheckCode::B902, Path::new("B902.py"); "B902")]
#[test_case(CheckCode::C400, Path::new("C400.py"); "C400")]
#[test_case(CheckCode::C401, Path::new("C401.py"); "C401")]
#[test_case(CheckCode::C402, Path::new("C402.py"); "C402")]
diff --git a/src/snapshots/ruff__linter__tests__B902_B902.py.snap b/src/snapshots/ruff__linter__tests__B902_B902.py.snap
new file mode 100644
index 0000000000..f68f242da3
--- /dev/null
+++ b/src/snapshots/ruff__linter__tests__B902_B902.py.snap
@@ -0,0 +1,85 @@
+---
+source: src/linter.rs
+expression: checks
+---
+- kind: BlindExcept
+ location:
+ row: 5
+ column: 7
+ end_location:
+ row: 5
+ column: 16
+ fix: ~
+- kind: BlindExcept
+ location:
+ row: 13
+ column: 7
+ end_location:
+ row: 13
+ column: 20
+ fix: ~
+- kind: BlindExcept
+ location:
+ row: 23
+ column: 7
+ end_location:
+ row: 23
+ column: 16
+ fix: ~
+- kind: BlindExcept
+ location:
+ row: 25
+ column: 7
+ end_location:
+ row: 25
+ column: 20
+ fix: ~
+- kind: BlindExcept
+ location:
+ row: 31
+ column: 7
+ end_location:
+ row: 31
+ column: 16
+ fix: ~
+- kind: BlindExcept
+ location:
+ row: 36
+ column: 11
+ end_location:
+ row: 36
+ column: 24
+ fix: ~
+- kind: BlindExcept
+ location:
+ row: 42
+ column: 7
+ end_location:
+ row: 42
+ column: 16
+ fix: ~
+- kind: BlindExcept
+ location:
+ row: 45
+ column: 11
+ end_location:
+ row: 45
+ column: 24
+ fix: ~
+- kind: BlindExcept
+ location:
+ row: 52
+ column: 11
+ end_location:
+ row: 52
+ column: 24
+ fix: ~
+- kind: BlindExcept
+ location:
+ row: 54
+ column: 7
+ end_location:
+ row: 54
+ column: 16
+ fix: ~
+