From a12c61e3695f65d7b598896a4b05e5d66db70e9d Mon Sep 17 00:00:00 2001 From: "Terence D. Honles" Date: Thu, 7 Sep 2023 11:47:44 +0200 Subject: [PATCH 1/2] fix lint errors when comparing types with == instead of `is` --- src/drf_yasg/inspectors/field.py | 2 +- src/drf_yasg/openapi.py | 4 ++-- src/drf_yasg/utils.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/drf_yasg/inspectors/field.py b/src/drf_yasg/inspectors/field.py index 4d456fbf..05ff2842 100644 --- a/src/drf_yasg/inspectors/field.py +++ b/src/drf_yasg/inspectors/field.py @@ -193,7 +193,7 @@ def get_queryset_from_view(view, serializer=None): if queryset is not None and serializer is not None: # make sure the view is actually using *this* serializer - assert type(serializer) == call_view_method(view, 'get_serializer_class', 'serializer_class') + assert type(serializer) is call_view_method(view, 'get_serializer_class', 'serializer_class') return queryset except Exception: # pragma: no cover diff --git a/src/drf_yasg/openapi.py b/src/drf_yasg/openapi.py index 0a2cfb8f..9679c80d 100644 --- a/src/drf_yasg/openapi.py +++ b/src/drf_yasg/openapi.py @@ -88,7 +88,7 @@ class SwaggerDict(OrderedDict): def __init__(self, **attrs): super(SwaggerDict, self).__init__() self._extras__ = attrs - if type(self) == SwaggerDict: + if type(self) is SwaggerDict: self._insert_extras__() def __setattr__(self, key, value): @@ -516,7 +516,7 @@ def __init__(self, resolver, name, scope, expected_type, ignore_unresolved=False :param bool ignore_unresolved: do not throw if the referenced object does not exist """ super(_Ref, self).__init__() - assert not type(self) == _Ref, "do not instantiate _Ref directly" + assert not type(self) is _Ref, "do not instantiate _Ref directly" ref_name = "#/{scope}/{name}".format(scope=scope, name=name) if not ignore_unresolved: obj = resolver.get(name, scope) diff --git a/src/drf_yasg/utils.py b/src/drf_yasg/utils.py index 494ce48c..15d18ac4 100644 --- a/src/drf_yasg/utils.py +++ b/src/drf_yasg/utils.py @@ -442,7 +442,7 @@ def force_real_str(s, encoding='utf-8', strings_only=False, errors='strict'): """ if s is not None: s = force_str(s, encoding, strings_only, errors) - if type(s) != str: + if type(s) is not str: s = '' + s # Remove common indentation to get the correct Markdown rendering From a7f484ad42bc45dbefe4b157e4e39b1ab07e644d Mon Sep 17 00:00:00 2001 From: "Terence D. Honles" Date: Thu, 2 Mar 2023 17:15:53 +0100 Subject: [PATCH 2/2] 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 = """\