From 9b56e1a4c839906d92e0568904731855bdce51a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristi=20V=C3=AEjdea?= Date: Thu, 9 Aug 2018 04:27:08 +0300 Subject: [PATCH] Avoid invalid usage of readOnly --- src/drf_yasg/inspectors/field.py | 2 ++ src/drf_yasg/openapi.py | 19 ++++++++++++++----- tests/reference.yaml | 1 - 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/drf_yasg/inspectors/field.py b/src/drf_yasg/inspectors/field.py index 5bd169c9..a7798a2c 100644 --- a/src/drf_yasg/inspectors/field.py +++ b/src/drf_yasg/inspectors/field.py @@ -118,6 +118,8 @@ def make_schema_definition(): definitions = self.components.with_scope(openapi.SCHEMA_DEFINITIONS) actual_schema = definitions.setdefault(ref_name, make_schema_definition) + actual_schema._remove_read_only() + actual_serializer = get_serializer_class(getattr(actual_schema, '_serializer', None)) this_serializer = get_serializer_class(field) if actual_serializer and actual_serializer != this_serializer: # pragma: no cover diff --git a/src/drf_yasg/openapi.py b/src/drf_yasg/openapi.py index e864da54..32ae0238 100644 --- a/src/drf_yasg/openapi.py +++ b/src/drf_yasg/openapi.py @@ -387,8 +387,6 @@ def __init__(self, name, in_, description=None, required=None, schema=None, :param default: default value if the parameter is not provided; must conform to parameter type """ super(Parameter, self).__init__(**extra) - if (not schema and not type) or (schema and type): - raise AssertionError("either schema or type are required for Parameter object!") self.name = name self.in_ = in_ self.description = description @@ -401,6 +399,10 @@ def __init__(self, name, in_, description=None, required=None, schema=None, self.items = items self.default = default self._insert_extras__() + if (not schema and not type) or (schema and type): + raise AssertionError("either schema or type are required for Parameter object (not both)!") + if schema and isinstance(schema, Schema): + schema._remove_read_only() if self['in'] == IN_PATH: # path parameters must always be required assert required is not False, "path parameter cannot be optional" @@ -465,6 +467,11 @@ def __init__(self, title=None, description=None, type=None, format=None, enum=No if pattern and type != TYPE_STRING: raise AssertionError("pattern can only be used when type is string") + def _remove_read_only(self): + # readOnly is only valid for Schemas inside another Schema's properties; + # when placing Schema elsewhere we must take care to remove the readOnly flag + self.pop('readOnly', '') + class _Ref(SwaggerDict): ref_name_re = re.compile(r"#/(?P.+)/(?P[^/]+)$") @@ -497,12 +504,12 @@ def resolve(self, resolver): ref_match = self.ref_name_re.match(self.ref) return resolver.get(ref_match.group('name'), scope=ref_match.group('scope')) - def __setitem__(self, key, value, **kwargs): + def __setitem__(self, key, value): if key == "$ref": - return super(_Ref, self).__setitem__(key, value, **kwargs) + return super(_Ref, self).__setitem__(key, value) raise NotImplementedError("only $ref can be set on Reference objects (not %s)" % key) - def __delitem__(self, key, **kwargs): + def __delitem__(self, key): raise NotImplementedError("cannot delete property of Reference object") @@ -560,6 +567,8 @@ def __init__(self, description, schema=None, examples=None, **extra): self.schema = schema self.examples = examples self._insert_extras__() + if schema and isinstance(schema, Schema): + schema._remove_read_only() class ReferenceResolver(object): diff --git a/tests/reference.yaml b/tests/reference.yaml index 97618505..18da22df 100644 --- a/tests/reference.yaml +++ b/tests/reference.yaml @@ -1599,7 +1599,6 @@ definitions: title: Foo type: string minLength: 1 - readOnly: true MethodFieldExample: title: Hint example type: object