django-upgrade --target-version=5.0 **/*.py

This commit is contained in:
Christian Clauss 2024-01-24 23:44:12 +01:00
parent 74689b1f44
commit d4dfcb5690
21 changed files with 53 additions and 111 deletions

View File

@ -7,7 +7,6 @@ ______ _____ _____ _____ __
\_| \_\____/\____/ \_/ |_| |_| \__,_|_| |_| |_|\___| \_/\_/ \___/|_| |_|\_|
"""
import django
__title__ = 'Django REST framework'
__version__ = '3.14.0'
@ -25,10 +24,6 @@ HTTP_HEADER_ENCODING = 'iso-8859-1'
ISO_8601 = 'iso-8601'
if django.VERSION < (3, 2):
default_app_config = 'rest_framework.apps.RestFrameworkConfig'
class RemovedInDRF315Warning(DeprecationWarning):
pass

View File

@ -17,7 +17,7 @@ def get_authorization_header(request):
Hide some test client ickyness where the header can be unicode.
"""
auth = request.META.get('HTTP_AUTHORIZATION', b'')
auth = request.headers.get('authorization', b'')
if isinstance(auth, str):
# Work around django test client oddness
auth = auth.encode(HTTP_HEADER_ENCODING)

View File

@ -1,4 +0,0 @@
import django
if django.VERSION < (3, 2):
default_app_config = 'rest_framework.authtoken.apps.AuthTokenConfig'

View File

@ -21,6 +21,7 @@ class TokenChangeList(ChangeList):
current_app=self.model_admin.admin_site.name)
@admin.register(TokenProxy)
class TokenAdmin(admin.ModelAdmin):
list_display = ('key', 'user', 'created')
fields = ('user',)
@ -50,6 +51,3 @@ class TokenAdmin(admin.ModelAdmin):
# Map back to actual Token, since delete() uses pk.
token = Token.objects.get(key=obj.key)
return super().delete_model(request, token)
admin.site.register(TokenProxy, TokenAdmin)

View File

@ -145,29 +145,10 @@ else:
return False
if django.VERSION >= (4, 2):
# Django 4.2+: use the stock parse_header_parameters function
# Note: Django 4.1 also has an implementation of parse_header_parameters
# which is slightly different from the one in 4.2, it needs
# the compatibility shim as well.
from django.utils.http import parse_header_parameters
else:
# Django <= 4.1: create a compatibility shim for parse_header_parameters
from django.http.multipartparser import parse_header
def parse_header_parameters(line):
# parse_header works with bytes, but parse_header_parameters
# works with strings. Call encode to convert the line to bytes.
main_value_pair, params = parse_header(line.encode())
return main_value_pair, {
# parse_header will convert *some* values to string.
# parse_header_parameters converts *all* values to string.
# Make sure all values are converted by calling decode on
# any remaining non-string values.
k: v if isinstance(v, str) else v.decode()
for k, v in params.items()
}
# Django 4.2+: use the stock parse_header_parameters function
# Note: Django 4.1 also has an implementation of parse_header_parameters
# which is slightly different from the one in 4.2, it needs
# the compatibility shim as well.
if django.VERSION >= (5, 1):
# Django 5.1+: use the stock ip_address_validators function

View File

@ -93,5 +93,5 @@ class DefaultContentNegotiation(BaseContentNegotiation):
Given the incoming request, return a tokenized list of media
type strings.
"""
header = request.META.get('HTTP_ACCEPT', '*/*')
header = request.headers.get('accept', '*/*')
return [token.strip() for token in header.split(',')]

View File

@ -3,7 +3,6 @@
import io
from importlib import import_module
import django
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.core.handlers.wsgi import WSGIHandler
@ -394,19 +393,7 @@ class URLPatternsTestCase(testcases.SimpleTestCase):
cls._override.enable()
if django.VERSION > (4, 0):
cls.addClassCleanup(cls._override.disable)
cls.addClassCleanup(cleanup_url_patterns, cls)
cls.addClassCleanup(cls._override.disable)
cls.addClassCleanup(cleanup_url_patterns, cls)
super().setUpClass()
if django.VERSION < (4, 0):
@classmethod
def tearDownClass(cls):
super().tearDownClass()
cls._override.disable()
if hasattr(cls, '_module_urlpatterns'):
cls._module.urlpatterns = cls._module_urlpatterns
else:
del cls._module.urlpatterns

View File

@ -26,7 +26,7 @@ class BaseThrottle:
if present and number of proxies is > 0. If not use all of
HTTP_X_FORWARDED_FOR if it is available, if not use REMOTE_ADDR.
"""
xff = request.META.get('HTTP_X_FORWARDED_FOR')
xff = request.headers.get('x-forwarded-for')
remote_addr = request.META.get('REMOTE_ADDR')
num_proxies = api_settings.NUM_PROXIES

View File

@ -1,6 +1,5 @@
import base64
import django
import pytest
from django.conf import settings
from django.contrib.auth.models import User
@ -236,15 +235,12 @@ class SessionAuthTests(TestCase):
Regression test for #6088
"""
# Remove this shim when dropping support for Django 3.0.
if django.VERSION < (3, 1):
from django.middleware.csrf import _get_new_csrf_token
else:
from django.middleware.csrf import (
_get_new_csrf_string, _mask_cipher_secret
)
from django.middleware.csrf import (
_get_new_csrf_string, _mask_cipher_secret
)
def _get_new_csrf_token():
return _mask_cipher_secret(_get_new_csrf_string())
def _get_new_csrf_token():
return _mask_cipher_secret(_get_new_csrf_string())
self.csrf_client.login(username=self.username, password=self.password)

View File

@ -87,10 +87,7 @@ def pytest_configure(config):
import rest_framework
settings.STATIC_ROOT = os.path.join(os.path.dirname(rest_framework.__file__), 'static-root')
backend = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'
if django.VERSION < (4, 2):
settings.STATICFILES_STORAGE = backend
else:
settings.STORAGES['staticfiles']['BACKEND'] = backend
settings.STORAGES['staticfiles']['BACKEND'] = backend
django.setup()

View File

@ -4,7 +4,7 @@ import unittest
from django.http import HttpResponse
from django.test import override_settings
from django.urls import path, re_path
from django.urls import path
from rest_framework.compat import coreapi, coreschema
from rest_framework.parsers import FileUploadParser
@ -180,7 +180,7 @@ class HeadersView(APIView):
urlpatterns = [
path('', SchemaView.as_view()),
path('example/', ListView.as_view()),
re_path(r'^example/(?P<id>[0-9]+)/$', DetailView.as_view()),
path('example/<int:id>/', DetailView.as_view()),
path('upload/', UploadView.as_view()),
path('download/', DownloadView.as_view()),
path('text/', TextView.as_view()),

View File

@ -65,7 +65,7 @@ class TestMiddleware(APITestCase):
key = 'abcd1234'
Token.objects.create(key=key, user=user)
self.client.get('/auth', HTTP_AUTHORIZATION='Token %s' % key)
self.client.get('/auth', headers={"authorization": 'Token %s' % key})
@override_settings(MIDDLEWARE=('tests.test_middleware.RequestPOSTMiddleware',))
def test_middleware_can_access_request_post_when_processing_response(self):

View File

@ -11,7 +11,6 @@ import json # noqa
import sys
import tempfile
import django
import pytest
from django.core.exceptions import ImproperlyConfigured
from django.core.serializers.json import DjangoJSONEncoder
@ -454,8 +453,6 @@ class TestPosgresFieldsMapping(TestCase):
fields = ['array_field', 'array_field_with_blank']
validators = ""
if django.VERSION < (4, 1):
validators = ", validators=[<django.core.validators.MaxLengthValidator object>]"
expected = dedent("""
TestSerializer():
array_field = ListField(allow_empty=False, child=CharField(label='Array field'%s))

View File

@ -4,7 +4,7 @@ import pytest
from _pytest.monkeypatch import MonkeyPatch
from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
from django.test import override_settings
from django.urls import re_path
from django.urls import path
from django.utils.datastructures import MultiValueDict
from rest_framework import relations, serializers
@ -152,7 +152,7 @@ class TestProxiedPrimaryKeyRelatedField(APISimpleTestCase):
urlpatterns = [
re_path(r'^example/(?P<name>.+)/$', lambda: None, name='example'),
path('example/<path:name>/', lambda: None, name='example'),
]

View File

@ -174,7 +174,7 @@ class RendererEndToEndTests(TestCase):
def test_default_renderer_serializes_content_on_accept_any(self):
"""If the Accept header is set to */* the default renderer should serialize the response."""
resp = self.client.get('/', HTTP_ACCEPT='*/*')
resp = self.client.get('/', headers={"accept": '*/*'})
self.assertEqual(resp['Content-Type'], RendererA.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
@ -182,7 +182,7 @@ class RendererEndToEndTests(TestCase):
def test_specified_renderer_serializes_content_default_case(self):
"""If the Accept header is set the specified renderer should serialize the response.
(In this case we check that works for the default renderer)"""
resp = self.client.get('/', HTTP_ACCEPT=RendererA.media_type)
resp = self.client.get('/', headers={"accept": RendererA.media_type})
self.assertEqual(resp['Content-Type'], RendererA.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
@ -190,14 +190,14 @@ class RendererEndToEndTests(TestCase):
def test_specified_renderer_serializes_content_non_default_case(self):
"""If the Accept header is set the specified renderer should serialize the response.
(In this case we check that works for a non-default renderer)"""
resp = self.client.get('/', HTTP_ACCEPT=RendererB.media_type)
resp = self.client.get('/', headers={"accept": RendererB.media_type})
self.assertEqual(resp['Content-Type'], RendererB.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
def test_unsatisfiable_accept_header_on_request_returns_406_status(self):
"""If the Accept header is unsatisfiable we should return a 406 Not Acceptable response."""
resp = self.client.get('/', HTTP_ACCEPT='foo/bar')
resp = self.client.get('/', headers={"accept": 'foo/bar'})
self.assertEqual(resp.status_code, status.HTTP_406_NOT_ACCEPTABLE)
def test_specified_renderer_serializes_content_on_format_query(self):
@ -228,14 +228,14 @@ class RendererEndToEndTests(TestCase):
RendererB.format
)
resp = self.client.get('/' + param,
HTTP_ACCEPT=RendererB.media_type)
headers={"accept": RendererB.media_type})
self.assertEqual(resp['Content-Type'], RendererB.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
def test_parse_error_renderers_browsable_api(self):
"""Invalid data should still render the browsable API correctly."""
resp = self.client.post('/parseerror', data='foobar', content_type='application/json', HTTP_ACCEPT='text/html')
resp = self.client.post('/parseerror', data='foobar', content_type='application/json', headers={"accept": 'text/html'})
self.assertEqual(resp['Content-Type'], 'text/html; charset=utf-8')
self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)
@ -714,13 +714,13 @@ class BrowsableAPIRendererTests(URLPatternsTestCase):
assert result is None
def test_extra_actions_dropdown(self):
resp = self.client.get('/api/examples/', HTTP_ACCEPT='text/html')
resp = self.client.get('/api/examples/', headers={"accept": 'text/html'})
assert 'id="extra-actions-menu"' in resp.content.decode()
assert '/api/examples/list_action/' in resp.content.decode()
assert '>Extra list action<' in resp.content.decode()
def test_extra_actions_dropdown_not_authed(self):
resp = self.client.get('/api/unauth-examples/', HTTP_ACCEPT='text/html')
resp = self.client.get('/api/unauth-examples/', headers={"accept": 'text/html'})
assert 'id="extra-actions-menu"' not in resp.content.decode()
assert '/api/examples/list_action/' not in resp.content.decode()
assert '>Extra list action<' not in resp.content.decode()

View File

@ -28,7 +28,7 @@ class Root(APIView):
}
post = request.POST
json = None
if request.META.get('CONTENT_TYPE') == 'application/json':
if request.headers.get('content-type') == 'application/json':
json = request.data
return Response({

View File

@ -154,7 +154,7 @@ class RendererIntegrationTests(TestCase):
def test_default_renderer_serializes_content_on_accept_any(self):
"""If the Accept header is set to */* the default renderer should serialize the response."""
resp = self.client.get('/', HTTP_ACCEPT='*/*')
resp = self.client.get('/', headers={"accept": '*/*'})
self.assertEqual(resp['Content-Type'], RendererA.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
@ -162,7 +162,7 @@ class RendererIntegrationTests(TestCase):
def test_specified_renderer_serializes_content_default_case(self):
"""If the Accept header is set the specified renderer should serialize the response.
(In this case we check that works for the default renderer)"""
resp = self.client.get('/', HTTP_ACCEPT=RendererA.media_type)
resp = self.client.get('/', headers={"accept": RendererA.media_type})
self.assertEqual(resp['Content-Type'], RendererA.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
@ -170,7 +170,7 @@ class RendererIntegrationTests(TestCase):
def test_specified_renderer_serializes_content_non_default_case(self):
"""If the Accept header is set the specified renderer should serialize the response.
(In this case we check that works for a non-default renderer)"""
resp = self.client.get('/', HTTP_ACCEPT=RendererB.media_type)
resp = self.client.get('/', headers={"accept": RendererB.media_type})
self.assertEqual(resp['Content-Type'], RendererB.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
@ -195,7 +195,7 @@ class RendererIntegrationTests(TestCase):
"""If both a 'format' query and a matching Accept header specified,
the renderer with the matching format attribute should serialize the response."""
resp = self.client.get('/?format=%s' % RendererB.format,
HTTP_ACCEPT=RendererB.media_type)
headers={"accept": RendererB.media_type})
self.assertEqual(resp['Content-Type'], RendererB.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)

View File

@ -2,7 +2,6 @@ import itertools
from io import BytesIO
from unittest.mock import patch
import django
from django.contrib.auth.models import User
from django.http import HttpResponseRedirect
from django.shortcuts import redirect
@ -20,7 +19,7 @@ from rest_framework.test import (
@api_view(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'])
def view(request):
data = {'auth': request.META.get('HTTP_AUTHORIZATION', b'')}
data = {'auth': request.headers.get('authorization', b'')}
if request.user:
data['user'] = request.user.username
if request.auth:
@ -316,7 +315,7 @@ class TestAPIRequestFactory(TestCase):
data=None,
content_type='application/json',
)
assert request.META['CONTENT_TYPE'] == 'application/json'
assert request.headers['content-type'] == 'application/json'
def check_urlpatterns(cls):
@ -334,18 +333,10 @@ class TestUrlPatternTestCase(URLPatternsTestCase):
super().setUpClass()
assert urlpatterns is cls.urlpatterns
if django.VERSION > (4, 0):
cls.addClassCleanup(
check_urlpatterns,
cls
)
if django.VERSION < (4, 0):
@classmethod
def tearDownClass(cls):
assert urlpatterns is cls.urlpatterns
super().tearDownClass()
assert urlpatterns is not cls.urlpatterns
cls.addClassCleanup(
check_urlpatterns,
cls
)
def test_urlpatterns(self):
assert self.client.get('/').status_code == 200

View File

@ -1,7 +1,7 @@
from collections import namedtuple
from django.test import TestCase
from django.urls import Resolver404, URLResolver, include, path, re_path
from django.urls import Resolver404, URLResolver, include, path
from django.urls.resolvers import RegexPattern
from rest_framework.test import APIRequestFactory
@ -93,7 +93,7 @@ class FormatSuffixTests(TestCase):
def test_format_suffix_django2_args(self):
urlpatterns = [
path('convtest/<int:pk>', dummy_view),
re_path(r'^retest/(?P<pk>[0-9]+)$', dummy_view),
path('retest/<int:pk>', dummy_view),
]
test_paths = [
URLTestPath('/convtest/42', (), {'pk': 42}),
@ -145,10 +145,10 @@ class FormatSuffixTests(TestCase):
def test_included_urls_mixed(self):
nested_patterns = [
path('path/<int:child>', dummy_view),
re_path(r'^re_path/(?P<child>[0-9]+)$', dummy_view)
path('re_path/<int:child>', dummy_view)
]
urlpatterns = [
re_path(r'^pre_path/(?P<parent>[0-9]+)/', include(nested_patterns), {'foo': 'bar'}),
path('pre_path/<int:parent>/', include(nested_patterns), {'foo': 'bar'}),
path('ppath/<int:parent>/', include(nested_patterns), {'foo': 'bar'}),
]
test_paths = [
@ -185,7 +185,7 @@ class FormatSuffixTests(TestCase):
def test_allowed_formats_re_path(self):
urlpatterns = [
re_path(r'^test$', dummy_view),
path('test', dummy_view),
]
self._test_allowed_formats(urlpatterns)

View File

@ -152,7 +152,7 @@ class TestURLReversing(URLPatternsTestCase, APITestCase):
path('v1/', include((included, 'v1'), namespace='v1')),
path('another/', dummy_view, name='another'),
re_path(r'^(?P<version>[v1|v2]+)/another/$', dummy_view, name='another'),
re_path(r'^(?P<foo>.+)/unversioned/$', dummy_view, name='unversioned'),
path('<path:foo>/unversioned/', dummy_view, name='unversioned'),
]

10
tox.ini
View File

@ -1,10 +1,13 @@
[tox]
; https://docs.djangoproject.com/en/stable/faq/install/#what-python-version-can-i-use-with-django
envlist =
{py36,py37,py38,py39}-django30
{py36,py37,py38,py39}-django31
{py36,py37,py38,py39,py310}-django32
{py38,py39,py310}-{django40,django41,django42,djangomain}
{py311}-{django41,django42,djangomain}
{py36,py37,py38,py39}-django32
{py38,py39}-{django40,django41,django42}
{py310}-{django32,django42,django50,djangomain}
{py311}-{django42,django50,djangomain}
{py312}-{django42,django50,djangomain}
base
dist
docs
@ -22,6 +25,7 @@ deps =
django40: Django>=4.0,<4.1
django41: Django>=4.1,<4.2
django42: Django>=4.2,<5.0
django50: Django>=5.0,<5.1
djangomain: https://github.com/django/django/archive/main.tar.gz
-rrequirements/requirements-testing.txt
-rrequirements/requirements-optionals.txt