I noticed that if you use a nested field for values in a structured Dict, the context is not automatically given to the nested schema. Is there a way to pass it the context?
Example:
class Inner(Schema):
foo = fields.String()
@validates('foo')
def validate_foo(self, value):
if 'foo_context' not in self.context:
raise ValidationError('no context!')
class Outer(Schema):
bar = fields.Dict(values=fields.Nested(Inner))
# gives no error:
Inner(context={'foo_context': 'foo'}).load({'foo': 'some foo'})
# gives 'no context!' error:
Outer(context={'foo_context': 'foo'}).load({'bar': { 'key': {'foo': 'some foo'}}})
I'm not familiar with the "context" feature, but from a quick glance, this looks like a bug.
Yeah, AFAIK, Dict does not pass down context to it's inner fields, like Nested does.
Does List pass the context correctly?
I'm afraid it does not.
It looks like List works as expected. The following test passes on 2.x-line:
def test_nested_list_fields_inherit_context(self):
class InnerSchema(Schema):
foo = fields.Field()
@validates('foo')
def validate_foo(self, value):
if 'foo_context' not in self.context:
raise ValidationError('Missing context')
class OuterSchema(Schema):
bars = fields.List(fields.Nested(InnerSchema()))
inner = InnerSchema(strict=True)
inner.context['foo_context'] = 'foo'
assert inner.load({'foo': 42})
outer = OuterSchema(strict=True)
outer.context['foo_context'] = 'foo'
assert outer.load({'bars': [{'foo': 42}]})
And I verified that the test fails if outer.context['foo_context'] = 'foo' is removed.
Dict needs to copy the _add_to_schema logic from List to link the "container" to the parent.
Thanks for the quick fix everyone!