Skip to content

Commit 94593b3

Browse files
Introduce RemovedInDRF…Warning classes to simplify deprecations. (encode#6480)
Closes encode#6290.
1 parent a216d02 commit 94593b3

File tree

8 files changed

+34
-20
lines changed

8 files changed

+34
-20
lines changed

docs/community/release-notes.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ REST framework releases follow a formal deprecation policy, which is in line wit
1818

1919
The timeline for deprecation of a feature present in version 1.0 would work as follows:
2020

21-
* Version 1.1 would remain **fully backwards compatible** with 1.0, but would raise `PendingDeprecationWarning` warnings if you use the feature that are due to be deprecated. These warnings are **silent by default**, but can be explicitly enabled when you're ready to start migrating any required changes. For example if you start running your tests using `python -Wd manage.py test`, you'll be warned of any API changes you need to make.
21+
* Version 1.1 would remain **fully backwards compatible** with 1.0, but would raise `RemovedInDRF13Warning` warnings, subclassing `PendingDeprecationWarning`, if you use the feature that are due to be deprecated. These warnings are **silent by default**, but can be explicitly enabled when you're ready to start migrating any required changes. For example if you start running your tests using `python -Wd manage.py test`, you'll be warned of any API changes you need to make.
2222

23-
* Version 1.2 would escalate these warnings to `DeprecationWarning`, which is loud by default.
23+
* Version 1.2 would escalate these warnings to subclass `DeprecationWarning`, which is loud by default.
2424

2525
* Version 1.3 would remove the deprecated bits of API entirely.
2626

rest_framework/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,11 @@
2323
ISO_8601 = 'iso-8601'
2424

2525
default_app_config = 'rest_framework.apps.RestFrameworkConfig'
26+
27+
28+
class RemovedInDRF310Warning(DeprecationWarning):
29+
pass
30+
31+
32+
class RemovedInDRF311Warning(PendingDeprecationWarning):
33+
pass

rest_framework/decorators.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from django.forms.utils import pretty_name
1515
from django.utils import six
1616

17+
from rest_framework import RemovedInDRF310Warning
1718
from rest_framework.views import APIView
1819

1920

@@ -225,7 +226,7 @@ def detail_route(methods=None, **kwargs):
225226
warnings.warn(
226227
"`detail_route` is deprecated and will be removed in 3.10 in favor of "
227228
"`action`, which accepts a `detail` bool. Use `@action(detail=True)` instead.",
228-
DeprecationWarning, stacklevel=2
229+
RemovedInDRF310Warning, stacklevel=2
229230
)
230231

231232
def decorator(func):
@@ -243,7 +244,7 @@ def list_route(methods=None, **kwargs):
243244
warnings.warn(
244245
"`list_route` is deprecated and will be removed in 3.10 in favor of "
245246
"`action`, which accepts a `detail` bool. Use `@action(detail=False)` instead.",
246-
DeprecationWarning, stacklevel=2
247+
RemovedInDRF310Warning, stacklevel=2
247248
)
248249

249250
def decorator(func):

rest_framework/filters.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from django.utils.encoding import force_text
1818
from django.utils.translation import ugettext_lazy as _
1919

20+
from rest_framework import RemovedInDRF310Warning
2021
from rest_framework.compat import (
2122
coreapi, coreschema, distinct, is_guardian_installed
2223
)
@@ -299,7 +300,7 @@ def __init__(self):
299300
warnings.warn(
300301
"`DjangoObjectPermissionsFilter` has been deprecated and moved to "
301302
"the 3rd-party django-rest-framework-guardian package.",
302-
DeprecationWarning, stacklevel=2
303+
RemovedInDRF310Warning, stacklevel=2
303304
)
304305
assert is_guardian_installed(), 'Using DjangoObjectPermissionsFilter, but django-guardian is not installed'
305306

rest_framework/routers.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
from django.utils import six
2626
from django.utils.deprecation import RenameMethodsBase
2727

28-
from rest_framework import views
28+
from rest_framework import (
29+
RemovedInDRF310Warning, RemovedInDRF311Warning, views
30+
)
2931
from rest_framework.response import Response
3032
from rest_framework.reverse import reverse
3133
from rest_framework.schemas import SchemaGenerator
@@ -43,7 +45,7 @@ def __new__(cls, url, name, initkwargs):
4345
"`DynamicDetailRoute` is deprecated and will be removed in 3.10 "
4446
"in favor of `DynamicRoute`, which accepts a `detail` boolean. Use "
4547
"`DynamicRoute(url, name, True, initkwargs)` instead.",
46-
DeprecationWarning, stacklevel=2
48+
RemovedInDRF310Warning, stacklevel=2
4749
)
4850
return DynamicRoute(url, name, True, initkwargs)
4951

@@ -54,7 +56,7 @@ def __new__(cls, url, name, initkwargs):
5456
"`DynamicListRoute` is deprecated and will be removed in 3.10 in "
5557
"favor of `DynamicRoute`, which accepts a `detail` boolean. Use "
5658
"`DynamicRoute(url, name, False, initkwargs)` instead.",
57-
DeprecationWarning, stacklevel=2
59+
RemovedInDRF310Warning, stacklevel=2
5860
)
5961
return DynamicRoute(url, name, False, initkwargs)
6062

@@ -77,7 +79,7 @@ def flatten(list_of_lists):
7779

7880
class RenameRouterMethods(RenameMethodsBase):
7981
renamed_methods = (
80-
('get_default_base_name', 'get_default_basename', PendingDeprecationWarning),
82+
('get_default_base_name', 'get_default_basename', RemovedInDRF311Warning),
8183
)
8284

8385

@@ -88,7 +90,7 @@ def __init__(self):
8890
def register(self, prefix, viewset, basename=None, base_name=None):
8991
if base_name is not None:
9092
msg = "The `base_name` argument is pending deprecation in favor of `basename`."
91-
warnings.warn(msg, PendingDeprecationWarning, 2)
93+
warnings.warn(msg, RemovedInDRF311Warning, 2)
9294

9395
assert not (basename and base_name), (
9496
"Do not provide both the `basename` and `base_name` arguments.")

tests/test_decorators.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import pytest
44
from django.test import TestCase
55

6-
from rest_framework import status
6+
from rest_framework import RemovedInDRF310Warning, status
77
from rest_framework.authentication import BasicAuthentication
88
from rest_framework.decorators import (
99
action, api_view, authentication_classes, detail_route, list_route,
@@ -290,7 +290,7 @@ def test_action():
290290
raise NotImplementedError
291291

292292
def test_detail_route_deprecation(self):
293-
with pytest.warns(DeprecationWarning) as record:
293+
with pytest.warns(RemovedInDRF310Warning) as record:
294294
@detail_route()
295295
def view(request):
296296
raise NotImplementedError
@@ -303,7 +303,7 @@ def view(request):
303303
)
304304

305305
def test_list_route_deprecation(self):
306-
with pytest.warns(DeprecationWarning) as record:
306+
with pytest.warns(RemovedInDRF310Warning) as record:
307307
@list_route()
308308
def view(request):
309309
raise NotImplementedError
@@ -317,7 +317,7 @@ def view(request):
317317

318318
def test_route_url_name_from_path(self):
319319
# pre-3.8 behavior was to base the `url_name` off of the `url_path`
320-
with pytest.warns(DeprecationWarning):
320+
with pytest.warns(RemovedInDRF310Warning):
321321
@list_route(url_path='foo_bar')
322322
def view(request):
323323
raise NotImplementedError

tests/test_permissions.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
from django.urls import ResolverMatch
1313

1414
from rest_framework import (
15-
HTTP_HEADER_ENCODING, authentication, generics, permissions, serializers,
16-
status, views
15+
HTTP_HEADER_ENCODING, RemovedInDRF310Warning, authentication, generics,
16+
permissions, serializers, status, views
1717
)
1818
from rest_framework.compat import PY36, is_guardian_installed, mock
1919
from rest_framework.filters import DjangoObjectPermissionsFilter
@@ -427,7 +427,7 @@ def test_django_object_permissions_filter_deprecated(self):
427427
message = ("`DjangoObjectPermissionsFilter` has been deprecated and moved "
428428
"to the 3rd-party django-rest-framework-guardian package.")
429429
self.assertEqual(len(w), 1)
430-
self.assertIs(w[-1].category, DeprecationWarning)
430+
self.assertIs(w[-1].category, RemovedInDRF310Warning)
431431
self.assertEqual(str(w[-1].message), message)
432432

433433
def test_can_read_list_permissions(self):

tests/test_routers.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
from django.test import TestCase, override_settings
1111
from django.urls import resolve, reverse
1212

13-
from rest_framework import permissions, serializers, viewsets
13+
from rest_framework import (
14+
RemovedInDRF311Warning, permissions, serializers, viewsets
15+
)
1416
from rest_framework.compat import get_regex_pattern
1517
from rest_framework.decorators import action
1618
from rest_framework.response import Response
@@ -508,7 +510,7 @@ def test_base_name_and_basename_assertion(self):
508510
def test_base_name_argument_deprecation(self):
509511
router = SimpleRouter()
510512

511-
with pytest.warns(PendingDeprecationWarning) as w:
513+
with pytest.warns(RemovedInDRF311Warning) as w:
512514
warnings.simplefilter('always')
513515
router.register('mock', MockViewSet, base_name='mock')
514516

@@ -535,7 +537,7 @@ def test_get_default_base_name_deprecation(self):
535537
msg = "`CustomRouter.get_default_base_name` method should be renamed `get_default_basename`."
536538

537539
# Class definition should raise a warning
538-
with pytest.warns(PendingDeprecationWarning) as w:
540+
with pytest.warns(RemovedInDRF311Warning) as w:
539541
warnings.simplefilter('always')
540542

541543
class CustomRouter(SimpleRouter):

0 commit comments

Comments
 (0)