from decimal import Decimal from typing import Literal import pytest from pydantic import ValidationError from sqlmodel import Field, SQLModel def test_decimal(): class Model(SQLModel): dec: Decimal = Field(max_digits=4, decimal_places=2) Model(dec=Decimal("3.14")) Model(dec=Decimal("69.42")) with pytest.raises(ValidationError): Model(dec=Decimal("3.142")) with pytest.raises(ValidationError): Model(dec=Decimal("0.069")) with pytest.raises(ValidationError): Model(dec=Decimal("420")) def test_discriminator(): # Example adapted from # [Pydantic docs](https://pydantic-docs.helpmanual.io/usage/types/#discriminated-unions-aka-tagged-unions): class Cat(SQLModel): pet_type: Literal["cat"] meows: int class Dog(SQLModel): pet_type: Literal["dog"] barks: float class Lizard(SQLModel): pet_type: Literal["reptile", "lizard"] scales: bool class Model(SQLModel): pet: Cat | Dog | Lizard = Field(..., discriminator="pet_type") n: int Model(pet={"pet_type": "dog", "barks": 3.14}, n=1) # type: ignore[arg-type] with pytest.raises(ValidationError): Model(pet={"pet_type": "dog"}, n=1) # type: ignore[arg-type] def test_repr(): class Model(SQLModel): id: int | None = Field(primary_key=True) foo: str = Field(repr=False) instance = Model(id=123, foo="bar") assert "foo=" not in repr(instance) def test_exclude(): class Model(SQLModel): id: int name: str value: int = Field(exclude=True) instance = Model(id=1, name="test", value=42) dict_representation = instance.model_dump() assert "id" in dict_representation assert "name" in dict_representation assert "value" not in dict_representation def test_include_is_deprecated(): with pytest.warns( DeprecationWarning, match="`include` is deprecated and does nothing. It will be removed, use `exclude` instead", ): class Model(SQLModel): values: list[int] = Field(include=True)