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: ~ +