diff --git a/rest_framework/compat.py b/rest_framework/compat.py index 1feaf9faa..2e6a8adda 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -131,13 +131,6 @@ except ImportError: requests = None -def is_guardian_installed(): - """ - django-guardian is optional and only imported if in INSTALLED_APPS. - """ - return 'guardian' in settings.INSTALLED_APPS - - # PATCH method is not implemented by Django if 'patch' not in View.http_method_names: View.http_method_names = View.http_method_names + ['patch'] diff --git a/rest_framework/filters.py b/rest_framework/filters.py index e3b0468c7..2af063926 100644 --- a/rest_framework/filters.py +++ b/rest_framework/filters.py @@ -3,7 +3,6 @@ Provides generic filtering backends that can be used to filter the results returned by list views. """ import operator -import warnings from functools import reduce from django.core.exceptions import ImproperlyConfigured @@ -14,10 +13,7 @@ from django.template import loader from django.utils.encoding import force_text from django.utils.translation import gettext_lazy as _ -from rest_framework import RemovedInDRF310Warning -from rest_framework.compat import ( - coreapi, coreschema, distinct, is_guardian_installed -) +from rest_framework.compat import coreapi, coreschema, distinct from rest_framework.settings import api_settings @@ -315,41 +311,3 @@ class OrderingFilter(BaseFilterBackend): }, }, ] - - -class DjangoObjectPermissionsFilter(BaseFilterBackend): - """ - A filter backend that limits results to those where the requesting user - has read object level permissions. - """ - def __init__(self): - warnings.warn( - "`DjangoObjectPermissionsFilter` has been deprecated and moved to " - "the 3rd-party django-rest-framework-guardian package.", - RemovedInDRF310Warning, stacklevel=2 - ) - assert is_guardian_installed(), 'Using DjangoObjectPermissionsFilter, but django-guardian is not installed' - - perm_format = '%(app_label)s.view_%(model_name)s' - - def filter_queryset(self, request, queryset, view): - # We want to defer this import until run-time, rather than import-time. - # See https://github.com/encode/django-rest-framework/issues/4608 - # (Also see #1624 for why we need to make this import explicitly) - from guardian import VERSION as guardian_version - from guardian.shortcuts import get_objects_for_user - - extra = {} - user = request.user - model_cls = queryset.model - kwargs = { - 'app_label': model_cls._meta.app_label, - 'model_name': model_cls._meta.model_name - } - permission = self.perm_format % kwargs - if tuple(guardian_version) >= (1, 3): - # Maintain behavior compatibility with versions prior to 1.3 - extra = {'accept_global_perms': False} - else: - extra = {} - return get_objects_for_user(user, permission, queryset, **extra) diff --git a/tests/test_permissions.py b/tests/test_permissions.py index 9c9300694..03b80aae8 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -1,21 +1,20 @@ import base64 import unittest -import warnings from unittest import mock import django import pytest +from django.conf import settings from django.contrib.auth.models import AnonymousUser, Group, Permission, User from django.db import models from django.test import TestCase from django.urls import ResolverMatch from rest_framework import ( - HTTP_HEADER_ENCODING, RemovedInDRF310Warning, authentication, generics, - permissions, serializers, status, views + HTTP_HEADER_ENCODING, authentication, generics, permissions, serializers, + status, views ) -from rest_framework.compat import PY36, is_guardian_installed -from rest_framework.filters import DjangoObjectPermissionsFilter +from rest_framework.compat import PY36 from rest_framework.routers import DefaultRouter from rest_framework.test import APIRequestFactory from tests.models import BasicModel @@ -309,7 +308,7 @@ class GetQuerysetObjectPermissionInstanceView(generics.RetrieveUpdateDestroyAPIV get_queryset_object_permissions_view = GetQuerysetObjectPermissionInstanceView.as_view() -@unittest.skipUnless(is_guardian_installed(), 'django-guardian not installed') +@unittest.skipUnless('guardian' in settings.INSTALLED_APPS, 'django-guardian not installed') class ObjectPermissionsIntegrationTests(TestCase): """ Integration tests for the object level permissions API. @@ -418,37 +417,14 @@ class ObjectPermissionsIntegrationTests(TestCase): self.assertEqual(response.status_code, status.HTTP_200_OK) # Read list - def test_django_object_permissions_filter_deprecated(self): - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - DjangoObjectPermissionsFilter() - - message = ("`DjangoObjectPermissionsFilter` has been deprecated and moved " - "to the 3rd-party django-rest-framework-guardian package.") - self.assertEqual(len(w), 1) - self.assertIs(w[-1].category, RemovedInDRF310Warning) - self.assertEqual(str(w[-1].message), message) - + # Note: this previously tested `DjangoObjectPermissionsFilter`, which has + # since been moved to a separate package. These now act as sanity checks. def test_can_read_list_permissions(self): request = factory.get('/', HTTP_AUTHORIZATION=self.credentials['readonly']) - object_permissions_list_view.cls.filter_backends = (DjangoObjectPermissionsFilter,) - # TODO: remove in version 3.10 - with warnings.catch_warnings(record=True): - warnings.simplefilter("always") - response = object_permissions_list_view(request) + response = object_permissions_list_view(request) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data[0].get('id'), 1) - def test_cannot_read_list_permissions(self): - request = factory.get('/', HTTP_AUTHORIZATION=self.credentials['writeonly']) - object_permissions_list_view.cls.filter_backends = (DjangoObjectPermissionsFilter,) - # TODO: remove in version 3.10 - with warnings.catch_warnings(record=True): - warnings.simplefilter("always") - response = object_permissions_list_view(request) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertListEqual(response.data, []) - def test_cannot_method_not_allowed(self): request = factory.generic('METHOD_NOT_ALLOWED', '/', HTTP_AUTHORIZATION=self.credentials['readonly']) response = object_permissions_list_view(request)