-
Notifications
You must be signed in to change notification settings - Fork 311
Raise warnings when deprecated fields are filled at model instantiation #1551
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Codecov Report
All modified and coverable lines are covered by tests ✅
📢 Thoughts on this report? Let us know!
CodSpeed Performance Report
Merging #1551 will not alter performance
Comparing changhc:8922-init-deprecated-field (a19365c) with main (5c96bec)
Summary
✅ 155 untouched benchmarks
Please review.
Meanwhile, I'd like to ask the reviewer's opinion on how we can make this thing "less slow". Since this implementation calls import, it will surely affect performance. Codspeed pointed out performance regression with my first commit because there I called import once and for all fields even when there were no deprecated fields. Now that import is moved so that it is called only when a warning needs to be raised. Performance looks fine according to the report, but this is because we don't have any benchmark for deprecated fields.
Since we know that performance will definitely be impacted, we can try to mitigate this. For instance, instead of calling import each time a deprecated field is filled, we can collect warnings and raise them all together in one warning at the end. There are some issues with this approach though. First, the final warning message will need to be more specific because all deprecation messages will be mixed up. We will need to indicate which fields are deprecated and which message belongs to which field for clarity, but this will be inconsistent with what is implemented in pydantic now, i.e. print the deprecation warning only without any additional information. Maybe we can just implement that here and change pydantic later on.
Another issue is when that final warning should be raised. Currently ModelFieldsValidator operates in a "fail early" fashion, i.e. when any field value fails validation, the whole model validation is terminated. Even if we raise the deprecation warning right before any error return, we won't be able to mention all deprecated fields unless we iterate through all fields separately first, but this will probably lead to performance issues. If we don't collect all deprecation warning but simply raise whatever we have observed, the user experience might not be good because users will be like "finding out the remaining "undetected" deprecation fields after fixing validation issues" instead of being able to see all issues upfront and fixing them in one go. This issue already exists with the current implementation though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks reasonable to me, we can get access to the warning type via the PyO3 API and let that handle the most efficient way to do it 😄
src/validators/model_fields.rs
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try this instead:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated. This works. Thanks! There's another UserWarning imported in the same way somewhere in the code base. I can create another PR to change that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would be a great follow-up, yes please 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
@Viicos if you're happy with the core schema & test then let's merge this, the Rust code LGTM.
So, some offline discussion with @Viicos:
- We were a bit unsure if we can merge this without first deciding on the Python API we'll add to the
pydanticpackage. Do we want to unconditionally add warnings on instantiation? This would sort of be a breaking change for users of deprecated fields. Maybe we need a more sophisticated opt-in; perhaps discussion on More support for deprecated fields/models pydantic#8922 is needed - Does this need to support dataclasses and typed dicts too?
For the first point: I'll gather comments in that issue.
For the second point: I think we should because deprecated fields should behave in the same way everywhere. I took a quick look at the relevant validators and I think the implementation will be quite similar. I think we can cover them in separate PRs. That would make things easier in case we need to revert anything.
Uh oh!
There was an error while loading. Please reload this page.
Change Summary
Raise warnings when deprecated fields receive values at model instantiation. My previous attempt at pydantic/pydantic#10865 was rejected because it led to performance issues, so I'm hoping that by moving the logic to pydantic-core will work better. At least doing it here means that the code won't need to loop over the input values one more time.
One extra config is added to the
model-fieldschema:deprecation_msg(Option<String>). A field is marked as deprecated when this config value is present. The actual deprecation message will be passed in from pydantic; this keeps handling the type of the deprecation message simple, and most importantly, there is already logic over there dealing with possible cases of deprecation messages and thus we should not duplicate the logic here.Also tested with pydantic and it worked.
Related issue number
Part of pydantic/pydantic#8922
Checklist
pydantic-core(except for expected changes)Selected Reviewer: @sydney-runkle