Skip to content

Commit 0c07f9a

Browse files
committed
raise warnings when deprecated fields are filled
1 parent 6472887 commit 0c07f9a

File tree

3 files changed

+34
-0
lines changed

3 files changed

+34
-0
lines changed

python/pydantic_core/core_schema.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2944,6 +2944,7 @@ class ModelField(TypedDict, total=False):
29442944
serialization_alias: str
29452945
serialization_exclude: bool # default: False
29462946
frozen: bool
2947+
deprecation_msg: str
29472948
metadata: Dict[str, Any]
29482949

29492950

@@ -2954,6 +2955,7 @@ def model_field(
29542955
serialization_alias: str | None = None,
29552956
serialization_exclude: bool | None = None,
29562957
frozen: bool | None = None,
2958+
deprecation_msg: str | None = None,
29572959
metadata: Dict[str, Any] | None = None,
29582960
) -> ModelField:
29592961
"""
@@ -2971,6 +2973,7 @@ def model_field(
29712973
serialization_alias: The alias to use as a key when serializing
29722974
serialization_exclude: Whether to exclude the field when serializing
29732975
frozen: Whether the field is frozen
2976+
deprecation_msg: A deprecation message indicating that the field is deprecated. `None` means that the field is not deprecated.
29742977
metadata: Any other information you want to include with the schema, not used by pydantic-core
29752978
"""
29762979
return _dict_not_none(
@@ -2980,6 +2983,7 @@ def model_field(
29802983
serialization_alias=serialization_alias,
29812984
serialization_exclude=serialization_exclude,
29822985
frozen=frozen,
2986+
deprecation_msg=deprecation_msg,
29832987
metadata=metadata,
29842988
)
29852989

src/validators/model_fields.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ struct Field {
2323
name_py: Py<PyString>,
2424
validator: CombinedValidator,
2525
frozen: bool,
26+
deprecation_msg: Option<String>,
2627
}
2728

2829
impl_py_gc_traverse!(Field { validator });
@@ -92,6 +93,7 @@ impl BuildValidator for ModelFieldsValidator {
9293
name_py: field_name_py.into(),
9394
validator,
9495
frozen: field_info.get_as::<bool>(intern!(py, "frozen"))?.unwrap_or(false),
96+
deprecation_msg: field_info.get_as::<String>(intern!(py, "deprecation_msg"))?,
9597
});
9698
}
9799

@@ -123,6 +125,8 @@ impl Validator for ModelFieldsValidator {
123125
// this validator does not yet support partial validation, disable it to avoid incorrect results
124126
state.allow_partial = false.into();
125127

128+
let deprecation_warning_type = py.import_bound("builtins")?.getattr("DeprecationWarning")?;
129+
126130
let strict = state.strict_or(self.strict);
127131
let from_attributes = state.extra().from_attributes.unwrap_or(self.from_attributes);
128132

@@ -184,6 +188,9 @@ impl Validator for ModelFieldsValidator {
184188
// extra logic either way
185189
used_keys.insert(lookup_path.first_key());
186190
}
191+
if let Some(msg) = &field.deprecation_msg {
192+
PyErr::warn_bound(py, &deprecation_warning_type, msg, 2)?;
193+
}
187194
match field.validator.validate(py, value.borrow_input(), state) {
188195
Ok(value) => {
189196
model_dict.set_item(&field.name_py, value)?;

tests/validators/test_model_fields.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1781,3 +1781,26 @@ def test_extra_behavior_ignore(config: Union[core_schema.CoreConfig, None], sche
17811781
}
17821782
]
17831783
assert 'not_f' not in m
1784+
1785+
1786+
def test_deprecation_msg():
1787+
v = SchemaValidator(
1788+
{
1789+
'type': 'model-fields',
1790+
'fields': {
1791+
'a': {'type': 'model-field', 'schema': {'type': 'int'}},
1792+
'b': {
1793+
'type': 'model-field',
1794+
'schema': {'type': 'default', 'schema': {'type': 'int'}, 'default': 2},
1795+
'deprecation_msg': 'hi',
1796+
},
1797+
},
1798+
}
1799+
)
1800+
1801+
# not touching the deprecated field: no warning
1802+
v.validate_python({'a': 1})
1803+
1804+
# validating the deprecated field: raise warning
1805+
with pytest.warns(DeprecationWarning, match='hi'):
1806+
v.validate_python({'a': 1, 'b': 1})

0 commit comments

Comments
 (0)