Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save btall/043c489039150ae8ef4b5828ca7cabe0 to your computer and use it in GitHub Desktop.
Save btall/043c489039150ae8ef4b5828ca7cabe0 to your computer and use it in GitHub Desktop.
colander workaround for the empty MappingSchema
#!/usr/bin/env python
from __future__ import print_function
import sys
import colander
from contextlib import contextmanager
person_1 = {
'firstname': 'foo',
'lastname': 'bar',
'address': {}
}
person_2 = {
'firstname': 'foobar',
'lastname': 'barbaz',
'address': {
'city': 'Paris',
'country': 'France',
'zipcode': 75009
}
}
class Address(colander.MappingSchema):
city = colander.SchemaNode(colander.String())
country = colander.SchemaNode(colander.String())
zipcode = colander.SchemaNode(colander.Integer())
class Person(colander.Schema):
lastname = colander.SchemaNode(colander.String())
firstname = colander.SchemaNode(colander.String())
address = Address(require=False, missing=colander.null)
@contextmanager
def _handle_empty_address(self, cstruct):
"""
Skip it, just the time to validation
And reinject it to the end of validating.
"""
try:
address = cstruct['address']
is_empty = all((address[field] == colander.null) for field in address)
if is_empty:
cstruct['address'] = colander.null
yield cstruct
finally:
cstruct['address'] = address
def deserialize(self, cstruct=colander.null):
with self._handle_empty_address(cstruct) as cstruct:
cstruct = super(Person, self).deserialize(cstruct)
return cstruct
def main():
validator = Person()
for person in (person_1, person_2):
try:
cstruct = validator.deserialize(person)
except colander.Invalid as err:
print(err, file=sys.stderr)
else:
print('person={} cstruct={}'.format(person, cstruct))
if __name__ == '__main__':
sys.exit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment