Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds deprecated function to track deprecations #3404

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/topics/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ The timeline for deprecation of a feature present in version 1.0 would work as f

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

Deprecations are marked using `rest_framework.compat.deprecated`, which accepts a version tuple for the version when code is first deprecated and message to pass to the `warnings` module:

from rest_framework.compat import deprecated
...
deprecated((3,1,0), "Using X for Y is deprecated. Prefer Z")

Note that in line with Django's policy, any parts of the framework not mentioned in the documentation should generally be considered private API, and may be subject to change.

## Upgrading
Expand Down
20 changes: 20 additions & 0 deletions rest_framework/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,32 @@
# flake8: noqa
from __future__ import unicode_literals

import warnings

import django
from django.conf import settings
from django.db import connection, transaction
from django.utils import six
from django.views.generic import View

from rest_framework import VERSION


def deprecated(since, message):
current_version = [int(i) for i in VERSION.split('.')]

assert current_version[0] == since[0], "Deprecated code must be removed before major version change. Current: {0} vs Deprecated Since: {1}".format(current_version[0], since[0])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it be > here ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might have been confused by the since argument. Maybe it should be named target_version or something similar.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps deprecated_from_version — I've no objection to long variable names.


minor_version_difference = current_version[1] - since[1]
assert minor_version_difference in [1,2], "Deprecated code must be removed within two minor versions"

warning_type = PendingDeprecationWarning if minor_version_difference == 1 else DeprecationWarning

warnings.warn(message, warning_type)




try:
import importlib # Available in Python 3.1+
except ImportError:
Expand Down
27 changes: 11 additions & 16 deletions rest_framework/pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"""
from __future__ import unicode_literals

import warnings
from base64 import b64decode, b64encode
from collections import namedtuple

Expand All @@ -16,7 +15,7 @@
from django.utils.six.moves.urllib import parse as urlparse
from django.utils.translation import ugettext_lazy as _

from rest_framework.compat import OrderedDict
from rest_framework.compat import OrderedDict, deprecated
from rest_framework.exceptions import NotFound
from rest_framework.response import Response
from rest_framework.settings import api_settings
Expand Down Expand Up @@ -216,13 +215,11 @@ def _handle_backwards_compat(self, view):
value = getattr(api_settings, settings_key, None)
if value is not None:
setattr(self, attr_name, value)
warnings.warn(
"The `%s` settings key is deprecated. "
"Use the `%s` attribute on the pagination class instead." % (
settings_key, attr_name
),
DeprecationWarning,
)
deprecated((3, 0, 0),
"The `%s` settings key is deprecated. "
"Use the `%s` attribute on the pagination class instead." % (
settings_key, attr_name)
)

for (view_attr, attr_name) in (
('paginate_by', 'page_size'),
Expand All @@ -233,13 +230,11 @@ def _handle_backwards_compat(self, view):
value = getattr(view, view_attr, None)
if value is not None:
setattr(self, attr_name, value)
warnings.warn(
"The `%s` view attribute is deprecated. "
"Use the `%s` attribute on the pagination class instead." % (
view_attr, attr_name
),
DeprecationWarning,
)
deprecated((3, 0, 0),
"The `%s` view attribute is deprecated. "
"Use the `%s` attribute on the pagination class instead." % (
view_attr, attr_name)
)

def paginate_queryset(self, queryset, request, view=None):
"""
Expand Down
2 changes: 1 addition & 1 deletion tests/test_atomic_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
from django.test import TestCase, TransactionTestCase
from django.utils.decorators import method_decorator
from django.utils.unittest import skipUnless
from tests.models import BasicModel

from rest_framework import status
from rest_framework.exceptions import APIException
from rest_framework.response import Response
from rest_framework.test import APIRequestFactory
from rest_framework.views import APIView
from tests.models import BasicModel

factory = APIRequestFactory()

Expand Down
6 changes: 3 additions & 3 deletions tests/test_generics.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
from django.shortcuts import get_object_or_404
from django.test import TestCase
from django.utils import six
from tests.models import (
BasicModel, ForeignKeySource, ForeignKeyTarget, RESTFrameworkModel
)

from rest_framework import generics, renderers, serializers, status
from rest_framework.response import Response
from rest_framework.test import APIRequestFactory
from tests.models import (
BasicModel, ForeignKeySource, ForeignKeyTarget, RESTFrameworkModel
)

factory = APIRequestFactory()

Expand Down
2 changes: 1 addition & 1 deletion tests/test_multitable_inheritance.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

from django.db import models
from django.test import TestCase
from tests.models import RESTFrameworkModel

from rest_framework import serializers
from tests.models import RESTFrameworkModel


# Models
Expand Down
2 changes: 1 addition & 1 deletion tests/test_permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from django.db import models
from django.test import TestCase
from django.utils import unittest
from tests.models import BasicModel

from rest_framework import (
HTTP_HEADER_ENCODING, authentication, generics, permissions, serializers,
Expand All @@ -16,7 +17,6 @@
from rest_framework.filters import DjangoObjectPermissionsFilter
from rest_framework.routers import DefaultRouter
from rest_framework.test import APIRequestFactory
from tests.models import BasicModel

factory = APIRequestFactory()

Expand Down
6 changes: 3 additions & 3 deletions tests/test_relations_hyperlink.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

from django.conf.urls import url
from django.test import TestCase

from rest_framework import serializers
from rest_framework.test import APIRequestFactory
from tests.models import (
ForeignKeySource, ForeignKeyTarget, ManyToManySource, ManyToManyTarget,
NullableForeignKeySource, NullableOneToOneSource, OneToOneTarget
)

from rest_framework import serializers
from rest_framework.test import APIRequestFactory

factory = APIRequestFactory()
request = factory.get('/') # Just to ensure we have a request in the serializer context

Expand Down
4 changes: 2 additions & 2 deletions tests/test_relations_pk.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

from django.test import TestCase
from django.utils import six

from rest_framework import serializers
from tests.models import (
ForeignKeySource, ForeignKeyTarget, ManyToManySource, ManyToManyTarget,
NullableForeignKeySource, NullableOneToOneSource, OneToOneTarget
)

from rest_framework import serializers


# ManyToMany
class ManyToManyTargetSerializer(serializers.ModelSerializer):
Expand Down
4 changes: 2 additions & 2 deletions tests/test_relations_slug.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from django.test import TestCase

from rest_framework import serializers
from tests.models import (
ForeignKeySource, ForeignKeyTarget, NullableForeignKeySource
)

from rest_framework import serializers


class ForeignKeyTargetSerializer(serializers.ModelSerializer):
sources = serializers.SlugRelatedField(
Expand Down
2 changes: 1 addition & 1 deletion tests/test_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.conf.urls import include, url
from django.test import TestCase
from django.utils import six
from tests.models import BasicModel

from rest_framework import generics, routers, serializers, status, viewsets
from rest_framework.renderers import (
Expand All @@ -11,7 +12,6 @@
from rest_framework.response import Response
from rest_framework.settings import api_settings
from rest_framework.views import APIView
from tests.models import BasicModel


# Serializer used to test BasicModel
Expand Down
2 changes: 1 addition & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
from django.core.exceptions import ImproperlyConfigured
from django.test import TestCase
from django.utils import six
from tests.models import BasicModel

import rest_framework.utils.model_meta
from rest_framework.utils.breadcrumbs import get_breadcrumbs
from rest_framework.utils.model_meta import _resolve_model
from rest_framework.views import APIView
from tests.models import BasicModel


class Root(APIView):
Expand Down