Schema additional properties support

This commit is contained in:
Artur Maciag 2018-05-30 11:15:17 +01:00
parent 19bfff89dc
commit 78f55ee80f
4 changed files with 52 additions and 2 deletions

View file

@ -28,6 +28,7 @@ class SchemaFactory(object):
deprecated = schema_deref.get('deprecated', False) deprecated = schema_deref.get('deprecated', False)
all_of_spec = schema_deref.get('allOf', None) all_of_spec = schema_deref.get('allOf', None)
one_of_spec = schema_deref.get('oneOf', None) one_of_spec = schema_deref.get('oneOf', None)
additional_properties_spec = schema_deref.get('additionalProperties')
properties = None properties = None
if properties_spec: if properties_spec:
@ -45,11 +46,16 @@ class SchemaFactory(object):
if items_spec: if items_spec:
items = self._create_items(items_spec) items = self._create_items(items_spec)
additional_properties = None
if additional_properties_spec:
additional_properties = self.create(additional_properties_spec)
return Schema( return Schema(
schema_type=schema_type, model=model, properties=properties, schema_type=schema_type, model=model, properties=properties,
items=items, schema_format=schema_format, required=required, items=items, schema_format=schema_format, required=required,
default=default, nullable=nullable, enum=enum, default=default, nullable=nullable, enum=enum,
deprecated=deprecated, all_of=all_of, one_of=one_of, deprecated=deprecated, all_of=all_of, one_of=one_of,
additional_properties=additional_properties,
) )
@property @property

View file

@ -28,7 +28,8 @@ class Schema(object):
def __init__( def __init__(
self, schema_type=None, model=None, properties=None, items=None, self, schema_type=None, model=None, properties=None, items=None,
schema_format=None, required=None, default=None, nullable=False, schema_format=None, required=None, default=None, nullable=False,
enum=None, deprecated=False, all_of=None, one_of=None): enum=None, deprecated=False, all_of=None, one_of=None,
additional_properties=None):
self.type = schema_type and SchemaType(schema_type) self.type = schema_type and SchemaType(schema_type)
self.model = model self.model = model
self.properties = properties and dict(properties) or {} self.properties = properties and dict(properties) or {}
@ -41,6 +42,7 @@ class Schema(object):
self.deprecated = deprecated self.deprecated = deprecated
self.all_of = all_of and list(all_of) or [] self.all_of = all_of and list(all_of) or []
self.one_of = one_of and list(one_of) or [] self.one_of = one_of and list(one_of) or []
self.additional_properties = additional_properties
self._all_required_properties_cache = None self._all_required_properties_cache = None
self._all_optional_properties_cache = None self._all_optional_properties_cache = None
@ -183,11 +185,16 @@ class Schema(object):
value_props_names = value.keys() value_props_names = value.keys()
extra_props = set(value_props_names) - set(all_props_names) extra_props = set(value_props_names) - set(all_props_names)
if extra_props: if extra_props and self.additional_properties is None:
raise UndefinedSchemaProperty( raise UndefinedSchemaProperty(
"Undefined properties in schema: {0}".format(extra_props)) "Undefined properties in schema: {0}".format(extra_props))
properties = {} properties = {}
for prop_name in extra_props:
prop_value = value[prop_name]
properties[prop_name] = self.additional_properties.unmarshal(
prop_value)
for prop_name, prop in iteritems(all_props): for prop_name, prop in iteritems(all_props):
try: try:
prop_value = value[prop_name] prop_value = value[prop_name]

View file

@ -284,6 +284,8 @@ components:
properties: properties:
rootCause: rootCause:
type: string type: string
additionalProperties:
type: string
responses: responses:
ErrorResponse: ErrorResponse:
description: unexpected error description: unexpected error

View file

@ -757,3 +757,38 @@ class TestPetstore(object):
with pytest.raises(InvalidMediaTypeValue): with pytest.raises(InvalidMediaTypeValue):
request.get_body(spec) request.get_body(spec)
def test_post_tags_additional_properties(
self, spec, response_validator):
host_url = 'http://petstore.swagger.io/v1'
path_pattern = '/v1/tags'
pet_name = 'Dog'
data_json = {
'name': pet_name,
}
data = json.dumps(data_json)
request = MockRequest(
host_url, 'POST', '/tags',
path_pattern=path_pattern, data=data,
)
parameters = request.get_parameters(spec)
body = request.get_body(spec)
assert parameters == {}
assert body == data_json
data_json = {
'code': 400,
'message': 'Bad request',
'rootCause': 'Tag already exist',
'additionalinfo': 'Tag Dog already exist',
}
data = json.dumps(data_json)
response = MockResponse(data, status_code=404)
response_result = response_validator.validate(request, response)
assert response_result.errors == []
assert response_result.data == data_json