diff --git a/.travis.yml b/.travis.yml
index 1a56f26..bb38d26 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,9 +1,7 @@
language: python
python:
- - "2.7"
-# command to install dependencies
-install: "pip install -r requirements.txt"
-# command to run tests
+- '3.6'
+install: pip install -r requirements.txt
script: py.test
deploy:
provider: script
@@ -12,5 +10,5 @@ deploy:
branch: master
env:
global:
- - ENCRYPTION_LABEL: "3e8c259749ef"
- - COMMIT_AUTHOR_EMAIL: "voidfiles@gmail.com"
+ - ENCRYPTION_LABEL: 1dbde6ec09a5
+ - COMMIT_AUTHOR_EMAIL: voidfiles@gmail.com
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..9340b01
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,8 @@
+FROM python:3
+
+
+ADD . /opt/code
+WORKDIR /opt/code/
+
+RUN pip install -r requirements.txt
+CMD ["python", "benchmark.py"]
diff --git a/README.md b/README.md
index cd59d92..34eefc2 100644
--- a/README.md
+++ b/README.md
@@ -6,13 +6,27 @@ You can find the latest benchmarks on [this page](https://voidfiles.github.io/py
Currently the following projects are benchmarked.
-* [Django REST framework](http://www.django-rest-framework.org/)
-* [serpy](https://github.com/clarkduvall/serpy)
-* [marshmallow](https://marshmallow.readthedocs.io/en/latest/)
+* [Django REST Framework](http://www.django-rest-framework.org/)
+* [serpy](http://serpy.readthedocs.io/)
+* [Marshmallow](https://marshmallow.readthedocs.io/en/latest/)
* [Strainer](https://github.com/voidfiles/strainer)
-* [Lollipop](https://github.com/maximkulkin/lollipop)
+* [Lollipop](http://lollipop.readthedocs.io/en/latest/)
+* [Kim](http://kim.readthedocs.io/en/latest/)
+* [Toasted Marshmallow](https://github.com/lyft/toasted-marshmallow)
+* [Colander](https://docs.pylonsproject.org/projects/colander/en/latest/)
+* [Lima](https://github.com/b6d/lima/)
+- [Serpyco](https://gitlab.com/sgrignard/serpyco)
+* [Avro](https://avro.apache.org/)
-Along with a baseline of a custom function that doesn't use a framework.
+Along with a baseline custom function that doesn't use a framework.
-Each framework is asked to serialize a list of 2 objects a 1000 times, and then 1 object a 1000 times.
+## Running the test suite
+
+A Docker container is bundled with the repository which you can use to run the benchmarks. Firstly make sure you have Docker installed.
+
+1. Install Docker
+
+2. Build the container `$ docker-compose build`
+
+3. Run the tests. `$ docker-compose run --rm tests`
diff --git a/benchmark.py b/benchmark.py
old mode 100644
new mode 100755
index e8d9dd9..c757131
--- a/benchmark.py
+++ b/benchmark.py
@@ -2,10 +2,10 @@
from tabulate import tabulate
from contextlib import contextmanager
-from subjects import (marsh, rf, serp, strain, hand, loli)
+from subjects import (marsh, rf, serp, strain, col, hand, loli, k, lim, tmarsh, avro, pickle, serpy)
from data import ParentTestObject
-SUBJECTS = (marsh, rf, serp, strain, hand, loli)
+SUBJECTS = (marsh, rf, serp, strain, col, hand, loli, k, lim, tmarsh, avro, pickle, serpy)
test_object = ParentTestObject()
@@ -19,17 +19,17 @@ def timer(tracker):
def test_many(func, limit=1000):
- for i in xrange(0, limit):
+ for i in range(0, limit):
subject.serialization_func([test_object, test_object], True)
def test_one(func, limit=1000):
- for i in xrange(0, limit):
+ for i in range(0, limit):
subject.serialization_func(test_object, False)
table = []
for subject in SUBJECTS:
- row = [subject.__name__]
+ row = [subject.name]
test_many(subject.serialization_func, 2) # Warmup
with timer(row):
@@ -42,4 +42,8 @@ def test_one(func, limit=1000):
table += [row]
table = sorted(table, key=lambda x: x[1] + x[2])
-print tabulate(table, headers=['Library', 'Many Objects', 'One Object',])
+relative_base = min([x[1] + x[2] for x in table])
+for row in table:
+ result = (row[1] + row[2]) / relative_base
+ row.append(result)
+print(tabulate(table, headers=['Library', 'Many Objects (seconds)', 'One Object (seconds)', 'Relative']))
diff --git a/create_report.sh b/create_report.sh
index 8e2adf2..320a75c 100755
--- a/create_report.sh
+++ b/create_report.sh
@@ -1,8 +1,18 @@
#! /bin/bash
cat README.md > REPORT.md
-echo "
" >> REPORT.md
+echo "\`\`\`" >> REPORT.md
python benchmark.py >> REPORT.md
-echo " " >> REPORT.md
+echo "\`\`\`" >> REPORT.md
+cat disscussion.md >> REPORT.md
mkdir -p out
-python -m markdown REPORT.md > out/index.html
+echo '' > out/index.html
+echo '' >> out/index.html
+echo ' ' >> out/index.html
+echo '' >> out/index.html
+echo '' >> out/index.html
+echo '' >> out/index.html
+python -m markdown -x markdown.extensions.fenced_code REPORT.md >> out/index.html
+echo '
' >> out/index.html
+echo '' >> out/index.html
+echo '' >> out/index.html
diff --git a/data.py b/data.py
index e7aa044..ff11bab 100644
--- a/data.py
+++ b/data.py
@@ -11,7 +11,7 @@ class ParentTestObject(object):
def __init__(self):
self.foo = 'bar'
self.sub = ChildTestObject()
- self.subs = [ChildTestObject(i) for i in xrange(10)]
+ self.subs = [ChildTestObject(i) for i in range(10)]
def bar(self):
return 5
diff --git a/deploy-key.enc b/deploy-key.enc
new file mode 100644
index 0000000..4c226d2
Binary files /dev/null and b/deploy-key.enc differ
diff --git a/deploy.sh b/deploy.sh
index 1965fda..40dbb59 100755
--- a/deploy.sh
+++ b/deploy.sh
@@ -48,10 +48,13 @@ ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key"
ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv"
ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR}
ENCRYPTED_IV=${!ENCRYPTED_IV_VAR}
-openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in ../deploy_key.enc -out deploy_key -d
-chmod 600 deploy_key
+openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in ../deploy-key.enc -out deploy-key -d
+chmod 600 deploy-key
eval `ssh-agent -s`
-ssh-add deploy_key
+ssh-add deploy-key
+
+rm -fR __pycache__
+rm -fR subjects/__pycache__
# Now that we're all set up, we can push.
git push $SSH_REPO $TARGET_BRANCH
diff --git a/deploy_key.enc b/deploy_key.enc
deleted file mode 100644
index 878c05c..0000000
Binary files a/deploy_key.enc and /dev/null differ
diff --git a/disscussion.md b/disscussion.md
new file mode 100644
index 0000000..1494574
--- /dev/null
+++ b/disscussion.md
@@ -0,0 +1,127 @@
+## The Benchmark
+
+Each framework is asked to serialize a list of 2 objects a 1000 times, and then 1 object a 1000 times.
+
+This is the current object that is being serialized.
+
+```python
+class ChildTestObject(object):
+ def __init__(self, multiplier=None):
+ self.w = 1000 * multiplier if multiplier else 100
+ self.x = 20 * multiplier if multiplier else 20
+ self.y = 'hello' * multiplier if multiplier else 'hello'
+ self.z = 10 * multiplier if multiplier else 10
+
+
+class ParentTestObject(object):
+ def __init__(self):
+ self.foo = 'bar'
+ self.sub = ChildTestObject()
+ self.subs = [ChildTestObject(i) for i in xrange(10)]
+
+ def bar(self):
+ return 5
+
+benchmark_object = ParentTestObject()
+```
+
+## Discussion
+
+Serialization from python objects to JSON, XML, or other transmission formats is a common task for many web related projects. In order to fill that need a number of frameworks have arised. While their aims are similar, they don't all share the same attributes. Here are how some of the features comapre.
+
+
+
+* **Serialization**: Does the framework provide a way of serializing python objects to simple datastructures
+* **Encoding**: Does the framework provide a way of encoding data into a wire format
+* **Deserialization**: Does the framework provide a way of deserializing simple data structures into complex data structures
+* **Validation**: Does the framework provide a way of validating datastructures, and reprorting error conditions
+* **Part of Framework**: Is serialization apart of a larger framework
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..21ff9bc
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,6 @@
+tests:
+ build: .
+ command: python benchmark.py
+ dockerfile: Dockerfile
+ volumes:
+ - .:/opt/code
diff --git a/requirements.txt b/requirements.txt
index 172f71b..8d71761 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,9 +1,14 @@
-marshmallow==2.10.4
-serpy==0.1.1
-djangorestframework==3.5.3
-django==1.9
+toastedmarshmallow==2.15.2.post1
+serpy==0.3.1
+colander==1.7.0
+djangorestframework==3.9.4
+django==2.2.13
pytest
-pystrainer==0.0.5
+pystrainer==1.3.0
tabulate==0.7.7
-lollipop==1.0.1
+lollipop==1.1.7
+py-kim==1.2.2
+lima==0.5
markdown
+avro-python3==1.8.2
+serpyco==1.1.0
\ No newline at end of file
diff --git a/subjects/avro.py b/subjects/avro.py
new file mode 100644
index 0000000..fe797b2
--- /dev/null
+++ b/subjects/avro.py
@@ -0,0 +1,74 @@
+import avro.schema
+from avro.io import DatumWriter
+
+name = 'Avro'
+
+class NullWriter(object):
+ def write(self, *args, **kwargs):
+ pass
+
+ def write_utf8(self, *args, **kwargs):
+ self.write(args, kwargs)
+
+ def write_int(self, *args, **kwargs):
+ self.write(args, kwargs)
+
+ def write_long(self, *args, **kwargs):
+ self.write(args, kwargs)
+
+schema_name_tracker = avro.schema.Names()
+
+child_test_object_schema = avro.schema.SchemaFromJSONData({
+ "namespace": "benchmark.avro",
+ "type": "record",
+ "name": "childTestObject",
+ "fields": [
+ {"name": "w", "type": "int"},
+ {"name": "x", "type": "int"},
+ {"name": "y", "type": "string"},
+ {"name": "z", "type": "int"}
+ ]
+}, names=schema_name_tracker)
+
+parent_test_object_schema = avro.schema.SchemaFromJSONData({
+ "namespace": "benchmark.avro",
+ "type": "record",
+ "name": "parentTestObject",
+ "fields": [
+ {"name": "foo", "type": "string"},
+ {"name": "sub", "type": "childTestObject"},
+ {
+ "name": "subs",
+ "type": {
+ "type": "array",
+ "items": "childTestObject"
+ }
+ }
+ ]
+}, names=schema_name_tracker)
+
+datum_writer = DatumWriter(writer_schema=parent_test_object_schema)
+null_binary_writer = NullWriter()
+
+# Avro for Python can't directly serialize a class, it must be a dictionary.
+def nested_class_to_dict(obj):
+ if not hasattr(obj,"__dict__"):
+ return obj
+ result = {}
+ for key, val in obj.__dict__.items():
+ if key.startswith("_"):
+ continue
+ element = []
+ if isinstance(val, list):
+ for item in val:
+ element.append(nested_class_to_dict(item))
+ else:
+ element = nested_class_to_dict(val)
+ result[key] = element
+ return result
+
+def serialization_func(to_serialize, many):
+ if many:
+ return [datum_writer.write(nested_class_to_dict(obj), null_binary_writer) for obj in to_serialize]
+ else:
+ return datum_writer.write(nested_class_to_dict(to_serialize), null_binary_writer)
diff --git a/subjects/col.py b/subjects/col.py
new file mode 100755
index 0000000..fe2e3b5
--- /dev/null
+++ b/subjects/col.py
@@ -0,0 +1,111 @@
+import colander
+from colander import null
+
+name = 'Colander'
+
+
+class ObjectType(colander.Mapping):
+ """
+ A colander type representing a generic python object
+ (uses colander mapping-based serialization).
+ """
+
+ def serialize(self, node, appstruct):
+ appstruct = appstruct.__dict__
+ return super(ObjectType, self).serialize(node, appstruct)
+
+ def deserialize(self, node, cstruct):
+ data = super(ObjectType, self).deserialize(node, cstruct)
+ appstruct = node.instance.__class__()
+ appstruct.__dict__.update(data)
+ return appstruct
+
+
+class ObjectSchema(colander.SchemaNode):
+ schema_type = ObjectType
+ instance = None
+
+ def serialize(self, appstruct):
+ if not self.instance:
+ # set the instance on all child schema nodes as they
+ # may need to access the instance environment
+ self.instance = appstruct
+ for subnode in self.children:
+ if isinstance(subnode, MethodSchema):
+ setattr(subnode, 'instance', appstruct)
+ return super(ObjectSchema, self).serialize(appstruct)
+
+ def deserialize(self, cstruct):
+ appstruct = super(ObjectSchema, self).deserialize(cstruct)
+ if not self.instance:
+ self.instance = appstruct
+ return appstruct
+
+
+class CallableSchema(colander.SchemaNode):
+ def serialize(self, appstruct):
+ if appstruct is null:
+ return null
+ appstruct = appstruct()
+ return super(CallableSchema, self).serialize(appstruct)
+
+ def deserialize(self, cstruct):
+ if cstruct is null:
+ return null
+ appstruct = super(CallableSchema, self).deserialize(cstruct)
+ return lambda: appstruct
+
+
+class MethodSchema(CallableSchema):
+ def serialize(self, appstruct):
+ if appstruct is null:
+ appstruct = getattr(self.instance, self.name)
+ return super(MethodSchema, self).serialize(appstruct)
+
+
+class Differential(colander.SchemaNode):
+ def __init__(self, typ, differential=0):
+ self.differential = differential
+ super(Differential, self).__init__(typ)
+
+ def serialize(self, appstruct):
+ # operator could be overloaded by the appstruct class if necessary
+ appstruct += self.differential
+ return super(Differential, self).serialize(appstruct)
+
+ def deserialize(self, cstruct):
+ # operator could be overloaded by the appstruct class if necessary
+ appstruct = super(Differential, self).deserialize(cstruct)
+ appstruct -= self.differential
+ return appstruct
+
+
+class ChildSchema(ObjectSchema):
+ w = colander.SchemaNode(colander.Int())
+ y = colander.SchemaNode(colander.String())
+ x = Differential(colander.Int(), 10)
+ z = colander.SchemaNode(colander.Int())
+
+
+class ChildListSchema(colander.SequenceSchema):
+ sub = ChildSchema()
+
+
+class ParentSchema(ObjectSchema):
+ foo = colander.SchemaNode(colander.String())
+ bar = MethodSchema(colander.Int())
+ sub = ChildSchema()
+ subs = ChildListSchema()
+
+
+class ParentListSchema(colander.SequenceSchema):
+ parents = ParentSchema()
+
+
+unit_schema = ParentSchema()
+seq_schema = ParentListSchema()
+
+
+def serialization_func(obj, many):
+ schema = seq_schema if many else unit_schema
+ return schema.serialize(obj)
diff --git a/subjects/hand.py b/subjects/hand.py
index 15788bd..8e29b8e 100644
--- a/subjects/hand.py
+++ b/subjects/hand.py
@@ -1,4 +1,4 @@
-__name__ = 'Custom'
+name = 'Custom'
def sub_to_cstruct(obj):
diff --git a/subjects/k.py b/subjects/k.py
new file mode 100644
index 0000000..7e49c89
--- /dev/null
+++ b/subjects/k.py
@@ -0,0 +1,42 @@
+from kim import Mapper, field
+
+name = 'kim'
+
+
+class Complex(object):
+ pass
+
+
+class SubResource(object):
+ pass
+
+
+def bar_pipe(session):
+ session.output['bar'] = session.data()
+
+
+def x_pipe(session):
+ session.output['x'] = session.data + 10
+
+
+class SubMapper(Mapper):
+ __type__ = SubResource
+ w = field.String()
+ x = field.String(extra_serialize_pipes={'output': [x_pipe]})
+ y = field.String()
+ z = field.String()
+
+
+class ComplexMapper(Mapper):
+ __type__ = Complex
+ foo = field.String()
+ bar = field.String(extra_serialize_pipes={'output': [bar_pipe]})
+ sub = field.Nested(SubMapper)
+ subs = field.Collection(field.Nested(SubMapper))
+
+
+def serialization_func(obj, many):
+ if many:
+ return ComplexMapper.many().serialize(obj)
+ else:
+ return ComplexMapper(obj=obj).serialize()
diff --git a/subjects/lim.py b/subjects/lim.py
new file mode 100644
index 0000000..4061d9f
--- /dev/null
+++ b/subjects/lim.py
@@ -0,0 +1,28 @@
+import lima
+
+name = 'lima'
+
+
+class SubM(lima.Schema):
+ w = lima.fields.Integer()
+ x = lima.fields.Integer(get=lambda obj: obj.x + 10)
+ y = lima.fields.Integer()
+ z = lima.fields.Integer()
+
+
+class ComplexM(lima.Schema):
+ foo = lima.fields.String()
+ bar = lima.fields.Integer(get=lambda obj: obj.bar())
+ sub = lima.fields.Embed(schema=SubM)
+ subs = lima.fields.Embed(schema=SubM, many=True)
+
+
+schema = ComplexM()
+many_scheam = ComplexM(many=True)
+
+
+def serialization_func(obj, many):
+ if many:
+ return many_scheam.dump(obj)
+ else:
+ return schema.dump(obj)
diff --git a/subjects/loli.py b/subjects/loli.py
index e230409..1c2e247 100644
--- a/subjects/loli.py
+++ b/subjects/loli.py
@@ -1,7 +1,7 @@
from collections import namedtuple
from lollipop.types import Object, String, Integer, List, FunctionField, MethodField
-__name__ = 'Lollipop'
+name = 'Lollipop'
SubS = namedtuple('SubS', ['w', 'x', 'y', 'z'])
ComplexS = namedtuple('ComplexS', ['foo', 'bar', 'sub', 'subs'])
diff --git a/subjects/marsh.py b/subjects/marsh.py
index b0ccc17..34112ff 100644
--- a/subjects/marsh.py
+++ b/subjects/marsh.py
@@ -1,6 +1,6 @@
import marshmallow
-__name__ = 'Marshmallow'
+name = 'Marshmallow'
class SubM(marshmallow.Schema):
@@ -14,8 +14,8 @@ def get_x(self, obj):
class ComplexM(marshmallow.Schema):
- foo = marshmallow.fields.Str()
bar = marshmallow.fields.Int()
+ foo = marshmallow.fields.Str()
sub = marshmallow.fields.Nested(SubM)
subs = marshmallow.fields.Nested(SubM, many=True)
diff --git a/subjects/pickle.py b/subjects/pickle.py
new file mode 100644
index 0000000..b67a780
--- /dev/null
+++ b/subjects/pickle.py
@@ -0,0 +1,7 @@
+import pickle
+
+name = 'Pickle'
+
+
+def serialization_func(obj, many):
+ return pickle.dumps(obj)
diff --git a/subjects/rf.py b/subjects/rf.py
index 19027d0..5c36cbc 100644
--- a/subjects/rf.py
+++ b/subjects/rf.py
@@ -6,11 +6,11 @@
from rest_framework import serializers as rf_serializers
-__name__ = 'Django REST Framework'
+name = 'Django REST Framework'
class SubRF(rf_serializers.Serializer):
- w = rf_serializers.FloatField()
+ w = rf_serializers.IntegerField()
x = rf_serializers.SerializerMethodField()
y = rf_serializers.CharField()
z = rf_serializers.IntegerField()
diff --git a/subjects/serp.py b/subjects/serp.py
index 3aa60b0..28f5668 100644
--- a/subjects/serp.py
+++ b/subjects/serp.py
@@ -1,6 +1,6 @@
import serpy
-__name__ = 'serpy'
+name = 'serpy'
class SubS(serpy.Serializer):
diff --git a/subjects/serpy.py b/subjects/serpy.py
new file mode 100644
index 0000000..66511f9
--- /dev/null
+++ b/subjects/serpy.py
@@ -0,0 +1,35 @@
+import dataclasses
+import typing
+
+import serpyco
+
+from data import ParentTestObject
+
+name = "serpyco"
+
+
+def get_x(obj):
+ return obj.x + 10
+
+
+@dataclasses.dataclass
+class SubM:
+ w: int
+ y: str
+ z: int
+ x: int = serpyco.field(getter=get_x)
+
+
+@dataclasses.dataclass
+class ComplexM:
+ foo: str
+ sub: SubM
+ subs: typing.List[SubM]
+ bar: int = serpyco.field(getter=ParentTestObject.bar)
+
+
+serializer = serpyco.Serializer(ComplexM)
+
+
+def serialization_func(obj, many):
+ return serializer.dump(obj, many=many)
diff --git a/subjects/strain.py b/subjects/strain.py
index 2f48f73..922799a 100644
--- a/subjects/strain.py
+++ b/subjects/strain.py
@@ -1,17 +1,17 @@
import strainer
-__name__ = 'Strainer'
+name = 'Strainer'
-sub_strainer_serializer = strainer.create_serializer(
+sub_strainer_serializer = strainer.serializer(
strainer.field('w'),
- strainer.field('x', to_representation=lambda obj: obj.x + 10),
+ strainer.field('x', attr_getter=lambda obj: obj.x + 10),
strainer.field('y'),
strainer.field('z'),
)
-complex_strainer_serializer = strainer.create_serializer(
+complex_strainer_serializer = strainer.serializer(
strainer.field('foo'),
- strainer.field('bar', to_representation=lambda obj: obj.bar()),
+ strainer.field('bar', attr_getter=lambda obj: obj.bar()),
strainer.child('sub', serializer=sub_strainer_serializer),
strainer.many('subs', serializer=sub_strainer_serializer),
)
@@ -19,6 +19,6 @@
def serialization_func(obj, many):
if many:
- return [complex_strainer_serializer.to_representation(x) for x in obj]
+ return [complex_strainer_serializer.serialize(x) for x in obj]
else:
- return complex_strainer_serializer.to_representation(obj)
+ return complex_strainer_serializer.serialize(obj)
diff --git a/subjects/tmarsh.py b/subjects/tmarsh.py
new file mode 100644
index 0000000..39d44cd
--- /dev/null
+++ b/subjects/tmarsh.py
@@ -0,0 +1,29 @@
+import toastedmarshmallow
+import marshmallow
+
+name = 'Toasted Marshmallow'
+
+
+class SubM(marshmallow.Schema):
+ w = marshmallow.fields.Int()
+ x = marshmallow.fields.Method('get_x')
+ y = marshmallow.fields.Str()
+ z = marshmallow.fields.Int()
+
+ def get_x(self, obj):
+ return obj.x + 10
+
+
+class ComplexM(marshmallow.Schema):
+ foo = marshmallow.fields.Str()
+ bar = marshmallow.fields.Int()
+ sub = marshmallow.fields.Nested(SubM)
+ subs = marshmallow.fields.Nested(SubM, many=True)
+
+
+schema = ComplexM()
+schema.jit = toastedmarshmallow.Jit
+
+
+def serialization_func(obj, many):
+ return schema.dump(obj, many=many).data
diff --git a/tests/test_serializers.py b/tests/test_serializers.py
index 64eaa83..1b8016a 100644
--- a/tests/test_serializers.py
+++ b/tests/test_serializers.py
@@ -1,6 +1,6 @@
-from subjects import marsh, rf, serp, strain, hand, loli
+from subjects import rf, serp, strain, col, hand, loli, k, lim, tmarsh
from data import ParentTestObject
-
+import pprint
TARGET = {
'foo': 'bar',
'bar': 5,
@@ -32,18 +32,22 @@
def test_serializers():
test_object = ParentTestObject()
- for subject in (rf, marsh, serp, strain, hand, loli):
- print subject.__name__
+ for subject in (rf, tmarsh, serp, strain, col, hand, loli, k, lim):
+ print(subject.__name__)
data = subject.serialization_func(test_object, False)
- assert data['foo'] == TARGET['foo']
- assert data['bar'] == TARGET['bar']
- assert data['sub']['w'] == TARGET['sub']['w']
- assert data['subs'][3]['y'] == TARGET['subs'][3]['y']
- assert data['subs'][3]['x'] == TARGET['subs'][3]['x']
+ pprint.pprint(data)
+ assert str(data['foo']) == str(TARGET['foo'])
+ assert str(data['bar']) == str(TARGET['bar'])
+ assert str(data['sub']['w']) == str(TARGET['sub']['w'])
+ assert str(data['subs'][3]['y']) == str(TARGET['subs'][3]['y'])
+ assert str(data['subs'][3]['x']) == str(TARGET['subs'][3]['x'])
datas = subject.serialization_func([test_object, test_object], True)
for data in datas:
- assert data['foo'] == TARGET['foo']
- assert data['sub']['w'] == TARGET['sub']['w']
- assert data['subs'][3]['y'] == TARGET['subs'][3]['y']
- assert data['subs'][3]['x'] == TARGET['subs'][3]['x']
+ assert str(data['foo']) == str(TARGET['foo'])
+ assert str(data['sub']['w']) == str(TARGET['sub']['w'])
+ assert str(data['subs'][3]['y']) == str(TARGET['subs'][3]['y'])
+ assert str(data['subs'][3]['x']) == str(TARGET['subs'][3]['x'])
+
+if __name__ == '__main__':
+ test_serializers()