diff --git a/crates/ruff/resources/test/fixtures/flake8_django/DJ001.py b/crates/ruff/resources/test/fixtures/flake8_django/DJ001.py index 4c1ec71e24..267c2b69d9 100644 --- a/crates/ruff/resources/test/fixtures/flake8_django/DJ001.py +++ b/crates/ruff/resources/test/fixtures/flake8_django/DJ001.py @@ -12,7 +12,16 @@ class IncorrectModel(models.Model): urlfield = models.URLField(max_length=255, null=True) -class IncorrectModelWithAliasedBase(DjangoModel): +class IncorrectModelWithAlias(DjangoModel): + charfield = DjangoModel.CharField(max_length=255, null=True) + textfield = SmthCharField(max_length=255, null=True) + slugfield = models.SlugField(max_length=255, null=True) + emailfield = models.EmailField(max_length=255, null=True) + filepathfield = models.FilePathField(max_length=255, null=True) + urlfield = models.URLField(max_length=255, null=True) + + +class IncorrectModelWithoutSuperclass: charfield = DjangoModel.CharField(max_length=255, null=True) textfield = SmthCharField(max_length=255, null=True) slugfield = models.SlugField(max_length=255, null=True) diff --git a/crates/ruff/src/checkers/ast.rs b/crates/ruff/src/checkers/ast.rs index 597e1873df..a2f5ead600 100644 --- a/crates/ruff/src/checkers/ast.rs +++ b/crates/ruff/src/checkers/ast.rs @@ -786,7 +786,7 @@ where if self.settings.rules.enabled(&Rule::NullableModelStringField) { self.diagnostics .extend(flake8_django::rules::nullable_model_string_field( - self, bases, body, + self, body, )); } if self.settings.rules.enabled(&Rule::ModelWithoutDunderStr) { diff --git a/crates/ruff/src/rules/flake8_django/rules/nullable_model_string_field.rs b/crates/ruff/src/rules/flake8_django/rules/nullable_model_string_field.rs index 1f65b5b8ff..3fbc0802e4 100644 --- a/crates/ruff/src/rules/flake8_django/rules/nullable_model_string_field.rs +++ b/crates/ruff/src/rules/flake8_django/rules/nullable_model_string_field.rs @@ -1,11 +1,14 @@ -use super::helpers; +use rustpython_parser::ast::Constant::Bool; +use rustpython_parser::ast::{Expr, ExprKind, Stmt, StmtKind}; + +use ruff_macros::{define_violation, derive_message_formats}; + use crate::ast::types::Range; use crate::checkers::ast::Checker; use crate::registry::Diagnostic; use crate::violation::Violation; -use ruff_macros::{define_violation, derive_message_formats}; -use rustpython_parser::ast::Constant::Bool; -use rustpython_parser::ast::{Expr, ExprKind, Stmt, StmtKind}; + +use super::helpers; define_violation!( /// ## What it does @@ -58,21 +61,13 @@ const NOT_NULL_TRUE_FIELDS: [&str; 6] = [ ]; /// DJ001 -pub fn nullable_model_string_field( - checker: &Checker, - bases: &[Expr], - body: &[Stmt], -) -> Vec { - if !bases.iter().any(|base| helpers::is_model(checker, base)) { - return vec![]; - } - +pub fn nullable_model_string_field(checker: &Checker, body: &[Stmt]) -> Vec { let mut errors = Vec::new(); for statement in body.iter() { let StmtKind::Assign {value, ..} = &statement.node else { continue }; - if let Some(field_name) = check_nullable_field(checker, value) { + if let Some(field_name) = is_nullable_field(checker, value) { errors.push(Diagnostic::new( NullableModelStringField { field_name: field_name.to_string(), @@ -84,7 +79,7 @@ pub fn nullable_model_string_field( errors } -fn check_nullable_field<'a>(checker: &'a Checker, value: &'a Expr) -> Option<&'a str> { +fn is_nullable_field<'a>(checker: &'a Checker, value: &'a Expr) -> Option<&'a str> { let ExprKind::Call {func, keywords, ..} = &value.node else { return None; }; diff --git a/crates/ruff/src/rules/flake8_django/snapshots/ruff__rules__flake8_django__tests__DJ001_DJ001.py.snap b/crates/ruff/src/rules/flake8_django/snapshots/ruff__rules__flake8_django__tests__DJ001_DJ001.py.snap index 156d4e7682..be1120b31c 100644 --- a/crates/ruff/src/rules/flake8_django/snapshots/ruff__rules__flake8_django__tests__DJ001_DJ001.py.snap +++ b/crates/ruff/src/rules/flake8_django/snapshots/ruff__rules__flake8_django__tests__DJ001_DJ001.py.snap @@ -134,4 +134,70 @@ expression: diagnostics column: 57 fix: ~ parent: ~ +- kind: + NullableModelStringField: + field_name: CharField + location: + row: 25 + column: 16 + end_location: + row: 25 + column: 64 + fix: ~ + parent: ~ +- kind: + NullableModelStringField: + field_name: CharField + location: + row: 26 + column: 16 + end_location: + row: 26 + column: 56 + fix: ~ + parent: ~ +- kind: + NullableModelStringField: + field_name: SlugField + location: + row: 27 + column: 16 + end_location: + row: 27 + column: 59 + fix: ~ + parent: ~ +- kind: + NullableModelStringField: + field_name: EmailField + location: + row: 28 + column: 17 + end_location: + row: 28 + column: 61 + fix: ~ + parent: ~ +- kind: + NullableModelStringField: + field_name: FilePathField + location: + row: 29 + column: 20 + end_location: + row: 29 + column: 67 + fix: ~ + parent: ~ +- kind: + NullableModelStringField: + field_name: URLField + location: + row: 30 + column: 15 + end_location: + row: 30 + column: 57 + fix: ~ + parent: ~