unique_items: Optional[bool] = None,
min_length: Optional[int] = None,
max_length: Optional[int] = None,
+ union_mode: Optional[Literal["smart", "left_to_right"]] = None,
allow_mutation: bool = True,
regex: Optional[str] = None,
discriminator: Optional[str] = None,
unique_items: Optional[bool] = None,
min_length: Optional[int] = None,
max_length: Optional[int] = None,
+ union_mode: Optional[Literal["smart", "left_to_right"]] = None,
allow_mutation: bool = True,
regex: Optional[str] = None,
discriminator: Optional[str] = None,
unique_items: Optional[bool] = None,
min_length: Optional[int] = None,
max_length: Optional[int] = None,
+ union_mode: Optional[Literal["smart", "left_to_right"]] = None,
allow_mutation: bool = True,
regex: Optional[str] = None,
discriminator: Optional[str] = None,
unique_items: Optional[bool] = None,
min_length: Optional[int] = None,
max_length: Optional[int] = None,
+ union_mode: Optional[Literal["smart", "left_to_right"]] = None,
allow_mutation: bool = True,
regex: Optional[str] = None,
discriminator: Optional[str] = None,
for param_name in (
"coerce_numbers_to_str",
"validate_default",
+ "union_mode",
):
if param_name in current_schema_extra:
msg = f"Pass `{param_name}` parameter directly to Field instead of passing it via `schema_extra`"
serialization_alias or schema_serialization_alias or alias
)
+ current_union_mode = union_mode or current_schema_extra.pop("union_mode", None)
+ if current_union_mode is not None:
+ field_info_kwargs["union_mode"] = current_union_mode
+
field_info = FieldInfo(
default,
default_factory=default_factory,
val: int = Field(default="123", schema_extra={"validate_default": True})
assert Model.model_validate({}).val == 123
+
+
+@pytest.mark.parametrize("union_mode", [None, "smart"])
+def test_union_mode_smart(union_mode: Optional[Literal["smart"]]):
+ class Model(SQLModel):
+ val: Union[float, int] = Field(union_mode=union_mode)
+
+ a = Model.model_validate({"val": 123})
+ assert isinstance(a.val, int) # float is first, but int is more precise
+
+ b = Model.model_validate({"val": 123.0})
+ assert isinstance(b.val, float)
+
+ c = Model.model_validate({"val": 123.1})
+ assert isinstance(c.val, float)
+
+
+def test_union_mode_left_to_right():
+ class Model(SQLModel):
+ val: Union[float, int] = Field(union_mode="left_to_right")
+
+ a = Model.model_validate({"val": 123})
+ assert isinstance(a.val, float)
+
+ b = Model.model_validate({"val": 123.0})
+ assert isinstance(b.val, float)
+
+ c = Model.model_validate({"val": 123.1})
+ assert isinstance(c.val, float)
+
+
+def test_union_mode_via_schema_extra(): # Current workaround. Remove after some time
+ with pytest.warns(
+ UserWarning,
+ match=(
+ "Pass `union_mode` parameter directly to Field instead of passing "
+ "it via `schema_extra`"
+ ),
+ ):
+
+ class Model(SQLModel):
+ val: Union[float, int] = Field(schema_extra={"union_mode": "smart"})
+
+ a = Model.model_validate({"val": 123})
+ assert isinstance(a.val, int) # float is first, but int is more precise
+
+ b = Model.model_validate({"val": 123.0})
+ assert isinstance(b.val, float)
+
+ c = Model.model_validate({"val": 123.1})
+ assert isinstance(c.val, float)