From 75989836be00835511e77437381f0d2b2f33a241 Mon Sep 17 00:00:00 2001 From: "Zhang, Ruiqi" Date: Fri, 28 Jul 2017 13:59:21 +0800 Subject: [PATCH] Fix a serialization bug that randomly skips fields if "x_of" is encountered --- AUTHORS | 1 + eve/methods/common.py | 33 +++++++++++++++---------------- eve/tests/methods/common.py | 39 +++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 17 deletions(-) diff --git a/AUTHORS b/AUTHORS index 837771202..be0b2bfec 100644 --- a/AUTHORS +++ b/AUTHORS @@ -125,6 +125,7 @@ Patches and Contributions - Petr JaĊĦek - Prayag Verma - Ralph Smith +- Raychee - Robert Wlodarczyk - Roberto 'Kalamun' Pasini - Rodrigo Rodriguez diff --git a/eve/methods/common.py b/eve/methods/common.py index 53cdd91f9..6ea458635 100644 --- a/eve/methods/common.py +++ b/eve/methods/common.py @@ -387,15 +387,16 @@ def serialize(document, resource=None, schema=None, fields=None): if field in schema: field_schema = schema[field] field_type = field_schema.get('type') - if field_type is None: - for x_of in ['allof', 'anyof', 'oneof', 'noneof']: - for optschema in field_schema.get(x_of, []): - schema = {field: optschema} - serialize(document, schema=schema) - x_of_type = '{0}_type'.format(x_of) - for opttype in field_schema.get(x_of_type, []): - schema = {field: {'type': opttype}} - serialize(document, schema=schema) + for x_of in ['allof', 'anyof', 'oneof', 'noneof']: + for optschema in field_schema.get(x_of, []): + optschema = dict(field_schema, **optschema) + optschema.pop(x_of, None) + serialize(document, schema={field: optschema}) + x_of_type = '{0}_type'.format(x_of) + for opttype in field_schema.get(x_of_type, []): + optschema = dict(field_schema, type=opttype) + optschema.pop(x_of_type, None) + serialize(document, schema={field: optschema}) if config.AUTO_CREATE_LISTS and field_type == 'list': # Convert single values to lists if not isinstance(document[field], list): @@ -432,16 +433,14 @@ def serialize(document, resource=None, schema=None, fields=None): # a list of items determined by *of rules for x_of in ['allof', 'anyof', 'oneof', 'noneof']: for optschema in field_schema.get(x_of, []): - schema = {field: { - 'type': field_type, - 'schema': optschema}} - serialize(document, schema=schema) + serialize(document, + schema={field: {'type': field_type, + 'schema': optschema}}) x_of_type = '{0}_type'.format(x_of) for opttype in field_schema.get(x_of_type, []): - schema = {field: { - 'type': field_type, - 'schema': {'type': opttype}}} - serialize(document, schema=schema) + serialize(document, + schema={field: {'type': field_type, + 'schema': {'type': opttype}}}) else: # a list of one type, arbitrary length field_type = field_schema.get('type') diff --git a/eve/tests/methods/common.py b/eve/tests/methods/common.py index 88ac4a63b..b92ae516d 100644 --- a/eve/tests/methods/common.py +++ b/eve/tests/methods/common.py @@ -11,6 +11,12 @@ from eve.tests.test_settings import MONGO_DBNAME from eve.utils import config +try: + from collections import OrderedDict # noqa +except ImportError: + # Python 2.6 needs this back-port + from ordereddict import OrderedDict + class TestSerializer(TestBase): def test_serialize_subdocument(self): @@ -329,6 +335,39 @@ def test_serialize_inside_x_of_rules(self): serialized = serialize(doc, schema=schema) self.assertTrue(isinstance(serialized['x_of-field'], ObjectId)) + def test_serialize_alongside_x_of_rules(self): + for x_of in ['allof', 'anyof', 'oneof', 'noneof']: + schema = OrderedDict([ + ('x_of-field', { + x_of: [ + {'type': 'objectid'}, + {'required': True} + ] + }), + ('oid-field', {'type': 'objectid'}) + ]) + doc = OrderedDict([('x_of-field', '50656e4538345b39dd0414f0'), ('oid-field', '50656e4538345b39dd0414f0')]) + with self.app.app_context(): + serialized = serialize(doc, schema=schema) + self.assertTrue(isinstance(serialized['x_of-field'], ObjectId)) + self.assertTrue(isinstance(serialized['oid-field'], ObjectId)) + + def test_serialize_list_alongside_x_of_rules(self): + for x_of in ['allof', 'anyof', 'oneof', 'noneof']: + schema = { + 'x_of-field': { + "type": "list", + x_of: [ + {"schema": {'type': 'objectid'}}, + {"schema": {'type': 'datetime'}} + ] + } + } + doc = {'x_of-field': ['50656e4538345b39dd0414f0']} + with self.app.app_context(): + serialized = serialize(doc, schema=schema) + self.assertTrue(isinstance(serialized['x_of-field'][0], ObjectId)) + def test_serialize_inside_nested_x_of_rules(self): schema = { 'nested-x_of-field': {