diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8939dd3db..27bbcb763 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,3 +31,9 @@ repos: hooks: - id: codespell exclude: locale|kickstarter-announcement.md|coreapi-0.1.1.js + +- repo: https://github.com/asottile/pyupgrade + rev: v3.19.1 + hooks: + - id: pyupgrade + args: ["--py39-plus", "--keep-percent-format"] diff --git a/rest_framework/authtoken/management/commands/drf_create_token.py b/rest_framework/authtoken/management/commands/drf_create_token.py index 3d6539244..3f4521fe4 100644 --- a/rest_framework/authtoken/management/commands/drf_create_token.py +++ b/rest_framework/authtoken/management/commands/drf_create_token.py @@ -42,4 +42,4 @@ class Command(BaseCommand): username) ) self.stdout.write( - 'Generated token {} for user {}'.format(token.key, username)) + f'Generated token {token.key} for user {username}') diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 6989edc0a..89c0a714c 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -111,7 +111,7 @@ def get_attribute(instance, attrs): # If we raised an Attribute or KeyError here it'd get treated # as an omitted field in `Field.get_attribute()`. Instead we # raise a ValueError to ensure the exception is not masked. - raise ValueError('Exception raised in callable attribute "{}"; original exception was: {}'.format(attr, exc)) + raise ValueError(f'Exception raised in callable attribute "{attr}"; original exception was: {exc}') return instance @@ -1103,7 +1103,7 @@ class DecimalField(Field): if self.localize: return localize_input(quantized) - return '{:f}'.format(quantized) + return f'{quantized:f}' def quantize(self, value): """ @@ -1861,7 +1861,7 @@ class SerializerMethodField(Field): def bind(self, field_name, parent): # The method name defaults to `get_{field_name}`. if self.method_name is None: - self.method_name = 'get_{field_name}'.format(field_name=field_name) + self.method_name = f'get_{field_name}' super().bind(field_name, parent) diff --git a/rest_framework/negotiation.py b/rest_framework/negotiation.py index b4bbfa1f5..23012f71f 100644 --- a/rest_framework/negotiation.py +++ b/rest_framework/negotiation.py @@ -65,7 +65,7 @@ class DefaultContentNegotiation(BaseContentNegotiation): full_media_type = ';'.join( (renderer.media_type,) + tuple( - '{}={}'.format(key, value) + f'{key}={value}' for key, value in media_type_wrapper.params.items() ) ) diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py index 7c15eca58..768f6cb95 100644 --- a/rest_framework/permissions.py +++ b/rest_framework/permissions.py @@ -225,7 +225,7 @@ class DjangoModelPermissions(BasePermission): if hasattr(view, 'get_queryset'): queryset = view.get_queryset() assert queryset is not None, ( - '{}.get_queryset() returned None'.format(view.__class__.__name__) + f'{view.__class__.__name__}.get_queryset() returned None' ) return queryset return view.queryset diff --git a/rest_framework/response.py b/rest_framework/response.py index 6e756544c..507ea595f 100644 --- a/rest_framework/response.py +++ b/rest_framework/response.py @@ -66,7 +66,7 @@ class Response(SimpleTemplateResponse): content_type = self.content_type if content_type is None and charset is not None: - content_type = "{}; charset={}".format(media_type, charset) + content_type = f"{media_type}; charset={charset}" elif content_type is None: content_type = media_type self['Content-Type'] = content_type diff --git a/rest_framework/schemas/coreapi.py b/rest_framework/schemas/coreapi.py index 582aba196..657178304 100644 --- a/rest_framework/schemas/coreapi.py +++ b/rest_framework/schemas/coreapi.py @@ -68,7 +68,7 @@ class LinkNode(dict): current_val = self.methods_counter[preferred_key] self.methods_counter[preferred_key] += 1 - key = '{}_{}'.format(preferred_key, current_val) + key = f'{preferred_key}_{current_val}' if key not in self: return key diff --git a/rest_framework/schemas/openapi.py b/rest_framework/schemas/openapi.py index 019eeb33e..eb7dc909d 100644 --- a/rest_framework/schemas/openapi.py +++ b/rest_framework/schemas/openapi.py @@ -82,7 +82,7 @@ class SchemaGenerator(BaseSchemaGenerator): continue if components_schemas[k] == components[k]: continue - warnings.warn('Schema component "{}" has been overridden with a different value.'.format(k)) + warnings.warn(f'Schema component "{k}" has been overridden with a different value.') components_schemas.update(components) @@ -644,7 +644,7 @@ class AutoSchema(ViewInspector): return self.get_serializer(path, method) def get_reference(self, serializer): - return {'$ref': '#/components/schemas/{}'.format(self.get_component_name(serializer))} + return {'$ref': f'#/components/schemas/{self.get_component_name(serializer)}'} def get_request_body(self, path, method): if method not in ('PUT', 'PATCH', 'POST'): diff --git a/rest_framework/utils/field_mapping.py b/rest_framework/utils/field_mapping.py index fc63f96fe..15c4b9105 100644 --- a/rest_framework/utils/field_mapping.py +++ b/rest_framework/utils/field_mapping.py @@ -66,7 +66,7 @@ def get_unique_validators(field_name, model_field): """ Returns a list of UniqueValidators that should be applied to the field. """ - field_set = set([field_name]) + field_set = {field_name} conditions = { c.condition for c in model_field.model._meta.constraints diff --git a/rest_framework/utils/serializer_helpers.py b/rest_framework/utils/serializer_helpers.py index 0e59aa66a..e6bd84f30 100644 --- a/rest_framework/utils/serializer_helpers.py +++ b/rest_framework/utils/serializer_helpers.py @@ -1,5 +1,4 @@ import contextlib -import sys from collections.abc import Mapping, MutableMapping from django.utils.encoding import force_str @@ -29,21 +28,20 @@ class ReturnDict(dict): # but preserve the raw data. return (dict, (dict(self),)) - if sys.version_info >= (3, 9): - # These are basically copied from OrderedDict, with `serializer` added. - def __or__(self, other): - if not isinstance(other, dict): - return NotImplemented - new = self.__class__(self, serializer=self.serializer) - new.update(other) - return new + # These are basically copied from OrderedDict, with `serializer` added. + def __or__(self, other): + if not isinstance(other, dict): + return NotImplemented + new = self.__class__(self, serializer=self.serializer) + new.update(other) + return new - def __ror__(self, other): - if not isinstance(other, dict): - return NotImplemented - new = self.__class__(other, serializer=self.serializer) - new.update(self) - return new + def __ror__(self, other): + if not isinstance(other, dict): + return NotImplemented + new = self.__class__(other, serializer=self.serializer) + new.update(self) + return new class ReturnList(list): diff --git a/setup.py b/setup.py index 952b5f50a..e5e78c2c7 100755 --- a/setup.py +++ b/setup.py @@ -81,7 +81,7 @@ setup( author_email='tom@tomchristie.com', # SEE NOTE BELOW (*) packages=find_packages(exclude=['tests*']), include_package_data=True, - install_requires=["django>=4.2", 'backports.zoneinfo;python_version<"3.9"'], + install_requires=["django>=4.2"], python_requires=">=3.9", zip_safe=False, classifiers=[ diff --git a/tests/schemas/test_coreapi.py b/tests/schemas/test_coreapi.py index 171f08646..a97b02fe1 100644 --- a/tests/schemas/test_coreapi.py +++ b/tests/schemas/test_coreapi.py @@ -1234,7 +1234,7 @@ class TestURLNamingCollisions(TestCase): for method, suffix in zip(methods, suffixes): if suffix is not None: - key = '{}_{}'.format(method, suffix) + key = f'{method}_{suffix}' else: key = method assert loc[key].url == url diff --git a/tests/schemas/test_managementcommand.py b/tests/schemas/test_managementcommand.py index c0713f43c..fa1b75fbf 100644 --- a/tests/schemas/test_managementcommand.py +++ b/tests/schemas/test_managementcommand.py @@ -70,7 +70,7 @@ class GenerateSchemaTests(TestCase): def test_accepts_custom_schema_generator(self): call_command('generateschema', - '--generator_class={}.{}'.format(__name__, CustomSchemaGenerator.__name__), + f'--generator_class={__name__}.{CustomSchemaGenerator.__name__}', stdout=self.out) out_json = yaml.safe_load(self.out.getvalue()) assert out_json == CustomSchemaGenerator.SCHEMA @@ -78,7 +78,7 @@ class GenerateSchemaTests(TestCase): def test_writes_schema_to_file_on_parameter(self): fd, path = tempfile.mkstemp() try: - call_command('generateschema', '--file={}'.format(path), stdout=self.out) + call_command('generateschema', f'--file={path}', stdout=self.out) # nothing on stdout assert not self.out.getvalue() diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index 9516bfec9..67be5cfbd 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -43,12 +43,12 @@ class ExceptionTestCase(TestCase): exception = Throttled(wait=2) assert exception.get_full_details() == { - 'message': 'Request was throttled. Expected available in {} seconds.'.format(2), + 'message': f'Request was throttled. Expected available in {2} seconds.', 'code': 'throttled'} exception = Throttled(wait=2, detail='Slow down!') assert exception.get_full_details() == { - 'message': 'Slow down! Expected available in {} seconds.'.format(2), + 'message': f'Slow down! Expected available in {2} seconds.', 'code': 'throttled'} diff --git a/tests/test_fields.py b/tests/test_fields.py index 1403a6a35..d574b07eb 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -2,12 +2,12 @@ import datetime import math import os import re -import sys import uuid import warnings from decimal import ROUND_DOWN, ROUND_UP, Decimal from enum import auto from unittest.mock import patch +from zoneinfo import ZoneInfo import pytest @@ -30,11 +30,6 @@ from rest_framework.fields import ( ) from tests.models import UUIDForeignKeyTarget -if sys.version_info >= (3, 9): - from zoneinfo import ZoneInfo -else: - from backports.zoneinfo import ZoneInfo - utc = datetime.timezone.utc # Tests for helper functions. @@ -641,10 +636,6 @@ class Test5087Regression: class TestTyping(TestCase): - @pytest.mark.skipif( - sys.version_info < (3, 7), - reason="subscriptable classes requires Python 3.7 or higher", - ) def test_field_is_subscriptable(self): assert serializers.Field is serializers.Field["foo"] @@ -671,7 +662,7 @@ class FieldValues: """ for input_value, expected_output in get_items(self.valid_inputs): assert self.field.run_validation(input_value) == expected_output, \ - 'input value: {}'.format(repr(input_value)) + f'input value: {repr(input_value)}' def test_invalid_inputs(self, *args): """ @@ -681,12 +672,12 @@ class FieldValues: with pytest.raises(serializers.ValidationError) as exc_info: self.field.run_validation(input_value) assert exc_info.value.detail == expected_failure, \ - 'input value: {}'.format(repr(input_value)) + f'input value: {repr(input_value)}' def test_outputs(self, *args): for output_value, expected_output in get_items(self.outputs): assert self.field.to_representation(output_value) == expected_output, \ - 'output value: {}'.format(repr(output_value)) + f'output value: {repr(output_value)}' # Boolean types... @@ -1431,7 +1422,7 @@ class TestDateField(FieldValues): outputs = { datetime.date(2001, 1, 1): '2001-01-01', '2001-01-01': '2001-01-01', - str('2016-01-10'): '2016-01-10', + '2016-01-10': '2016-01-10', None: None, '': None, } @@ -1498,7 +1489,7 @@ class TestDateTimeField(FieldValues): datetime.datetime(2001, 1, 1, 13, 00): '2001-01-01T13:00:00Z', datetime.datetime(2001, 1, 1, 13, 00, tzinfo=utc): '2001-01-01T13:00:00Z', '2001-01-01T00:00:00': '2001-01-01T00:00:00', - str('2016-01-10T00:00:00'): '2016-01-10T00:00:00', + '2016-01-10T00:00:00': '2016-01-10T00:00:00', None: None, '': None, } diff --git a/tests/test_generics.py b/tests/test_generics.py index 9990389c9..25b96fcbb 100644 --- a/tests/test_generics.py +++ b/tests/test_generics.py @@ -1,5 +1,3 @@ -import sys - import pytest from django.db import models from django.http import Http404 @@ -291,7 +289,7 @@ class TestInstanceView(TestCase): """ data = {'text': 'foo'} filtered_out_pk = BasicModel.objects.filter(text='filtered out')[0].pk - request = factory.put('/{}'.format(filtered_out_pk), data, format='json') + request = factory.put(f'/{filtered_out_pk}', data, format='json') response = self.view(request, pk=filtered_out_pk).render() assert response.status_code == status.HTTP_404_NOT_FOUND @@ -703,23 +701,11 @@ class TestSerializer(TestCase): class TestTyping(TestCase): - @pytest.mark.skipif( - sys.version_info < (3, 7), - reason="subscriptable classes requires Python 3.7 or higher", - ) def test_genericview_is_subscriptable(self): assert generics.GenericAPIView is generics.GenericAPIView["foo"] - @pytest.mark.skipif( - sys.version_info < (3, 7), - reason="subscriptable classes requires Python 3.7 or higher", - ) def test_listview_is_subscriptable(self): assert generics.ListAPIView is generics.ListAPIView["foo"] - @pytest.mark.skipif( - sys.version_info < (3, 7), - reason="subscriptable classes requires Python 3.7 or higher", - ) def test_instanceview_is_subscriptable(self): assert generics.RetrieveAPIView is generics.RetrieveAPIView["foo"] diff --git a/tests/test_model_serializer.py b/tests/test_model_serializer.py index f1f9518cb..eac51ae70 100644 --- a/tests/test_model_serializer.py +++ b/tests/test_model_serializer.py @@ -9,7 +9,6 @@ import datetime import decimal import json # noqa import re -import sys import tempfile import pytest @@ -397,10 +396,6 @@ class TestDurationFieldMapping(TestCase): fields = '__all__' expected = dedent(""" - TestSerializer(): - id = IntegerField(label='ID', read_only=True) - duration_field = DurationField(max_value=datetime.timedelta(3), min_value=datetime.timedelta(1)) - """) if sys.version_info < (3, 7) else dedent(""" TestSerializer(): id = IntegerField(label='ID', read_only=True) duration_field = DurationField(max_value=datetime.timedelta(days=3), min_value=datetime.timedelta(days=1)) diff --git a/tests/test_pagination.py b/tests/test_pagination.py index d8feae52b..d8f66e95b 100644 --- a/tests/test_pagination.py +++ b/tests/test_pagination.py @@ -536,7 +536,7 @@ class TestLimitOffset: content = self.get_paginated_content(queryset) next_limit = self.pagination.default_limit next_offset = self.pagination.default_limit - next_url = 'http://testserver/?limit={}&offset={}'.format(next_limit, next_offset) + next_url = f'http://testserver/?limit={next_limit}&offset={next_offset}' assert queryset == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] assert content.get('next') == next_url @@ -549,7 +549,7 @@ class TestLimitOffset: content = self.get_paginated_content(queryset) next_limit = self.pagination.default_limit next_offset = self.pagination.default_limit - next_url = 'http://testserver/?limit={}&offset={}'.format(next_limit, next_offset) + next_url = f'http://testserver/?limit={next_limit}&offset={next_offset}' assert queryset == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] assert content.get('next') == next_url @@ -565,9 +565,9 @@ class TestLimitOffset: max_limit = self.pagination.max_limit next_offset = offset + max_limit prev_offset = offset - max_limit - base_url = 'http://testserver/?limit={}'.format(max_limit) - next_url = base_url + '&offset={}'.format(next_offset) - prev_url = base_url + '&offset={}'.format(prev_offset) + base_url = f'http://testserver/?limit={max_limit}' + next_url = base_url + f'&offset={next_offset}' + prev_url = base_url + f'&offset={prev_offset}' assert queryset == list(range(51, 66)) assert content.get('next') == next_url assert content.get('previous') == prev_url diff --git a/tests/test_permissions.py b/tests/test_permissions.py index 2c908ba3f..93fe7b941 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -353,7 +353,7 @@ class ObjectPermissionsIntegrationTests(TestCase): 'delete': f('delete', model_name) } for perm in perms.values(): - perm = '{}.{}'.format(app_label, perm) + perm = f'{app_label}.{perm}' assign_perm(perm, everyone) everyone.user_set.add(*users.values()) @@ -718,7 +718,7 @@ class PermissionsCompositionTests(TestCase): assert hasperm is False def test_operand_holder_is_hashable(self): - assert hash((permissions.IsAuthenticated & permissions.IsAdminUser)) + assert hash(permissions.IsAuthenticated & permissions.IsAdminUser) def test_operand_holder_hash_same_for_same_operands_and_operator(self): first_operand_holder = ( diff --git a/tests/test_relations_pk.py b/tests/test_relations_pk.py index 7a4878a2b..14513f2bb 100644 --- a/tests/test_relations_pk.py +++ b/tests/test_relations_pk.py @@ -586,7 +586,7 @@ class OneToOnePrimaryKeyTests(TestCase): source = OneToOnePKSourceSerializer(data={'name': 'source-2', 'target': target_pk}) # Then: The source is valid with the serializer if not source.is_valid(): - self.fail("Expected OneToOnePKTargetSerializer to be valid but had errors: {}".format(source.errors)) + self.fail(f"Expected OneToOnePKTargetSerializer to be valid but had errors: {source.errors}") # Then: Saving the serializer creates a new object new_source = source.save() # Then: The new object has the same pk as the target object diff --git a/tests/test_renderers.py b/tests/test_renderers.py index d04ff300f..1b396575d 100644 --- a/tests/test_renderers.py +++ b/tests/test_renderers.py @@ -408,7 +408,7 @@ class UnicodeJSONRendererTests(TestCase): obj = {'should_escape': '\u2028\u2029'} renderer = JSONRenderer() content = renderer.render(obj, 'application/json') - self.assertEqual(content, '{"should_escape":"\\u2028\\u2029"}'.encode()) + self.assertEqual(content, b'{"should_escape":"\\u2028\\u2029"}') class AsciiJSONRendererTests(TestCase): @@ -421,7 +421,7 @@ class AsciiJSONRendererTests(TestCase): obj = {'countries': ['United Kingdom', 'France', 'EspaƱa']} renderer = AsciiJSONRenderer() content = renderer.render(obj, 'application/json') - self.assertEqual(content, '{"countries":["United Kingdom","France","Espa\\u00f1a"]}'.encode()) + self.assertEqual(content, b'{"countries":["United Kingdom","France","Espa\\u00f1a"]}') # Tests for caching issue, #346 diff --git a/tests/test_request.py b/tests/test_request.py index 4263f2682..fe3efd96b 100644 --- a/tests/test_request.py +++ b/tests/test_request.py @@ -3,7 +3,6 @@ Tests for content parsing, and form-overloaded content parsing. """ import copy import os.path -import sys import tempfile import pytest @@ -375,9 +374,5 @@ class TestDeepcopy(TestCase): class TestTyping(TestCase): - @pytest.mark.skipif( - sys.version_info < (3, 7), - reason="subscriptable classes requires Python 3.7 or higher", - ) def test_request_is_subscriptable(self): assert Request is Request["foo"] diff --git a/tests/test_response.py b/tests/test_response.py index 00b5691b0..83f8a6717 100644 --- a/tests/test_response.py +++ b/tests/test_response.py @@ -1,6 +1,3 @@ -import sys - -import pytest from django.test import TestCase, override_settings from django.urls import include, path, re_path @@ -270,7 +267,7 @@ class Issue807Tests(TestCase): """ headers = {"HTTP_ACCEPT": RendererC.media_type} resp = self.client.get('/', **headers) - expected = "{}; charset={}".format(RendererC.media_type, RendererC.charset) + expected = f"{RendererC.media_type}; charset={RendererC.charset}" self.assertEqual(expected, resp['Content-Type']) def test_content_type_set_explicitly_on_response(self): @@ -289,9 +286,5 @@ class Issue807Tests(TestCase): class TestTyping(TestCase): - @pytest.mark.skipif( - sys.version_info < (3, 7), - reason="subscriptable classes requires Python 3.7 or higher", - ) def test_response_is_subscriptable(self): assert Response is Response["foo"] diff --git a/tests/test_routers.py b/tests/test_routers.py index 887f601d5..91a6189d5 100644 --- a/tests/test_routers.py +++ b/tests/test_routers.py @@ -447,9 +447,9 @@ class TestDynamicListAndDetailRouter(TestCase): url_path = endpoint.url_path if method_name.startswith('list_'): - assert route.url == '^{{prefix}}/{0}{{trailing_slash}}$'.format(url_path) + assert route.url == f'^{{prefix}}/{url_path}{{trailing_slash}}$' else: - assert route.url == '^{{prefix}}/{{lookup}}/{0}{{trailing_slash}}$'.format(url_path) + assert route.url == f'^{{prefix}}/{{lookup}}/{url_path}{{trailing_slash}}$' # check method to function mapping if method_name.endswith('_post'): method_map = 'post' @@ -488,14 +488,14 @@ class TestRegexUrlPath(URLPatternsTestCase, TestCase): def test_regex_url_path_list(self): kwarg = '1234' - response = self.client.get('/regex/list/{}/'.format(kwarg)) + response = self.client.get(f'/regex/list/{kwarg}/') assert response.status_code == 200 assert json.loads(response.content.decode()) == {'kwarg': kwarg} def test_regex_url_path_detail(self): pk = '1' kwarg = '1234' - response = self.client.get('/regex/{}/detail/{}/'.format(pk, kwarg)) + response = self.client.get(f'/regex/{pk}/detail/{kwarg}/') assert response.status_code == 200 assert json.loads(response.content.decode()) == {'pk': pk, 'kwarg': kwarg} @@ -557,14 +557,14 @@ class TestUrlPath(URLPatternsTestCase, TestCase): def test_list_extra_action(self): kwarg = 1234 - response = self.client.get('/path/list/{}/'.format(kwarg)) + response = self.client.get(f'/path/list/{kwarg}/') assert response.status_code == 200 assert json.loads(response.content.decode()) == {'kwarg': kwarg} def test_detail_extra_action(self): pk = '1' kwarg = 1234 - response = self.client.get('/path/{}/detail/{}/'.format(pk, kwarg)) + response = self.client.get(f'/path/{pk}/detail/{kwarg}/') assert response.status_code == 200 assert json.loads(response.content.decode()) == {'pk': pk, 'kwarg': kwarg} diff --git a/tests/test_serializer.py b/tests/test_serializer.py index 10fa8afb9..cefa2ee38 100644 --- a/tests/test_serializer.py +++ b/tests/test_serializer.py @@ -1,7 +1,6 @@ import inspect import pickle import re -import sys from collections import ChainMap from collections.abc import Mapping @@ -205,10 +204,6 @@ class TestSerializer: exceptions.ErrorDetail(string='Raised error', code='invalid') ]} - @pytest.mark.skipif( - sys.version_info < (3, 7), - reason="subscriptable classes requires Python 3.7 or higher", - ) def test_serializer_is_subscriptable(self): assert serializers.Serializer is serializers.Serializer["foo"] @@ -743,10 +738,6 @@ class TestDeclaredFieldInheritance: class Test8301Regression: - @pytest.mark.skipif( - sys.version_info < (3, 9), - reason="dictionary union operator requires Python 3.9 or higher", - ) def test_ReturnDict_merging(self): # Serializer.data returns ReturnDict, this is essentially a test for that. diff --git a/tests/test_serializer_lists.py b/tests/test_serializer_lists.py index 4070de7a5..42ebf4771 100644 --- a/tests/test_serializer_lists.py +++ b/tests/test_serializer_lists.py @@ -1,5 +1,3 @@ -import sys - import pytest from django.http import QueryDict from django.utils.datastructures import MultiValueDict @@ -60,10 +58,6 @@ class TestListSerializer: assert serializer.is_valid() assert serializer.validated_data == expected_output - @pytest.mark.skipif( - sys.version_info < (3, 7), - reason="subscriptable classes requires Python 3.7 or higher", - ) def test_list_serializer_is_subscriptable(self): assert serializers.ListSerializer is serializers.ListSerializer["foo"] diff --git a/tests/test_validation.py b/tests/test_validation.py index 6e00b48c2..a2cdd1dcb 100644 --- a/tests/test_validation.py +++ b/tests/test_validation.py @@ -148,14 +148,14 @@ class TestMaxValueValidatorValidation(TestCase): def test_max_value_validation_success(self): obj = ValidationMaxValueValidatorModel.objects.create(number_value=100) - request = factory.patch('/{}'.format(obj.pk), {'number_value': 98}, format='json') + request = factory.patch(f'/{obj.pk}', {'number_value': 98}, format='json') view = UpdateMaxValueValidationModel().as_view() response = view(request, pk=obj.pk).render() assert response.status_code == status.HTTP_200_OK def test_max_value_validation_fail(self): obj = ValidationMaxValueValidatorModel.objects.create(number_value=100) - request = factory.patch('/{}'.format(obj.pk), {'number_value': 101}, format='json') + request = factory.patch(f'/{obj.pk}', {'number_value': 101}, format='json') view = UpdateMaxValueValidationModel().as_view() response = view(request, pk=obj.pk).render() assert response.content == b'{"number_value":["Ensure this value is less than or equal to 100."]}'