From e87feedb1a07c21b25bf34352e56dc99d4d665e4 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Thu, 29 Jan 2026 14:02:17 +0100 Subject: [PATCH 1/4] Deprecate `const` parameter of `Field` --- sqlmodel/main.py | 29 ++++++++++++++++++++++++----- tests/test_pydantic/test_field.py | 10 ++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/sqlmodel/main.py b/sqlmodel/main.py index 84478f24cf..9a0b3bbada 100644 --- a/sqlmodel/main.py +++ b/sqlmodel/main.py @@ -3,6 +3,7 @@ import builtins import ipaddress import uuid +import warnings import weakref from collections.abc import Mapping, Sequence, Set from datetime import date, datetime, time, timedelta @@ -11,6 +12,7 @@ from pathlib import Path from typing import ( TYPE_CHECKING, + Annotated, Any, Callable, ClassVar, @@ -89,6 +91,8 @@ ] OnDeleteType = Literal["CASCADE", "SET NULL", "RESTRICT"] +CONST_DEPRECATION_MSG = "`const` is deprecated and doesn't work, use `Literal` instead" + def __dataclass_transform__( *, @@ -213,7 +217,10 @@ def Field( description: Optional[str] = None, exclude: Union[Set[Union[int, str]], Mapping[Union[int, str], Any], Any] = None, include: Union[Set[Union[int, str]], Mapping[Union[int, str], Any], Any] = None, - const: Optional[bool] = None, + const: Annotated[ + Optional[bool], + deprecated(CONST_DEPRECATION_MSG), + ] = None, gt: Optional[float] = None, ge: Optional[float] = None, lt: Optional[float] = None, @@ -256,7 +263,10 @@ def Field( description: Optional[str] = None, exclude: Union[Set[Union[int, str]], Mapping[Union[int, str], Any], Any] = None, include: Union[Set[Union[int, str]], Mapping[Union[int, str], Any], Any] = None, - const: Optional[bool] = None, + const: Annotated[ + Optional[bool], + deprecated(CONST_DEPRECATION_MSG), + ] = None, gt: Optional[float] = None, ge: Optional[float] = None, lt: Optional[float] = None, @@ -308,7 +318,10 @@ def Field( description: Optional[str] = None, exclude: Union[Set[Union[int, str]], Mapping[Union[int, str], Any], Any] = None, include: Union[Set[Union[int, str]], Mapping[Union[int, str], Any], Any] = None, - const: Optional[bool] = None, + const: Annotated[ + Optional[bool], + deprecated(CONST_DEPRECATION_MSG), + ] = None, gt: Optional[float] = None, ge: Optional[float] = None, lt: Optional[float] = None, @@ -341,7 +354,10 @@ def Field( description: Optional[str] = None, exclude: Union[Set[Union[int, str]], Mapping[Union[int, str], Any], Any] = None, include: Union[Set[Union[int, str]], Mapping[Union[int, str], Any], Any] = None, - const: Optional[bool] = None, + const: Annotated[ + Optional[bool], + deprecated(CONST_DEPRECATION_MSG), + ] = None, gt: Optional[float] = None, ge: Optional[float] = None, lt: Optional[float] = None, @@ -371,6 +387,10 @@ def Field( schema_extra: Optional[dict[str, Any]] = None, ) -> Any: current_schema_extra = schema_extra or {} + + if const is not None: + warnings.warn(CONST_DEPRECATION_MSG, DeprecationWarning, stacklevel=2) + # Extract possible alias settings from schema_extra so we can control precedence schema_validation_alias = current_schema_extra.pop("validation_alias", None) schema_serialization_alias = current_schema_extra.pop("serialization_alias", None) @@ -380,7 +400,6 @@ def Field( "description": description, "exclude": exclude, "include": include, - "const": const, "gt": gt, "ge": ge, "lt": lt, diff --git a/tests/test_pydantic/test_field.py b/tests/test_pydantic/test_field.py index 140b02fd9b..5139d6a890 100644 --- a/tests/test_pydantic/test_field.py +++ b/tests/test_pydantic/test_field.py @@ -54,3 +54,13 @@ class Model(SQLModel): instance = Model(id=123, foo="bar") assert "foo=" not in repr(instance) + + +def test_const_is_deprecated(): + with pytest.warns( + DeprecationWarning, + match="`const` is deprecated and doesn't work, use `Literal` instead", + ): + + class Model(SQLModel): + int_value: int = Field(default=10, const=True) From 81403a5d93455114b061de3c734b0c5f0f63baa9 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Thu, 29 Jan 2026 14:06:11 +0100 Subject: [PATCH 2/4] Deprecate `unique_items` parameter of `Field` --- sqlmodel/main.py | 26 +++++++++++++++++++++----- tests/test_pydantic/test_field.py | 10 ++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/sqlmodel/main.py b/sqlmodel/main.py index 9a0b3bbada..388c45a388 100644 --- a/sqlmodel/main.py +++ b/sqlmodel/main.py @@ -92,6 +92,9 @@ OnDeleteType = Literal["CASCADE", "SET NULL", "RESTRICT"] CONST_DEPRECATION_MSG = "`const` is deprecated and doesn't work, use `Literal` instead" +UNIQUE_ITEMS_DEPRECATION_MSG = ( + "`unique_items` is deprecated and doesn't work, use `set` type instead" +) def __dataclass_transform__( @@ -230,7 +233,10 @@ def Field( decimal_places: Optional[int] = None, min_items: Optional[int] = None, max_items: Optional[int] = None, - unique_items: Optional[bool] = None, + unique_items: Annotated[ + Optional[bool], + deprecated(UNIQUE_ITEMS_DEPRECATION_MSG), + ] = None, min_length: Optional[int] = None, max_length: Optional[int] = None, allow_mutation: bool = True, @@ -276,7 +282,10 @@ def Field( decimal_places: Optional[int] = None, min_items: Optional[int] = None, max_items: Optional[int] = None, - unique_items: Optional[bool] = None, + unique_items: Annotated[ + Optional[bool], + deprecated(UNIQUE_ITEMS_DEPRECATION_MSG), + ] = None, min_length: Optional[int] = None, max_length: Optional[int] = None, allow_mutation: bool = True, @@ -331,7 +340,10 @@ def Field( decimal_places: Optional[int] = None, min_items: Optional[int] = None, max_items: Optional[int] = None, - unique_items: Optional[bool] = None, + unique_items: Annotated[ + Optional[bool], + deprecated(UNIQUE_ITEMS_DEPRECATION_MSG), + ] = None, min_length: Optional[int] = None, max_length: Optional[int] = None, allow_mutation: bool = True, @@ -367,7 +379,10 @@ def Field( decimal_places: Optional[int] = None, min_items: Optional[int] = None, max_items: Optional[int] = None, - unique_items: Optional[bool] = None, + unique_items: Annotated[ + Optional[bool], + deprecated(UNIQUE_ITEMS_DEPRECATION_MSG), + ] = None, min_length: Optional[int] = None, max_length: Optional[int] = None, allow_mutation: bool = True, @@ -390,6 +405,8 @@ def Field( if const is not None: warnings.warn(CONST_DEPRECATION_MSG, DeprecationWarning, stacklevel=2) + if unique_items is not None: + warnings.warn(UNIQUE_ITEMS_DEPRECATION_MSG, DeprecationWarning, stacklevel=2) # Extract possible alias settings from schema_extra so we can control precedence schema_validation_alias = current_schema_extra.pop("validation_alias", None) @@ -409,7 +426,6 @@ def Field( "decimal_places": decimal_places, "min_items": min_items, "max_items": max_items, - "unique_items": unique_items, "min_length": min_length, "max_length": max_length, "allow_mutation": allow_mutation, diff --git a/tests/test_pydantic/test_field.py b/tests/test_pydantic/test_field.py index 5139d6a890..0608abe660 100644 --- a/tests/test_pydantic/test_field.py +++ b/tests/test_pydantic/test_field.py @@ -64,3 +64,13 @@ def test_const_is_deprecated(): class Model(SQLModel): int_value: int = Field(default=10, const=True) + + +def test_unique_items_is_deprecated(): + with pytest.warns( + DeprecationWarning, + match="`unique_items` is deprecated and doesn't work, use `set` type instead", + ): + + class Model(SQLModel): + values: list[int] = Field(unique_items=True) From b3b44fe2ad13394db8e3941a92f3a503eeb409d9 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Fri, 28 Aug 2026 21:37:24 +0200 Subject: [PATCH 3/4] Raise error instead of warning --- sqlmodel/main.py | 5 ++--- tests/test_pydantic/test_field.py | 8 ++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/sqlmodel/main.py b/sqlmodel/main.py index a410e1dedc..af97208008 100644 --- a/sqlmodel/main.py +++ b/sqlmodel/main.py @@ -3,7 +3,6 @@ import builtins import ipaddress import uuid -import warnings from collections.abc import Callable, Mapping, Sequence, Set from dataclasses import dataclass from datetime import date, datetime, time, timedelta @@ -436,9 +435,9 @@ def Field( current_schema_extra = schema_extra or {} if const is not None: - warnings.warn(CONST_DEPRECATION_MSG, DeprecationWarning, stacklevel=2) + raise RuntimeError(CONST_DEPRECATION_MSG) if unique_items is not None: - warnings.warn(UNIQUE_ITEMS_DEPRECATION_MSG, DeprecationWarning, stacklevel=2) + raise RuntimeError(UNIQUE_ITEMS_DEPRECATION_MSG) # Extract possible alias settings from schema_extra so we can control precedence schema_validation_alias = current_schema_extra.pop("validation_alias", None) diff --git a/tests/test_pydantic/test_field.py b/tests/test_pydantic/test_field.py index 01555361d2..a0f911debd 100644 --- a/tests/test_pydantic/test_field.py +++ b/tests/test_pydantic/test_field.py @@ -57,8 +57,8 @@ class Model(SQLModel): def test_const_is_deprecated(): - with pytest.warns( - DeprecationWarning, + with pytest.raises( + RuntimeError, match="`const` is deprecated and doesn't work, use `Literal` instead", ): @@ -67,8 +67,8 @@ class Model(SQLModel): def test_unique_items_is_deprecated(): - with pytest.warns( - DeprecationWarning, + with pytest.raises( + RuntimeError, match="`unique_items` is deprecated and doesn't work, use `set` type instead", ): From 065c3ba326961051332e6cd0fff979ea381d2cd5 Mon Sep 17 00:00:00 2001 From: "pr-push[bot]" Date: Fri, 28 Aug 2026 19:45:42 +0000 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=8E=A8=20Auto=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_pydantic/test_field.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_pydantic/test_field.py b/tests/test_pydantic/test_field.py index de3c208674..b43d6419f2 100644 --- a/tests/test_pydantic/test_field.py +++ b/tests/test_pydantic/test_field.py @@ -106,6 +106,8 @@ def test_unique_items_is_deprecated(): class Model(SQLModel): values: list[int] = Field(unique_items=True) + + def test_min_items(): with pytest.warns( DeprecationWarning,