mirror of
https://github.com/correl/openapi-core.git
synced 2024-12-28 19:19:23 +00:00
Property read-only and write-only support
This commit is contained in:
parent
975ac0d7c9
commit
1bea6013c3
16 changed files with 233 additions and 166 deletions
|
@ -9,9 +9,6 @@ from openapi_core.schema.schemas.enums import SchemaType
|
|||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
_CONTEXT = UnmarshalContext.REQUEST
|
||||
|
||||
|
||||
class Parameter(object):
|
||||
"""Represents an OpenAPI operation Parameter."""
|
||||
|
||||
|
|
|
@ -26,8 +26,3 @@ class SchemaFormat(Enum):
|
|||
DATETIME = 'date-time'
|
||||
PASSWORD = 'password'
|
||||
UUID = 'uuid'
|
||||
|
||||
|
||||
class UnmarshalContext(Enum):
|
||||
REQUEST = 'request'
|
||||
RESPONSE = 'response'
|
||||
|
|
|
@ -60,9 +60,6 @@ class Schema(object):
|
|||
self.read_only = read_only
|
||||
self.write_only = write_only
|
||||
|
||||
if self.read_only and self.write_only:
|
||||
raise OpenAPISchemaError("Schema cannot be readOnly AND writeOnly")
|
||||
|
||||
self.extensions = extensions and dict(extensions) or {}
|
||||
|
||||
self._all_required_properties_cache = None
|
||||
|
|
|
@ -3,9 +3,6 @@ from distutils.util import strtobool
|
|||
from six import string_types
|
||||
from json import dumps
|
||||
|
||||
from openapi_core.schema.schemas.enums import UnmarshalContext
|
||||
from openapi_core.schema.schemas.exceptions import UnmarshalContextNotSet
|
||||
|
||||
|
||||
def forcebool(val):
|
||||
if isinstance(val, string_types):
|
||||
|
|
|
@ -35,6 +35,19 @@ def nullable(validator, is_nullable, instance, schema):
|
|||
yield ValidationError("None for not nullable")
|
||||
|
||||
|
||||
def required(validator, required, instance, schema):
|
||||
if not validator.is_type(instance, "object"):
|
||||
return
|
||||
for property in required:
|
||||
if property not in instance:
|
||||
prop_schema = schema['properties'][property]
|
||||
read_only = prop_schema.get('readOnly', False)
|
||||
write_only = prop_schema.get('writeOnly', False)
|
||||
if validator.write and read_only or validator.read and write_only:
|
||||
continue
|
||||
yield ValidationError("%r is a required property" % property)
|
||||
|
||||
|
||||
def additionalProperties(validator, aP, instance, schema):
|
||||
if not validator.is_type(instance, "object"):
|
||||
return
|
||||
|
@ -54,5 +67,21 @@ def additionalProperties(validator, aP, instance, schema):
|
|||
yield ValidationError(error % extras_msg(extras))
|
||||
|
||||
|
||||
def readOnly(validator, ro, instance, schema):
|
||||
if not validator.write or not ro:
|
||||
return
|
||||
|
||||
yield ValidationError(
|
||||
"Tried to write read-only proparty with %s" % (instance))
|
||||
|
||||
|
||||
def writeOnly(validator, wo, instance, schema):
|
||||
if not validator.read or not wo:
|
||||
return
|
||||
|
||||
yield ValidationError(
|
||||
"Tried to read write-only proparty with %s" % (instance))
|
||||
|
||||
|
||||
def not_implemented(validator, value, instance, schema):
|
||||
pass
|
||||
|
|
|
@ -21,7 +21,6 @@ BaseOAS30Validator = create(
|
|||
u"uniqueItems": _validators.uniqueItems,
|
||||
u"maxProperties": _validators.maxProperties,
|
||||
u"minProperties": _validators.minProperties,
|
||||
u"required": _validators.required,
|
||||
u"enum": _validators.enum,
|
||||
# adjusted to OAS
|
||||
u"type": oas_validators.type,
|
||||
|
@ -31,6 +30,7 @@ BaseOAS30Validator = create(
|
|||
u"not": _validators.not_,
|
||||
u"items": oas_validators.items,
|
||||
u"properties": _validators.properties,
|
||||
u"required": oas_validators.required,
|
||||
u"additionalProperties": oas_validators.additionalProperties,
|
||||
# TODO: adjust description
|
||||
u"format": oas_validators.format,
|
||||
|
@ -39,8 +39,8 @@ BaseOAS30Validator = create(
|
|||
# fixed OAS fields
|
||||
u"nullable": oas_validators.nullable,
|
||||
u"discriminator": oas_validators.not_implemented,
|
||||
u"readOnly": oas_validators.not_implemented,
|
||||
u"writeOnly": oas_validators.not_implemented,
|
||||
u"readOnly": oas_validators.readOnly,
|
||||
u"writeOnly": oas_validators.writeOnly,
|
||||
u"xml": oas_validators.not_implemented,
|
||||
u"externalDocs": oas_validators.not_implemented,
|
||||
u"example": oas_validators.not_implemented,
|
||||
|
@ -54,6 +54,11 @@ BaseOAS30Validator = create(
|
|||
|
||||
class OAS30Validator(BaseOAS30Validator):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.read = kwargs.pop('read', None)
|
||||
self.write = kwargs.pop('write', None)
|
||||
super(OAS30Validator, self).__init__(*args, **kwargs)
|
||||
|
||||
def iter_errors(self, instance, _schema=None):
|
||||
if _schema is None:
|
||||
_schema = self.schema
|
||||
|
|
7
openapi_core/unmarshalling/schemas/enums.py
Normal file
7
openapi_core/unmarshalling/schemas/enums.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
"""OpenAPI core unmarshalling schemas enums module"""
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class UnmarshalContext(Enum):
|
||||
REQUEST = 'request'
|
||||
RESPONSE = 'response'
|
|
@ -5,6 +5,7 @@ from openapi_core.schema.schemas.enums import SchemaType, SchemaFormat
|
|||
from openapi_core.schema.schemas.models import Schema
|
||||
from openapi_core.schema_validator import OAS30Validator
|
||||
from openapi_core.schema_validator import oas30_format_checker
|
||||
from openapi_core.unmarshalling.schemas.enums import UnmarshalContext
|
||||
from openapi_core.unmarshalling.schemas.exceptions import (
|
||||
FormatterNotFoundError,
|
||||
)
|
||||
|
@ -29,11 +30,17 @@ class SchemaUnmarshallersFactory(object):
|
|||
SchemaType.ANY: AnyUnmarshaller,
|
||||
}
|
||||
|
||||
def __init__(self, resolver=None, custom_formatters=None):
|
||||
CONTEXT_VALIDATION = {
|
||||
UnmarshalContext.REQUEST: 'write',
|
||||
UnmarshalContext.RESPONSE: 'read',
|
||||
}
|
||||
|
||||
def __init__(self, resolver=None, custom_formatters=None, context=None):
|
||||
self.resolver = resolver
|
||||
if custom_formatters is None:
|
||||
custom_formatters = {}
|
||||
self.custom_formatters = custom_formatters
|
||||
self.context = context
|
||||
|
||||
def create(self, schema, type_override=None):
|
||||
"""Create unmarshaller from the schema."""
|
||||
|
@ -50,7 +57,9 @@ class SchemaUnmarshallersFactory(object):
|
|||
elif schema_type in self.COMPLEX_UNMARSHALLERS:
|
||||
klass = self.COMPLEX_UNMARSHALLERS[schema_type]
|
||||
kwargs = dict(
|
||||
schema=schema, unmarshallers_factory=self)
|
||||
schema=schema, unmarshallers_factory=self,
|
||||
context=self.context,
|
||||
)
|
||||
|
||||
formatter = self.get_formatter(klass.FORMATTERS, schema.format)
|
||||
|
||||
|
@ -70,10 +79,17 @@ class SchemaUnmarshallersFactory(object):
|
|||
return default_formatters.get(schema_format)
|
||||
|
||||
def get_validator(self, schema):
|
||||
format_checker = deepcopy(oas30_format_checker)
|
||||
format_checker = self._get_format_checker()
|
||||
kwargs = {
|
||||
'resolver': self.resolver,
|
||||
'format_checker': format_checker,
|
||||
}
|
||||
if self.context is not None:
|
||||
kwargs[self.CONTEXT_VALIDATION[self.context]] = True
|
||||
return OAS30Validator(schema.__dict__, **kwargs)
|
||||
|
||||
def _get_format_checker(self):
|
||||
fc = deepcopy(oas30_format_checker)
|
||||
for name, formatter in self.custom_formatters.items():
|
||||
format_checker.checks(name)(formatter.validate)
|
||||
return OAS30Validator(
|
||||
schema.__dict__,
|
||||
resolver=self.resolver, format_checker=format_checker,
|
||||
)
|
||||
fc.checks(name)(formatter.validate)
|
||||
return fc
|
||||
|
|
|
@ -13,6 +13,7 @@ from openapi_core.schema_validator._types import (
|
|||
is_object, is_number, is_string,
|
||||
)
|
||||
from openapi_core.schema_validator._format import oas30_format_checker
|
||||
from openapi_core.unmarshalling.schemas.enums import UnmarshalContext
|
||||
from openapi_core.unmarshalling.schemas.exceptions import (
|
||||
UnmarshalError, ValidateError, InvalidSchemaValue,
|
||||
InvalidSchemaFormatValue,
|
||||
|
@ -120,9 +121,12 @@ class BooleanUnmarshaller(PrimitiveTypeUnmarshaller):
|
|||
|
||||
class ComplexUnmarshaller(PrimitiveTypeUnmarshaller):
|
||||
|
||||
def __init__(self, formatter, validator, schema, unmarshallers_factory):
|
||||
def __init__(
|
||||
self, formatter, validator, schema, unmarshallers_factory,
|
||||
context=None):
|
||||
super(ComplexUnmarshaller, self).__init__(formatter, validator, schema)
|
||||
self.unmarshallers_factory = unmarshallers_factory
|
||||
self.context = context
|
||||
|
||||
|
||||
class ArrayUnmarshaller(ComplexUnmarshaller):
|
||||
|
@ -206,6 +210,10 @@ class ObjectUnmarshaller(ComplexUnmarshaller):
|
|||
properties[prop_name] = prop_value
|
||||
|
||||
for prop_name, prop in iteritems(all_props):
|
||||
if self.context == UnmarshalContext.REQUEST and prop.read_only:
|
||||
continue
|
||||
if self.context == UnmarshalContext.RESPONSE and prop.write_only:
|
||||
continue
|
||||
try:
|
||||
prop_value = value[prop_name]
|
||||
except KeyError:
|
||||
|
|
|
@ -11,9 +11,9 @@ from openapi_core.schema.parameters.exceptions import (
|
|||
)
|
||||
from openapi_core.schema.paths.exceptions import InvalidPath
|
||||
from openapi_core.schema.request_bodies.exceptions import MissingRequestBody
|
||||
from openapi_core.schema.schemas.enums import UnmarshalContext
|
||||
from openapi_core.schema.servers.exceptions import InvalidServer
|
||||
from openapi_core.security.exceptions import SecurityError
|
||||
from openapi_core.unmarshalling.schemas.enums import UnmarshalContext
|
||||
from openapi_core.unmarshalling.schemas.exceptions import (
|
||||
UnmarshalError, ValidateError,
|
||||
)
|
||||
|
@ -24,8 +24,6 @@ from openapi_core.validation.request.datatypes import (
|
|||
from openapi_core.validation.util import get_operation_pattern
|
||||
|
||||
|
||||
_CONTEXT = UnmarshalContext.REQUEST
|
||||
|
||||
class RequestValidator(object):
|
||||
|
||||
def __init__(
|
||||
|
@ -259,7 +257,9 @@ class RequestValidator(object):
|
|||
SchemaUnmarshallersFactory,
|
||||
)
|
||||
unmarshallers_factory = SchemaUnmarshallersFactory(
|
||||
self.spec._resolver, self.custom_formatters)
|
||||
self.spec._resolver, self.custom_formatters,
|
||||
context=UnmarshalContext.REQUEST,
|
||||
)
|
||||
unmarshaller = unmarshallers_factory.create(
|
||||
param_or_media_type.schema)
|
||||
return unmarshaller(value)
|
||||
|
|
|
@ -6,16 +6,14 @@ from openapi_core.schema.media_types.exceptions import InvalidContentType
|
|||
from openapi_core.schema.responses.exceptions import (
|
||||
InvalidResponse, MissingResponseContent,
|
||||
)
|
||||
from openapi_core.schema.schemas.enums import UnmarshalContext
|
||||
from openapi_core.schema.servers.exceptions import InvalidServer
|
||||
from openapi_core.unmarshalling.schemas.enums import UnmarshalContext
|
||||
from openapi_core.unmarshalling.schemas.exceptions import (
|
||||
UnmarshalError, ValidateError,
|
||||
)
|
||||
from openapi_core.validation.response.datatypes import ResponseValidationResult
|
||||
from openapi_core.validation.util import get_operation_pattern
|
||||
|
||||
_CONTEXT = UnmarshalContext.RESPONSE
|
||||
|
||||
|
||||
class ResponseValidator(object):
|
||||
|
||||
|
@ -76,7 +74,6 @@ class ResponseValidator(object):
|
|||
|
||||
try:
|
||||
media_type = operation_response[response.mimetype]
|
||||
|
||||
except InvalidContentType as exc:
|
||||
return None, [exc, ]
|
||||
|
||||
|
@ -143,7 +140,9 @@ class ResponseValidator(object):
|
|||
SchemaUnmarshallersFactory,
|
||||
)
|
||||
unmarshallers_factory = SchemaUnmarshallersFactory(
|
||||
self.spec._resolver, self.custom_formatters)
|
||||
self.spec._resolver, self.custom_formatters,
|
||||
context=UnmarshalContext.RESPONSE,
|
||||
)
|
||||
unmarshaller = unmarshallers_factory.create(
|
||||
param_or_media_type.schema)
|
||||
return unmarshaller(value)
|
||||
|
|
|
@ -268,5 +268,9 @@ class TestPetstore(object):
|
|||
if not spec.components:
|
||||
return
|
||||
|
||||
for _, schema in iteritems(spec.components.schemas):
|
||||
for schema_name, schema in iteritems(spec.components.schemas):
|
||||
assert type(schema) == Schema
|
||||
|
||||
schema_spec = spec_dict['components']['schemas'][schema_name]
|
||||
assert schema.read_only == schema_spec.get('readOnly', False)
|
||||
assert schema.write_only == schema_spec.get('writeOnly', False)
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from openapi_core.schema.media_types.exceptions import InvalidMediaTypeValue
|
||||
from openapi_core.schema.schemas.enums import UnmarshalContext
|
||||
from openapi_core.schema.schemas.exceptions import InvalidSchemaProperty
|
||||
from openapi_core.shortcuts import create_spec
|
||||
from openapi_core.validation.response.validators import ResponseValidator
|
||||
from openapi_core.validation.request.validators import RequestValidator
|
||||
from openapi_core.wrappers.mock import MockRequest, MockResponse
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def response_validator(spec):
|
||||
return ResponseValidator(spec)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def request_validator(spec):
|
||||
return RequestValidator(spec)
|
||||
|
||||
|
||||
@pytest.fixture('class')
|
||||
def spec(factory):
|
||||
spec_dict = factory.spec_from_file("data/v3.0/read_only_write_only.yaml")
|
||||
return create_spec(spec_dict)
|
||||
|
||||
|
||||
class TestReadOnly(object):
|
||||
|
||||
def test_write_a_read_only_property(self, request_validator):
|
||||
data = json.dumps({
|
||||
'id': 10,
|
||||
'name': "Pedro"
|
||||
})
|
||||
|
||||
request = MockRequest(host_url='', method='POST',
|
||||
path='/users', data=data)
|
||||
|
||||
with pytest.raises(InvalidMediaTypeValue) as ex:
|
||||
request_validator.validate(request).raise_for_errors()
|
||||
assert isinstance(ex.value.original_exception, InvalidSchemaProperty)
|
||||
ex = ex.value.original_exception
|
||||
|
||||
assert ex.property_name == 'id'
|
||||
assert UnmarshalContext.REQUEST.value in str(ex.original_exception)
|
||||
|
||||
def test_read_only_property_response(self, response_validator):
|
||||
data = json.dumps({
|
||||
'id': 10,
|
||||
'name': "Pedro"
|
||||
})
|
||||
|
||||
request = MockRequest(host_url='', method='POST',
|
||||
path='/users')
|
||||
|
||||
response = MockResponse(data)
|
||||
|
||||
is_valid = response_validator.validate(request, response)
|
||||
is_valid.raise_for_errors()
|
||||
|
||||
assert len(is_valid.errors) == 0
|
||||
assert is_valid.data.id == 10
|
||||
assert is_valid.data.name == "Pedro"
|
|
@ -1,63 +0,0 @@
|
|||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from openapi_core.schema.media_types.exceptions import InvalidMediaTypeValue
|
||||
from openapi_core.schema.schemas.enums import UnmarshalContext
|
||||
from openapi_core.schema.schemas.exceptions import InvalidSchemaProperty
|
||||
from openapi_core.shortcuts import create_spec
|
||||
from openapi_core.validation.response.validators import ResponseValidator
|
||||
from openapi_core.validation.request.validators import RequestValidator
|
||||
from openapi_core.wrappers.mock import MockRequest, MockResponse
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def response_validator(spec):
|
||||
return ResponseValidator(spec)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def request_validator(spec):
|
||||
return RequestValidator(spec)
|
||||
|
||||
|
||||
@pytest.fixture('class')
|
||||
def spec(factory):
|
||||
spec_dict = factory.spec_from_file("data/v3.0/read_only_write_only.yaml")
|
||||
return create_spec(spec_dict)
|
||||
|
||||
|
||||
class TestWriteOnly(object):
|
||||
|
||||
def test_write_only_property(self, request_validator):
|
||||
data = json.dumps({
|
||||
'name': "Pedro",
|
||||
'hidden': False
|
||||
})
|
||||
|
||||
request = MockRequest(host_url='', method='POST',
|
||||
path='/users', data=data)
|
||||
|
||||
is_valid = request_validator.validate(request)
|
||||
is_valid.raise_for_errors()
|
||||
assert is_valid.body.name == "Pedro"
|
||||
assert is_valid.body.hidden is False
|
||||
|
||||
def test_read_a_write_only_property(self, response_validator):
|
||||
data = json.dumps({
|
||||
'id': 10,
|
||||
'name': "Pedro",
|
||||
'hidden': True
|
||||
})
|
||||
|
||||
request = MockRequest(host_url='', method='POST',
|
||||
path='/users')
|
||||
response = MockResponse(data)
|
||||
|
||||
with pytest.raises(InvalidMediaTypeValue) as ex:
|
||||
response_validator.validate(request, response).raise_for_errors()
|
||||
assert isinstance(ex.value.original_exception, InvalidSchemaProperty)
|
||||
ex = ex.value.original_exception
|
||||
|
||||
assert ex.property_name == 'hidden'
|
||||
assert UnmarshalContext.RESPONSE.value in str(ex.original_exception)
|
97
tests/integration/validation/test_read_only_write_only.py
Normal file
97
tests/integration/validation/test_read_only_write_only.py
Normal file
|
@ -0,0 +1,97 @@
|
|||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from openapi_core.shortcuts import create_spec
|
||||
from openapi_core.unmarshalling.schemas.exceptions import InvalidSchemaValue
|
||||
from openapi_core.validation.response.validators import ResponseValidator
|
||||
from openapi_core.validation.request.validators import RequestValidator
|
||||
from openapi_core.testing import MockRequest, MockResponse
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def response_validator(spec):
|
||||
return ResponseValidator(spec)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def request_validator(spec):
|
||||
return RequestValidator(spec)
|
||||
|
||||
|
||||
@pytest.fixture('class')
|
||||
def spec(factory):
|
||||
spec_dict = factory.spec_from_file("data/v3.0/read_only_write_only.yaml")
|
||||
return create_spec(spec_dict)
|
||||
|
||||
|
||||
class TestReadOnly(object):
|
||||
|
||||
def test_write_a_read_only_property(self, request_validator):
|
||||
data = json.dumps({
|
||||
'id': 10,
|
||||
'name': "Pedro",
|
||||
})
|
||||
|
||||
request = MockRequest(host_url='', method='POST',
|
||||
path='/users', data=data)
|
||||
|
||||
result = request_validator.validate(request)
|
||||
|
||||
assert type(result.errors[0]) == InvalidSchemaValue
|
||||
assert result.body is None
|
||||
|
||||
def test_read_only_property_response(self, response_validator):
|
||||
data = json.dumps({
|
||||
'id': 10,
|
||||
'name': "Pedro",
|
||||
})
|
||||
|
||||
request = MockRequest(host_url='', method='POST',
|
||||
path='/users')
|
||||
|
||||
response = MockResponse(data)
|
||||
|
||||
result = response_validator.validate(request, response)
|
||||
|
||||
assert not result.errors
|
||||
assert result.data == {
|
||||
'id': 10,
|
||||
'name': "Pedro",
|
||||
}
|
||||
|
||||
|
||||
class TestWriteOnly(object):
|
||||
|
||||
def test_write_only_property(self, request_validator):
|
||||
data = json.dumps({
|
||||
'name': "Pedro",
|
||||
'hidden': False,
|
||||
})
|
||||
|
||||
request = MockRequest(host_url='', method='POST',
|
||||
path='/users', data=data)
|
||||
|
||||
result = request_validator.validate(request)
|
||||
|
||||
assert not result.errors
|
||||
assert result.body == {
|
||||
'name': "Pedro",
|
||||
'hidden': False,
|
||||
}
|
||||
|
||||
def test_read_a_write_only_property(self, response_validator):
|
||||
data = json.dumps({
|
||||
'id': 10,
|
||||
'name': "Pedro",
|
||||
'hidden': True,
|
||||
})
|
||||
|
||||
request = MockRequest(host_url='', method='POST',
|
||||
path='/users')
|
||||
response = MockResponse(data)
|
||||
|
||||
result = response_validator.validate(request, response)
|
||||
|
||||
assert type(result.errors[0]) == InvalidSchemaValue
|
||||
assert result.data is None
|
|
@ -8,6 +8,7 @@ from openapi_core.schema.parameters.models import Parameter
|
|||
from openapi_core.schema.schemas.enums import SchemaType
|
||||
from openapi_core.schema.schemas.models import Schema
|
||||
from openapi_core.schema.schemas.types import NoValue
|
||||
from openapi_core.unmarshalling.schemas.enums import UnmarshalContext
|
||||
from openapi_core.unmarshalling.schemas.exceptions import (
|
||||
InvalidSchemaFormatValue, InvalidSchemaValue, UnmarshalError,
|
||||
FormatterNotFoundError,
|
||||
|
@ -20,9 +21,10 @@ from openapi_core.unmarshalling.schemas.formatters import Formatter
|
|||
|
||||
@pytest.fixture
|
||||
def unmarshaller_factory():
|
||||
def create_unmarshaller(schema, custom_formatters=None):
|
||||
def create_unmarshaller(schema, custom_formatters=None, context=None):
|
||||
return SchemaUnmarshallersFactory(
|
||||
custom_formatters=custom_formatters).create(schema)
|
||||
custom_formatters=custom_formatters, context=context).create(
|
||||
schema)
|
||||
return create_unmarshaller
|
||||
|
||||
|
||||
|
@ -429,3 +431,45 @@ class TestSchemaUnmarshallerCall(object):
|
|||
|
||||
result = unmarshaller_factory(schema)(value)
|
||||
assert result == value
|
||||
|
||||
def test_read_only_properties(self, unmarshaller_factory):
|
||||
id_property = Schema('integer', read_only=True)
|
||||
|
||||
def properties():
|
||||
yield ('id', id_property)
|
||||
|
||||
obj_schema = Schema('object', properties=properties(), required=['id'])
|
||||
|
||||
# readOnly properties may be admitted in a Response context
|
||||
result = unmarshaller_factory(
|
||||
obj_schema, context=UnmarshalContext.RESPONSE)({"id": 10})
|
||||
assert result == {
|
||||
'id': 10,
|
||||
}
|
||||
|
||||
# readOnly properties are not admitted on a Request context
|
||||
result = unmarshaller_factory(
|
||||
obj_schema, context=UnmarshalContext.REQUEST)({"id": 10})
|
||||
|
||||
assert result == {}
|
||||
|
||||
def test_write_only_properties(self, unmarshaller_factory):
|
||||
id_property = Schema('integer', write_only=True)
|
||||
|
||||
def properties():
|
||||
yield ('id', id_property)
|
||||
|
||||
obj_schema = Schema('object', properties=properties(), required=['id'])
|
||||
|
||||
# readOnly properties may be admitted in a Response context
|
||||
result = unmarshaller_factory(
|
||||
obj_schema, context=UnmarshalContext.REQUEST)({"id": 10})
|
||||
assert result == {
|
||||
'id': 10,
|
||||
}
|
||||
|
||||
# readOnly properties are not admitted on a Request context
|
||||
result = unmarshaller_factory(
|
||||
obj_schema, context=UnmarshalContext.RESPONSE)({"id": 10})
|
||||
|
||||
assert result == {}
|
||||
|
|
Loading…
Reference in a new issue