-
-
Notifications
You must be signed in to change notification settings - Fork 883
Expand file tree
/
Copy pathtest_field.py
More file actions
142 lines (101 loc) · 3.98 KB
/
Copy pathtest_field.py
File metadata and controls
142 lines (101 loc) · 3.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
from decimal import Decimal
from typing import Annotated, Any, Literal
import pytest
from pydantic import ValidationError
from sqlmodel import Discriminator, Field, SQLModel, Tag
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_discriminator_callable():
# Example adapted from
# [Pydantic docs](https://docs.pydantic.dev/latest/concepts/unions/#discriminated-unions-with-callable-discriminator):
class Pie(SQLModel):
pass
class ApplePie(Pie):
fruit: Literal["apple"] = "apple"
class PumpkinPie(Pie):
filling: Literal["pumpkin"] = "pumpkin"
def get_discriminator_value(v: Any) -> str:
if isinstance(v, dict):
return v.get("fruit", v.get("filling"))
return getattr(v, "fruit", getattr(v, "filling", None))
class ThanksgivingDinner(SQLModel):
dessert: (
Annotated[ApplePie, Tag("apple")] | Annotated[PumpkinPie, Tag("pumpkin")]
) = Field(
discriminator=Discriminator(get_discriminator_value),
)
apple_pie = ThanksgivingDinner.model_validate({"dessert": {"fruit": "apple"}})
assert isinstance(apple_pie.dessert, ApplePie)
pumpkin_pie = ThanksgivingDinner.model_validate({"dessert": {"filling": "pumpkin"}})
assert isinstance(pumpkin_pie.dessert, PumpkinPie)
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_const_is_deprecated():
with pytest.raises(
RuntimeError,
match="`const` is deprecated and doesn't work, use `Literal` instead",
):
class Model(SQLModel):
int_value: int = Field(default=10, const=True)
def test_unique_items_is_deprecated():
with pytest.raises(
RuntimeError,
match="`unique_items` is deprecated and doesn't work, use `set` type instead",
):
class Model(SQLModel):
values: list[int] = Field(unique_items=True)
def test_min_items():
with pytest.warns(
DeprecationWarning,
match="`min_items` is deprecated and will be removed, use `min_length` instead",
):
class Model(SQLModel):
items: list[int] = Field(min_items=2)
Model(items=[1, 2])
with pytest.raises(ValidationError) as exc_info:
Model(items=[1])
assert len(exc_info.value.errors()) == 1
assert exc_info.value.errors()[0]["type"] == "too_short"
def test_max_items():
with pytest.warns(
DeprecationWarning,
match="`max_items` is deprecated and will be removed, use `max_length` instead",
):
class Model(SQLModel):
items: list[int] = Field(max_items=2)
Model(items=[1, 2])
with pytest.raises(ValidationError) as exc_info:
Model(items=[1, 2, 3])
assert len(exc_info.value.errors()) == 1
assert exc_info.value.errors()[0]["type"] == "too_long"