-
Notifications
You must be signed in to change notification settings - Fork 10
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
#100 Propagate meta dict to Nested dataclasses #106
Conversation
Codecov Report
@@ Coverage Diff @@
## master #106 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 6 6
Lines 446 456 +10
Branches 69 72 +3
=========================================
+ Hits 446 456 +10
Continue to review full report at Codecov.
|
@@ -130,7 +130,7 @@ def class_schema( | |||
attributes[field.name] = field_for_schema( | |||
hints.get(field.name, field.type), | |||
_get_field_default(field), | |||
field.metadata, | |||
{**meta, **field.metadata}, |
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.
Because we're using field.metadata
second here, the parent Schema's meta
dict will not overwrite a Nested field's potential metadata params.
@@ -289,7 +289,8 @@ def field_for_schema( | |||
|
|||
if field is None: | |||
nested = forward_reference or class_schema(typ) | |||
field = marshmallow.fields.Nested(nested) | |||
params = {k: v for k, v in metadata.items() if type(k) is str} |
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.
Because we are filtering for string keys, we don't have to worry about the Sentinel key breaking any typing expectations downstream.
@@ -289,7 +289,8 @@ def field_for_schema( | |||
|
|||
if field is None: | |||
nested = forward_reference or class_schema(typ) | |||
field = marshmallow.fields.Nested(nested) | |||
params = {k: v for k, v in metadata.items() if type(k) is str} | |||
field = marshmallow.fields.Nested(nested, **params) |
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.
Because the Nested class accepts **kwargs
in its signature, we don't have to worry about extraneous params breaking anything downstream.
edit: Did not notice that that PR was already posted by someone else |
@altendky Would you like me to refactor this into a feature flag that we can check for in the |
We need to know |
It seems like maybe we should be able to specify some propagating settings and some not. Like separate @python-desert, I'm not quite following, sorry. The meta class seems to be mostly about serialization with a little deserialization. As you said, it needs to be passed pretty earlier in this curious process of classes that get instantiated to seemingly hold no state (that I have dealt with) and then have methods called on them. But I'm not clear if an error is being pointed out about this proposal. |
If it helps illustrate, I'd like to clarify the motivation for this proposed change: The primary use case behind this feature is that when we work with DTOs (e.g. HTTP requests or RabbitMQ messages) and DAOs (e.g. Mongo documents or Redis maps), we cannot always trust that the response objects we receive back will perfectly align with what we expect. This is the reason why the The current design with Desert (and with Marshmallow) only allows us to use the About @python-desert 's comment -- If we don't want to pass along these params, then another solution I could refactor this into would be to just change this to be a branch such that only the |
I agree it has value. It certainly plays into APIs where adding new items is allowed and considered backward compatible as old clients are expected to ignore them. And I'm sure various other cases. |
What happens when |
The ones we'd want to push are the ones that are a policy, like "how do we handle unknown keys". Maybe there are others. Also maybe worth talking about alternative places to set policy, such as |
This is a really good point that I hadn't considered fully. Because of this counterexample, maybe the right thing to do would be for this to be a setting that we can change in Desert for everything, rather than to just specify it by schema. For my own personal use cases, I'd argue that the more permissive option should win but I'm not sure if that should be the policy. |
Just an idea -- wouldn't it be sufficient to just subclass the dataclass in question to effectively duplicate it and ensure that its Schema can have multiple settings? For example: @dataclass
class MorePermissive:
whatever: int
@dataclass
class LessPermissive(MorePermissive):
pass
foo = desert.schema(MorePermissive)
bar = desert.schema(LessPermissive, meta={"unknown": marshmallow.EXCLUDE}) The benefit we get from this approach is that we can have multiple schemas for the same dataclass and use the most permissive version of it for function argument purposes. |
Hi there,
This PR changes default behavior for Nested dataclasses so that the
meta
dict that we pass intodesert.schema
will be propagated to all child dataclasses.I've also taken the liberty of adding a test to demonstrate that it works as intended.
If you feel that this should not be default behavior, we can make this functionality live behind a feature flag
meta
dict that we can branch off of.Fixes #100