[ruff] Add more Pydantic models variants to the list of default copy semantics (RUF012) (#16291)
Some checks failed
CI / Determine changes (push) Has been cancelled
CI / cargo fmt (push) Has been cancelled
CI / cargo build (release) (push) Has been cancelled
CI / python package (push) Has been cancelled
CI / pre-commit (push) Has been cancelled
CI / mkdocs (push) Has been cancelled
CI / cargo clippy (push) Has been cancelled
CI / cargo test (linux) (push) Has been cancelled
CI / cargo test (linux, release) (push) Has been cancelled
CI / cargo test (windows) (push) Has been cancelled
CI / cargo test (wasm) (push) Has been cancelled
CI / cargo build (msrv) (push) Has been cancelled
CI / cargo fuzz build (push) Has been cancelled
CI / fuzz parser (push) Has been cancelled
CI / test scripts (push) Has been cancelled
CI / ecosystem (push) Has been cancelled
CI / cargo shear (push) Has been cancelled
CI / formatter instabilities and black similarity (push) Has been cancelled
CI / test ruff-lsp (push) Has been cancelled
CI / benchmarks (push) Has been cancelled

This commit is contained in:
Victorien 2025-02-21 08:28:13 +01:00 committed by GitHub
parent 4d63c16c19
commit 793264db13
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 78 additions and 55 deletions

View file

@ -81,28 +81,42 @@ class H(BaseModel):
final_variable: Final[list[int]] = []
from pydantic.v1 import BaseModel as V1BaseModel
class I(V1BaseModel):
mutable_default: list[int] = []
from pydantic.v1.generics import GenericModel
class J(GenericModel):
mutable_default: list[int] = []
def sqlmodel_import_checker():
from sqlmodel.main import SQLModel
class I(SQLModel):
class K(SQLModel):
id: int
mutable_default: list[int] = []
from sqlmodel import SQLModel
class J(SQLModel):
class L(SQLModel):
id: int
name: str
class K(SQLModel):
class M(SQLModel):
id: int
i_s: list[J] = []
class L(SQLModel):
class N(SQLModel):
id: int
i_j: list[K] = list()
i_j: list[L] = list()
# Lint should account for deferred annotations
# See https://github.com/astral-sh/ruff/issues/15857

View file

@ -165,7 +165,7 @@ pub(super) fn dataclass_kind<'a>(
/// Returns `true` if the given class has "default copy" semantics.
///
/// For example, Pydantic `BaseModel` and `BaseSettings` subclassses copy attribute defaults on
/// For example, Pydantic `BaseModel` and `BaseSettings` subclasses 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,
@ -174,7 +174,16 @@ pub(super) fn has_default_copy_semantics(
analyze::class::any_qualified_base_class(class_def, semantic, &|qualified_name| {
matches!(
qualified_name.segments(),
["pydantic", "BaseModel" | "BaseSettings" | "BaseConfig"]
[
"pydantic",
"BaseModel" | "RootModel" | "BaseSettings" | "BaseConfig"
] | ["pydantic", "generics", "GenericModel"]
| [
"pydantic",
"v1",
"BaseModel" | "BaseSettings" | "BaseConfig"
]
| ["pydantic", "v1", "generics", "GenericModel"]
| ["pydantic_settings", "BaseSettings"]
| ["msgspec", "Struct"]
| ["sqlmodel", "SQLModel"]

View file

@ -31,78 +31,78 @@ RUF012.py:25:26: RUF012 Mutable class attributes should be annotated with `typin
27 | class_variable: ClassVar[list[int]] = []
|
RUF012.py:89:38: RUF012 Mutable class attributes should be annotated with `typing.ClassVar`
|
87 | class I(SQLModel):
88 | id: int
89 | mutable_default: list[int] = []
| ^^ RUF012
90 |
91 | from sqlmodel import SQLModel
|
RUF012.py:114:36: RUF012 Mutable class attributes should be annotated with `typing.ClassVar`
RUF012.py:103:38: RUF012 Mutable class attributes should be annotated with `typing.ClassVar`
|
112 | }
113 |
114 | mutable_default: 'list[int]' = []
101 | class K(SQLModel):
102 | id: int
103 | mutable_default: list[int] = []
| ^^ RUF012
104 |
105 | from sqlmodel import SQLModel
|
RUF012.py:128:36: RUF012 Mutable class attributes should be annotated with `typing.ClassVar`
|
126 | }
127 |
128 | mutable_default: 'list[int]' = []
| ^^ RUF012
115 | immutable_annotation: 'Sequence[int]'= []
116 | without_annotation = []
129 | immutable_annotation: 'Sequence[int]'= []
130 | without_annotation = []
|
RUF012.py:115:44: RUF012 Mutable class attributes should be annotated with `typing.ClassVar`
RUF012.py:129:44: RUF012 Mutable class attributes should be annotated with `typing.ClassVar`
|
114 | mutable_default: 'list[int]' = []
115 | immutable_annotation: 'Sequence[int]'= []
128 | mutable_default: 'list[int]' = []
129 | immutable_annotation: 'Sequence[int]'= []
| ^^ RUF012
116 | without_annotation = []
117 | class_variable: 'ClassVar[list[int]]' = []
130 | without_annotation = []
131 | class_variable: 'ClassVar[list[int]]' = []
|
RUF012.py:116:26: RUF012 Mutable class attributes should be annotated with `typing.ClassVar`
RUF012.py:130:26: RUF012 Mutable class attributes should be annotated with `typing.ClassVar`
|
114 | mutable_default: 'list[int]' = []
115 | immutable_annotation: 'Sequence[int]'= []
116 | without_annotation = []
128 | mutable_default: 'list[int]' = []
129 | immutable_annotation: 'Sequence[int]'= []
130 | without_annotation = []
| ^^ RUF012
117 | class_variable: 'ClassVar[list[int]]' = []
118 | final_variable: 'Final[list[int]]' = []
131 | class_variable: 'ClassVar[list[int]]' = []
132 | final_variable: 'Final[list[int]]' = []
|
RUF012.py:117:45: RUF012 Mutable class attributes should be annotated with `typing.ClassVar`
RUF012.py:131:45: RUF012 Mutable class attributes should be annotated with `typing.ClassVar`
|
115 | immutable_annotation: 'Sequence[int]'= []
116 | without_annotation = []
117 | class_variable: 'ClassVar[list[int]]' = []
129 | immutable_annotation: 'Sequence[int]'= []
130 | without_annotation = []
131 | class_variable: 'ClassVar[list[int]]' = []
| ^^ RUF012
118 | final_variable: 'Final[list[int]]' = []
119 | class_variable_without_subscript: 'ClassVar' = []
132 | final_variable: 'Final[list[int]]' = []
133 | class_variable_without_subscript: 'ClassVar' = []
|
RUF012.py:118:42: RUF012 Mutable class attributes should be annotated with `typing.ClassVar`
RUF012.py:132:42: RUF012 Mutable class attributes should be annotated with `typing.ClassVar`
|
116 | without_annotation = []
117 | class_variable: 'ClassVar[list[int]]' = []
118 | final_variable: 'Final[list[int]]' = []
130 | without_annotation = []
131 | class_variable: 'ClassVar[list[int]]' = []
132 | final_variable: 'Final[list[int]]' = []
| ^^ RUF012
119 | class_variable_without_subscript: 'ClassVar' = []
120 | final_variable_without_subscript: 'Final' = []
133 | class_variable_without_subscript: 'ClassVar' = []
134 | final_variable_without_subscript: 'Final' = []
|
RUF012.py:119:52: RUF012 Mutable class attributes should be annotated with `typing.ClassVar`
RUF012.py:133:52: RUF012 Mutable class attributes should be annotated with `typing.ClassVar`
|
117 | class_variable: 'ClassVar[list[int]]' = []
118 | final_variable: 'Final[list[int]]' = []
119 | class_variable_without_subscript: 'ClassVar' = []
131 | class_variable: 'ClassVar[list[int]]' = []
132 | final_variable: 'Final[list[int]]' = []
133 | class_variable_without_subscript: 'ClassVar' = []
| ^^ RUF012
120 | final_variable_without_subscript: 'Final' = []
134 | final_variable_without_subscript: 'Final' = []
|
RUF012.py:120:49: RUF012 Mutable class attributes should be annotated with `typing.ClassVar`
RUF012.py:134:49: RUF012 Mutable class attributes should be annotated with `typing.ClassVar`
|
118 | final_variable: 'Final[list[int]]' = []
119 | class_variable_without_subscript: 'ClassVar' = []
120 | final_variable_without_subscript: 'Final' = []
132 | final_variable: 'Final[list[int]]' = []
133 | class_variable_without_subscript: 'ClassVar' = []
134 | final_variable_without_subscript: 'Final' = []
| ^^ RUF012
|