From a7f484ad42bc45dbefe4b157e4e39b1ab07e644d Mon Sep 17 00:00:00 2001 From: "Terence D. Honles" Date: Thu, 2 Mar 2023 17:15:53 +0100 Subject: [PATCH] fix type hints when using postponed evaluation of annotations (PEP-563) --- src/drf_yasg/inspectors/field.py | 25 +++++++++++++------------ tests/test_schema_generator.py | 2 +- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/drf_yasg/inspectors/field.py b/src/drf_yasg/inspectors/field.py index 05ff2842..ec25d7a6 100644 --- a/src/drf_yasg/inspectors/field.py +++ b/src/drf_yasg/inspectors/field.py @@ -6,7 +6,6 @@ from contextlib import suppress from collections import OrderedDict from decimal import Decimal -from inspect import signature as inspect_signature import typing from django.core import validators @@ -617,17 +616,19 @@ def field_to_swagger_object(self, field, swagger_object_type, use_references, ** return self.probe_field_inspectors(serializer, swagger_object_type, use_references, read_only=True) else: # look for Python 3.5+ style type hinting of the return value - hint_class = inspect_signature(method).return_annotation - - if not inspect.isclass(hint_class) and hasattr(hint_class, '__args__'): - hint_class = hint_class.__args__[0] - if inspect.isclass(hint_class) and not issubclass(hint_class, inspect._empty): - type_info = get_basic_type_info_from_hint(hint_class) - - if type_info is not None: - SwaggerType, ChildSwaggerType = self._get_partial_types(field, swagger_object_type, - use_references, **kwargs) - return SwaggerType(**type_info) + hint_class = typing.get_type_hints(method).get('return') + + # annotations such as typing.Optional have an __instancecheck__ + # hook and will not look like classes, but `issubclass` needs + # a class as its first argument, so only in that case abort + if inspect.isclass(hint_class) and issubclass(hint_class, inspect._empty): + return NotHandled + + type_info = get_basic_type_info_from_hint(hint_class) + if type_info is not None: + SwaggerType, ChildSwaggerType = self._get_partial_types(field, swagger_object_type, + use_references, **kwargs) + return SwaggerType(**type_info) return NotHandled diff --git a/tests/test_schema_generator.py b/tests/test_schema_generator.py index 063e7c08..85999074 100644 --- a/tests/test_schema_generator.py +++ b/tests/test_schema_generator.py @@ -345,7 +345,7 @@ def retrieve(self, request, pk=None): ) swagger = generator.get_schema(None, True) property_schema = swagger["definitions"]["OptionalMethod"]["properties"]["x"] - assert property_schema == openapi.Schema(title='X', type=expected_type, readOnly=True) + assert property_schema == openapi.Schema(title='X', type=expected_type, readOnly=True, x_nullable=True) EXPECTED_DESCRIPTION = """\