Skip to content

Commit

Permalink
fix panic in validate_assignment when field has gone missing (#1532)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt authored Nov 5, 2024
1 parent 085e61d commit 4cb82bf
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 15 deletions.
15 changes: 10 additions & 5 deletions src/validators/model_fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,11 +421,16 @@ impl Validator for ModelFieldsValidator {
let new_extra = match &self.extra_behavior {
ExtraBehavior::Allow => {
let non_extra_data = PyDict::new_bound(py);
self.fields.iter().for_each(|f| {
let popped_value = PyAnyMethods::get_item(&**new_data, &f.name).unwrap();
new_data.del_item(&f.name).unwrap();
non_extra_data.set_item(&f.name, popped_value).unwrap();
});
self.fields.iter().try_for_each(|f| -> PyResult<()> {
let Some(popped_value) = new_data.get_item(&f.name)? else {
// field not present in __dict__ for some reason; let the rest of the
// validation pipeline handle it later
return Ok(());
};
new_data.del_item(&f.name)?;
non_extra_data.set_item(&f.name, popped_value)?;
Ok(())
})?;
let new_extra = new_data.copy()?;
new_data.clear();
new_data.update(non_extra_data.as_mapping())?;
Expand Down
26 changes: 16 additions & 10 deletions tests/validators/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -1036,17 +1036,17 @@ def __init__(self):
self.__pydantic_extra__ = None

v = SchemaValidator(
{
'type': 'model',
'cls': MyModel,
'schema': {
'type': 'model-fields',
'fields': {
'field_a': {'type': 'model-field', 'schema': {'type': 'str'}},
'field_b': {'type': 'model-field', 'schema': {'type': 'int'}},
core_schema.model_schema(
MyModel,
core_schema.model_fields_schema(
{
'field_a': core_schema.model_field(core_schema.str_schema()),
'field_b': core_schema.model_field(core_schema.int_schema()),
},
},
}
extra_behavior='allow',
),
extra_behavior='allow',
)
)

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

# try deleting a field
del m.field_b
# assignment to `field_a` should not care about `field_b` missing
v.validate_assignment(m, 'field_a', 'hello world', from_attributes=True)
assert m.field_a == 'hello world'


def test_validate_assignment_function():
class MyModel:
Expand Down

0 comments on commit 4cb82bf

Please sign in to comment.