-
Notifications
You must be signed in to change notification settings - Fork 4
Add marshmallow helpers #24
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
eebed9c to
8e8516b
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.
Awesome!
You still need to expose the new classes, right? I would just make the marshmallow module public and that's it, so we don't mix the extension with the actual quantities code.
I mean, not really, it is enough to use the |
|
But you still need to expose at least |
|
BTW, I would expose the fields too, just in case other people want to make some advanced use and do their own mapping or something. |
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.
It would also be nice to add some tests for this.
I have! I just forgot to add that to the commit! |
|
Updated
|
029065b to
cbd3e48
Compare
Haha, so much for a different PR... |
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.
Some more comments, but really cool stuff.
| _QUANTITY_SUBCLASSES = [ | ||
| Current, | ||
| Energy, | ||
| Frequency, | ||
| Percentage, | ||
| Power, | ||
| Temperature, | ||
| Voltage, | ||
| ] | ||
|
|
||
|
|
||
| def _create_quantity_field_class( | ||
| quantity_subclass: Type[Quantity], | ||
| ) -> Type[fields.Field]: | ||
| """Dynamically create a QuantityField subclass for a given Quantity subclass.""" | ||
| class_name = f"{quantity_subclass.__name__}Field" | ||
|
|
||
| field_class: Type[fields.Field] = type( | ||
| class_name, | ||
| (_QuantityField,), | ||
| { | ||
| "__init__": lambda self, **kwargs: super(field_class, self).__init__( | ||
| field_type=quantity_subclass, **kwargs | ||
| ), | ||
| "__module__": __name__, | ||
| }, | ||
| ) | ||
|
|
||
| return field_class |
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.
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 get the sentiment, but.. I am pretty sure no-one really needs to use those classes directly
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.
Like, if we want documentation for this, i would just refer people to the QuantityField class which in that case we should make public then.
but again, I don't see any use-case why someone wants to access them.
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's a fair point, but it really makes it virtually impossible to discover these classes, and makes reading the docs of the module (which is important because of QuantitySchema) very awkward.
To be honest if we are going to keep this code as it is, then I wouldn't export those classes at all, I think exporting them like this is basically useless and makes reading the docs about the important stuff more difficult.
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 agree exporting those classes is useless :P
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.
Though I guess that exported variable here can be used for a users own Schema.TYPE_MAPPING, so there is that.
| class _QuantityField(fields.Field): | ||
| """Custom field for Quantity objects supporting per-field serialization configuration.""" | ||
|
|
||
| def __init__(self, field_type: Type[Quantity], **kwargs: Any) -> None: |
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 would specify the options explicitly here (like serialize_as_string_default), and only leave the **kwargs for the options that are forwarded to the super() if possible. Otherwise is hard to know which options it really takes in the docs (for the parent, you can always go check the parent class docs).
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 seems.. complicated?
For one, that field class and init c'tor is pretty much never used directly.
Why not keep the configuration as it is done here, through the "metadata" key
where we also configure all the other field specific things like validation, key name etc..
Like, I see zero reason to do this one thing differently than all the other things we can configure per-field?
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 guess I just don't understand this code very well. I thought this was a base class, but now I see it takes the field_type as argument instead. I don't know, compared to the previous version where there was a class for each field, for me this is extremely hard to read and understand, that's my main complain 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.
It took me a while as well 😅
This class works for all quantities.
The only thing derived classes need to do is pass their specific quantity type.
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.
Deserialization automatically detects the type (float/str), serialization uses the schema default which can be overridden by a field-specific key.
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 still don't understand why, specially now that boilerplate code like this can be automatically generated with a few tabs, we want to keep dynamic unreadable code instead of having some much more obvious as self-explanatory. I see zero advantages of this approach compared to the verbose previous version and a lot of drawbacks.
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 still don't understand why
Why what? Why dynamic creation? Because that would be a different comment thread..
I am not strongly against it, I just see zero benefit as noone uses the resulting code directly..
And I doubt it makes things much clearer really.. just lots of noise
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.
From the end user PoV I'm fine with making all the fields "private" and not export them at all if we think nobody will use them. For me one or the other, but the current approach it's just exporting something that's unusable for anyone reading the docs and only adding confusion.
In terms of code, I really don't understand this code and would really prefer not to have it in the repository, again, specially when there is a super clear and easy alternative. There is no need for any black magic here, it should be very simple. The only reason I can see for it is to save a few keystrokes.
That said, I don't feel strong enough to keep investing time on it, I'm fine to merge as is as long as we don't export the fields for now, then we can see in a future PR to improve it to be able to export the fields if there is a need for it.
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 see I'm always late with my comments that end up in "I'm fine with merging as is" 😝
|
Removed EXCLUDE and updated documentation extensively |
Signed-off-by: Mathias L. Baumann <[email protected]>
|
Updated: Now explicitly writing out all QuantityField subclasses |
Instead of dynamic generation we now generate the whole class so it can be discovered and documented. Signed-off-by: Mathias L. Baumann <[email protected]>

No description provided.