Skip to content

Conversation

@benglewis
Copy link

@benglewis benglewis commented Jan 30, 2025

Update the validate_smart function to identify the correct object class in a discriminated union by using the class with the greatest number of matching fields and the greatest percentage of matching fields.

  • Modify validate_smart function in src/validators/union.rs to calculate the number and percentage of matching fields for each class and select the best match.
  • Add test cases in tests/validators/test_union.py to verify the updated validate_smart function for discriminated unions and ensure correct class selection based on the number and percentage of matching fields.

For more details, open the Copilot Workspace session.

…minated unions

Update the `validate_smart` function to identify the correct object class in a discriminated union by using the class with the greatest number of matching fields and the greatest percentage of matching fields.

* Modify `validate_smart` function in `src/validators/union.rs` to calculate the number and percentage of matching fields for each class and select the best match.
* Add test cases in `tests/validators/test_union.py` to verify the updated `validate_smart` function for discriminated unions and ensure correct class selection based on the number and percentage of matching fields.

---

For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/pydantic/pydantic-core/tree/main?shareId=XXXX-XXXX-XXXX-XXXX).
Copy link
Contributor

@davidhewitt davidhewitt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a reasonable heuristic to me when picking what the best match should be, thanks.

cc @dmontagu we've talked about this kind of idea long ago, this seems like a reasonable small iteration towards a good result 👍

let mut errors = MaybeErrors::new(self.custom_error.as_ref());

let mut best_match: Option<(Py<PyAny>, Exactness, Option<usize>)> = None;
let mut best_match: Option<(Py<PyAny>, Exactness, Option<usize>, usize, f64)> = None;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think now that we have so many fields here, we should create a struct for these so we can give them names.

let new_exactness = state.exactness.unwrap_or(Exactness::Lax);
let new_fields_set_count = state.fields_set_count;
let new_fields_set_percentage = new_fields_set_count.map(|count| {
let total_fields = input.as_dict().map_or(0, |dict| dict.len());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't depend on the validator so can be done once at the start of the function (i.e. above the self.choices loop.)

let new_fields_set_count = state.fields_set_count;
let new_fields_set_percentage = new_fields_set_count.map(|count| {
let total_fields = input.as_dict().map_or(0, |dict| dict.len());
count as f64 / total_fields as f64
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid a divide by zero here I think that we should keep total_fields as Option<usize>. For example consider an int or str input, these have no fields.

… in a discriminated union

* Modify `validate_smart` to iterate through choices and calculate the number and percentage of matching fields for each class
* Adjust `validate_smart` to select the class with the highest number and percentage of matching fields
* Add test cases in `test_union.py` to verify the updated `validate_smart` function for discriminated unions
* Include test cases to check the correct class selection based on the number and percentage of matching fields
@benglewis
Copy link
Author

After a little research, I realized that the pydantic code actually works as-is for our case, but the bug was in SQLModel :/ :
fastapi/sqlmodel#1311

@benglewis benglewis closed this Mar 17, 2025
@benglewis benglewis deleted the fix-union-validator branch March 17, 2025 10:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants