Pydantic model not detected by RUF012
- List of keywords you searched for before creating this issue: pydantic ruf012
- The current Ruff version : 0.5.0
RUF012 normally ignores pydantic models but not when the class inherits from an imported model. Eg: file b.py
from pydantic import BaseModel
class B(BaseModel):
pass
file a.py
from pydantic import BaseModel
from b import B
class Foo(B):
foo: list[str] = []
class C(BaseModel):
pass
class Bar(C):
bar: list[str] = []
Then run ruff
ruff check --select RUF012
a.py:5:22: RUF012 Mutable class attributes should be annotated with `typing.ClassVar`
|
4 | class Foo(B):
5 | foo: list[str] = []
| ^^ RUF012
6 |
7 | class C(BaseModel):
|
Found 1 error.
I would expect ruff to not error.
Ruff doesn't support multi-file analysis yet, we can't inspect the type across the import boundary
xref https://github.com/astral-sh/ruff/issues/7447
Thanks for the info. I'll follow #7447 with interest then.
We're actively working on it, but it's a ways out.
I nice workaround would be to make it possible to extend has_default_copy_semantics() list:
https://github.com/astral-sh/ruff/blob/10d3e64ccdf69d90c3252a15b3408a4238427792/crates/ruff_linter/src/rules/ruff/rules/helpers.rs#L166C1-L183C2
/// Returns `true` if the given class has "default copy" semantics.
///
/// For example, Pydantic `BaseModel` and `BaseSettings` subclassses copy attribute defaults on
/// instance creation. As such, the use of mutable default values is safe for such classes.
pub(super) fn has_default_copy_semantics(
class_def: &ast::StmtClassDef,
semantic: &SemanticModel,
) -> bool {
analyze::class::any_qualified_base_class(class_def, semantic, &|qualified_name| {
matches!(
qualified_name.segments(),
["pydantic", "BaseModel" | "BaseSettings" | "BaseConfig"]
| ["pydantic_settings", "BaseSettings"]
| ["msgspec", "Struct"]
| ["sqlmodel", "SQLModel"]
)
})
}
Would you be open to take such a PR?
(such a solution would pobably also "close" https://github.com/astral-sh/ruff/issues/5639)
Making that configurable was discussed a bit here https://github.com/astral-sh/ruff/issues/14892#issuecomment-2536960816, and it sounded like the preference is to hold off in favor of using type inference, once ruff supports that.
Similar to #5639. Maybe this issue can be closed and followed in the other one for multiple files ?
That makes sense to me, they do sound like the same root issue. Thanks for following up!