min_length: Optional[int] = None,
max_length: Optional[int] = None,
union_mode: Optional[Literal["smart", "left_to_right"]] = None,
+ fail_fast: Optional[bool] = None,
allow_mutation: bool = True,
regex: Optional[str] = None,
discriminator: Optional[str] = None,
min_length: Optional[int] = None,
max_length: Optional[int] = None,
union_mode: Optional[Literal["smart", "left_to_right"]] = None,
+ fail_fast: Optional[bool] = None,
allow_mutation: bool = True,
regex: Optional[str] = None,
discriminator: Optional[str] = None,
min_length: Optional[int] = None,
max_length: Optional[int] = None,
union_mode: Optional[Literal["smart", "left_to_right"]] = None,
+ fail_fast: Optional[bool] = None,
allow_mutation: bool = True,
regex: Optional[str] = None,
discriminator: Optional[str] = None,
min_length: Optional[int] = None,
max_length: Optional[int] = None,
union_mode: Optional[Literal["smart", "left_to_right"]] = None,
+ fail_fast: Optional[bool] = None,
allow_mutation: bool = True,
regex: Optional[str] = None,
discriminator: Optional[str] = None,
"coerce_numbers_to_str",
"validate_default",
"union_mode",
+ "fail_fast",
):
if param_name in current_schema_extra:
msg = f"Pass `{param_name}` parameter directly to Field instead of passing it via `schema_extra`"
current_validate_default = validate_default or current_schema_extra.pop(
"validate_default", None
)
+ current_fail_fast = fail_fast or current_schema_extra.pop("fail_fast", None)
field_info_kwargs = {
"alias": alias,
"title": title,
"unique_items": unique_items,
"min_length": min_length,
"max_length": max_length,
+ "fail_fast": current_fail_fast,
"allow_mutation": allow_mutation,
"regex": regex,
"discriminator": discriminator,
c = Model.model_validate({"val": 123.1})
assert isinstance(c.val, float)
+
+
+def test_fail_fast_true():
+ class Model(SQLModel):
+ val: list[int] = Field(fail_fast=True)
+
+ with pytest.raises(ValidationError) as exc_info:
+ Model.model_validate({"val": [1.1, "not an int"]})
+
+ errors = exc_info.value.errors()
+ assert len(errors) == 1
+ assert errors[0]["type"] == "int_from_float"
+
+
+@pytest.mark.parametrize("fail_fast", [None, False])
+def test_fail_fast_false(fail_fast: Optional[bool]):
+ class Model(SQLModel):
+ val: list[int] = Field(fail_fast=fail_fast)
+
+ with pytest.raises(ValidationError) as exc_info:
+ Model.model_validate({"val": [1.1, "not an int"]})
+
+ errors = exc_info.value.errors()
+ assert len(errors) == 2
+ error_types = {error["type"] for error in errors}
+
+ assert "int_from_float" in error_types
+ assert "int_parsing" in error_types
+
+
+def test_fail_fast_via_schema_extra(): # Current workaround. Remove after some time
+ with pytest.warns(
+ UserWarning,
+ match=(
+ "Pass `fail_fast` parameter directly to Field instead of passing "
+ "it via `schema_extra`"
+ ),
+ ):
+
+ class Model(SQLModel):
+ val: list[int] = Field(schema_extra={"fail_fast": True})
+
+ with pytest.raises(ValidationError) as exc_info:
+ Model.model_validate({"val": [1.1, "not an int"]})
+
+ errors = exc_info.value.errors()
+ assert len(errors) == 1
+ assert errors[0]["type"] == "int_from_float"