def test_enum_choices(): @enum.unique class TestIntEnum(enum.IntEnum): TEST_1 = 1 TEST_2 = 2 TEST_3 = 3 class TestModel(middle.Model): some_enum = middle.field(type=TestIntEnum, description="Some test enumeration") api = parse(TestModel) assert isinstance(api, OpenAPI) assert api.specification == {"$ref": "#/components/schemas/TestModel"} assert api.components == { "TestModel": { "properties": { "some_enum": { "$ref": "#/components/schemas/TestIntEnum", "description": "Some test enumeration", } }, "type": "object", "required": ["some_enum"], }, "TestIntEnum": { "type": "integer", "format": "int64", "choices": [1, 2, 3], }, }
def test_enum_choices_no_component(): @enum.unique class TestIntEnum(enum.IntEnum): TEST_1 = 1 TEST_2 = 2 TEST_3 = 3 class TestModel(middle.Model): some_enum = middle.field(type=TestIntEnum) with middle.config.temp(openapi_enum_as_component=False): api = parse(TestModel) assert isinstance(api, OpenAPI) assert api.specification == {"$ref": "#/components/schemas/TestModel"} assert api.components == { "TestModel": { "properties": { "some_enum": { "type": "integer", "format": "int64", "choices": [1, 2, 3], } }, "type": "object", "required": ["some_enum"], } }
def test_union_type_not_nullable(): class TestModel(middle.Model): lots_of_values = middle.field(type=t.Union[str, int, float]) api = parse(TestModel) assert isinstance(api, OpenAPI) assert api.specification == {"$ref": "#/components/schemas/TestModel"} assert api.components == { "TestModel": { "properties": { "lots_of_values": { "anyOf": [ { "type": "string" }, { "type": "integer", "format": "int64" }, { "type": "number", "format": "double" }, ] } }, "type": "object", "required": ["lots_of_values"], } }
def test_simple_model_with_typing(): class TestModel(middle.Model): __description__ = "Test model for unit tests" name = middle.field(type=t.List[str], description="List of names", default=[]) api = parse(TestModel) assert isinstance(api, OpenAPI) assert api.specification == {"$ref": "#/components/schemas/TestModel"} assert api.components == { "TestModel": { "properties": { "name": { "type": "array", "description": "List of names", "items": { "type": "string" }, } }, "description": "Test model for unit tests", "type": "object", "required": [], } }
def test_dict_type(): class TestModel(middle.Model): options = middle.field( type=t.Dict[str, str], description="Options for TestModel", min_properties=1, ) api = parse(TestModel) assert isinstance(api, OpenAPI) assert api.specification == {"$ref": "#/components/schemas/TestModel"} assert api.components == { "TestModel": { "properties": { "options": { "type": "object", "description": "Options for TestModel", "minProperties": 1, "additionalProperties": { "type": "string" }, } }, "type": "object", "required": ["options"], } }
def test_model_within_model(): class InnerModel(middle.Model): name = middle.field(type=str, min_length=3, description="The person name") age = middle.field(type=int, minimum=18, description="The person age") class TestModel(middle.Model): person = middle.field(type=InnerModel, description="The person to access this resource") active = middle.field(type=bool, description="If the resource is active") api = parse(TestModel) assert isinstance(api, OpenAPI) assert api.specification == {"$ref": "#/components/schemas/TestModel"} assert api.components == { "InnerModel": { "properties": { "name": { "type": "string", "minLength": 3, "description": "The person name", }, "age": { "type": "integer", "format": "int64", "minimum": 18, "description": "The person age", }, }, "description": "The person to access this resource", "type": "object", "required": ["name", "age"], }, "TestModel": { "properties": { "person": { "$ref": "#/components/schemas/InnerModel" }, "active": { "type": "boolean", "description": "If the resource is active", }, }, "type": "object", "required": ["person", "active"], }, }
def test_bool_type(): class TestModel(middle.Model): switch = middle.field(type=bool) api = parse(TestModel) assert isinstance(api, OpenAPI) assert api.specification == {"$ref": "#/components/schemas/TestModel"} assert api.components == { "TestModel": { "properties": { "switch": { "type": "boolean" } }, "type": "object", "required": ["switch"], } }
def test_datetime_type(): class TestModel(middle.Model): when = middle.field(type=datetime.datetime) api = parse(TestModel) assert isinstance(api, OpenAPI) assert api.specification == {"$ref": "#/components/schemas/TestModel"} assert api.components == { "TestModel": { "properties": { "when": { "type": "string", "format": "date-time" } }, "type": "object", "required": ["when"], } }
def test_optional_type(): class TestModel(middle.Model): maybe_name = middle.field(type=t.Optional[str]) api = parse(TestModel) assert isinstance(api, OpenAPI) assert api.specification == {"$ref": "#/components/schemas/TestModel"} assert api.components == { "TestModel": { "properties": { "maybe_name": { "type": "string", "nullable": True } }, "type": "object", "required": [], } }
def test_simple_model(): class TestModel(middle.Model): name = middle.field(type=str, description="The name", min_length=5) api = parse(TestModel) assert isinstance(api, OpenAPI) assert api.specification == {"$ref": "#/components/schemas/TestModel"} assert api.components == { "TestModel": { "properties": { "name": { "type": "string", "description": "The name", "minLength": 5, } }, "type": "object", "required": ["name"], } }
def test_byte_type(): class TestModel(middle.Model): file_data = middle.field(type=bytes, description="The contents of the file") api = parse(TestModel) assert isinstance(api, OpenAPI) assert api.specification == {"$ref": "#/components/schemas/TestModel"} assert api.components == { "TestModel": { "properties": { "file_data": { "type": "string", "format": "byte", "description": "The contents of the file", } }, "type": "object", "required": ["file_data"], } }
def test_complex_model(): api = parse(Game) assert isinstance(api, OpenAPI) assert api.specification == {"$ref": "#/components/schemas/Game"} assert api.components == { "PlatformEnum": { "type": "string", "choices": ["XBOX1", "PLAYSTATION4", "PC"], }, "Player": { "type": "object", "properties": { "nickname": { "type": "string", "description": "The nickname of the player over the internet", }, "youtube_channel": { "type": "string", "description": "The YouTube channel of the player", }, }, "required": ["nickname"], }, "LanguageEnum": { "type": "integer", "format": "int64", "choices": [1, 2, 3, 4, 5], }, "CityRegionEnum": { "type": "string", "choices": ["TROPICAL", "TEMPERATE", "BOREAL"], }, "City": { "type": "object", "properties": { "name": {"type": "string", "description": "The city name"}, "region": { "$ref": "#/components/schemas/CityRegionEnum", "description": "The region this city is located", }, }, "required": ["name"], "description": "One awesome city built", }, "Game": { "type": "object", "properties": { "name": { "type": "string", "description": "The name of the game", }, "platform": { "$ref": "#/components/schemas/PlatformEnum", "description": "Which platform it runs on", }, "score": { "type": "number", "format": "double", "minimum": 0, "maximum": 10, "multipleOf": 0.1, "description": "The average score of the game", }, "resolution_tested": { "type": "string", "pattern": "^\d+x\d+$", "description": "The resolution which the game was tested", }, "genre": { "type": "array", "items": {"type": "string"}, "minItems": 1, "uniqueItems": True, "description": "One or more genres this game is part of", }, "rating": { "type": "object", "additionalProperties": { "type": "number", "format": "double", }, "minProperties": 3, "description": "Ratings given on specialized websites", }, "players": { "type": "array", "items": {"$ref": "#/components/schemas/Player"}, "description": "Some of the notorious players of this game", }, "language": { "$ref": "#/components/schemas/LanguageEnum", "description": "The main language of the game", }, "awesome_city": {"$ref": "#/components/schemas/City"}, "remarkable_resources": { "anyOf": [ {"$ref": "#/components/schemas/Player"}, {"$ref": "#/components/schemas/City"}, ], "description": "Some remarkable resources of this game over the internet", }, }, "required": [ "name", "platform", "score", "resolution_tested", "genre", "rating", "players", "language", "awesome_city", "remarkable_resources", ], "description": "An electronic game model", }, }
def test_invalid_type_for_schema(): class TestModel(middle.Model): name = middle.field(type=t.Tuple[str, int]) with pytest.raises(InvalidType): parse(TestModel)
def test_invalid_dict_type(): class TestModel(middle.Model): options = middle.field(type=t.Dict[float, str]) with pytest.raises(TypeError): parse(TestModel)