Skip to content

Commit

Permalink
fix type hints when using postponed evaluation of annotations (PEP-563)
Browse files Browse the repository at this point in the history
  • Loading branch information
terencehonles committed Mar 3, 2023
1 parent 065b4f1 commit 50506cb
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 14 deletions.
27 changes: 14 additions & 13 deletions src/drf_yasg/inspectors/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from packaging import version
from collections import OrderedDict
from decimal import Decimal
from inspect import signature as inspect_signature

from django.core import validators
from django.db import models
Expand Down Expand Up @@ -394,7 +393,7 @@ def decimal_field_type(field):
(models.TimeField, (openapi.TYPE_STRING, None)),
(models.UUIDField, (openapi.TYPE_STRING, openapi.FORMAT_UUID)),
(models.CharField, (openapi.TYPE_STRING, None)),
]
]

ip_format = {'ipv4': openapi.FORMAT_IPV4, 'ipv6': openapi.FORMAT_IPV6}

Expand Down Expand Up @@ -607,17 +606,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

Expand Down
2 changes: 1 addition & 1 deletion tests/test_schema_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,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 = """\
Expand Down

0 comments on commit 50506cb

Please sign in to comment.