From dc463296575aea53790286965abfd560716888c5 Mon Sep 17 00:00:00 2001 From: Graeme Coupar Date: Thu, 26 Nov 2015 20:38:30 +0000 Subject: [PATCH] Add support for marshalling dict-like objects. The `is_dict_like` function in `schema.py` was just checking if the object's type was a dict. This causes it to treat any dict subclass as a model, which fails because dict subclasses are not models. Updating to check if the item is an instance of `collections.Mapping` (or `collections.abc.Mapping` on python 3) fixes this. --- bravado_core/schema.py | 8 +++++-- tests/marshal/marshal_schema_object_test.py | 24 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/bravado_core/schema.py b/bravado_core/schema.py index d2cf85dc..8f814a7c 100644 --- a/bravado_core/schema.py +++ b/bravado_core/schema.py @@ -1,5 +1,10 @@ from bravado_core.exception import SwaggerMappingError +try: + from collections import Mapping +except ImportError: + from collections.abc import Mapping + # 'object' and 'array' are omitted since this should really be read as # "Swagger types that map to python primitives" SWAGGER_PRIMITIVES = ( @@ -45,8 +50,7 @@ def is_dict_like(spec): :param spec: swagger object specification in dict form :rtype: boolean """ - # TODO: check magic method instead - return type(spec) == dict + return isinstance(spec, Mapping) def is_list_like(spec): diff --git a/tests/marshal/marshal_schema_object_test.py b/tests/marshal/marshal_schema_object_test.py index 4a8c136f..dce10b30 100644 --- a/tests/marshal/marshal_schema_object_test.py +++ b/tests/marshal/marshal_schema_object_test.py @@ -1,4 +1,5 @@ import copy +from collections import OrderedDict import pytest @@ -29,6 +30,29 @@ def test_dicts_can_be_used_instead_of_models(petstore_dict): assert expected == result +def test_ordered_dicts_can_be_used_instead_of_models(petstore_dict): + petstore_spec = Spec.from_dict(petstore_dict) + pet_spec = petstore_spec.spec_dict['definitions']['Pet'] + pet = OrderedDict({ + 'id': 1, + 'name': 'Fido', + 'status': 'sold', + 'photoUrls': ['wagtail.png', 'bark.png'], + 'category': { + 'id': 200, + 'name': 'friendly', + }, + 'tags': [ + {'id': 99, 'name': 'mini'}, + {'id': 100, 'name': 'brown'}, + ], + }) + expected = copy.deepcopy(pet) + result = marshal_schema_object(petstore_spec, pet_spec, pet) + assert expected == result + + + def test_unknown_type_raises_error(empty_swagger_spec): invalid_spec = {'type': 'foo'} with pytest.raises(SwaggerMappingError) as excinfo: