fix Optional typing hint for SerializerMethodField (#428)

master
Étienne Noss 2019-09-29 18:01:28 +02:00 committed by Cristi Vîjdea
parent 8578b93eba
commit 1352c2a23b
2 changed files with 43 additions and 0 deletions

View File

@ -610,6 +610,8 @@ class SerializerMethodFieldInspector(FieldInspector):
# 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)

View File

@ -1,4 +1,5 @@
import json
import sys
from collections import OrderedDict
import pytest
@ -17,6 +18,11 @@ from drf_yasg.errors import SwaggerGenerationError
from drf_yasg.generators import OpenAPISchemaGenerator
from drf_yasg.utils import swagger_auto_schema
try:
import typing
except ImportError:
typing = None
def test_schema_is_valid(swagger, codec_yaml):
codec_yaml.encode(swagger)
@ -293,3 +299,38 @@ def test_json_field():
swagger = generator.get_schema(None, True)
property_schema = swagger["definitions"]["TestJSONField"]["properties"]["json"]
assert property_schema == openapi.Schema(title='Json', type=openapi.TYPE_OBJECT)
@pytest.mark.parametrize('py_type, expected_type', [
(str, openapi.TYPE_STRING),
(int, openapi.TYPE_INTEGER),
(float, openapi.TYPE_NUMBER),
(bool, openapi.TYPE_BOOLEAN),
])
@pytest.mark.skipif(typing is None or sys.version_info.major < 3, reason="typing not supported")
def test_optional_return_type(py_type, expected_type):
class OptionalMethodSerializer(serializers.Serializer):
x = serializers.SerializerMethodField()
def get_x(self, instance):
pass
# Add the type annotation here in order to avoid a SyntaxError in py27
get_x.__annotations__["return"] = typing.Optional[py_type]
class OptionalMethodViewSet(viewsets.ViewSet):
@swagger_auto_schema(responses={200: openapi.Response("OK", OptionalMethodSerializer)})
def retrieve(self, request, pk=None):
return Response({'optional': None})
router = routers.DefaultRouter()
router.register(r'optional', OptionalMethodViewSet, **_basename_or_base_name('optional'))
generator = OpenAPISchemaGenerator(
info=openapi.Info(title='Test optional parameter', default_version='v1'),
patterns=router.urls
)
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)