Skip to content

Commit 2d02c4c

Browse files
YuriiMotovtiangolo
andauthored
🗑️ Deprecate min_items and max_items parameters of Field (#1731)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
1 parent 83db52b commit 2d02c4c

2 files changed

Lines changed: 85 additions & 10 deletions

File tree

sqlmodel/main.py

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import builtins
44
import ipaddress
55
import uuid
6+
import warnings
67
from collections.abc import Callable, Mapping, Sequence, Set
78
from dataclasses import dataclass
89
from datetime import date, datetime, time, timedelta
@@ -11,6 +12,7 @@
1112
from pathlib import Path
1213
from typing import (
1314
TYPE_CHECKING,
15+
Annotated,
1416
Any,
1517
ClassVar,
1618
Literal,
@@ -89,6 +91,13 @@
8991
)
9092
OnDeleteType = Literal["CASCADE", "SET NULL", "RESTRICT"]
9193

94+
MIN_ITEMS_DEPRECATION_MSG = (
95+
"`min_items` is deprecated and will be removed, use `min_length` instead"
96+
)
97+
MAX_ITEMS_DEPRECATION_MSG = (
98+
"`max_items` is deprecated and will be removed, use `max_length` instead"
99+
)
100+
92101

93102
def __dataclass_transform__(
94103
*,
@@ -253,8 +262,14 @@ def Field(
253262
multiple_of: float | None = None,
254263
max_digits: int | None = None,
255264
decimal_places: int | None = None,
256-
min_items: int | None = None,
257-
max_items: int | None = None,
265+
min_items: Annotated[
266+
int | None,
267+
deprecated(MIN_ITEMS_DEPRECATION_MSG),
268+
] = None,
269+
max_items: Annotated[
270+
int | None,
271+
deprecated(MAX_ITEMS_DEPRECATION_MSG),
272+
] = None,
258273
unique_items: bool | None = None,
259274
min_length: int | None = None,
260275
max_length: int | None = None,
@@ -296,8 +311,14 @@ def Field(
296311
multiple_of: float | None = None,
297312
max_digits: int | None = None,
298313
decimal_places: int | None = None,
299-
min_items: int | None = None,
300-
max_items: int | None = None,
314+
min_items: Annotated[
315+
int | None,
316+
deprecated(MIN_ITEMS_DEPRECATION_MSG),
317+
] = None,
318+
max_items: Annotated[
319+
int | None,
320+
deprecated(MAX_ITEMS_DEPRECATION_MSG),
321+
] = None,
301322
unique_items: bool | None = None,
302323
min_length: int | None = None,
303324
max_length: int | None = None,
@@ -348,8 +369,14 @@ def Field(
348369
multiple_of: float | None = None,
349370
max_digits: int | None = None,
350371
decimal_places: int | None = None,
351-
min_items: int | None = None,
352-
max_items: int | None = None,
372+
min_items: Annotated[
373+
int | None,
374+
deprecated(MIN_ITEMS_DEPRECATION_MSG),
375+
] = None,
376+
max_items: Annotated[
377+
int | None,
378+
deprecated(MAX_ITEMS_DEPRECATION_MSG),
379+
] = None,
353380
unique_items: bool | None = None,
354381
min_length: int | None = None,
355382
max_length: int | None = None,
@@ -381,8 +408,14 @@ def Field(
381408
multiple_of: float | None = None,
382409
max_digits: int | None = None,
383410
decimal_places: int | None = None,
384-
min_items: int | None = None,
385-
max_items: int | None = None,
411+
min_items: Annotated[
412+
int | None,
413+
deprecated(MIN_ITEMS_DEPRECATION_MSG),
414+
] = None,
415+
max_items: Annotated[
416+
int | None,
417+
deprecated(MAX_ITEMS_DEPRECATION_MSG),
418+
] = None,
386419
unique_items: bool | None = None,
387420
min_length: int | None = None,
388421
max_length: int | None = None,
@@ -403,6 +436,16 @@ def Field(
403436
schema_extra: dict[str, Any] | None = None,
404437
) -> Any:
405438
current_schema_extra = schema_extra or {}
439+
440+
if min_items is not None:
441+
warnings.warn(MIN_ITEMS_DEPRECATION_MSG, DeprecationWarning, stacklevel=2)
442+
if min_length is None:
443+
min_length = min_items
444+
if max_items is not None:
445+
warnings.warn(MAX_ITEMS_DEPRECATION_MSG, DeprecationWarning, stacklevel=2)
446+
if max_length is None:
447+
max_length = max_items
448+
406449
# Extract possible alias settings from schema_extra so we can control precedence
407450
schema_validation_alias = current_schema_extra.pop("validation_alias", None)
408451
schema_serialization_alias = current_schema_extra.pop("serialization_alias", None)
@@ -420,8 +463,6 @@ def Field(
420463
"multiple_of": multiple_of,
421464
"max_digits": max_digits,
422465
"decimal_places": decimal_places,
423-
"min_items": min_items,
424-
"max_items": max_items,
425466
"unique_items": unique_items,
426467
"min_length": min_length,
427468
"max_length": max_length,

tests/test_pydantic/test_field.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,37 @@ class Model(SQLModel):
5454

5555
instance = Model(id=123, foo="bar")
5656
assert "foo=" not in repr(instance)
57+
58+
59+
def test_min_items():
60+
with pytest.warns(
61+
DeprecationWarning,
62+
match="`min_items` is deprecated and will be removed, use `min_length` instead",
63+
):
64+
65+
class Model(SQLModel):
66+
items: list[int] = Field(min_items=2)
67+
68+
Model(items=[1, 2])
69+
70+
with pytest.raises(ValidationError) as exc_info:
71+
Model(items=[1])
72+
assert len(exc_info.value.errors()) == 1
73+
assert exc_info.value.errors()[0]["type"] == "too_short"
74+
75+
76+
def test_max_items():
77+
with pytest.warns(
78+
DeprecationWarning,
79+
match="`max_items` is deprecated and will be removed, use `max_length` instead",
80+
):
81+
82+
class Model(SQLModel):
83+
items: list[int] = Field(max_items=2)
84+
85+
Model(items=[1, 2])
86+
87+
with pytest.raises(ValidationError) as exc_info:
88+
Model(items=[1, 2, 3])
89+
assert len(exc_info.value.errors()) == 1
90+
assert exc_info.value.errors()[0]["type"] == "too_long"

0 commit comments

Comments
 (0)