From b2c823778857aded8e3a981072c03891e69eb126 Mon Sep 17 00:00:00 2001 From: Perrin Samuels Date: Fri, 31 May 2024 13:36:31 -0700 Subject: [PATCH 1/2] do not wrap an example list value in another list --- drf_spectacular/plumbing.py | 6 ++-- tests/test_examples.py | 58 +++++++++++++++++++++++++++++++++++-- tests/test_examples.yml | 5 ++++ 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/drf_spectacular/plumbing.py b/drf_spectacular/plumbing.py index 69d9f7fc..fe0db72d 100644 --- a/drf_spectacular/plumbing.py +++ b/drf_spectacular/plumbing.py @@ -1408,18 +1408,18 @@ class TmpView(views.APIView): def build_listed_example_value(value: Any, paginator, direction): if not paginator or direction == 'request': - return [value] + return value if type(value) is list else [value] sentinel = object() schema = paginator.get_paginated_response_schema(sentinel) if schema is sentinel: - return [value] + return value if type(value) is list else [value] def drilldown_schema_example(schema, sentinel): # Recursively travel schema properties to build example. if schema is sentinel: - return [value] + return value if type(value) is list else [value] if 'properties' in schema.keys(): return { field_name: drilldown_schema_example(field_schema, sentinel) diff --git a/tests/test_examples.py b/tests/test_examples.py index a1646dee..5330f66b 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -56,6 +56,11 @@ class BSerializer(serializers.Serializer): value={"field": 222}, request_only=True, ), + OpenApiExample( + 'Serializer C Example List', + value=[{"field": 333}, {"field": 444}], + response_only=True, + ), ] ) class CSerializer(serializers.Serializer): @@ -180,7 +185,16 @@ class PaginatedExamplesViewSet(ExampleTestWithExtendedViewSet): 'results': [{'field': 111}], }, 'summary': 'Serializer C Example RO' - } + }, + 'SerializerCExampleList': { + 'value': { + 'count': 123, + 'next': 'http://api.example.org/accounts/?offset=400&limit=100', + 'previous': 'http://api.example.org/accounts/?offset=200&limit=100', + 'results': [{'field': 333}, {'field': 444}], + }, + 'summary': 'Serializer C Example List' + }, } @@ -236,11 +250,22 @@ class PaginatedExamplesViewSet(ExampleTestWithExtendedViewSet): 'results': [{'field': 111}], }, 'summary': 'Serializer C Example RO' - } + }, + 'SerializerCExampleList': { + 'value': { + 'pagination': { + 'count': 123, + 'next': 'http://api.example.org/accounts/?offset=400&limit=100', + 'previous': 'http://api.example.org/accounts/?offset=200&limit=100', + }, + 'results': [{'field': 333}, {'field': 444}], + }, + 'summary': 'Serializer C Example List' + }, } -def test_example_request_response_listed_examples(no_warnings): +def test_example_request_response_singular_examples(no_warnings): @extend_schema( request=ASerializer(many=True), responses=ASerializer(many=True), @@ -263,6 +288,29 @@ class XView(generics.CreateAPIView): } +def test_example_request_response_listed_examples(no_warnings): + @extend_schema( + request=ASerializer(many=True), + responses=ASerializer(many=True), + examples=[ + OpenApiExample('Ex', [{'id': '2345'}, {'id': '2345'}]) + ] + ) + class XView(generics.CreateAPIView): + pass + + schema = generate_schema('e', view=XView) + operation = schema['paths']['/e']['post'] + assert operation['requestBody']['content']['application/json'] == { + 'schema': {'type': 'array', 'items': {'$ref': '#/components/schemas/A'}}, + 'examples': {'Ex': {'value': [{'id': '2345'},{'id': '2345'}]}} + } + assert operation['responses']['201']['content']['application/json'] == { + 'schema': {'type': 'array', 'items': {'$ref': '#/components/schemas/A'}}, + 'examples': {'Ex': {'value': [{'id': '2345'},{'id': '2345'}]}} + } + + def test_examples_list_detection_on_non_200_decoration(no_warnings): class ExceptionSerializer(serializers.Serializer): api_status_code = serializers.CharField() @@ -375,5 +423,9 @@ class PaginatedExamplesViewSet(ExampleTestWithExtendedViewSet): 'SerializerCExampleRO': { 'value': [{'field': 111}], 'summary': 'Serializer C Example RO' + }, + 'SerializerCExampleList': { + 'value': [{'field': 333}, {'field': 444}], + 'summary': 'Serializer C Example List' } } diff --git a/tests/test_examples.yml b/tests/test_examples.yml index 7e18cffd..a64dfd0d 100644 --- a/tests/test_examples.yml +++ b/tests/test_examples.yml @@ -40,6 +40,11 @@ paths: value: - field: 111 summary: Serializer C Example RO + SerializerCExampleList: + value: + - field: 333 + - field: 444 + summary: Serializer C Example List description: '' post: operationId: schema_create From 9da38505fc7b6f40b892761ce2278b30dc7d5ff5 Mon Sep 17 00:00:00 2001 From: Perrin Samuels Date: Fri, 31 May 2024 15:33:53 -0700 Subject: [PATCH 2/2] add missing whitespace for linter --- tests/test_examples.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_examples.py b/tests/test_examples.py index 5330f66b..9a75541f 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -303,11 +303,11 @@ class XView(generics.CreateAPIView): operation = schema['paths']['/e']['post'] assert operation['requestBody']['content']['application/json'] == { 'schema': {'type': 'array', 'items': {'$ref': '#/components/schemas/A'}}, - 'examples': {'Ex': {'value': [{'id': '2345'},{'id': '2345'}]}} + 'examples': {'Ex': {'value': [{'id': '2345'}, {'id': '2345'}]}} } assert operation['responses']['201']['content']['application/json'] == { 'schema': {'type': 'array', 'items': {'$ref': '#/components/schemas/A'}}, - 'examples': {'Ex': {'value': [{'id': '2345'},{'id': '2345'}]}} + 'examples': {'Ex': {'value': [{'id': '2345'}, {'id': '2345'}]}} }