import builtins
import ipaddress
import uuid
+import warnings
import weakref
from collections.abc import Mapping, Sequence, Set
from datetime import date, datetime, time, timedelta
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,
+ coerce_numbers_to_str: Optional[bool] = None,
gt: Optional[float] = None,
ge: Optional[float] = None,
lt: Optional[float] = 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,
+ coerce_numbers_to_str: Optional[bool] = None,
gt: Optional[float] = None,
ge: Optional[float] = None,
lt: Optional[float] = 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,
+ coerce_numbers_to_str: Optional[bool] = None,
gt: Optional[float] = None,
ge: Optional[float] = None,
lt: Optional[float] = 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,
+ coerce_numbers_to_str: Optional[bool] = None,
gt: Optional[float] = None,
ge: Optional[float] = None,
lt: Optional[float] = None,
schema_extra: Optional[dict[str, Any]] = None,
) -> Any:
current_schema_extra = schema_extra or {}
+
+ for param_name in ("coerce_numbers_to_str",):
+ if param_name in current_schema_extra:
+ msg = f"Pass `{param_name}` parameter directly to Field instead of passing it via `schema_extra`"
+ warnings.warn(msg, UserWarning, 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)
+ current_coerce_numbers_to_str = coerce_numbers_to_str or current_schema_extra.pop(
+ "coerce_numbers_to_str", None
+ )
field_info_kwargs = {
"alias": alias,
"title": title,
"exclude": exclude,
"include": include,
"const": const,
+ "coerce_numbers_to_str": current_coerce_numbers_to_str,
"gt": gt,
"ge": ge,
"lt": lt,
instance = Model(id=123, foo="bar")
assert "foo=" not in repr(instance)
+
+
+def test_coerce_numbers_to_str_true():
+ class Model(SQLModel):
+ val: str = Field(coerce_numbers_to_str=True)
+
+ assert Model.model_validate({"val": 123}).val == "123"
+ assert Model.model_validate({"val": 45.67}).val == "45.67"
+
+
+@pytest.mark.parametrize("coerce_numbers_to_str", [None, False])
+def test_coerce_numbers_to_str_false(coerce_numbers_to_str: Optional[bool]):
+ class Model2(SQLModel):
+ val: str = Field(coerce_numbers_to_str=coerce_numbers_to_str)
+
+ with pytest.raises(ValidationError):
+ Model2.model_validate({"val": 123})
+
+
+def test_coerce_numbers_to_str_via_schema_extra(): # Current workaround. Remove after some time
+ with pytest.warns(
+ UserWarning,
+ match=(
+ "Pass `coerce_numbers_to_str` parameter directly to Field instead of passing "
+ "it via `schema_extra`"
+ ),
+ ):
+
+ class Model(SQLModel):
+ val: str = Field(schema_extra={"coerce_numbers_to_str": True})
+
+ assert Model.model_validate({"val": 123}).val == "123"
+ assert Model.model_validate({"val": 45.67}).val == "45.67"