Skip to content

Commit 4cb82bf

Browse files
authored
fix panic in validate_assignment when field has gone missing (#1532)
1 parent 085e61d commit 4cb82bf

File tree

2 files changed

+26
-15
lines changed

2 files changed

+26
-15
lines changed

src/validators/model_fields.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -421,11 +421,16 @@ impl Validator for ModelFieldsValidator {
421421
let new_extra = match &self.extra_behavior {
422422
ExtraBehavior::Allow => {
423423
let non_extra_data = PyDict::new_bound(py);
424-
self.fields.iter().for_each(|f| {
425-
let popped_value = PyAnyMethods::get_item(&**new_data, &f.name).unwrap();
426-
new_data.del_item(&f.name).unwrap();
427-
non_extra_data.set_item(&f.name, popped_value).unwrap();
428-
});
424+
self.fields.iter().try_for_each(|f| -> PyResult<()> {
425+
let Some(popped_value) = new_data.get_item(&f.name)? else {
426+
// field not present in __dict__ for some reason; let the rest of the
427+
// validation pipeline handle it later
428+
return Ok(());
429+
};
430+
new_data.del_item(&f.name)?;
431+
non_extra_data.set_item(&f.name, popped_value)?;
432+
Ok(())
433+
})?;
429434
let new_extra = new_data.copy()?;
430435
new_data.clear();
431436
new_data.update(non_extra_data.as_mapping())?;

tests/validators/test_model.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,17 +1036,17 @@ def __init__(self):
10361036
self.__pydantic_extra__ = None
10371037

10381038
v = SchemaValidator(
1039-
{
1040-
'type': 'model',
1041-
'cls': MyModel,
1042-
'schema': {
1043-
'type': 'model-fields',
1044-
'fields': {
1045-
'field_a': {'type': 'model-field', 'schema': {'type': 'str'}},
1046-
'field_b': {'type': 'model-field', 'schema': {'type': 'int'}},
1039+
core_schema.model_schema(
1040+
MyModel,
1041+
core_schema.model_fields_schema(
1042+
{
1043+
'field_a': core_schema.model_field(core_schema.str_schema()),
1044+
'field_b': core_schema.model_field(core_schema.int_schema()),
10471045
},
1048-
},
1049-
}
1046+
extra_behavior='allow',
1047+
),
1048+
extra_behavior='allow',
1049+
)
10501050
)
10511051

10521052
m = MyModel()
@@ -1063,6 +1063,12 @@ def __init__(self):
10631063
v.validate_assignment(m, 'field_b', '322', from_attributes=True)
10641064
assert m.field_b == 322
10651065

1066+
# try deleting a field
1067+
del m.field_b
1068+
# assignment to `field_a` should not care about `field_b` missing
1069+
v.validate_assignment(m, 'field_a', 'hello world', from_attributes=True)
1070+
assert m.field_a == 'hello world'
1071+
10661072

10671073
def test_validate_assignment_function():
10681074
class MyModel:

0 commit comments

Comments
 (0)