mirror of https://github.com/astral-sh/ruff
Merge bc0ad6ec5a into b0bc990cbf
This commit is contained in:
commit
57287a8797
|
|
@ -1189,6 +1189,16 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
|||
(Flake8Logging, "014") => rules::flake8_logging::rules::ExcInfoOutsideExceptHandler,
|
||||
(Flake8Logging, "015") => rules::flake8_logging::rules::RootLoggerCall,
|
||||
|
||||
// flake8-mock-spec
|
||||
(Flake8MockSpec, "010") => (RuleGroup::Preview, rules::flake8_mock_spec::rules::Mock),
|
||||
(Flake8MockSpec, "011") => (RuleGroup::Preview, rules::flake8_mock_spec::rules::MagicMock),
|
||||
(Flake8MockSpec, "012") => (RuleGroup::Preview, rules::flake8_mock_spec::rules::NonCallableMock),
|
||||
(Flake8MockSpec, "013") => (RuleGroup::Preview, rules::flake8_mock_spec::rules::AsyncMock),
|
||||
(Flake8MockSpec, "014") => (RuleGroup::Preview, rules::flake8_mock_spec::rules::ThreadingMock),
|
||||
(Flake8MockSpec, "020") => (RuleGroup::Preview, rules::flake8_mock_spec::rules::Patch),
|
||||
(Flake8MockSpec, "021") => (RuleGroup::Preview, rules::flake8_mock_spec::rules::PatchObject),
|
||||
(Flake8MockSpec, "022") => (RuleGroup::Preview, rules::flake8_mock_spec::rules::PatchMultiple),
|
||||
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,6 +112,9 @@ pub enum Linter {
|
|||
/// [flake8-logging-format](https://pypi.org/project/flake8-logging-format/)
|
||||
#[prefix = "G"]
|
||||
Flake8LoggingFormat,
|
||||
/// [flake8-mock-spec](https://pypi.org/project/flake8-mock-spec/)
|
||||
#[prefix = "TMS"]
|
||||
Flake8MockSpec,
|
||||
/// [flake8-no-pep420](https://pypi.org/project/flake8-no-pep420/)
|
||||
#[prefix = "INP"]
|
||||
Flake8NoPep420,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
|
||||
use crate::Violation;
|
||||
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct AsyncMock;
|
||||
|
||||
impl Violation for AsyncMock {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"`unittest.mock.AsyncMock` without `spec` or `spec_set` argument".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn mock(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::UNITTEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
if checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(&call.func)
|
||||
.is_some_and(|qualified_name| {
|
||||
matches!(qualified_name.segments(), ["unittest", "mock", "AsyncMock"])
|
||||
})
|
||||
{
|
||||
if call.arguments.find_argument("spec", 0).is_none()
|
||||
&& call.arguments.find_keyword("spec_set").is_none()
|
||||
{
|
||||
let mut diagnostic = checker.report_diagnostic(AsyncMock, call.func.range());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
|
||||
use crate::Violation;
|
||||
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct MagicMock;
|
||||
|
||||
impl Violation for MagicMock {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"`unittest.mock.MagicMock` without `spec` or `spec_set` argument".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn mock(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::UNITTEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
if checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(&call.func)
|
||||
.is_some_and(|qualified_name| {
|
||||
matches!(qualified_name.segments(), ["unittest", "mock", "MagicMock"])
|
||||
})
|
||||
{
|
||||
if call.arguments.find_argument("spec", 0).is_none()
|
||||
&& call.arguments.find_keyword("spec_set").is_none()
|
||||
{
|
||||
let mut diagnostic = checker.report_diagnostic(MagicMock, call.func.range());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
|
||||
use crate::Violation;
|
||||
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct Mock;
|
||||
|
||||
impl Violation for Mock {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"`unittest.mock.Mock` without `spec` or `spec_set` argument".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn mock(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::UNITTEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
if checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(&call.func)
|
||||
.is_some_and(|qualified_name| {
|
||||
matches!(qualified_name.segments(), ["unittest", "mock", "Mock"])
|
||||
})
|
||||
{
|
||||
if call.arguments.find_argument("spec", 0).is_none()
|
||||
&& call.arguments.find_keyword("spec_set").is_none()
|
||||
{
|
||||
let mut diagnostic = checker.report_diagnostic(Mock, call.func.range());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
|
||||
use crate::Violation;
|
||||
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct NonCallableMock;
|
||||
|
||||
impl Violation for NonCallableMock {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"`unittest.mock.NonCallableMock` without `spec` or `spec_set` argument".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn mock(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::UNITTEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
if checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(&call.func)
|
||||
.is_some_and(|qualified_name| {
|
||||
matches!(qualified_name.segments(), ["unittest", "mock", "NonCallableMock"])
|
||||
})
|
||||
{
|
||||
if call.arguments.find_argument("spec", 0).is_none()
|
||||
&& call.arguments.find_keyword("spec_set").is_none()
|
||||
{
|
||||
let mut diagnostic = checker.report_diagnostic(NonCallableMock, call.func.range());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
|
||||
use crate::Violation;
|
||||
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct Patch;
|
||||
|
||||
impl Violation for Patch {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"`unittest.mock.patch` without one any `autospec`, `new`, `new_callable`, `spec` or `spec_set` argument".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn mock(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::UNITTEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
if checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(&call.func)
|
||||
.is_some_and(|qualified_name| {
|
||||
matches!(qualified_name.segments(), ["unittest", "mock", "patch"])
|
||||
})
|
||||
{
|
||||
if call.arguments.find_keyword("autospec").is_none()
|
||||
&& call.arguments.find_argument("new", 1).is_none()
|
||||
&& call.arguments.find_keyword("new_callable").is_none()
|
||||
&& call.arguments.find_keyword("spec").is_none()
|
||||
&& call.arguments.find_keyword("spec_set").is_none()
|
||||
{
|
||||
let mut diagnostic = checker.report_diagnostic(Patch, call.func.range());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
|
||||
use crate::Violation;
|
||||
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct PatchMultiple;
|
||||
|
||||
impl Violation for PatchMultiple {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"`unittest.mock.patch.multiple` without one any `autospec`, `new`, `new_callable`, `spec` or `spec_set` argument".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn mock(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::UNITTEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
if checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(&call.func)
|
||||
.is_some_and(|qualified_name| {
|
||||
matches!(qualified_name.segments(), ["unittest", "mock", "patch", "multiple"])
|
||||
})
|
||||
{
|
||||
if call.arguments.find_keyword("autospec").is_none()
|
||||
&& call.arguments.find_keyword("new_callable").is_none()
|
||||
&& call.arguments.find_argument("spec", 1).is_none()
|
||||
&& call.arguments.find_keyword("spec_set").is_none()
|
||||
{
|
||||
let mut diagnostic = checker.report_diagnostic(PatchMultiple, call.func.range());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
|
||||
use crate::Violation;
|
||||
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct PatchObject;
|
||||
|
||||
impl Violation for PatchObject {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"`unittest.mock.patch.object` without one any `autospec`, `new`, `new_callable`, `spec` or `spec_set` argument".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn mock(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::UNITTEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
if checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(&call.func)
|
||||
.is_some_and(|qualified_name| {
|
||||
matches!(qualified_name.segments(), ["unittest", "mock", "patch", "object"])
|
||||
})
|
||||
{
|
||||
if call.arguments.find_keyword("autospec").is_none()
|
||||
&& call.arguments.find_argument("new", 2).is_none()
|
||||
&& call.arguments.find_keyword("new_callable").is_none()
|
||||
&& call.arguments.find_keyword("spec").is_none()
|
||||
&& call.arguments.find_keyword("spec_set").is_none()
|
||||
{
|
||||
let mut diagnostic = checker.report_diagnostic(PatchObject, call.func.range());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
|
||||
use crate::Violation;
|
||||
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct ThreadingMock;
|
||||
|
||||
impl Violation for ThreadingMock {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"`unittest.mock.ThreadingMock` without `spec` or `spec_set` argument".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn mock(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::UNITTEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
if checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(&call.func)
|
||||
.is_some_and(|qualified_name| {
|
||||
matches!(qualified_name.segments(), ["unittest", "mock", "ThreadingMock"])
|
||||
})
|
||||
{
|
||||
if call.arguments.find_argument("spec", 0).is_none()
|
||||
&& call.arguments.find_keyword("spec_set").is_none()
|
||||
{
|
||||
let mut diagnostic = checker.report_diagnostic(ThreadingMock, call.func.range());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1486,6 +1486,7 @@ impl<'a> SemanticModel<'a> {
|
|||
"airflow" => self.seen.insert(Modules::AIRFLOW),
|
||||
"hashlib" => self.seen.insert(Modules::HASHLIB),
|
||||
"crypt" => self.seen.insert(Modules::CRYPT),
|
||||
"unittest" => self.seen.insert(Modules::UNITTEST),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -2254,6 +2255,7 @@ bitflags! {
|
|||
const AIRFLOW = 1 << 27;
|
||||
const HASHLIB = 1 << 28;
|
||||
const CRYPT = 1 << 29;
|
||||
const UNITTEST = 1 << 30;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue