Skip to content

Commit

Permalink
Fix propagation of options to Nested containers
Browse files Browse the repository at this point in the history
  • Loading branch information
lafrech committed Dec 4, 2018
1 parent 69352c4 commit d05db56
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
12 changes: 12 additions & 0 deletions marshmallow/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,9 @@ def __init__(self, cls_or_instance, **kwargs):
'marshmallow.base.FieldABC',
)
self.container = cls_or_instance
if isinstance(self.container, Nested):
self.only = self.container.only
self.exclude = self.container.exclude

def get_value(self, obj, attr, accessor=None):
"""Return the value for a given key from an object."""
Expand All @@ -587,6 +590,9 @@ def _bind_to_schema(self, field_name, schema):
self.container = copy.deepcopy(self.container)
self.container.parent = self
self.container.name = field_name
if isinstance(self.container, Nested):
self.container.only = self.only
self.container.exclude = self.exclude

def _serialize(self, value, attr, obj, **kwargs):
if value is None:
Expand Down Expand Up @@ -1208,6 +1214,9 @@ def __init__(self, values=None, keys=None, **kwargs):
'marshmallow.base.FieldABC',
)
self.value_container = values
if isinstance(self.value_container, Nested):
self.only = self.value_container.only
self.exclude = self.value_container.exclude
if keys is None:
self.key_container = None
elif isinstance(keys, type):
Expand All @@ -1231,6 +1240,9 @@ def _bind_to_schema(self, field_name, schema):
self.value_container = copy.deepcopy(self.value_container)
self.value_container.parent = self
self.value_container.name = field_name
if isinstance(self.value_container, Nested):
self.value_container.only = self.only
self.value_container.exclude = self.exclude
if self.key_container:
self.key_container = copy.deepcopy(self.key_container)
self.key_container.parent = self
Expand Down
66 changes: 66 additions & 0 deletions tests/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,3 +240,69 @@ class MySchema(Schema):
elif field_unknown == RAISE or (schema_unknown == RAISE and not field_unknown):
with pytest.raises(ValidationError):
MySchema().load({'nested': {'x': 1}})

class TestListNested:

@pytest.mark.parametrize('param', ('only', 'exclude'))
def test_list_nested_only_and_exclude_propagated_to_nested(self, param):

class Child(Schema):
name = fields.String()
age = fields.Integer()

class Family(Schema):
children = fields.List(fields.Nested(Child))

schema = Family(**{param: ['children.name']})
assert getattr(schema.fields['children'].container, param) == {'name'}

@pytest.mark.parametrize('param', ('only', 'exclude'))
def test_list_nested_only_and_exclude_merged_with_nested(self, param):

class Child(Schema):
name = fields.String()
surname = fields.String()
age = fields.Integer()

class Family(Schema):
children = fields.List(fields.Nested(Child, **{param: ('name', 'surname')}))

schema = Family(**{param: ['children.name', 'children.age']})
expected = {
'only': {'name'},
'exclude': {'name', 'surname', 'age'},
}[param]
assert getattr(schema.fields['children'].container, param) == expected

class TestDictNested:

@pytest.mark.parametrize('param', ('only', 'exclude'))
def test_dict_nested_only_and_exclude_propagated_to_nested(self, param):

class Child(Schema):
name = fields.String()
age = fields.Integer()

class Family(Schema):
children = fields.Dict(values=fields.Nested(Child))

schema = Family(**{param: ['children.name']})
assert getattr(schema.fields['children'].value_container, param) == {'name'}

@pytest.mark.parametrize('param', ('only', 'exclude'))
def test_dict_nested_only_and_exclude_merged_with_nested(self, param):

class Child(Schema):
name = fields.String()
surname = fields.String()
age = fields.Integer()

class Family(Schema):
children = fields.Dict(values=fields.Nested(Child, **{param: ('name', 'surname')}))

schema = Family(**{param: ['children.name', 'children.age']})
expected = {
'only': {'name'},
'exclude': {'name', 'surname', 'age'},
}[param]
assert getattr(schema.fields['children'].value_container, param) == expected

0 comments on commit d05db56

Please sign in to comment.