From 1e8b172a77f7bafb739cc504dac17d1ec2b31bf8 Mon Sep 17 00:00:00 2001 From: Pedro Borges Date: Thu, 21 Sep 2023 13:30:54 +0200 Subject: [PATCH] Fix (#1079) crash when generating schema for field with UUID choices. The crash was fixed by replacing the JSON encoder used to hash elements for enum deduplication with DRF JSON encoder which is capable of handling type outside of the usual JSON standard types. --- drf_spectacular/plumbing.py | 3 ++- tests/test_postprocessing.py | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/drf_spectacular/plumbing.py b/drf_spectacular/plumbing.py index 1b14d380..85b61e96 100644 --- a/drf_spectacular/plumbing.py +++ b/drf_spectacular/plumbing.py @@ -37,6 +37,7 @@ from rest_framework.fields import empty from rest_framework.settings import api_settings from rest_framework.test import APIRequestFactory +from rest_framework.utils.encoders import JSONEncoder from rest_framework.utils.mediatypes import _MediaType from rest_framework.utils.serializer_helpers import ReturnDict, ReturnList from uritemplate import URITemplate @@ -839,7 +840,7 @@ def load_enum_name_overrides(): def list_hash(lst): - return hashlib.sha256(json.dumps(list(lst), sort_keys=True).encode()).hexdigest() + return hashlib.sha256(json.dumps(list(lst), sort_keys=True, cls=JSONEncoder).encode()).hexdigest() def anchor_pattern(pattern: str) -> str: diff --git a/tests/test_postprocessing.py b/tests/test_postprocessing.py index 3ef0c3fc..3fcf61e4 100644 --- a/tests/test_postprocessing.py +++ b/tests/test_postprocessing.py @@ -314,3 +314,29 @@ def get(self, request): 'items': {'$ref': '#/components/schemas/QualityLevelsEnum'}, 'readOnly': True } + + +def test_uuid_choices(no_warnings): + + import uuid + + class XSerializer(serializers.Serializer): + foo = serializers.ChoiceField( + choices=[ + (uuid.UUID('93d7527f-de3c-4a76-9cc2-5578675630d4'), 'baz'), + (uuid.UUID('47a4b873-409e-4e43-81d5-fafc3faeb849'), 'bar') + ] + ) + + class XAPIView(APIView): + @extend_schema(responses=XSerializer) + def get(self, request): + pass # pragma: no cover + + schema = generate_schema('x', view=XAPIView) + + assert 'FooEnum' in schema['components']['schemas'] + assert schema['components']['schemas']['FooEnum']['enum'] == [ + uuid.UUID('93d7527f-de3c-4a76-9cc2-5578675630d4'), + uuid.UUID('47a4b873-409e-4e43-81d5-fafc3faeb849') + ]