From fbc63a0a2ee98d1afee242b923f891358f7b8e9e Mon Sep 17 00:00:00 2001 From: Jake Moshenko Date: Fri, 9 Dec 2016 14:51:15 -0500 Subject: [PATCH 1/3] Enable unmarshalling nullable primitives. --- bravado_core/unmarshal.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bravado_core/unmarshal.py b/bravado_core/unmarshal.py index 26a074f6..c96ecd19 100644 --- a/bravado_core/unmarshal.py +++ b/bravado_core/unmarshal.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +import collections + from six import iteritems from bravado_core import formatter @@ -37,7 +39,9 @@ def unmarshal_schema_object(swagger_spec, schema_object_spec, value): "The following schema object is missing a type field: {0}" .format(schema_object_spec.get('x-model', str(schema_object_spec)))) - if obj_type in SWAGGER_PRIMITIVES: + if (obj_type in SWAGGER_PRIMITIVES or + (isinstance(obj_type, collections.Iterable) and + not isinstance(obj_type, str))): return unmarshal_primitive(swagger_spec, schema_object_spec, value) if obj_type == 'array': From c6d3b8bf2eb08799364fdeaf448b8867f9697ca8 Mon Sep 17 00:00:00 2001 From: Jake Moshenko Date: Fri, 9 Dec 2016 14:52:03 -0500 Subject: [PATCH 2/3] Rename resource tags to bind under valid python identifiers. --- bravado_core/resource.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bravado_core/resource.py b/bravado_core/resource.py index 8254163d..7d56e55e 100644 --- a/bravado_core/resource.py +++ b/bravado_core/resource.py @@ -1,5 +1,6 @@ from collections import defaultdict import logging +import re from six import iteritems @@ -71,7 +72,8 @@ def build_resources(swagger_spec): resources = {} for tag, ops in iteritems(tag_to_ops): - resources[tag] = Resource(tag, ops) + resource_identifier = re.sub('[^0-9a-zA-Z_]', '', tag) + resources[resource_identifier] = Resource(tag, ops) return resources From 1700898f020369746e9884d9115c26474cfe6d25 Mon Sep 17 00:00:00 2001 From: Jake Moshenko Date: Fri, 9 Dec 2016 14:53:41 -0500 Subject: [PATCH 3/3] Enable allOf in all schemas, not just predefined models. --- bravado_core/unmarshal.py | 24 +++++++++++++++++++----- bravado_core/validate.py | 35 ++++++++++++++++++++++------------- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/bravado_core/unmarshal.py b/bravado_core/unmarshal.py index c96ecd19..c94220ea 100644 --- a/bravado_core/unmarshal.py +++ b/bravado_core/unmarshal.py @@ -14,7 +14,8 @@ from bravado_core.schema import SWAGGER_PRIMITIVES -def unmarshal_schema_object(swagger_spec, schema_object_spec, value): +def unmarshal_schema_object(swagger_spec, schema_object_spec, value, + all_of_parent=False): """Unmarshal the value using the given schema object specification. Unmarshaling includes: @@ -25,6 +26,7 @@ def unmarshal_schema_object(swagger_spec, schema_object_spec, value): :type swagger_spec: :class:`bravado_core.spec.Spec` :type schema_object_spec: dict :type value: int, float, long, string, unicode, boolean, list, dict, etc + :type all_of_parent: boolean :return: unmarshaled value :rtype: int, float, long, string, unicode, boolean, list, dict, object (in @@ -32,6 +34,12 @@ def unmarshal_schema_object(swagger_spec, schema_object_spec, value): """ deref = swagger_spec.deref schema_object_spec = deref(schema_object_spec) + + all_of = deref(schema_object_spec.get('allOf')) + if all_of: + return [unmarshal_schema_object(swagger_spec, one_schema, value, True) + for one_schema in all_of] + try: obj_type = schema_object_spec['type'] except KeyError: @@ -55,7 +63,8 @@ def unmarshal_schema_object(swagger_spec, schema_object_spec, value): return unmarshal_model(swagger_spec, schema_object_spec, value) if obj_type == 'object': - return unmarshal_object(swagger_spec, schema_object_spec, value) + return unmarshal_object(swagger_spec, schema_object_spec, value, + all_of_parent) if obj_type == 'file': return value @@ -106,12 +115,14 @@ def unmarshal_array(swagger_spec, array_spec, array_value): ] -def unmarshal_object(swagger_spec, object_spec, object_value): +def unmarshal_object(swagger_spec, object_spec, object_value, + filter_undeclared=False): """Unmarshal a jsonschema type of 'object' into a python dict. :type swagger_spec: :class:`bravado_core.spec.Spec` :type object_spec: dict :type object_value: dict + :type filter_undeclared boolean :rtype: dict :raises: SwaggerMappingError """ @@ -126,9 +137,13 @@ def unmarshal_object(swagger_spec, object_spec, object_value): object_spec = deref(object_spec) required_fields = object_spec.get('required', []) + all_properties = collapsed_properties(deref(object_spec), swagger_spec) result = {} for k, v in iteritems(object_value): + if k not in all_properties and filter_undeclared: + continue + prop_spec = get_spec_for_prop( swagger_spec, object_spec, object_value, k) if v is None and k not in required_fields: @@ -140,8 +155,7 @@ def unmarshal_object(swagger_spec, object_spec, object_value): result[k] = v # re-introduce and None'ify any properties that weren't passed - properties = collapsed_properties(deref(object_spec), swagger_spec) - for prop_name, prop_spec in iteritems(properties): + for prop_name, prop_spec in iteritems(all_properties): if prop_name not in result: result[prop_name] = None return result diff --git a/bravado_core/validate.py b/bravado_core/validate.py index 4226896d..4a16083c 100644 --- a/bravado_core/validate.py +++ b/bravado_core/validate.py @@ -17,24 +17,33 @@ def validate_schema_object(swagger_spec, schema_object_spec, value): :raises SwaggerValidationError: when user-defined format validation fails. """ deref = swagger_spec.deref - schema_object_spec = deref(schema_object_spec) - obj_type = deref(schema_object_spec.get('type')) - if obj_type in SWAGGER_PRIMITIVES: - validate_primitive(swagger_spec, schema_object_spec, value) + schemas = [] - elif obj_type == 'array': - validate_array(swagger_spec, schema_object_spec, value) + all_of = deref(schema_object_spec.get('allOf')) + if all_of is not None: + schemas = [deref(sub_schema) for sub_schema in all_of] + else: + schemas = [deref(schema_object_spec)] - elif obj_type == 'object': - validate_object(swagger_spec, schema_object_spec, value) + for one_schema in schemas: + obj_type = deref(one_schema.get('type')) - elif obj_type == 'file': - pass + if obj_type in SWAGGER_PRIMITIVES: + validate_primitive(swagger_spec, one_schema, value) - else: - raise SwaggerMappingError('Unknown type {0} for value {1}'.format( - obj_type, value)) + elif obj_type == 'array': + validate_array(swagger_spec, one_schema, value) + + elif obj_type == 'object': + validate_object(swagger_spec, one_schema, value) + + elif obj_type == 'file': + pass + + else: + raise SwaggerMappingError('Unknown type {0} for value {1}'.format( + obj_type, value)) def validate_primitive(swagger_spec, primitive_spec, value):