Skip to content

Commit

Permalink
feat: implement TRY003
Browse files Browse the repository at this point in the history
  • Loading branch information
karpa4o4 committed Jan 25, 2023
1 parent 58cc970 commit 8bc98c1
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,7 @@ For more, see [tryceratops](https://pypi.org/project/tryceratops/1.1.0/) on PyPI
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| TRY002 | raise-vanilla-class | Create your own exception | |
| TRY003 | raise-vanilla-args | Avoid specifying long messages outside the exception class | |
| TRY004 | prefer-type-error | Prefer `TypeError` exception for invalid type | 🛠 |
| TRY200 | reraise-no-cause | Use `raise from` to specify exception cause | |
| TRY201 | verbose-raise | Use `raise` without specifying exception name | |
Expand Down
32 changes: 32 additions & 0 deletions resources/test/fixtures/tryceratops/TRY003.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
class BadArgCantBeEven(Exception):
pass


class GoodArgCantBeEven(Exception):
def __init__(self, arg):
super().__init__(f"The argument '{arg}' should be even")


def bad(a):
if a % 2 == 0:
raise BadArgCantBeEven(f"The argument '{a}' should be even")


def another_bad(a):
if a % 2 == 0:
raise BadArgCantBeEven(f"The argument {a} should not be odd.")


def and_another_bad(a):
if a % 2 == 0:
raise BadArgCantBeEven('The argument `a` should not be odd.')


def good(a: int):
if a % 2 == 0:
raise GoodArgCantBeEven(a)


def another_good(a):
if a % 2 == 0:
raise GoodArgCantBeEven(a)
1 change: 1 addition & 0 deletions ruff.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1769,6 +1769,7 @@
"TRY0",
"TRY00",
"TRY002",
"TRY003",
"TRY004",
"TRY2",
"TRY20",
Expand Down
5 changes: 5 additions & 0 deletions src/checkers/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1399,6 +1399,11 @@ where
tryceratops::rules::raise_vanilla_class(self, expr);
}
}
if self.settings.rules.enabled(&Rule::RaiseVanillaArgs) {
if let Some(expr) = exc {
tryceratops::rules::raise_vanilla_args(self, expr);
}
}
}
StmtKind::AugAssign { target, .. } => {
self.handle_node_load(target);
Expand Down
1 change: 1 addition & 0 deletions src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ ruff_macros::define_rule_mapping!(
TYP005 => rules::flake8_type_checking::rules::EmptyTypeCheckingBlock,
// tryceratops
TRY002 => rules::tryceratops::rules::RaiseVanillaClass,
TRY003 => rules::tryceratops::rules::RaiseVanillaArgs,
TRY004 => rules::tryceratops::rules::PreferTypeError,
TRY200 => rules::tryceratops::rules::ReraiseNoCause,
TRY201 => rules::tryceratops::rules::VerboseRaise,
Expand Down
1 change: 1 addition & 0 deletions src/rules/tryceratops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ mod tests {
use crate::settings;

#[test_case(Rule::RaiseVanillaClass, Path::new("TRY002.py"); "TRY002")]
#[test_case(Rule::RaiseVanillaArgs, Path::new("TRY003.py"); "TRY003")]
#[test_case(Rule::PreferTypeError, Path::new("TRY004.py"); "TRY004")]
#[test_case(Rule::ReraiseNoCause, Path::new("TRY200.py"); "TRY200")]
#[test_case(Rule::VerboseRaise, Path::new("TRY201.py"); "TRY201")]
Expand Down
2 changes: 2 additions & 0 deletions src/rules/tryceratops/rules/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
pub use prefer_type_error::{prefer_type_error, PreferTypeError};
pub use raise_vanilla_args::{raise_vanilla_args, RaiseVanillaArgs};
pub use raise_vanilla_class::{raise_vanilla_class, RaiseVanillaClass};
pub use raise_within_try::{raise_within_try, RaiseWithinTry};
pub use reraise_no_cause::{reraise_no_cause, ReraiseNoCause};
pub use try_consider_else::{try_consider_else, TryConsiderElse};
pub use verbose_raise::{verbose_raise, VerboseRaise};

mod prefer_type_error;
mod raise_vanilla_args;
mod raise_vanilla_class;
mod raise_within_try;
mod reraise_no_cause;
Expand Down
50 changes: 50 additions & 0 deletions src/rules/tryceratops/rules/raise_vanilla_args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use ruff_macros::derive_message_formats;
use rustpython_ast::{Constant, Expr, ExprKind};

use crate::ast::types::Range;
use crate::checkers::ast::Checker;
use crate::define_violation;
use crate::registry::Diagnostic;
use crate::violation::Violation;

define_violation!(
pub struct RaiseVanillaArgs;
);
impl Violation for RaiseVanillaArgs {
#[derive_message_formats]
fn message(&self) -> String {
format!("Avoid specifying long messages outside the exception class")
}
}

const WHITESPACE: &str = " ";

fn get_string_arg_value(arg: &Expr) -> Option<String> {
match &arg.node {
ExprKind::JoinedStr { values } => {
let value = values
.iter()
.map(|val| get_string_arg_value(val).unwrap_or_default())
.collect::<String>();
Some(value)
}
ExprKind::Constant { value, .. } => match value {
Constant::Str(val) => Some(val.to_string()),
_ => None,
},
_ => None,
}
}

/// TRY003
pub fn raise_vanilla_args(checker: &mut Checker, expr: &Expr) {
if let ExprKind::Call { args, .. } = &expr.node {
if let Some(arg_value) = get_string_arg_value(&args[0]) {
if arg_value.contains(WHITESPACE) {
checker
.diagnostics
.push(Diagnostic::new(RaiseVanillaArgs, Range::from_located(expr)));
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
source: src/rules/tryceratops/mod.rs
expression: diagnostics
---
- kind:
RaiseVanillaArgs: ~
location:
row: 12
column: 14
end_location:
row: 12
column: 68
fix: ~
parent: ~
- kind:
RaiseVanillaArgs: ~
location:
row: 17
column: 14
end_location:
row: 17
column: 70
fix: ~
parent: ~
- kind:
RaiseVanillaArgs: ~
location:
row: 22
column: 14
end_location:
row: 22
column: 69
fix: ~
parent: ~

0 comments on commit 8bc98c1

Please sign in to comment.