mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-02 09:52:18 +00:00
refactor: use remove_argument helper in pyupgrade
This commit is contained in:
parent
d76a47d366
commit
63fc912ed8
9 changed files with 521 additions and 271 deletions
|
@ -14,3 +14,60 @@ def ok_other_scope():
|
||||||
@pytest.fixture(scope="function")
|
@pytest.fixture(scope="function")
|
||||||
def error():
|
def error():
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="function", name="my_fixture")
|
||||||
|
def error_multiple_args():
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="my_fixture", scope="function")
|
||||||
|
def error_multiple_args():
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="my_fixture", scope="function", **kwargs)
|
||||||
|
def error_second_arg():
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
# pytest.fixture does not take positional arguments, however this
|
||||||
|
# tests the general case as we use a helper function that should
|
||||||
|
# work for all cases.
|
||||||
|
@pytest.fixture("my_fixture", scope="function")
|
||||||
|
def error_arg():
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(
|
||||||
|
scope="function",
|
||||||
|
name="my_fixture",
|
||||||
|
)
|
||||||
|
def error_multiple_args():
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(
|
||||||
|
name="my_fixture",
|
||||||
|
scope="function",
|
||||||
|
)
|
||||||
|
def error_multiple_args():
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(
|
||||||
|
"hello",
|
||||||
|
name,
|
||||||
|
*args
|
||||||
|
,
|
||||||
|
|
||||||
|
# another comment ,)
|
||||||
|
|
||||||
|
scope=\
|
||||||
|
"function" # some comment ),
|
||||||
|
,
|
||||||
|
|
||||||
|
name2=name, name3="my_fixture", **kwargs
|
||||||
|
)
|
||||||
|
def error_multiple_args():
|
||||||
|
...
|
||||||
|
|
|
@ -3,7 +3,9 @@ use itertools::Itertools;
|
||||||
use libcst_native::{
|
use libcst_native::{
|
||||||
Codegen, CodegenState, ImportNames, ParenthesizableWhitespace, SmallStatement, Statement,
|
Codegen, CodegenState, ImportNames, ParenthesizableWhitespace, SmallStatement, Statement,
|
||||||
};
|
};
|
||||||
use rustpython_parser::ast::{ExcepthandlerKind, Location, Stmt, StmtKind};
|
use rustpython_parser::ast::{ExcepthandlerKind, Expr, Keyword, Location, Stmt, StmtKind};
|
||||||
|
use rustpython_parser::lexer;
|
||||||
|
use rustpython_parser::lexer::Tok;
|
||||||
|
|
||||||
use crate::ast::helpers;
|
use crate::ast::helpers;
|
||||||
use crate::ast::helpers::to_absolute;
|
use crate::ast::helpers::to_absolute;
|
||||||
|
@ -321,6 +323,108 @@ pub fn remove_unused_imports<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generic function te remove (keyword)arguments in function calls
|
||||||
|
/// and class definitions. (For classes `args` should be considered `bases`)
|
||||||
|
///
|
||||||
|
/// Supports the removal of parentheses when this is the only (kw)arg left.
|
||||||
|
/// For this behaviour set `remove_parentheses` to `true`.
|
||||||
|
pub fn remove_argument(
|
||||||
|
locator: &Locator,
|
||||||
|
stmt_at: Location,
|
||||||
|
expr_at: Location,
|
||||||
|
expr_end: Location,
|
||||||
|
args: &[Expr],
|
||||||
|
keywords: &[Keyword],
|
||||||
|
remove_parentheses: bool,
|
||||||
|
) -> Result<Fix> {
|
||||||
|
// TODO: preserve trailing comments
|
||||||
|
let contents = locator.slice_source_code_at(stmt_at);
|
||||||
|
|
||||||
|
let mut fix_start = None;
|
||||||
|
let mut fix_end = None;
|
||||||
|
|
||||||
|
let n_keywords = keywords.len() + args.len();
|
||||||
|
if n_keywords == 0 {
|
||||||
|
bail!("No arguments or keywords to remove");
|
||||||
|
}
|
||||||
|
|
||||||
|
if n_keywords == 1 {
|
||||||
|
// Case 1: there is only one argument.
|
||||||
|
let mut count: usize = 0;
|
||||||
|
for (start, tok, end) in lexer::make_tokenizer_located(contents, stmt_at).flatten() {
|
||||||
|
if matches!(tok, Tok::Lpar) {
|
||||||
|
if count == 0 {
|
||||||
|
fix_start = Some(if remove_parentheses {
|
||||||
|
start
|
||||||
|
} else {
|
||||||
|
Location::new(start.row(), start.column() + 1)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches!(tok, Tok::Rpar) {
|
||||||
|
count -= 1;
|
||||||
|
if count == 0 {
|
||||||
|
fix_end = Some(if remove_parentheses {
|
||||||
|
end
|
||||||
|
} else {
|
||||||
|
Location::new(end.row(), end.column() - 1)
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if args
|
||||||
|
.iter()
|
||||||
|
.map(|node| node.location)
|
||||||
|
.chain(keywords.iter().map(|node| node.location))
|
||||||
|
.any(|location| location > expr_at)
|
||||||
|
{
|
||||||
|
// Case 2: argument or keyword is _not_ the last node.
|
||||||
|
let mut seen_comma = false;
|
||||||
|
for (start, tok, end) in lexer::make_tokenizer_located(contents, stmt_at).flatten() {
|
||||||
|
if seen_comma {
|
||||||
|
if matches!(tok, Tok::NonLogicalNewline) {
|
||||||
|
// Also delete any non-logical newlines after the comma.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fix_end = Some(if matches!(tok, Tok::Newline) {
|
||||||
|
end
|
||||||
|
} else {
|
||||||
|
start
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if start == expr_at {
|
||||||
|
fix_start = Some(start);
|
||||||
|
}
|
||||||
|
if fix_start.is_some() && matches!(tok, Tok::Comma) {
|
||||||
|
seen_comma = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Case 3: argument or keyword is the last node, so we have to find the last
|
||||||
|
// comma in the stmt.
|
||||||
|
for (start, tok, _) in lexer::make_tokenizer_located(contents, stmt_at).flatten() {
|
||||||
|
if start == expr_at {
|
||||||
|
fix_end = Some(expr_end);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if matches!(tok, Tok::Comma) {
|
||||||
|
fix_start = Some(start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match (fix_start, fix_end) {
|
||||||
|
(Some(start), Some(end)) => Ok(Fix::deletion(start, end)),
|
||||||
|
_ => {
|
||||||
|
bail!("No fix could be constructed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
|
@ -386,11 +386,11 @@ ruff_macros::define_rule_mapping!(
|
||||||
EM102 => violations::FStringInException,
|
EM102 => violations::FStringInException,
|
||||||
EM103 => violations::DotFormatInException,
|
EM103 => violations::DotFormatInException,
|
||||||
// flake8-pytest-style
|
// flake8-pytest-style
|
||||||
PT001 => violations::IncorrectFixtureParenthesesStyle,
|
PT001 => rules::flake8_pytest_style::rules::IncorrectFixtureParenthesesStyle,
|
||||||
PT002 => violations::FixturePositionalArgs,
|
PT002 => rules::flake8_pytest_style::rules::FixturePositionalArgs,
|
||||||
PT003 => violations::ExtraneousScopeFunction,
|
PT003 => rules::flake8_pytest_style::rules::ExtraneousScopeFunction,
|
||||||
PT004 => violations::MissingFixtureNameUnderscore,
|
PT004 => rules::flake8_pytest_style::rules::MissingFixtureNameUnderscore,
|
||||||
PT005 => violations::IncorrectFixtureNameUnderscore,
|
PT005 => rules::flake8_pytest_style::rules::IncorrectFixtureNameUnderscore,
|
||||||
PT006 => violations::ParametrizeNamesWrongType,
|
PT006 => violations::ParametrizeNamesWrongType,
|
||||||
PT007 => violations::ParametrizeValuesWrongType,
|
PT007 => violations::ParametrizeValuesWrongType,
|
||||||
PT008 => violations::PatchWithLambda,
|
PT008 => violations::PatchWithLambda,
|
||||||
|
@ -403,13 +403,13 @@ ruff_macros::define_rule_mapping!(
|
||||||
PT016 => violations::FailWithoutMessage,
|
PT016 => violations::FailWithoutMessage,
|
||||||
PT017 => violations::AssertInExcept,
|
PT017 => violations::AssertInExcept,
|
||||||
PT018 => violations::CompositeAssertion,
|
PT018 => violations::CompositeAssertion,
|
||||||
PT019 => violations::FixtureParamWithoutValue,
|
PT019 => rules::flake8_pytest_style::rules::FixtureParamWithoutValue,
|
||||||
PT020 => violations::DeprecatedYieldFixture,
|
PT020 => rules::flake8_pytest_style::rules::DeprecatedYieldFixture,
|
||||||
PT021 => violations::FixtureFinalizerCallback,
|
PT021 => rules::flake8_pytest_style::rules::FixtureFinalizerCallback,
|
||||||
PT022 => violations::UselessYieldFixture,
|
PT022 => rules::flake8_pytest_style::rules::UselessYieldFixture,
|
||||||
PT023 => violations::IncorrectMarkParenthesesStyle,
|
PT023 => violations::IncorrectMarkParenthesesStyle,
|
||||||
PT024 => violations::UnnecessaryAsyncioMarkOnFixture,
|
PT024 => rules::flake8_pytest_style::rules::UnnecessaryAsyncioMarkOnFixture,
|
||||||
PT025 => violations::ErroneousUseFixturesOnFixture,
|
PT025 => rules::flake8_pytest_style::rules::ErroneousUseFixturesOnFixture,
|
||||||
PT026 => violations::UseFixturesWithoutParameters,
|
PT026 => violations::UseFixturesWithoutParameters,
|
||||||
// flake8-pie
|
// flake8-pie
|
||||||
PIE790 => rules::flake8_pie::rules::NoUnnecessaryPass,
|
PIE790 => rules::flake8_pie::rules::NoUnnecessaryPass,
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use rustpython_ast::{Arguments, Expr, ExprKind, Location, Stmt, StmtKind};
|
use anyhow::Result;
|
||||||
|
use log::error;
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
use rustpython_ast::{Arguments, Expr, ExprKind, Keyword, Location, Stmt, StmtKind};
|
||||||
|
|
||||||
use super::helpers::{
|
use super::helpers::{
|
||||||
get_mark_decorators, get_mark_name, is_abstractmethod_decorator, is_pytest_fixture,
|
get_mark_decorators, get_mark_name, is_abstractmethod_decorator, is_pytest_fixture,
|
||||||
|
@ -8,10 +11,164 @@ use crate::ast::helpers::{collect_arg_names, collect_call_path};
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::ast::visitor;
|
use crate::ast::visitor;
|
||||||
use crate::ast::visitor::Visitor;
|
use crate::ast::visitor::Visitor;
|
||||||
|
use crate::autofix::helpers::remove_argument;
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
use crate::fix::Fix;
|
use crate::fix::Fix;
|
||||||
use crate::registry::{Diagnostic, Rule};
|
use crate::registry::{Diagnostic, Rule};
|
||||||
use crate::violations;
|
use crate::source_code::Locator;
|
||||||
|
use crate::violation::{AlwaysAutofixableViolation, Violation};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct IncorrectFixtureParenthesesStyle {
|
||||||
|
pub expected_parens: String,
|
||||||
|
pub actual_parens: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
impl AlwaysAutofixableViolation for IncorrectFixtureParenthesesStyle {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
let IncorrectFixtureParenthesesStyle {
|
||||||
|
expected_parens,
|
||||||
|
actual_parens,
|
||||||
|
} = self;
|
||||||
|
format!("Use `@pytest.fixture{expected_parens}` over `@pytest.fixture{actual_parens}`")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn autofix_title(&self) -> String {
|
||||||
|
"Add/remove parentheses".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct FixturePositionalArgs {
|
||||||
|
pub function: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
impl Violation for FixturePositionalArgs {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
let FixturePositionalArgs { function } = self;
|
||||||
|
format!("Configuration for fixture `{function}` specified via positional args, use kwargs")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct ExtraneousScopeFunction;
|
||||||
|
);
|
||||||
|
impl Violation for ExtraneousScopeFunction {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
format!("`scope='function'` is implied in `@pytest.fixture()`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct MissingFixtureNameUnderscore {
|
||||||
|
pub function: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
impl Violation for MissingFixtureNameUnderscore {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
let MissingFixtureNameUnderscore { function } = self;
|
||||||
|
format!("Fixture `{function}` does not return anything, add leading underscore")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct IncorrectFixtureNameUnderscore {
|
||||||
|
pub function: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
impl Violation for IncorrectFixtureNameUnderscore {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
let IncorrectFixtureNameUnderscore { function } = self;
|
||||||
|
format!("Fixture `{function}` returns a value, remove leading underscore")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct FixtureParamWithoutValue {
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
impl Violation for FixtureParamWithoutValue {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
let FixtureParamWithoutValue { name } = self;
|
||||||
|
format!(
|
||||||
|
"Fixture `{name}` without value is injected as parameter, use \
|
||||||
|
`@pytest.mark.usefixtures` instead"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct DeprecatedYieldFixture;
|
||||||
|
);
|
||||||
|
impl Violation for DeprecatedYieldFixture {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
format!("`@pytest.yield_fixture` is deprecated, use `@pytest.fixture`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct FixtureFinalizerCallback;
|
||||||
|
);
|
||||||
|
impl Violation for FixtureFinalizerCallback {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
format!("Use `yield` instead of `request.addfinalizer`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UselessYieldFixture {
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
impl AlwaysAutofixableViolation for UselessYieldFixture {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
let UselessYieldFixture { name } = self;
|
||||||
|
format!("No teardown in fixture `{name}`, use `return` instead of `yield`")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn autofix_title(&self) -> String {
|
||||||
|
"Replace `yield` with `return`".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct ErroneousUseFixturesOnFixture;
|
||||||
|
);
|
||||||
|
impl AlwaysAutofixableViolation for ErroneousUseFixturesOnFixture {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
format!("`pytest.mark.usefixtures` has no effect on fixtures")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn autofix_title(&self) -> String {
|
||||||
|
"Remove `pytest.mark.usefixtures`".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UnnecessaryAsyncioMarkOnFixture;
|
||||||
|
);
|
||||||
|
impl AlwaysAutofixableViolation for UnnecessaryAsyncioMarkOnFixture {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
format!("`pytest.mark.asyncio` is unnecessary for fixtures")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn autofix_title(&self) -> String {
|
||||||
|
"Remove `pytest.mark.asyncio`".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
/// Visitor that skips functions
|
/// Visitor that skips functions
|
||||||
|
@ -80,7 +237,7 @@ fn pytest_fixture_parentheses(
|
||||||
actual: &str,
|
actual: &str,
|
||||||
) {
|
) {
|
||||||
let mut diagnostic = Diagnostic::new(
|
let mut diagnostic = Diagnostic::new(
|
||||||
violations::IncorrectFixtureParenthesesStyle {
|
IncorrectFixtureParenthesesStyle {
|
||||||
expected_parens: preferred.to_string(),
|
expected_parens: preferred.to_string(),
|
||||||
actual_parens: actual.to_string(),
|
actual_parens: actual.to_string(),
|
||||||
},
|
},
|
||||||
|
@ -92,6 +249,17 @@ fn pytest_fixture_parentheses(
|
||||||
checker.diagnostics.push(diagnostic);
|
checker.diagnostics.push(diagnostic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fix_extraneous_scope_function(
|
||||||
|
locator: &Locator,
|
||||||
|
stmt_at: Location,
|
||||||
|
expr_at: Location,
|
||||||
|
expr_end: Location,
|
||||||
|
args: &[Expr],
|
||||||
|
keywords: &[Keyword],
|
||||||
|
) -> Result<Fix> {
|
||||||
|
remove_argument(locator, stmt_at, expr_at, expr_end, args, keywords, false)
|
||||||
|
}
|
||||||
|
|
||||||
/// PT001, PT002, PT003
|
/// PT001, PT002, PT003
|
||||||
fn check_fixture_decorator(checker: &mut Checker, func_name: &str, decorator: &Expr) {
|
fn check_fixture_decorator(checker: &mut Checker, func_name: &str, decorator: &Expr) {
|
||||||
match &decorator.node {
|
match &decorator.node {
|
||||||
|
@ -116,7 +284,7 @@ fn check_fixture_decorator(checker: &mut Checker, func_name: &str, decorator: &E
|
||||||
|
|
||||||
if checker.settings.rules.enabled(&Rule::FixturePositionalArgs) && !args.is_empty() {
|
if checker.settings.rules.enabled(&Rule::FixturePositionalArgs) && !args.is_empty() {
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
violations::FixturePositionalArgs {
|
FixturePositionalArgs {
|
||||||
function: func_name.to_string(),
|
function: func_name.to_string(),
|
||||||
},
|
},
|
||||||
Range::from_located(decorator),
|
Range::from_located(decorator),
|
||||||
|
@ -134,10 +302,26 @@ fn check_fixture_decorator(checker: &mut Checker, func_name: &str, decorator: &E
|
||||||
|
|
||||||
if let Some(scope_keyword) = scope_keyword {
|
if let Some(scope_keyword) = scope_keyword {
|
||||||
if keyword_is_literal(scope_keyword, "function") {
|
if keyword_is_literal(scope_keyword, "function") {
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
let mut diagnostic = Diagnostic::new(
|
||||||
violations::ExtraneousScopeFunction,
|
ExtraneousScopeFunction,
|
||||||
Range::from_located(scope_keyword),
|
Range::from_located(scope_keyword),
|
||||||
));
|
);
|
||||||
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
|
match fix_extraneous_scope_function(
|
||||||
|
checker.locator,
|
||||||
|
decorator.location,
|
||||||
|
diagnostic.location,
|
||||||
|
diagnostic.end_location,
|
||||||
|
args,
|
||||||
|
keywords,
|
||||||
|
) {
|
||||||
|
Ok(fix) => {
|
||||||
|
diagnostic.amend(fix);
|
||||||
|
}
|
||||||
|
Err(e) => error!("Failed to generate fix: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checker.diagnostics.push(diagnostic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,7 +356,7 @@ fn check_fixture_returns(checker: &mut Checker, func: &Stmt, func_name: &str, bo
|
||||||
&& func_name.starts_with('_')
|
&& func_name.starts_with('_')
|
||||||
{
|
{
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
violations::IncorrectFixtureNameUnderscore {
|
IncorrectFixtureNameUnderscore {
|
||||||
function: func_name.to_string(),
|
function: func_name.to_string(),
|
||||||
},
|
},
|
||||||
Range::from_located(func),
|
Range::from_located(func),
|
||||||
|
@ -186,7 +370,7 @@ fn check_fixture_returns(checker: &mut Checker, func: &Stmt, func_name: &str, bo
|
||||||
&& !func_name.starts_with('_')
|
&& !func_name.starts_with('_')
|
||||||
{
|
{
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
violations::MissingFixtureNameUnderscore {
|
MissingFixtureNameUnderscore {
|
||||||
function: func_name.to_string(),
|
function: func_name.to_string(),
|
||||||
},
|
},
|
||||||
Range::from_located(func),
|
Range::from_located(func),
|
||||||
|
@ -199,7 +383,7 @@ fn check_fixture_returns(checker: &mut Checker, func: &Stmt, func_name: &str, bo
|
||||||
if let ExprKind::Yield { .. } = value.node {
|
if let ExprKind::Yield { .. } = value.node {
|
||||||
if visitor.yield_statements.len() == 1 {
|
if visitor.yield_statements.len() == 1 {
|
||||||
let mut diagnostic = Diagnostic::new(
|
let mut diagnostic = Diagnostic::new(
|
||||||
violations::UselessYieldFixture {
|
UselessYieldFixture {
|
||||||
name: func_name.to_string(),
|
name: func_name.to_string(),
|
||||||
},
|
},
|
||||||
Range::from_located(stmt),
|
Range::from_located(stmt),
|
||||||
|
@ -228,7 +412,7 @@ fn check_test_function_args(checker: &mut Checker, args: &Arguments) {
|
||||||
let name = &arg.node.arg;
|
let name = &arg.node.arg;
|
||||||
if name.starts_with('_') {
|
if name.starts_with('_') {
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
violations::FixtureParamWithoutValue {
|
FixtureParamWithoutValue {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
},
|
},
|
||||||
Range::from_located(arg),
|
Range::from_located(arg),
|
||||||
|
@ -241,7 +425,7 @@ fn check_test_function_args(checker: &mut Checker, args: &Arguments) {
|
||||||
fn check_fixture_decorator_name(checker: &mut Checker, decorator: &Expr) {
|
fn check_fixture_decorator_name(checker: &mut Checker, decorator: &Expr) {
|
||||||
if is_pytest_yield_fixture(decorator, checker) {
|
if is_pytest_yield_fixture(decorator, checker) {
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
violations::DeprecatedYieldFixture,
|
DeprecatedYieldFixture,
|
||||||
Range::from_located(decorator),
|
Range::from_located(decorator),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -261,7 +445,7 @@ fn check_fixture_addfinalizer(checker: &mut Checker, args: &Arguments, body: &[S
|
||||||
|
|
||||||
if let Some(addfinalizer) = visitor.addfinalizer_call {
|
if let Some(addfinalizer) = visitor.addfinalizer_call {
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
violations::FixtureFinalizerCallback,
|
FixtureFinalizerCallback,
|
||||||
Range::from_located(addfinalizer),
|
Range::from_located(addfinalizer),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -278,10 +462,8 @@ fn check_fixture_marks(checker: &mut Checker, decorators: &[Expr]) {
|
||||||
.enabled(&Rule::UnnecessaryAsyncioMarkOnFixture)
|
.enabled(&Rule::UnnecessaryAsyncioMarkOnFixture)
|
||||||
{
|
{
|
||||||
if name == "asyncio" {
|
if name == "asyncio" {
|
||||||
let mut diagnostic = Diagnostic::new(
|
let mut diagnostic =
|
||||||
violations::UnnecessaryAsyncioMarkOnFixture,
|
Diagnostic::new(UnnecessaryAsyncioMarkOnFixture, Range::from_located(mark));
|
||||||
Range::from_located(mark),
|
|
||||||
);
|
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
let start = Location::new(mark.location.row(), 0);
|
let start = Location::new(mark.location.row(), 0);
|
||||||
let end = Location::new(mark.end_location.unwrap().row() + 1, 0);
|
let end = Location::new(mark.end_location.unwrap().row() + 1, 0);
|
||||||
|
@ -297,10 +479,8 @@ fn check_fixture_marks(checker: &mut Checker, decorators: &[Expr]) {
|
||||||
.enabled(&Rule::ErroneousUseFixturesOnFixture)
|
.enabled(&Rule::ErroneousUseFixturesOnFixture)
|
||||||
{
|
{
|
||||||
if name == "usefixtures" {
|
if name == "usefixtures" {
|
||||||
let mut diagnostic = Diagnostic::new(
|
let mut diagnostic =
|
||||||
violations::ErroneousUseFixturesOnFixture,
|
Diagnostic::new(ErroneousUseFixturesOnFixture, Range::from_located(mark));
|
||||||
Range::from_located(mark),
|
|
||||||
);
|
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
let start = Location::new(mark.location.row(), 0);
|
let start = Location::new(mark.location.row(), 0);
|
||||||
let end = Location::new(mark.end_location.unwrap().row() + 1, 0);
|
let end = Location::new(mark.end_location.unwrap().row() + 1, 0);
|
||||||
|
|
|
@ -2,7 +2,12 @@ pub use assertion::{
|
||||||
assert_falsy, assert_in_exception_handler, composite_condition, unittest_assertion,
|
assert_falsy, assert_in_exception_handler, composite_condition, unittest_assertion,
|
||||||
};
|
};
|
||||||
pub use fail::fail_call;
|
pub use fail::fail_call;
|
||||||
pub use fixture::fixture;
|
pub use fixture::{
|
||||||
|
fixture, DeprecatedYieldFixture, ErroneousUseFixturesOnFixture, ExtraneousScopeFunction,
|
||||||
|
FixtureFinalizerCallback, FixtureParamWithoutValue, FixturePositionalArgs,
|
||||||
|
IncorrectFixtureNameUnderscore, IncorrectFixtureParenthesesStyle, MissingFixtureNameUnderscore,
|
||||||
|
UnnecessaryAsyncioMarkOnFixture, UselessYieldFixture,
|
||||||
|
};
|
||||||
pub use imports::{import, import_from};
|
pub use imports::{import, import_from};
|
||||||
pub use marks::marks;
|
pub use marks::marks;
|
||||||
pub use parametrize::parametrize;
|
pub use parametrize::parametrize;
|
||||||
|
|
|
@ -10,6 +10,140 @@ expression: diagnostics
|
||||||
end_location:
|
end_location:
|
||||||
row: 14
|
row: 14
|
||||||
column: 32
|
column: 32
|
||||||
fix: ~
|
fix:
|
||||||
|
content:
|
||||||
|
- ""
|
||||||
|
location:
|
||||||
|
row: 14
|
||||||
|
column: 16
|
||||||
|
end_location:
|
||||||
|
row: 14
|
||||||
|
column: 32
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
ExtraneousScopeFunction: ~
|
||||||
|
location:
|
||||||
|
row: 19
|
||||||
|
column: 16
|
||||||
|
end_location:
|
||||||
|
row: 19
|
||||||
|
column: 32
|
||||||
|
fix:
|
||||||
|
content:
|
||||||
|
- ""
|
||||||
|
location:
|
||||||
|
row: 19
|
||||||
|
column: 16
|
||||||
|
end_location:
|
||||||
|
row: 19
|
||||||
|
column: 34
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
ExtraneousScopeFunction: ~
|
||||||
|
location:
|
||||||
|
row: 24
|
||||||
|
column: 35
|
||||||
|
end_location:
|
||||||
|
row: 24
|
||||||
|
column: 51
|
||||||
|
fix:
|
||||||
|
content:
|
||||||
|
- ""
|
||||||
|
location:
|
||||||
|
row: 24
|
||||||
|
column: 33
|
||||||
|
end_location:
|
||||||
|
row: 24
|
||||||
|
column: 51
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
ExtraneousScopeFunction: ~
|
||||||
|
location:
|
||||||
|
row: 29
|
||||||
|
column: 35
|
||||||
|
end_location:
|
||||||
|
row: 29
|
||||||
|
column: 51
|
||||||
|
fix:
|
||||||
|
content:
|
||||||
|
- ""
|
||||||
|
location:
|
||||||
|
row: 29
|
||||||
|
column: 35
|
||||||
|
end_location:
|
||||||
|
row: 29
|
||||||
|
column: 53
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
ExtraneousScopeFunction: ~
|
||||||
|
location:
|
||||||
|
row: 37
|
||||||
|
column: 30
|
||||||
|
end_location:
|
||||||
|
row: 37
|
||||||
|
column: 46
|
||||||
|
fix:
|
||||||
|
content:
|
||||||
|
- ""
|
||||||
|
location:
|
||||||
|
row: 37
|
||||||
|
column: 28
|
||||||
|
end_location:
|
||||||
|
row: 37
|
||||||
|
column: 46
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
ExtraneousScopeFunction: ~
|
||||||
|
location:
|
||||||
|
row: 43
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 43
|
||||||
|
column: 20
|
||||||
|
fix:
|
||||||
|
content:
|
||||||
|
- ""
|
||||||
|
location:
|
||||||
|
row: 43
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 44
|
||||||
|
column: 4
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
ExtraneousScopeFunction: ~
|
||||||
|
location:
|
||||||
|
row: 52
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 52
|
||||||
|
column: 20
|
||||||
|
fix:
|
||||||
|
content:
|
||||||
|
- ""
|
||||||
|
location:
|
||||||
|
row: 51
|
||||||
|
column: 21
|
||||||
|
end_location:
|
||||||
|
row: 52
|
||||||
|
column: 20
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
ExtraneousScopeFunction: ~
|
||||||
|
location:
|
||||||
|
row: 66
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 67
|
||||||
|
column: 18
|
||||||
|
fix:
|
||||||
|
content:
|
||||||
|
- ""
|
||||||
|
location:
|
||||||
|
row: 66
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 70
|
||||||
|
column: 4
|
||||||
parent: ~
|
parent: ~
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,9 @@ use libcst_native::{
|
||||||
Codegen, CodegenState, Expression, ParenthesizableWhitespace, SmallStatement, Statement,
|
Codegen, CodegenState, Expression, ParenthesizableWhitespace, SmallStatement, Statement,
|
||||||
};
|
};
|
||||||
use rustpython_ast::{Expr, Keyword, Location};
|
use rustpython_ast::{Expr, Keyword, Location};
|
||||||
use rustpython_parser::lexer;
|
|
||||||
use rustpython_parser::lexer::Tok;
|
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
|
use crate::autofix::helpers::remove_argument;
|
||||||
use crate::fix::Fix;
|
use crate::fix::Fix;
|
||||||
use crate::source_code::{Locator, Stylist};
|
use crate::source_code::{Locator, Stylist};
|
||||||
|
|
||||||
|
@ -14,93 +13,14 @@ pub fn remove_class_def_base(
|
||||||
locator: &Locator,
|
locator: &Locator,
|
||||||
stmt_at: Location,
|
stmt_at: Location,
|
||||||
expr_at: Location,
|
expr_at: Location,
|
||||||
|
expr_end: Location,
|
||||||
bases: &[Expr],
|
bases: &[Expr],
|
||||||
keywords: &[Keyword],
|
keywords: &[Keyword],
|
||||||
) -> Option<Fix> {
|
) -> Option<Fix> {
|
||||||
let contents = locator.slice_source_code_at(stmt_at);
|
if let Ok(fix) = remove_argument(locator, stmt_at, expr_at, expr_end, bases, keywords, true) {
|
||||||
|
Some(fix)
|
||||||
// Case 1: `object` is the only base.
|
|
||||||
if bases.len() == 1 && keywords.is_empty() {
|
|
||||||
let mut fix_start = None;
|
|
||||||
let mut fix_end = None;
|
|
||||||
let mut count: usize = 0;
|
|
||||||
for (start, tok, end) in lexer::make_tokenizer_located(contents, stmt_at).flatten() {
|
|
||||||
if matches!(tok, Tok::Lpar) {
|
|
||||||
if count == 0 {
|
|
||||||
fix_start = Some(start);
|
|
||||||
}
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if matches!(tok, Tok::Rpar) {
|
|
||||||
count -= 1;
|
|
||||||
if count == 0 {
|
|
||||||
fix_end = Some(end);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return match (fix_start, fix_end) {
|
|
||||||
(Some(start), Some(end)) => Some(Fix::deletion(start, end)),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if bases
|
|
||||||
.iter()
|
|
||||||
.map(|node| node.location)
|
|
||||||
.chain(keywords.iter().map(|node| node.location))
|
|
||||||
.any(|location| location > expr_at)
|
|
||||||
{
|
|
||||||
// Case 2: `object` is _not_ the last node.
|
|
||||||
let mut fix_start: Option<Location> = None;
|
|
||||||
let mut fix_end: Option<Location> = None;
|
|
||||||
let mut seen_comma = false;
|
|
||||||
for (start, tok, end) in lexer::make_tokenizer_located(contents, stmt_at).flatten() {
|
|
||||||
if seen_comma {
|
|
||||||
if matches!(tok, Tok::NonLogicalNewline) {
|
|
||||||
// Also delete any non-logical newlines after the comma.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if matches!(tok, Tok::Newline) {
|
|
||||||
fix_end = Some(end);
|
|
||||||
} else {
|
|
||||||
fix_end = Some(start);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if start == expr_at {
|
|
||||||
fix_start = Some(start);
|
|
||||||
}
|
|
||||||
if fix_start.is_some() && matches!(tok, Tok::Comma) {
|
|
||||||
seen_comma = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match (fix_start, fix_end) {
|
|
||||||
(Some(start), Some(end)) => Some(Fix::deletion(start, end)),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Case 3: `object` is the last node, so we have to find the last token that
|
None
|
||||||
// isn't a comma.
|
|
||||||
let mut fix_start: Option<Location> = None;
|
|
||||||
let mut fix_end: Option<Location> = None;
|
|
||||||
for (start, tok, end) in lexer::make_tokenizer_located(contents, stmt_at).flatten() {
|
|
||||||
if start == expr_at {
|
|
||||||
fix_end = Some(end);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if matches!(tok, Tok::Comma) {
|
|
||||||
fix_start = Some(start);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match (fix_start, fix_end) {
|
|
||||||
(Some(start), Some(end)) => Some(Fix::deletion(start, end)),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ pub fn useless_object_inheritance(
|
||||||
checker.locator,
|
checker.locator,
|
||||||
stmt.location,
|
stmt.location,
|
||||||
diagnostic.location,
|
diagnostic.location,
|
||||||
|
diagnostic.end_location,
|
||||||
bases,
|
bases,
|
||||||
keywords,
|
keywords,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -4684,76 +4684,6 @@ impl Violation for DotFormatInException {
|
||||||
|
|
||||||
// flake8-pytest-style
|
// flake8-pytest-style
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct IncorrectFixtureParenthesesStyle {
|
|
||||||
pub expected_parens: String,
|
|
||||||
pub actual_parens: String,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
impl AlwaysAutofixableViolation for IncorrectFixtureParenthesesStyle {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
let IncorrectFixtureParenthesesStyle {
|
|
||||||
expected_parens,
|
|
||||||
actual_parens,
|
|
||||||
} = self;
|
|
||||||
format!("Use `@pytest.fixture{expected_parens}` over `@pytest.fixture{actual_parens}`")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
|
||||||
"Add/remove parentheses".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct FixturePositionalArgs {
|
|
||||||
pub function: String,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
impl Violation for FixturePositionalArgs {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
let FixturePositionalArgs { function } = self;
|
|
||||||
format!("Configuration for fixture `{function}` specified via positional args, use kwargs")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct ExtraneousScopeFunction;
|
|
||||||
);
|
|
||||||
impl Violation for ExtraneousScopeFunction {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
format!("`scope='function'` is implied in `@pytest.fixture()`")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct MissingFixtureNameUnderscore {
|
|
||||||
pub function: String,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
impl Violation for MissingFixtureNameUnderscore {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
let MissingFixtureNameUnderscore { function } = self;
|
|
||||||
format!("Fixture `{function}` does not return anything, add leading underscore")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct IncorrectFixtureNameUnderscore {
|
|
||||||
pub function: String,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
impl Violation for IncorrectFixtureNameUnderscore {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
let IncorrectFixtureNameUnderscore { function } = self;
|
|
||||||
format!("Fixture `{function}` returns a value, remove leading underscore")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
pub struct ParametrizeNamesWrongType {
|
pub struct ParametrizeNamesWrongType {
|
||||||
pub expected: ParametrizeNameType,
|
pub expected: ParametrizeNameType,
|
||||||
|
@ -4905,59 +4835,6 @@ impl Violation for CompositeAssertion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct FixtureParamWithoutValue {
|
|
||||||
pub name: String,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
impl Violation for FixtureParamWithoutValue {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
let FixtureParamWithoutValue { name } = self;
|
|
||||||
format!(
|
|
||||||
"Fixture `{name}` without value is injected as parameter, use \
|
|
||||||
`@pytest.mark.usefixtures` instead"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct DeprecatedYieldFixture;
|
|
||||||
);
|
|
||||||
impl Violation for DeprecatedYieldFixture {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
format!("`@pytest.yield_fixture` is deprecated, use `@pytest.fixture`")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct FixtureFinalizerCallback;
|
|
||||||
);
|
|
||||||
impl Violation for FixtureFinalizerCallback {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
format!("Use `yield` instead of `request.addfinalizer`")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UselessYieldFixture {
|
|
||||||
pub name: String,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
impl AlwaysAutofixableViolation for UselessYieldFixture {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
let UselessYieldFixture { name } = self;
|
|
||||||
format!("No teardown in fixture `{name}`, use `return` instead of `yield`")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
|
||||||
"Replace `yield` with `return`".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
pub struct IncorrectMarkParenthesesStyle {
|
pub struct IncorrectMarkParenthesesStyle {
|
||||||
pub mark_name: String,
|
pub mark_name: String,
|
||||||
|
@ -4984,34 +4861,6 @@ impl AlwaysAutofixableViolation for IncorrectMarkParenthesesStyle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UnnecessaryAsyncioMarkOnFixture;
|
|
||||||
);
|
|
||||||
impl AlwaysAutofixableViolation for UnnecessaryAsyncioMarkOnFixture {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
format!("`pytest.mark.asyncio` is unnecessary for fixtures")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
|
||||||
"Remove `pytest.mark.asyncio`".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct ErroneousUseFixturesOnFixture;
|
|
||||||
);
|
|
||||||
impl AlwaysAutofixableViolation for ErroneousUseFixturesOnFixture {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
format!("`pytest.mark.usefixtures` has no effect on fixtures")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
|
||||||
"Remove `pytest.mark.usefixtures`".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
pub struct UseFixturesWithoutParameters;
|
pub struct UseFixturesWithoutParameters;
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue