no-input-model-mutation
Return replacement values instead of mutating caller-owned Pydantic models.
Why
Assignments through shared model inputs also change every caller alias. Copying only the outer list or model retains nested aliases and can make repeated transformations observe each other's changes.
Fix
Return replacement models and explicitly capture the result. Copy each changed ancestor; permit fresh local builders and use exact suppressions for documented in-place APIs. model_copy updates must already satisfy the complete model contract.
Examples
from pydantic import BaseModel
class Attachment(BaseModel): url: str
class Record(BaseModel): attachment: Attachment
def sign(record: Record): copied = record.model_copy() copied.attachment.url = "signed"from pydantic import BaseModel
class Attachment(BaseModel): url: str
class Record(BaseModel): attachment: Attachment
def sign(record: Record): attachment = record.attachment.model_copy(update={"url": "signed"}) return record.model_copy(update={"attachment": attachment})from pydantic import BaseModel
class Record(BaseModel): name: str
def rename(record: Record): record.name = "new"from pydantic import BaseModel
class Record(BaseModel): name: str
def rename(record: Record): return record.model_copy(update={"name": "new"})