def test_all_of_conflict_in_value( oas_type: str, prop_key: str, prop_value: bool, ) -> None: with pytest.raises(exceptions.OASConflict) as err: parse_type.resolve( components={}, work_item={ 'allOf': [ { 'type': oas_type, prop_key: prop_value, }, { 'type': oas_type, prop_key: not prop_value, }, ], }, ) assert ( f'{prop_key} value differs between mixed schemas. ' f'a={prop_value} != b={not prop_value}. When using "anyOf,oneOf,allOf" values in ' f'same location must be equal. ' f'Either make it so or remove one of the duplicating properties.' ) == str(err.value)
def test_discriminator_and__additional_properties( additional_properties: bool, should_raise: bool, ) -> None: try: parse_type.resolve( {}, { 'type': 'object', 'discriminator': { 'propertyName': 'petTypee', }, 'additionalProperties': additional_properties, 'properties': { 'name': { 'type': 'string', }, 'petType': { 'type': 'string', }, }, 'required': [ 'name', 'petType', ], }, ) except ValueError as err: if should_raise: assert err.args[ 0] == 'Discriminator petTypee not found in object properties [name, petType]' else: raise AssertionError( 'If additionalProperties==true discriminator may be found in them, ' 'therefore this exception should not occur.', )
def test_example_wrong_type(example: t.Any) -> None: with pytest.raises(exceptions.OASInvalidTypeValue): parse_type.resolve( {}, { 'type': 'string', 'example': example, }, )
def test_wrong_value_type(key: str, value: t.Any) -> None: with pytest.raises(exceptions.OASInvalidTypeValue): parse_type.resolve( {}, { 'type': 'boolean', key: value, }, )
def test_default_wrong_type(default: t.Any) -> None: with pytest.raises(exceptions.OASInvalidTypeValue): parse_type.resolve( {}, { 'type': 'string', 'default': default, }, )
def test_invalid_min_max_length( min_length: int, max_length: int, ) -> None: with pytest.raises(exceptions.OASInvalidConstraints): parse_type.resolve( {}, { 'type': 'string', 'minLength': min_length, 'maxLength': max_length, }, )
def test_all_of_more_than_one_type() -> None: with pytest.raises(exceptions.OASConflict): parse_type.resolve( components={}, work_item={ 'allOf': [ { 'type': 'string', }, { 'type': 'number', }, ], }, )
def test_all_of_any() -> None: mix_type = parse_type.resolve( components={}, work_item={ 'allOf': [ { 'default': 10, }, { 'default': 10, 'example': 'Test', }, { 'readOnly': True, }, { 'writeOnly': False, }, ], }, ) assert isinstance(mix_type, model.OASAnyType) assert 10 == mix_type.default assert 'Test' == mix_type.example assert mix_type.read_only assert not mix_type.write_only assert not mix_type.deprecated
def test_discriminator() -> None: oas_object = parse_type.resolve( {}, { 'type': 'object', 'discriminator': { 'propertyName': 'petType', }, 'properties': { 'name': { 'type': 'string', }, 'petType': { 'type': 'string', }, }, 'required': [ 'name', 'petType', ], }, ) assert isinstance(oas_object, model.OASObjectType) assert oas_object.discriminator assert oas_object.discriminator.property_name == 'petType' assert not oas_object.discriminator.mapping
def test_all_of_boolean() -> None: mix_type = parse_type.resolve( components={}, work_item={ 'allOf': [ { 'default': True, }, { 'default': True, 'example': False, }, { 'type': 'boolean', 'readOnly': True, }, { 'deprecated': False, }, { 'writeOnly': False, }, ], }, ) assert isinstance(mix_type, model.OASBooleanType) assert mix_type.default assert not mix_type.example assert mix_type.read_only assert not mix_type.write_only assert not mix_type.deprecated
def test_any_of_is_any() -> None: mix_type = parse_type.resolve( components={}, work_item={ 'anyOf': [ { 'type': 'string', }, { 'type': 'number', }, { 'type': 'integer', }, { 'type': 'boolean', }, { 'type': 'array', 'items': {}, }, { 'type': 'object', }, ], }, ) assert isinstance(mix_type, model.OASAnyType)
def test_python_type() -> None: assert issubclass(parse_type.resolve( {}, { 'type': 'boolean', }, ).python_type, bool)
def test_oas_file_python_type() -> None: assert bytes == parse_type.resolve( {}, { 'type': 'string', 'format': 'binary', }, ).python_type
def _do() -> t.Any: return parse_type.resolve( components={ 'schemas': { 'Dog': { 'type': 'object', 'properties': { 'bark': { 'type': 'string', }, }, }, 'Cat': { 'type': 'object', 'properties': { 'mew': { 'type': 'string', }, }, }, 'Pet': { 'type': 'object', 'properties': { 'name': { 'type': 'string', }, 'petType': { 'type': 'string', }, }, 'required': ['name', 'petType'], 'discriminator': { 'propertyName': 'petType', 'mapping': m_1, }, }, }, }, work_item={ 'allOf': [ { '$ref': '#/components/schemas/Pet', }, { 'properties': { 'bark': { 'type': 'string', }, }, 'discriminator': { 'propertyName': 'petType', 'mapping': m_2, }, }, ], }, )
def test_correct_python_type() -> None: oas_string = parse_type.resolve( {}, { 'type': 'string', }, ) assert isinstance(oas_string, model.OASStringType) assert issubclass(oas_string.python_type, str)
def test_correct_python_type() -> None: assert issubclass( parse_type.resolve( {}, { 'type': 'object', }, ).python_type, dict, )
def test_oas_type() -> None: assert parse_type.resolve( {}, { 'type': 'array', 'uniqueItems': False, 'items': { 'schema': { 'type': 'string', }, }, }, ).oas_type == 'array'
def test_all_of_object_ref_properties() -> None: mix_type = parse_type.resolve( components={ 'schemas': { 'Weight': { 'type': 'number', 'example': 15.0, 'format': 'kilogram', }, 'Mighty': { 'type': 'boolean', 'example': True, }, 'Hammer': { 'type': 'object', 'required': ['weight'], 'properties': { 'weight': { '$ref': '#/components/schemas/Weight', }, }, }, }, }, work_item={ 'allOf': [ { '$ref': '#/components/schemas/Hammer', }, { 'properties': { 'isMighty': { '$ref': '#/components/schemas/Mighty', }, 'weight': { '$ref': '#/components/schemas/Weight', }, }, }, ], }, ) assert isinstance(mix_type, model.OASObjectType) assert 2 == len(mix_type.properties) assert 'weight' in mix_type.properties assert isinstance(mix_type.properties['weight'], model.OASNumberType) assert 'isMighty' in mix_type.properties assert isinstance(mix_type.properties['isMighty'], model.OASBooleanType)
def test_oas_file( str_format: str, expected_cls: t.Type[t.Any], ) -> None: assert isinstance( parse_type.resolve( {}, { 'type': 'string', 'format': str_format, }, ), expected_cls, )
def _do() -> t.Any: return parse_type.resolve( components={ 'schemas': { 'Weight': { 'type': 'number', 'example': 15.0, 'format': 'kilogram', }, 'Mighty': { 'type': 'boolean', 'example': True, }, 'Power': { 'type': 'number', }, 'Hammer': { 'type': 'object', 'required': ['weight'], 'properties': { 'weight': { '$ref': '#/components/schemas/Weight', }, }, }, }, }, work_item={ 'allOf': [ { '$ref': '#/components/schemas/Hammer', }, { 'properties': { 'isMighty': { '$ref': '#/components/schemas/Mighty', }, }, }, { 'additionalProperties': ap_1, }, { 'additionalProperties': ap_2, }, ], }, )
def test_free_form( properties: t.Optional[t.Dict[str, t.Any]], additional_properties: t.Union[bool, model.OASType[t.Any]], expected_result: bool, ) -> None: oas_object = parse_type.resolve( {}, { 'type': 'object', 'additionalProperties': additional_properties, 'properties': properties, }, ) assert isinstance(oas_object, model.OASObjectType) assert oas_object.is_free_form is expected_result
def _build_media_type( mime_type: str, media_type_def: t.Dict[str, t.Any], ) -> model.OASMediaType: # raw_example = media_type_def.get('example', None) # raw_examples = media_type_def.get('examples', {}) # raw_encoding = media_type_def.get('encoding', None) # if not (raw_example and raw_examples) and schema.example is not None: # raw_examples = [{mime_type: schema.example}] # elif raw_examples is None and raw_example is not None: # raw_examples = [{mime_type: raw_example}] return model.OASMediaType(schema=parse_type.resolve( components, media_type_def['schema'], ), )
def _do() -> t.Any: return parse_type.resolve( components={ 'schemas': { 'Pet': { **(p_1 or {}), **{ 'type': 'object', 'properties': { 'name': { 'type': 'string', }, 'petType': { 'type': 'string', }, }, 'required': ['name', 'petType'], }, }, }, }, work_item={ 'allOf': [ { '$ref': '#/components/schemas/Pet', }, { **(p_2 or {}), **{ 'properties': { 'packSize': { 'type': 'integer', 'format': 'int32', 'description': 'the size of the pack the dog is from', 'default': 0, 'minimum': 0, }, }, 'required': [ 'packSize', ], }, }, ], }, )
def test_pattern( pattern: str, should_match: t.List[str], should_not_match: t.List[str], ) -> None: oas_string = parse_type.resolve( {}, { 'type': 'string', 'pattern': pattern, }, ) assert isinstance(oas_string, model.OASStringType) assert oas_string.pattern is not None for example in should_match: assert oas_string.pattern.match( example) is not None, f'{pattern} did not match' for example in should_not_match: assert oas_string.pattern.match( example) is None, f'{pattern} did match'
def test_any_one_of( mix_key: str, in_mix: t.List[t.Dict[str, t.Any]], expected_schemas: t.List[t.Tuple[bool, t.Type[model.OASType[t.Any]]]], ) -> None: mix_type = parse_type.resolve( components={}, work_item={ mix_key: in_mix, }, ) assert isinstance(mix_type, (model.OASAnyOfType, model.OASOneOfType)) assert len(mix_type.schemas) == len(in_mix) assert list( map( lambda v: (v[0], type(v[1])), mix_type.schemas, ), ) == expected_schemas
def test_all_of_array() -> None: mix_type = parse_type.resolve( components={ 'schemas': { 'Hammer': { 'type': 'object', 'required': ['weight'], 'properties': { 'weight': { 'type': 'number', }, }, }, }, }, work_item={ 'nullable': True, 'readOnly': True, 'writeOnly': False, 'allOf': [ { 'type': 'array', 'items': { '$ref': '#/components/schemas/Hammer', }, }, { 'uniqueItems': True, }, ], }, ) assert isinstance(mix_type, model.OASArrayType) assert isinstance(mix_type.items_type, model.OASObjectType) assert mix_type.unique_items assert mix_type.nullable assert mix_type.read_only assert not mix_type.write_only
def test_python_type( unique_items: bool, python_type: t.Type[t.Any], ) -> None: arr_python_type = parse_type.resolve( {}, { 'type': 'array', 'uniqueItems': unique_items, 'items': { 'schema': { 'type': 'string', }, }, }, ).python_type assert issubclass( arr_python_type, python_type, )
def test_all_of_integer(oas_type: str) -> None: mix_type = parse_type.resolve( components={}, work_item={ 'default': 4 if oas_type == 'integer' else 4.0, 'example': 2 if oas_type == 'integer' else 2.0, 'allOf': [ { 'minimum': 2 if oas_type == 'integer' else 2.0, }, { 'maximum': 10 if oas_type == 'integer' else 10.0, }, { 'multipleOf': 2 if oas_type == 'integer' else 2.0, }, { 'type': oas_type, 'deprecated': False, }, ], }, ) assert isinstance(mix_type, model.OASNumberType) assert issubclass( mix_type.number_cls, int if oas_type == 'integer' else float, ) assert (2 if oas_type == 'integer' else 2.0) == mix_type.minimum assert (10 if oas_type == 'integer' else 10.0) == mix_type.maximum assert (4 if oas_type == 'integer' else 4.0) == mix_type.default assert (2 if oas_type == 'integer' else 2.0) == mix_type.example assert (2 if oas_type == 'integer' else 2.0) == mix_type.multiple_of assert not mix_type.deprecated
def test_oas_type() -> None: parse_type.resolve({}, {'type': 'object'}).oas_type == 'object'
def test_all_of_object() -> None: mix_type = parse_type.resolve( components={}, work_item={ 'allOf': [ { 'type': 'object', 'required': [ 'name', ], 'properties': { 'name': { 'type': 'string', }, }, }, { 'properties': { 'lastName': { 'type': 'string', }, }, }, { 'deprecated': True, 'required': [ 'lastName', ], }, { 'required': [ 'name', 'lastName', 'fullName', ], 'properties': { 'lastName': { 'type': 'string', 'writeOnly': True, 'deprecated': True, }, 'name': { 'type': 'string', 'writeOnly': True, 'deprecated': True, }, 'fullName': { 'type': 'string', 'writeOnly': True, }, }, }, ], }, ) assert isinstance(mix_type, model.OASObjectType) assert 3 == len(mix_type.properties) assert 'name' in mix_type.properties assert isinstance(mix_type.properties['name'], model.OASStringType) assert mix_type.properties['name'].write_only assert mix_type.properties['name'].deprecated assert isinstance(mix_type.properties['fullName'], model.OASStringType) assert mix_type.properties['fullName'].write_only assert not mix_type.properties['fullName'].deprecated assert isinstance(mix_type.properties['lastName'], model.OASStringType) assert mix_type.properties['lastName'].write_only assert mix_type.properties['lastName'].deprecated assert 3 == len(mix_type.required) assert 'lastName' in mix_type.required assert 'name' in mix_type.required assert mix_type.deprecated