From d3b105a9a5d68d4f4ddf283ed3b817844e37a9cd Mon Sep 17 00:00:00 2001 From: JONEMI19 Date: Sat, 8 Jul 2023 11:46:58 +0000 Subject: [PATCH] improve test coverage --- fastapi/_compat.py | 38 +++++++-------------------------- tests/main.py | 9 ++------ tests/test_application.py | 45 ++++++--------------------------------- 3 files changed, 16 insertions(+), 76 deletions(-) diff --git a/fastapi/_compat.py b/fastapi/_compat.py index 68302fdbe..9aad9196b 100644 --- a/fastapi/_compat.py +++ b/fastapi/_compat.py @@ -424,11 +424,10 @@ else: if (field.shape in mapping_shapes) and not lenient_issubclass( # type: ignore[attr-defined] field.type_, BaseModel ): - if field.sub_fields is None: # type: ignore[attr-defined] - return False - for sub_field in field.sub_fields: # type: ignore[attr-defined] - if not is_scalar_field(sub_field): - return False + if field.sub_fields is not None: + for sub_field in field.sub_fields: # type: ignore[attr-defined] + if not is_scalar_field(sub_field): + return False return True return False @@ -436,11 +435,10 @@ else: if (field.shape in mapping_shapes) and not lenient_issubclass( # type: ignore[attr-defined] field.type_, BaseModel ): - if field.sub_fields is None: # type: ignore[attr-defined] - return False - for sub_field in field.sub_fields: # type: ignore[attr-defined] - if not is_scalar_sequence_field(sub_field): - return False + if field.sub_fields is not None: # type: ignore[attr-defined] + for sub_field in field.sub_fields: # type: ignore[attr-defined] + if not is_scalar_sequence_field(sub_field): + return False return True return False @@ -628,16 +626,6 @@ def field_annotation_is_scalar_sequence(annotation: Union[Type[Any], None]) -> b def field_annotation_is_scalar_mapping(annotation: Union[Type[Any], None]) -> bool: - origin = get_origin(annotation) - if origin is Union or origin is UnionType: - at_least_one_scalar_mapping = False - for arg in get_args(annotation): - if field_annotation_is_scalar_mapping(arg): - at_least_one_scalar_mapping = True - continue - elif not field_annotation_is_scalar(arg): - return False - return at_least_one_scalar_mapping return field_annotation_is_mapping(annotation) and all( field_annotation_is_scalar(sub_annotation) for sub_annotation in get_args(annotation) @@ -647,16 +635,6 @@ def field_annotation_is_scalar_mapping(annotation: Union[Type[Any], None]) -> bo def field_annotation_is_scalar_sequence_mapping( annotation: Union[Type[Any], None] ) -> bool: - origin = get_origin(annotation) - if origin is Union or origin is UnionType: - at_least_one_scalar_mapping = False - for arg in get_args(annotation): - if field_annotation_is_scalar_mapping(arg): - at_least_one_scalar_mapping = True - continue - elif not field_annotation_is_scalar(arg): - return False - return at_least_one_scalar_mapping return field_annotation_is_mapping(annotation) and all( field_annotation_is_scalar_sequence(sub_annotation) for sub_annotation in get_args(annotation)[1:] diff --git a/tests/main.py b/tests/main.py index f9cf6f400..654e77a40 100644 --- a/tests/main.py +++ b/tests/main.py @@ -1,5 +1,5 @@ import http -from typing import FrozenSet, List, Mapping, Optional +from typing import FrozenSet, List, Mapping, Optional, Union from fastapi import FastAPI, Path, Query @@ -184,11 +184,6 @@ def get_query_param_required_type(query: int = Query()): return f"foo bar {query}" -@app.get("/query/sequence-params") -def get_sequence_query_params(query: Mapping[str, List[int]] = Query({})): - return f"foo bar {query}" - - @app.get("/query/mapping-params") def get_mapping_query_params(queries: Mapping[str, str] = Query({})): return f"foo bar {queries['foo']} {queries['bar']}" @@ -201,7 +196,7 @@ def get_sequence_mapping_query_params(queries: Mapping[str, List[int]] = Query({ @app.get("/query/mixed-params") def get_mixed_mapping_query_params( - sequence_mapping_queries: Mapping[str, List[str]] = Query({}), + sequence_mapping_queries: Mapping[str, List[Union[str, int]]] = Query({}), mapping_query: Mapping[str, str] = Query(), query: str = Query(), ): diff --git a/tests/test_application.py b/tests/test_application.py index 17f2ca31e..741d80182 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -1163,44 +1163,6 @@ def test_openapi_schema(): }, } }, - "/query/sequence-params": { - "get": { - "summary": "Get Sequence Query Params", - "operationId": "get_sequence_query_params_query_sequence_params_get", - "parameters": [ - { - "required": False, - "schema": { - "additionalProperties": { - "items": {"type": "integer"}, - "type": "array", - }, - "type": "object", - "title": "Query", - "default": {}, - }, - "name": "query", - "in": "query", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, "/query/mapping-params": { "get": { "summary": "Get Mapping Query Params", @@ -1283,7 +1245,12 @@ def test_openapi_schema(): "required": False, "schema": { "additionalProperties": { - "items": {"type": "string"}, + "items": { + "anyOf": [ + {"type": "string"}, + {"type": "integer"}, + ] + }, "type": "array", }, "type": "object",