mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-04 10:48:32 +00:00
Move remaining flake8-pytest-style violations to rule modules (#2482)
This commit is contained in:
parent
8e53a4d1d3
commit
b4b8782243
10 changed files with 264 additions and 258 deletions
|
@ -394,26 +394,26 @@ ruff_macros::define_rule_mapping!(
|
|||
PT003 => rules::flake8_pytest_style::rules::ExtraneousScopeFunction,
|
||||
PT004 => rules::flake8_pytest_style::rules::MissingFixtureNameUnderscore,
|
||||
PT005 => rules::flake8_pytest_style::rules::IncorrectFixtureNameUnderscore,
|
||||
PT006 => violations::ParametrizeNamesWrongType,
|
||||
PT007 => violations::ParametrizeValuesWrongType,
|
||||
PT008 => violations::PatchWithLambda,
|
||||
PT009 => violations::UnittestAssertion,
|
||||
PT010 => violations::RaisesWithoutException,
|
||||
PT011 => violations::RaisesTooBroad,
|
||||
PT012 => violations::RaisesWithMultipleStatements,
|
||||
PT013 => violations::IncorrectPytestImport,
|
||||
PT015 => violations::AssertAlwaysFalse,
|
||||
PT016 => violations::FailWithoutMessage,
|
||||
PT017 => violations::AssertInExcept,
|
||||
PT018 => violations::CompositeAssertion,
|
||||
PT006 => rules::flake8_pytest_style::rules::ParametrizeNamesWrongType,
|
||||
PT007 => rules::flake8_pytest_style::rules::ParametrizeValuesWrongType,
|
||||
PT008 => rules::flake8_pytest_style::rules::PatchWithLambda,
|
||||
PT009 => rules::flake8_pytest_style::rules::UnittestAssertion,
|
||||
PT010 => rules::flake8_pytest_style::rules::RaisesWithoutException,
|
||||
PT011 => rules::flake8_pytest_style::rules::RaisesTooBroad,
|
||||
PT012 => rules::flake8_pytest_style::rules::RaisesWithMultipleStatements,
|
||||
PT013 => rules::flake8_pytest_style::rules::IncorrectPytestImport,
|
||||
PT015 => rules::flake8_pytest_style::rules::AssertAlwaysFalse,
|
||||
PT016 => rules::flake8_pytest_style::rules::FailWithoutMessage,
|
||||
PT017 => rules::flake8_pytest_style::rules::AssertInExcept,
|
||||
PT018 => rules::flake8_pytest_style::rules::CompositeAssertion,
|
||||
PT019 => rules::flake8_pytest_style::rules::FixtureParamWithoutValue,
|
||||
PT020 => rules::flake8_pytest_style::rules::DeprecatedYieldFixture,
|
||||
PT021 => rules::flake8_pytest_style::rules::FixtureFinalizerCallback,
|
||||
PT022 => rules::flake8_pytest_style::rules::UselessYieldFixture,
|
||||
PT023 => violations::IncorrectMarkParenthesesStyle,
|
||||
PT023 => rules::flake8_pytest_style::rules::IncorrectMarkParenthesesStyle,
|
||||
PT024 => rules::flake8_pytest_style::rules::UnnecessaryAsyncioMarkOnFixture,
|
||||
PT025 => rules::flake8_pytest_style::rules::ErroneousUseFixturesOnFixture,
|
||||
PT026 => violations::UseFixturesWithoutParameters,
|
||||
PT026 => rules::flake8_pytest_style::rules::UseFixturesWithoutParameters,
|
||||
// flake8-pie
|
||||
PIE790 => rules::flake8_pie::rules::NoUnnecessaryPass,
|
||||
PIE794 => rules::flake8_pie::rules::DupeClassFieldDefinitions,
|
||||
|
|
|
@ -9,9 +9,64 @@ use crate::ast::types::Range;
|
|||
use crate::ast::visitor;
|
||||
use crate::ast::visitor::Visitor;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::define_violation;
|
||||
use crate::fix::Fix;
|
||||
use crate::registry::Diagnostic;
|
||||
use crate::violations;
|
||||
use crate::violation::{AlwaysAutofixableViolation, Violation};
|
||||
use ruff_macros::derive_message_formats;
|
||||
|
||||
define_violation!(
|
||||
pub struct CompositeAssertion;
|
||||
);
|
||||
impl Violation for CompositeAssertion {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Assertion should be broken down into multiple parts")
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct AssertInExcept {
|
||||
pub name: String,
|
||||
}
|
||||
);
|
||||
impl Violation for AssertInExcept {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let AssertInExcept { name } = self;
|
||||
format!(
|
||||
"Found assertion on exception `{name}` in except block, use `pytest.raises()` instead"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct AssertAlwaysFalse;
|
||||
);
|
||||
impl Violation for AssertAlwaysFalse {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Assertion always fails, replace with `pytest.fail()`")
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct UnittestAssertion {
|
||||
pub assertion: String,
|
||||
}
|
||||
);
|
||||
impl AlwaysAutofixableViolation for UnittestAssertion {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let UnittestAssertion { assertion } = self;
|
||||
format!("Use a regular `assert` instead of unittest-style `{assertion}`")
|
||||
}
|
||||
|
||||
fn autofix_title(&self) -> String {
|
||||
let UnittestAssertion { assertion } = self;
|
||||
format!("Replace `{assertion}(...)` with `assert ...`")
|
||||
}
|
||||
}
|
||||
|
||||
/// Visitor that tracks assert statements and checks if they reference
|
||||
/// the exception name.
|
||||
|
@ -52,7 +107,7 @@ where
|
|||
if let Some(current_assert) = self.current_assert {
|
||||
if id.as_str() == self.exception_name {
|
||||
self.errors.push(Diagnostic::new(
|
||||
violations::AssertInExcept {
|
||||
AssertInExcept {
|
||||
name: id.to_string(),
|
||||
},
|
||||
Range::from_located(current_assert),
|
||||
|
@ -102,7 +157,7 @@ pub fn unittest_assertion(
|
|||
ExprKind::Attribute { attr, .. } => {
|
||||
if let Ok(unittest_assert) = UnittestAssert::try_from(attr.as_str()) {
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
violations::UnittestAssertion {
|
||||
UnittestAssertion {
|
||||
assertion: unittest_assert.to_string(),
|
||||
},
|
||||
Range::from_located(func),
|
||||
|
@ -129,7 +184,7 @@ pub fn unittest_assertion(
|
|||
pub fn assert_falsy(assert_stmt: &Stmt, test_expr: &Expr) -> Option<Diagnostic> {
|
||||
if is_falsy_constant(test_expr) {
|
||||
Some(Diagnostic::new(
|
||||
violations::AssertAlwaysFalse,
|
||||
AssertAlwaysFalse,
|
||||
Range::from_located(assert_stmt),
|
||||
))
|
||||
} else {
|
||||
|
@ -157,7 +212,7 @@ pub fn assert_in_exception_handler(handlers: &[Excepthandler]) -> Vec<Diagnostic
|
|||
pub fn composite_condition(assert_stmt: &Stmt, test_expr: &Expr) -> Option<Diagnostic> {
|
||||
if is_composite_condition(test_expr) {
|
||||
Some(Diagnostic::new(
|
||||
violations::CompositeAssertion,
|
||||
CompositeAssertion,
|
||||
Range::from_located(assert_stmt),
|
||||
))
|
||||
} else {
|
||||
|
|
|
@ -4,8 +4,20 @@ use super::helpers::{is_empty_or_null_string, is_pytest_fail};
|
|||
use crate::ast::helpers::SimpleCallArgs;
|
||||
use crate::ast::types::Range;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::define_violation;
|
||||
use crate::registry::Diagnostic;
|
||||
use crate::violations;
|
||||
use crate::violation::Violation;
|
||||
use ruff_macros::derive_message_formats;
|
||||
|
||||
define_violation!(
|
||||
pub struct FailWithoutMessage;
|
||||
);
|
||||
impl Violation for FailWithoutMessage {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("No message passed to `pytest.fail()`")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fail_call(checker: &mut Checker, call: &Expr, args: &[Expr], keywords: &[Keyword]) {
|
||||
if is_pytest_fail(call, checker) {
|
||||
|
@ -15,13 +27,13 @@ pub fn fail_call(checker: &mut Checker, call: &Expr, args: &[Expr], keywords: &[
|
|||
if let Some(msg) = msg {
|
||||
if is_empty_or_null_string(msg) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
violations::FailWithoutMessage,
|
||||
FailWithoutMessage,
|
||||
Range::from_located(call),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
violations::FailWithoutMessage,
|
||||
FailWithoutMessage,
|
||||
Range::from_located(call),
|
||||
));
|
||||
}
|
||||
|
|
|
@ -1,8 +1,20 @@
|
|||
use rustpython_ast::Stmt;
|
||||
|
||||
use crate::ast::types::Range;
|
||||
use crate::define_violation;
|
||||
use crate::registry::Diagnostic;
|
||||
use crate::violations;
|
||||
use crate::violation::Violation;
|
||||
use ruff_macros::derive_message_formats;
|
||||
|
||||
define_violation!(
|
||||
pub struct IncorrectPytestImport;
|
||||
);
|
||||
impl Violation for IncorrectPytestImport {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Found incorrect import of pytest, use simple `import pytest` instead")
|
||||
}
|
||||
}
|
||||
|
||||
fn is_pytest_or_subpackage(imported_name: &str) -> bool {
|
||||
imported_name == "pytest" || imported_name.starts_with("pytest.")
|
||||
|
@ -14,7 +26,7 @@ pub fn import(import_from: &Stmt, name: &str, asname: Option<&str>) -> Option<Di
|
|||
if let Some(alias) = asname {
|
||||
if alias != name {
|
||||
return Some(Diagnostic::new(
|
||||
violations::IncorrectPytestImport,
|
||||
IncorrectPytestImport,
|
||||
Range::from_located(import_from),
|
||||
));
|
||||
}
|
||||
|
@ -39,7 +51,7 @@ pub fn import_from(
|
|||
if let Some(module) = module {
|
||||
if is_pytest_or_subpackage(module) {
|
||||
return Some(Diagnostic::new(
|
||||
violations::IncorrectPytestImport,
|
||||
IncorrectPytestImport,
|
||||
Range::from_located(import_from),
|
||||
));
|
||||
}
|
||||
|
|
|
@ -1,11 +1,52 @@
|
|||
use rustpython_ast::{Expr, ExprKind, Location};
|
||||
|
||||
use super::helpers::{get_mark_decorators, get_mark_name};
|
||||
use crate::ast::types::Range;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::define_violation;
|
||||
use crate::fix::Fix;
|
||||
use crate::registry::{Diagnostic, Rule};
|
||||
use crate::violations;
|
||||
use crate::violation::AlwaysAutofixableViolation;
|
||||
use ruff_macros::derive_message_formats;
|
||||
use rustpython_ast::{Expr, ExprKind, Location};
|
||||
|
||||
define_violation!(
|
||||
pub struct IncorrectMarkParenthesesStyle {
|
||||
pub mark_name: String,
|
||||
pub expected_parens: String,
|
||||
pub actual_parens: String,
|
||||
}
|
||||
);
|
||||
impl AlwaysAutofixableViolation for IncorrectMarkParenthesesStyle {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let IncorrectMarkParenthesesStyle {
|
||||
mark_name,
|
||||
expected_parens,
|
||||
actual_parens,
|
||||
} = self;
|
||||
format!(
|
||||
"Use `@pytest.mark.{mark_name}{expected_parens}` over \
|
||||
`@pytest.mark.{mark_name}{actual_parens}`"
|
||||
)
|
||||
}
|
||||
|
||||
fn autofix_title(&self) -> String {
|
||||
"Add/remove parentheses".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct UseFixturesWithoutParameters;
|
||||
);
|
||||
impl AlwaysAutofixableViolation for UseFixturesWithoutParameters {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Useless `pytest.mark.usefixtures` without parameters")
|
||||
}
|
||||
|
||||
fn autofix_title(&self) -> String {
|
||||
"Remove `usefixtures` decorator or pass parameters".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
fn pytest_mark_parentheses(
|
||||
checker: &mut Checker,
|
||||
|
@ -15,7 +56,7 @@ fn pytest_mark_parentheses(
|
|||
actual: &str,
|
||||
) {
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
violations::IncorrectMarkParenthesesStyle {
|
||||
IncorrectMarkParenthesesStyle {
|
||||
mark_name: get_mark_name(decorator).to_string(),
|
||||
expected_parens: preferred.to_string(),
|
||||
actual_parens: actual.to_string(),
|
||||
|
@ -68,10 +109,8 @@ fn check_useless_usefixtures(checker: &mut Checker, decorator: &Expr) {
|
|||
}
|
||||
|
||||
if !has_parameters {
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
violations::UseFixturesWithoutParameters,
|
||||
Range::from_located(decorator),
|
||||
);
|
||||
let mut diagnostic =
|
||||
Diagnostic::new(UseFixturesWithoutParameters, Range::from_located(decorator));
|
||||
if checker.patch(diagnostic.kind.rule()) {
|
||||
let at_start = Location::new(decorator.location.row(), decorator.location.column() - 1);
|
||||
diagnostic.amend(Fix::deletion(at_start, decorator.end_location.unwrap()));
|
||||
|
|
|
@ -1,18 +1,22 @@
|
|||
pub use assertion::{
|
||||
assert_falsy, assert_in_exception_handler, composite_condition, unittest_assertion,
|
||||
AssertAlwaysFalse, AssertInExcept, CompositeAssertion, UnittestAssertion,
|
||||
};
|
||||
pub use fail::fail_call;
|
||||
pub use fail::{fail_call, FailWithoutMessage};
|
||||
pub use fixture::{
|
||||
fixture, DeprecatedYieldFixture, ErroneousUseFixturesOnFixture, ExtraneousScopeFunction,
|
||||
FixtureFinalizerCallback, FixtureParamWithoutValue, FixturePositionalArgs,
|
||||
IncorrectFixtureNameUnderscore, IncorrectFixtureParenthesesStyle, MissingFixtureNameUnderscore,
|
||||
UnnecessaryAsyncioMarkOnFixture, UselessYieldFixture,
|
||||
};
|
||||
pub use imports::{import, import_from};
|
||||
pub use marks::marks;
|
||||
pub use parametrize::parametrize;
|
||||
pub use patch::patch_with_lambda;
|
||||
pub use raises::{complex_raises, raises_call};
|
||||
pub use imports::{import, import_from, IncorrectPytestImport};
|
||||
pub use marks::{marks, IncorrectMarkParenthesesStyle, UseFixturesWithoutParameters};
|
||||
pub use parametrize::{parametrize, ParametrizeNamesWrongType, ParametrizeValuesWrongType};
|
||||
pub use patch::{patch_with_lambda, PatchWithLambda};
|
||||
pub use raises::{
|
||||
complex_raises, raises_call, RaisesTooBroad, RaisesWithMultipleStatements,
|
||||
RaisesWithoutException,
|
||||
};
|
||||
|
||||
mod assertion;
|
||||
mod fail;
|
||||
|
|
|
@ -1,14 +1,47 @@
|
|||
use rustpython_ast::{Constant, Expr, ExprContext, ExprKind};
|
||||
|
||||
use super::super::types;
|
||||
use super::helpers::{is_pytest_parametrize, split_names};
|
||||
use crate::ast::helpers::{create_expr, unparse_expr};
|
||||
use crate::ast::types::Range;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::define_violation;
|
||||
use crate::fix::Fix;
|
||||
use crate::registry::{Diagnostic, Rule};
|
||||
use crate::source_code::Generator;
|
||||
use crate::violations;
|
||||
use crate::violation::{AlwaysAutofixableViolation, Violation};
|
||||
use ruff_macros::derive_message_formats;
|
||||
use rustpython_ast::{Constant, Expr, ExprContext, ExprKind};
|
||||
|
||||
define_violation!(
|
||||
pub struct ParametrizeNamesWrongType {
|
||||
pub expected: types::ParametrizeNameType,
|
||||
}
|
||||
);
|
||||
impl AlwaysAutofixableViolation for ParametrizeNamesWrongType {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let ParametrizeNamesWrongType { expected } = self;
|
||||
format!("Wrong name(s) type in `@pytest.mark.parametrize`, expected `{expected}`")
|
||||
}
|
||||
|
||||
fn autofix_title(&self) -> String {
|
||||
let ParametrizeNamesWrongType { expected } = self;
|
||||
format!("Use a `{expected}` for parameter names")
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct ParametrizeValuesWrongType {
|
||||
pub values: types::ParametrizeValuesType,
|
||||
pub row: types::ParametrizeValuesRowType,
|
||||
}
|
||||
);
|
||||
impl Violation for ParametrizeValuesWrongType {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let ParametrizeValuesWrongType { values, row } = self;
|
||||
format!("Wrong values type in `@pytest.mark.parametrize` expected `{values}` of `{row}`")
|
||||
}
|
||||
}
|
||||
|
||||
fn get_parametrize_decorator<'a>(checker: &Checker, decorators: &'a [Expr]) -> Option<&'a Expr> {
|
||||
decorators
|
||||
|
@ -66,7 +99,7 @@ fn check_names(checker: &mut Checker, expr: &Expr) {
|
|||
match names_type {
|
||||
types::ParametrizeNameType::Tuple => {
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
violations::ParametrizeNamesWrongType {
|
||||
ParametrizeNamesWrongType {
|
||||
expected: names_type,
|
||||
},
|
||||
Range::from_located(expr),
|
||||
|
@ -98,7 +131,7 @@ fn check_names(checker: &mut Checker, expr: &Expr) {
|
|||
}
|
||||
types::ParametrizeNameType::List => {
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
violations::ParametrizeNamesWrongType {
|
||||
ParametrizeNamesWrongType {
|
||||
expected: names_type,
|
||||
},
|
||||
Range::from_located(expr),
|
||||
|
@ -140,7 +173,7 @@ fn check_names(checker: &mut Checker, expr: &Expr) {
|
|||
types::ParametrizeNameType::Tuple => {}
|
||||
types::ParametrizeNameType::List => {
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
violations::ParametrizeNamesWrongType {
|
||||
ParametrizeNamesWrongType {
|
||||
expected: names_type,
|
||||
},
|
||||
Range::from_located(expr),
|
||||
|
@ -162,7 +195,7 @@ fn check_names(checker: &mut Checker, expr: &Expr) {
|
|||
}
|
||||
types::ParametrizeNameType::Csv => {
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
violations::ParametrizeNamesWrongType {
|
||||
ParametrizeNamesWrongType {
|
||||
expected: names_type,
|
||||
},
|
||||
Range::from_located(expr),
|
||||
|
@ -191,7 +224,7 @@ fn check_names(checker: &mut Checker, expr: &Expr) {
|
|||
types::ParametrizeNameType::List => {}
|
||||
types::ParametrizeNameType::Tuple => {
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
violations::ParametrizeNamesWrongType {
|
||||
ParametrizeNamesWrongType {
|
||||
expected: names_type,
|
||||
},
|
||||
Range::from_located(expr),
|
||||
|
@ -215,7 +248,7 @@ fn check_names(checker: &mut Checker, expr: &Expr) {
|
|||
}
|
||||
types::ParametrizeNameType::Csv => {
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
violations::ParametrizeNamesWrongType {
|
||||
ParametrizeNamesWrongType {
|
||||
expected: names_type,
|
||||
},
|
||||
Range::from_located(expr),
|
||||
|
@ -261,7 +294,7 @@ fn check_values(checker: &mut Checker, names: &Expr, values: &Expr) {
|
|||
ExprKind::List { elts, .. } => {
|
||||
if values_type != types::ParametrizeValuesType::List {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
violations::ParametrizeValuesWrongType {
|
||||
ParametrizeValuesWrongType {
|
||||
values: values_type,
|
||||
row: values_row_type,
|
||||
},
|
||||
|
@ -275,7 +308,7 @@ fn check_values(checker: &mut Checker, names: &Expr, values: &Expr) {
|
|||
ExprKind::Tuple { elts, .. } => {
|
||||
if values_type != types::ParametrizeValuesType::Tuple {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
violations::ParametrizeValuesWrongType {
|
||||
ParametrizeValuesWrongType {
|
||||
values: values_type,
|
||||
row: values_row_type,
|
||||
},
|
||||
|
@ -292,7 +325,7 @@ fn check_values(checker: &mut Checker, names: &Expr, values: &Expr) {
|
|||
|
||||
fn handle_single_name(checker: &mut Checker, expr: &Expr, value: &Expr) {
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
violations::ParametrizeNamesWrongType {
|
||||
ParametrizeNamesWrongType {
|
||||
expected: types::ParametrizeNameType::Csv,
|
||||
},
|
||||
Range::from_located(expr),
|
||||
|
@ -319,7 +352,7 @@ fn handle_value_rows(
|
|||
ExprKind::Tuple { .. } => {
|
||||
if values_row_type != types::ParametrizeValuesRowType::Tuple {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
violations::ParametrizeValuesWrongType {
|
||||
ParametrizeValuesWrongType {
|
||||
values: values_type,
|
||||
row: values_row_type,
|
||||
},
|
||||
|
@ -330,7 +363,7 @@ fn handle_value_rows(
|
|||
ExprKind::List { .. } => {
|
||||
if values_row_type != types::ParametrizeValuesRowType::List {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
violations::ParametrizeValuesWrongType {
|
||||
ParametrizeValuesWrongType {
|
||||
values: values_type,
|
||||
row: values_row_type,
|
||||
},
|
||||
|
|
|
@ -5,8 +5,20 @@ use crate::ast::helpers::{collect_arg_names, compose_call_path, SimpleCallArgs};
|
|||
use crate::ast::types::Range;
|
||||
use crate::ast::visitor;
|
||||
use crate::ast::visitor::Visitor;
|
||||
use crate::define_violation;
|
||||
use crate::registry::Diagnostic;
|
||||
use crate::violations;
|
||||
use crate::violation::Violation;
|
||||
use ruff_macros::derive_message_formats;
|
||||
|
||||
define_violation!(
|
||||
pub struct PatchWithLambda;
|
||||
);
|
||||
impl Violation for PatchWithLambda {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Use `return_value=` instead of patching with `lambda`")
|
||||
}
|
||||
}
|
||||
|
||||
const PATCH_NAMES: &[&str] = &[
|
||||
"mocker.patch",
|
||||
|
@ -72,10 +84,7 @@ fn check_patch_call(
|
|||
visitor.visit_expr(body);
|
||||
|
||||
if !visitor.uses_args {
|
||||
return Some(Diagnostic::new(
|
||||
violations::PatchWithLambda,
|
||||
Range::from_located(call),
|
||||
));
|
||||
return Some(Diagnostic::new(PatchWithLambda, Range::from_located(call)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,46 @@ use super::helpers::is_empty_or_null_string;
|
|||
use crate::ast::helpers::{format_call_path, to_call_path};
|
||||
use crate::ast::types::Range;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::define_violation;
|
||||
use crate::registry::{Diagnostic, Rule};
|
||||
use crate::violations;
|
||||
use crate::violation::Violation;
|
||||
use ruff_macros::derive_message_formats;
|
||||
|
||||
define_violation!(
|
||||
pub struct RaisesWithMultipleStatements;
|
||||
);
|
||||
impl Violation for RaisesWithMultipleStatements {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("`pytest.raises()` block should contain a single simple statement")
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct RaisesTooBroad {
|
||||
pub exception: String,
|
||||
}
|
||||
);
|
||||
impl Violation for RaisesTooBroad {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let RaisesTooBroad { exception } = self;
|
||||
format!(
|
||||
"`pytest.raises({exception})` is too broad, set the `match` parameter or use a more \
|
||||
specific exception"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct RaisesWithoutException;
|
||||
);
|
||||
impl Violation for RaisesWithoutException {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("set the expected exception in `pytest.raises()`")
|
||||
}
|
||||
}
|
||||
|
||||
fn is_pytest_raises(checker: &Checker, func: &Expr) -> bool {
|
||||
checker.resolve_call_path(func).map_or(false, |call_path| {
|
||||
|
@ -32,7 +70,7 @@ pub fn raises_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords:
|
|||
{
|
||||
if args.is_empty() && keywords.is_empty() {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
violations::RaisesWithoutException,
|
||||
RaisesWithoutException,
|
||||
Range::from_located(func),
|
||||
));
|
||||
}
|
||||
|
@ -88,7 +126,7 @@ pub fn complex_raises(checker: &mut Checker, stmt: &Stmt, items: &[Withitem], bo
|
|||
|
||||
if is_too_complex {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
violations::RaisesWithMultipleStatements,
|
||||
RaisesWithMultipleStatements,
|
||||
Range::from_located(stmt),
|
||||
));
|
||||
}
|
||||
|
@ -117,7 +155,7 @@ fn exception_needs_match(checker: &mut Checker, exception: &Expr) {
|
|||
}
|
||||
}) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
violations::RaisesTooBroad {
|
||||
RaisesTooBroad {
|
||||
exception: call_path,
|
||||
},
|
||||
Range::from_located(exception),
|
||||
|
|
|
@ -8,9 +8,6 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use crate::define_violation;
|
||||
use crate::rules::flake8_debugger::types::DebuggerUsingType;
|
||||
use crate::rules::flake8_pytest_style::types::{
|
||||
ParametrizeNameType, ParametrizeValuesRowType, ParametrizeValuesType,
|
||||
};
|
||||
use crate::rules::pyupgrade::types::Primitive;
|
||||
use crate::violation::{AlwaysAutofixableViolation, AutofixKind, Availability, Violation};
|
||||
|
||||
|
@ -3761,199 +3758,6 @@ impl Violation for DotFormatInException {
|
|||
}
|
||||
}
|
||||
|
||||
// flake8-pytest-style
|
||||
|
||||
define_violation!(
|
||||
pub struct ParametrizeNamesWrongType {
|
||||
pub expected: ParametrizeNameType,
|
||||
}
|
||||
);
|
||||
impl AlwaysAutofixableViolation for ParametrizeNamesWrongType {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let ParametrizeNamesWrongType { expected } = self;
|
||||
format!("Wrong name(s) type in `@pytest.mark.parametrize`, expected `{expected}`")
|
||||
}
|
||||
|
||||
fn autofix_title(&self) -> String {
|
||||
let ParametrizeNamesWrongType { expected } = self;
|
||||
format!("Use a `{expected}` for parameter names")
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct ParametrizeValuesWrongType {
|
||||
pub values: ParametrizeValuesType,
|
||||
pub row: ParametrizeValuesRowType,
|
||||
}
|
||||
);
|
||||
impl Violation for ParametrizeValuesWrongType {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let ParametrizeValuesWrongType { values, row } = self;
|
||||
format!("Wrong values type in `@pytest.mark.parametrize` expected `{values}` of `{row}`")
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct PatchWithLambda;
|
||||
);
|
||||
impl Violation for PatchWithLambda {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Use `return_value=` instead of patching with `lambda`")
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct UnittestAssertion {
|
||||
pub assertion: String,
|
||||
}
|
||||
);
|
||||
impl AlwaysAutofixableViolation for UnittestAssertion {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let UnittestAssertion { assertion } = self;
|
||||
format!("Use a regular `assert` instead of unittest-style `{assertion}`")
|
||||
}
|
||||
|
||||
fn autofix_title(&self) -> String {
|
||||
let UnittestAssertion { assertion } = self;
|
||||
format!("Replace `{assertion}(...)` with `assert ...`")
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct RaisesWithoutException;
|
||||
);
|
||||
impl Violation for RaisesWithoutException {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("set the expected exception in `pytest.raises()`")
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct RaisesTooBroad {
|
||||
pub exception: String,
|
||||
}
|
||||
);
|
||||
impl Violation for RaisesTooBroad {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let RaisesTooBroad { exception } = self;
|
||||
format!(
|
||||
"`pytest.raises({exception})` is too broad, set the `match` parameter or use a more \
|
||||
specific exception"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct RaisesWithMultipleStatements;
|
||||
);
|
||||
impl Violation for RaisesWithMultipleStatements {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("`pytest.raises()` block should contain a single simple statement")
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct IncorrectPytestImport;
|
||||
);
|
||||
impl Violation for IncorrectPytestImport {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Found incorrect import of pytest, use simple `import pytest` instead")
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct AssertAlwaysFalse;
|
||||
);
|
||||
impl Violation for AssertAlwaysFalse {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Assertion always fails, replace with `pytest.fail()`")
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct FailWithoutMessage;
|
||||
);
|
||||
impl Violation for FailWithoutMessage {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("No message passed to `pytest.fail()`")
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct AssertInExcept {
|
||||
pub name: String,
|
||||
}
|
||||
);
|
||||
impl Violation for AssertInExcept {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let AssertInExcept { name } = self;
|
||||
format!(
|
||||
"Found assertion on exception `{name}` in except block, use `pytest.raises()` instead"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct CompositeAssertion;
|
||||
);
|
||||
impl Violation for CompositeAssertion {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Assertion should be broken down into multiple parts")
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct IncorrectMarkParenthesesStyle {
|
||||
pub mark_name: String,
|
||||
pub expected_parens: String,
|
||||
pub actual_parens: String,
|
||||
}
|
||||
);
|
||||
impl AlwaysAutofixableViolation for IncorrectMarkParenthesesStyle {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let IncorrectMarkParenthesesStyle {
|
||||
mark_name,
|
||||
expected_parens,
|
||||
actual_parens,
|
||||
} = self;
|
||||
format!(
|
||||
"Use `@pytest.mark.{mark_name}{expected_parens}` over \
|
||||
`@pytest.mark.{mark_name}{actual_parens}`"
|
||||
)
|
||||
}
|
||||
|
||||
fn autofix_title(&self) -> String {
|
||||
"Add/remove parentheses".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
define_violation!(
|
||||
pub struct UseFixturesWithoutParameters;
|
||||
);
|
||||
impl AlwaysAutofixableViolation for UseFixturesWithoutParameters {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Useless `pytest.mark.usefixtures` without parameters")
|
||||
}
|
||||
|
||||
fn autofix_title(&self) -> String {
|
||||
"Remove `usefixtures` decorator or pass parameters".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
// ruff
|
||||
|
||||
define_violation!(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue