diff --git a/docs/custom_spec.rst b/docs/custom_spec.rst index 1f8fef0..8b67ea4 100644 --- a/docs/custom_spec.rst +++ b/docs/custom_spec.rst @@ -314,7 +314,7 @@ implemented like so: )) class ArticleViewSet(viewsets.ModelViewSet): filter_backends = (DjangoFilterBackend,) - filter_fields = ('title',) + filterset_fields = ('title',) ... diff --git a/src/drf_yasg/management/commands/generate_swagger.py b/src/drf_yasg/management/commands/generate_swagger.py index fc481ff..fef3e7f 100644 --- a/src/drf_yasg/management/commands/generate_swagger.py +++ b/src/drf_yasg/management/commands/generate_swagger.py @@ -158,6 +158,7 @@ class Command(BaseCommand): else: # normally this would be easily done with open(mode='x'/'w'), # but python 2 is a pain in the ass as usual + # TODO: simplify when dropping support for python 2.7 flags = os.O_CREAT | os.O_WRONLY flags = flags | (os.O_TRUNC if overwrite else os.O_EXCL) with os.fdopen(os.open(output_file, flags), "w") as stream: diff --git a/src/drf_yasg/openapi.py b/src/drf_yasg/openapi.py index a7e0f22..172ceab 100644 --- a/src/drf_yasg/openapi.py +++ b/src/drf_yasg/openapi.py @@ -12,6 +12,11 @@ from inflection import camelize from .utils import filter_none, force_real_str +try: + from collections import abc as collections_abc +except ImportError: + collections_abc = collections + logger = logging.getLogger(__name__) TYPE_OBJECT = "object" #: @@ -136,7 +141,7 @@ class SwaggerDict(OrderedDict): # handle __proxy__ objects from django.utils.functional.lazy obj = obj._proxy____cast() - if isinstance(obj, collections.Mapping): + if isinstance(obj, collections_abc.Mapping): result = OrderedDict() memo[id(obj)] = result items = obj.items() @@ -147,7 +152,7 @@ class SwaggerDict(OrderedDict): return result elif isinstance(obj, six.string_types): return force_real_str(obj) - elif isinstance(obj, collections.Iterable) and not isinstance(obj, collections.Iterator): + elif isinstance(obj, collections_abc.Iterable) and not isinstance(obj, collections_abc.Iterator): return type(obj)(SwaggerDict._as_odict(elem, memo) for elem in obj) return obj diff --git a/src/drf_yasg/views.py b/src/drf_yasg/views.py index 20f8db0..e091350 100644 --- a/src/drf_yasg/views.py +++ b/src/drf_yasg/views.py @@ -112,7 +112,7 @@ def get_schema_view(info=None, url=None, patterns=None, urlconf=None, public=Fal def as_cached_view(cls, cache_timeout=0, cache_kwargs=None, **initkwargs): """ Calls .as_view() and wraps the result in a cache_page decorator. - See https://docs.djangoproject.com/en/1.11/topics/cache/ + See https://docs.djangoproject.com/en/dev/topics/cache/ :param int cache_timeout: same as cache_page; set to 0 for no cache :param dict cache_kwargs: dictionary of kwargs to be passed to cache_page @@ -131,7 +131,7 @@ def get_schema_view(info=None, url=None, patterns=None, urlconf=None, public=Fal def without_ui(cls, cache_timeout=0, cache_kwargs=None): """ Instantiate this view with just JSON and YAML renderers, optionally wrapped with cache_page. - See https://docs.djangoproject.com/en/1.11/topics/cache/. + See https://docs.djangoproject.com/en/dev/topics/cache/. :param int cache_timeout: same as cache_page; set to 0 for no cache :param dict cache_kwargs: dictionary of kwargs to be passed to cache_page @@ -143,7 +143,7 @@ def get_schema_view(info=None, url=None, patterns=None, urlconf=None, public=Fal def with_ui(cls, renderer='swagger', cache_timeout=0, cache_kwargs=None): """ Instantiate this view with a Web UI renderer, optionally wrapped with cache_page. - See https://docs.djangoproject.com/en/1.11/topics/cache/. + See https://docs.djangoproject.com/en/dev/topics/cache/. :param str renderer: UI renderer; allowed values are ``swagger``, ``redoc`` :param int cache_timeout: same as cache_page; set to 0 for no cache diff --git a/testproj/articles/views.py b/testproj/articles/views.py index 944c33c..1397592 100644 --- a/testproj/articles/views.py +++ b/testproj/articles/views.py @@ -84,7 +84,10 @@ class ArticleViewSet(viewsets.ModelViewSet): pagination_class = ArticlePagination filter_backends = (DjangoFilterBackend, OrderingFilter) - filter_fields = ('title',) + filterset_fields = ('title',) + # django-filter 1.1 compatibility; was renamed to filterset_fields in 2.0 + # TODO: remove when dropping support for Django 1.11 + filter_fields = filterset_fields ordering_fields = ('date_modified', 'date_created') ordering = ('date_created',) diff --git a/testproj/testproj/util.py b/testproj/testproj/util.py index 8bf52f4..10f8b8c 100644 --- a/testproj/testproj/util.py +++ b/testproj/testproj/util.py @@ -1,4 +1,4 @@ -from django.contrib.staticfiles.templatetags.staticfiles import static +from django.templatetags.static import static from django.utils.functional import lazy static_lazy = lazy(static, str) diff --git a/tests/test_schema_generator.py b/tests/test_schema_generator.py index 2a74c95..87b9dfe 100644 --- a/tests/test_schema_generator.py +++ b/tests/test_schema_generator.py @@ -1,8 +1,10 @@ +import inspect import json from collections import OrderedDict import pytest from django.conf.urls import url +from django.utils.inspect import get_func_args from rest_framework import routers, serializers, viewsets from rest_framework.decorators import api_view from rest_framework.response import Response @@ -86,6 +88,14 @@ def test_securiy_requirements(swagger_settings, mock_schema_request): assert swagger['security'] == [] +def _basename_or_base_name(basename): + # freaking DRF... TODO: remove when dropping support for DRF 3.8 + if 'basename' in get_func_args(routers.BaseRouter.register): + return {'basename': basename} + else: + return {'base_name': basename} + + def test_replaced_serializer(): class DetailSerializer(serializers.Serializer): detail = serializers.CharField() @@ -99,7 +109,7 @@ def test_replaced_serializer(): return Response(serializer.data) router = routers.DefaultRouter() - router.register(r'details', DetailViewSet, base_name='details') + router.register(r'details', DetailViewSet, **_basename_or_base_name('details')) generator = OpenAPISchemaGenerator( info=openapi.Info(title="Test generator", default_version="v1"), @@ -172,7 +182,7 @@ def test_action_mapping(): pass router = routers.DefaultRouter() - router.register(r'action', ActionViewSet, base_name='action') + router.register(r'action', ActionViewSet, **_basename_or_base_name('action')) generator = OpenAPISchemaGenerator( info=openapi.Info(title="Test generator", default_version="v1"), @@ -208,7 +218,7 @@ def test_choice_field(choices, expected_type): return Response({'detail': None}) router = routers.DefaultRouter() - router.register(r'details', DetailViewSet, base_name='details') + router.register(r'details', DetailViewSet, **_basename_or_base_name('details')) generator = OpenAPISchemaGenerator( info=openapi.Info(title="Test generator", default_version="v1"),