Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Comparison between Marshmallow and Colander
import timeit
import uuid
import colander
import marshmallow
class BarList(colander.SequenceSchema):
item = colander.SchemaNode(
colander.Integer(), validator=colander.Range(min=1))
class SignupSchema(colander.MappingSchema):
@staticmethod
def schema_type():
return colander.Mapping(unknown='preserve')
username = colander.SchemaNode(colander.String())
foo = colander.SchemaNode(
colander.Integer(), validator=colander.Range(min=1))
bar = BarList()
@colander.deferred
def def_uuid(node, kw):
return str(uuid.uuid4())
@colander.deferred
def def_validator(node, kw):
return colander.Function(lambda v: kw['bound'] == v)
class SignupSchemaWithDeferred(SignupSchema):
uuid = colander.SchemaNode(colander.String(), missing=def_uuid)
bound = colander.SchemaNode(colander.String(), validator=def_validator)
class SignupSchemaM(marshmallow.Schema):
class Meta:
strict = True
ordered = True
preserve = True
username = marshmallow.fields.String(required=True)
foo = marshmallow.fields.Integer(
required=True,
validate=[marshmallow.validate.Range(min=1)])
bar = marshmallow.fields.List(marshmallow.fields.Integer(
validate=[marshmallow.validate.Range(min=1)]), many=True)
@marshmallow.post_load(pass_original=True)
def _add_unknown(self, data, original):
"""Preserve unknown keys during deserialization."""
for key, val in original.items():
if key not in self.fields:
data[key] = val
return data
class SignupSchemaContextM(SignupSchemaM):
uuid = marshmallow.fields.String(missing=lambda: str(uuid.uuid4()))
bound = marshmallow.fields.String()
@marshmallow.validates('bound')
def validate_bound(self, value):
if self.context['bound'] != value:
raise marshmallow.ValidationError('WRONG!')
data = {'foo': 1, 'bar': [1, 2, 3],
'bound': 'YYYY',
'baz': {'a': 'test',
'b': ['a', 'b', 'c']},
'username': 'ergo'}
colander_schema = SignupSchema()
def test_colander():
return colander_schema.deserialize(data)
colander_bind_schema = SignupSchemaWithDeferred()
def test_colander_bind():
schema = colander_bind_schema.bind(bound='YYYY')
return schema.deserialize(data)
ma_schema = SignupSchemaM()
def test_marshmallow():
return ma_schema.load(data)
ma_context_schema = SignupSchemaContextM()
ma_context_schema.context.setdefault('bound', 'YYYY')
def test_marshmallow_context():
return ma_context_schema.load(data)
print(test_colander_bind())
print(test_marshmallow_context())
c_result = timeit.timeit(test_colander, number=10000)
m_result = timeit.timeit(test_marshmallow, number=10000)
print(f'Colander took {c_result:.4f}')
print(f'Marshmallow took {m_result:.4f}')
print('-----------------------')
print(f'Marshmallow took {m_result/c_result:.2f}x of Colander execution time')
print('\nNow testing with binds/context\n')
c_result = timeit.timeit(test_colander_bind, number=10000)
m_result = timeit.timeit(test_marshmallow_context, number=10000)
print(f'Colander w/bind took {c_result:.4f}')
print(f'Marshmallow w/context took {m_result:.4f}')
print('-----------------------')
print(f'Marshmallow w/context took {m_result/c_result:.2f}x of Colander w/bind execution time')
@sloria

This comment has been minimized.

Copy link
Owner Author

sloria commented Apr 12, 2018

Marshmallow 2

Colander took 0.1307
Marshmallow took 0.3534
-----------------------
Marshmallow took 2.70x of Colander execution time

Now testing with binds/context

Colander w/bind took 3.8629
Marshmallow w/context took 0.5908
-----------------------
Marshmallow w/context took 0.15x of Colander w/bind execution time

Marshmallow 3

Colander took 0.1407
Marshmallow took 0.3630
-----------------------
Marshmallow took 2.58x of Colander execution time

Now testing with binds/context

Colander w/bind took 3.6548
Marshmallow w/context took 0.5586
-----------------------
Marshmallow w/context took 0.15x of Colander w/bind execution time
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.