-
Notifications
You must be signed in to change notification settings - Fork 832
derive(FromPyObject): adds default option #4829
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
a3d6c7d
to
baf2fce
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! This looks pretty good already.
Note that the default value is only used if the key fetching fails (item/attr not present...) but errors are still raised if the value extraction fails
I think this makes sense 👍.
Some points that come to my mind:
- We should document this option in the
FromPyObject
section of the guide, probably with some example showcasing the error decision from above. - It looks like this should work for tuple structs (we should add a test), how about complex enums?
- How does this interact with
from_py_with
? I would say only one or the other makes sense, and we should error if both are supplied.
quote!(Default::default()) | ||
}; | ||
quote!(if let Ok(value) = #getter { |
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.
Default
and Ok
are unhygienic, we should add this option to the hygiene
tests.
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.
Fixed. Thank you for spotting!
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 idea makes sense to me, agreed with all the above 👍
Possible design question: serde uses Should we be doing similar? I wonder what the advantage of the function is, I guess it's more general? Is it for hygiene reasons? 🤔 |
I think this is mostly for historical reasons from before Rust allowed expressions (or identifiers) in attributes. Nowadays making use of proper tokens instead of stringly typing it is prefered I would say. IMO it is also way more convenient to just write the expression inline instead of having to write a function for every default. |
True, and if we allow arbitrary expressions we can always allow something like |
Thank you for the reviews. I will apply the changes you asked for.
The
It seems fairly well defined to me and is consistent with the behavior of I am going to add an extra test covering the usage of the two options together |
Ah, having it written out like that makes sense. (In my head it felt more convoluted around error cases 😁) I'm good with keeping it as is then. Maybe this is also a good addition for the guide section.
Sounds good, thank you! |
Takes an optional expression to set a custom value that is not the one from the Default trait
adb2541
to
9cbf084
Compare
@Icxolu Thank you again for your review! I have improved test coverage and fixed hygiene.
Done!
Yes, but it would need some extra code. I would prefer to do it in a follow-up MR. On complex enums, I guess it would work too with the surprising behavior that a variant |
6f5a8de
to
15b354b
Compare
15b354b
to
1df9a53
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.
Yes, but it would need some extra code. I would prefer to do it in a follow-up MR.
Sure thing. In that case we should probably make sure here, that we properly error out if applied to tuple structs or enums with some ui tests until we add additional support in the future.
guide/src/conversions/traits.md
Outdated
- `pyo3(default)`, `pyo3(default = ...)` | ||
- if the argument is set, uses the given default value. | ||
- in this case, the argument must be a Rust expression returning a value of the desired Rust type. | ||
- if the argument is not set, [`Default::default`](https://doc.rust-lang.org/std/default/trait.Default.html#tymethod.default) is used. | ||
- this attribute is only supported on named struct fields. |
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 think we should mention here, that the default is used only if the lookup failed (not when the extraction failed).
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.
Done!
9834b90
to
b7ef575
Compare
b7ef575
to
4e6f1f7
Compare
Thank you! After doing some testing, the current code already works with enum variant named fields so I added support to them. I also included an error when all fields are set as |
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 you! I think this looks perfect now 🚀
Takes an optional expression to set a custom value that is not the one from the
Default
traitNote that the default value is only used if the key fetching fails (item/attr not present...) but errors are still raised if the value extraction fails
Issue #4643