-
Notifications
You must be signed in to change notification settings - Fork 280
allow sorting keys on to_json and to_python by passing in sort_keys #1637
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
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
📢 Thoughts on this report? Let us know! |
CodSpeed Performance ReportMerging #1637 will not alter performanceComparing Summary
|
07a31f5
to
7222c8d
Compare
please review |
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.
Main issue is perf regression
I separated the test out, I also refactor the functions so we can reuse when Let me know what else I need to improve. Thanks |
please review, not sure how I can take it from here |
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.
Hmm I see now that this is not recursive (it only applies to the top level keys). Would it be hard to make it recursive? I fear that if we implement the non-recursive version someone is going to come along and want the recursive version... if so we can make it a Literal['recursive', 'top-level', 'unsorted']
or something like that.
0cf4b6d
to
95f9329
Compare
Added different sort mode as above, updated the PR description. |
please review 👍 |
95f9329
to
c83a212
Compare
please review 👍 |
c83a212
to
0075a4b
Compare
please review 👍 There is this test that is failing, unclear if its related to my change. Let me know any other places i can optimize. Thanks! |
dce2689
to
5ce696c
Compare
please review 👍 |
dfe7380
to
1b8d824
Compare
please review 👍 |
1 similar comment
please review 👍 |
@DouweM please review :) |
dc0ec59
to
11501f6
Compare
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 for your work on this @aezomz! I'm a Rust newbie as well, but I have a feeling we can significantly simplify this code by dropping the recursive dict sorting and moving this to the serializer for the dict type specifically. Can you give that a try please?
I also think it's worth seeing if we can reduce the duplication between the if sort_keys
/else
branches, but I know Rust typing may make that tricky...
Let me know if you get stuck, we can bring in some of our Rust experts!
src/serializers/fields.rs
Outdated
@@ -229,6 +208,124 @@ impl GeneralFieldsSerializer { | |||
} | |||
} | |||
|
|||
fn sort_dict_recursive<'py>(py: Python<'py>, value: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyAny>> { |
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.
I know this was suggested in a previous review, but instead of doing this recursively here, would it be an option to implement single-level sorting in this file and in src/serializers/type_serializers/dict.rs
, so that it works on any dict serialization, not just when nested in a model/dataclass/typeddict?
That way, we may not need this recursive helper function anymore, and possibly can do away with process_field_entry_python
entirely, since items.sort_by(|(a, _, _), (b, _, _)| a.cmp(b))
is already happening in main_serde_serialize
and main_to_python
.
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 for guiding me.
I did a refactor based on your advice!
However, i still have to add a few functions to ensure that we dont repeat our code too much.
@@ -242,24 +339,67 @@ impl GeneralFieldsSerializer { | |||
// we don't both with `used_fields` here because on unions, `to_python(..., mode='json')` is used |
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.
The comment just above here says "we maintain the order of the input dict", that's not correct anymore!
src/serializers/fields.rs
Outdated
if extra.exclude_none && value.is_none() { | ||
if let Some(field) = op_field { | ||
if field.required { | ||
if !extra.sort_keys { |
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.
Can we swap these branches so we have the true case first followed by the false case? Same for the other instance of if !extra.sort_keys
11501f6
to
200865b
Compare
Hello Pydantic Team! This is my first time contributing to a Rust and Pyo3 related repo.
I am also new in Rust.
Do you think this PR will make sense?
Since I have been trying to do model_dump_json with sort keys too.
This feature should simulate the same as how we use
json.dumps(data, sort_keys=True)
Take note that
field_d
is extra and still manage to sortPlease let me know if I miss out any other features that
sort_keys=True
is suppose to do!Thanks!
Change Summary
allow sorting keys on to_json and to_python by passing in sort_keys
Related issue number
should fix pydantic/pydantic#7424
Might need to create another MR on Python repo though, need to check.
Checklist
pydantic-core
(except for expected changes)Selected Reviewer: @davidhewitt