Add pyupgrade to pre-commit hooks (#9682)

This commit is contained in:
Ülgen Sarıkavak 2025-04-09 09:24:18 +03:00 committed by GitHub
parent 2fbfaae507
commit ea1da76196
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 47 additions and 41 deletions

View File

@ -31,3 +31,9 @@ repos:
hooks: hooks:
- id: codespell - id: codespell
exclude: locale|kickstarter-announcement.md|coreapi-0.1.1.js 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"]

View File

@ -42,4 +42,4 @@ class Command(BaseCommand):
username) username)
) )
self.stdout.write( self.stdout.write(
'Generated token {} for user {}'.format(token.key, username)) f'Generated token {token.key} for user {username}')

View File

@ -111,7 +111,7 @@ def get_attribute(instance, attrs):
# If we raised an Attribute or KeyError here it'd get treated # If we raised an Attribute or KeyError here it'd get treated
# as an omitted field in `Field.get_attribute()`. Instead we # as an omitted field in `Field.get_attribute()`. Instead we
# raise a ValueError to ensure the exception is not masked. # 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 return instance
@ -1103,7 +1103,7 @@ class DecimalField(Field):
if self.localize: if self.localize:
return localize_input(quantized) return localize_input(quantized)
return '{:f}'.format(quantized) return f'{quantized:f}'
def quantize(self, value): def quantize(self, value):
""" """
@ -1861,7 +1861,7 @@ class SerializerMethodField(Field):
def bind(self, field_name, parent): def bind(self, field_name, parent):
# The method name defaults to `get_{field_name}`. # The method name defaults to `get_{field_name}`.
if self.method_name is None: 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) super().bind(field_name, parent)

View File

@ -65,7 +65,7 @@ class DefaultContentNegotiation(BaseContentNegotiation):
full_media_type = ';'.join( full_media_type = ';'.join(
(renderer.media_type,) + (renderer.media_type,) +
tuple( tuple(
'{}={}'.format(key, value) f'{key}={value}'
for key, value in media_type_wrapper.params.items() for key, value in media_type_wrapper.params.items()
) )
) )

View File

@ -225,7 +225,7 @@ class DjangoModelPermissions(BasePermission):
if hasattr(view, 'get_queryset'): if hasattr(view, 'get_queryset'):
queryset = view.get_queryset() queryset = view.get_queryset()
assert queryset is not None, ( assert queryset is not None, (
'{}.get_queryset() returned None'.format(view.__class__.__name__) f'{view.__class__.__name__}.get_queryset() returned None'
) )
return queryset return queryset
return view.queryset return view.queryset

View File

@ -66,7 +66,7 @@ class Response(SimpleTemplateResponse):
content_type = self.content_type content_type = self.content_type
if content_type is None and charset is not None: 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: elif content_type is None:
content_type = media_type content_type = media_type
self['Content-Type'] = content_type self['Content-Type'] = content_type

View File

@ -68,7 +68,7 @@ class LinkNode(dict):
current_val = self.methods_counter[preferred_key] current_val = self.methods_counter[preferred_key]
self.methods_counter[preferred_key] += 1 self.methods_counter[preferred_key] += 1
key = '{}_{}'.format(preferred_key, current_val) key = f'{preferred_key}_{current_val}'
if key not in self: if key not in self:
return key return key

View File

@ -82,7 +82,7 @@ class SchemaGenerator(BaseSchemaGenerator):
continue continue
if components_schemas[k] == components[k]: if components_schemas[k] == components[k]:
continue 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) components_schemas.update(components)
@ -644,7 +644,7 @@ class AutoSchema(ViewInspector):
return self.get_serializer(path, method) return self.get_serializer(path, method)
def get_reference(self, serializer): 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): def get_request_body(self, path, method):
if method not in ('PUT', 'PATCH', 'POST'): if method not in ('PUT', 'PATCH', 'POST'):

View File

@ -66,7 +66,7 @@ def get_unique_validators(field_name, model_field):
""" """
Returns a list of UniqueValidators that should be applied to the field. Returns a list of UniqueValidators that should be applied to the field.
""" """
field_set = set([field_name]) field_set = {field_name}
conditions = { conditions = {
c.condition c.condition
for c in model_field.model._meta.constraints for c in model_field.model._meta.constraints

View File

@ -1234,7 +1234,7 @@ class TestURLNamingCollisions(TestCase):
for method, suffix in zip(methods, suffixes): for method, suffix in zip(methods, suffixes):
if suffix is not None: if suffix is not None:
key = '{}_{}'.format(method, suffix) key = f'{method}_{suffix}'
else: else:
key = method key = method
assert loc[key].url == url assert loc[key].url == url

View File

@ -70,7 +70,7 @@ class GenerateSchemaTests(TestCase):
def test_accepts_custom_schema_generator(self): def test_accepts_custom_schema_generator(self):
call_command('generateschema', call_command('generateschema',
'--generator_class={}.{}'.format(__name__, CustomSchemaGenerator.__name__), f'--generator_class={__name__}.{CustomSchemaGenerator.__name__}',
stdout=self.out) stdout=self.out)
out_json = yaml.safe_load(self.out.getvalue()) out_json = yaml.safe_load(self.out.getvalue())
assert out_json == CustomSchemaGenerator.SCHEMA assert out_json == CustomSchemaGenerator.SCHEMA
@ -78,7 +78,7 @@ class GenerateSchemaTests(TestCase):
def test_writes_schema_to_file_on_parameter(self): def test_writes_schema_to_file_on_parameter(self):
fd, path = tempfile.mkstemp() fd, path = tempfile.mkstemp()
try: try:
call_command('generateschema', '--file={}'.format(path), stdout=self.out) call_command('generateschema', f'--file={path}', stdout=self.out)
# nothing on stdout # nothing on stdout
assert not self.out.getvalue() assert not self.out.getvalue()

View File

@ -43,12 +43,12 @@ class ExceptionTestCase(TestCase):
exception = Throttled(wait=2) exception = Throttled(wait=2)
assert exception.get_full_details() == { 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'} 'code': 'throttled'}
exception = Throttled(wait=2, detail='Slow down!') exception = Throttled(wait=2, detail='Slow down!')
assert exception.get_full_details() == { 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'} 'code': 'throttled'}

View File

@ -662,7 +662,7 @@ class FieldValues:
""" """
for input_value, expected_output in get_items(self.valid_inputs): for input_value, expected_output in get_items(self.valid_inputs):
assert self.field.run_validation(input_value) == expected_output, \ 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): def test_invalid_inputs(self, *args):
""" """
@ -672,12 +672,12 @@ class FieldValues:
with pytest.raises(serializers.ValidationError) as exc_info: with pytest.raises(serializers.ValidationError) as exc_info:
self.field.run_validation(input_value) self.field.run_validation(input_value)
assert exc_info.value.detail == expected_failure, \ assert exc_info.value.detail == expected_failure, \
'input value: {}'.format(repr(input_value)) f'input value: {repr(input_value)}'
def test_outputs(self, *args): def test_outputs(self, *args):
for output_value, expected_output in get_items(self.outputs): for output_value, expected_output in get_items(self.outputs):
assert self.field.to_representation(output_value) == expected_output, \ assert self.field.to_representation(output_value) == expected_output, \
'output value: {}'.format(repr(output_value)) f'output value: {repr(output_value)}'
# Boolean types... # Boolean types...
@ -1422,7 +1422,7 @@ class TestDateField(FieldValues):
outputs = { outputs = {
datetime.date(2001, 1, 1): '2001-01-01', datetime.date(2001, 1, 1): '2001-01-01',
'2001-01-01': '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: None,
'': None, '': None,
} }
@ -1489,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): '2001-01-01T13:00:00Z',
datetime.datetime(2001, 1, 1, 13, 00, tzinfo=utc): '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', '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: None,
'': None, '': None,
} }

View File

@ -289,7 +289,7 @@ class TestInstanceView(TestCase):
""" """
data = {'text': 'foo'} data = {'text': 'foo'}
filtered_out_pk = BasicModel.objects.filter(text='filtered out')[0].pk 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() response = self.view(request, pk=filtered_out_pk).render()
assert response.status_code == status.HTTP_404_NOT_FOUND assert response.status_code == status.HTTP_404_NOT_FOUND

View File

@ -536,7 +536,7 @@ class TestLimitOffset:
content = self.get_paginated_content(queryset) content = self.get_paginated_content(queryset)
next_limit = self.pagination.default_limit next_limit = self.pagination.default_limit
next_offset = 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 queryset == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
assert content.get('next') == next_url assert content.get('next') == next_url
@ -549,7 +549,7 @@ class TestLimitOffset:
content = self.get_paginated_content(queryset) content = self.get_paginated_content(queryset)
next_limit = self.pagination.default_limit next_limit = self.pagination.default_limit
next_offset = 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 queryset == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
assert content.get('next') == next_url assert content.get('next') == next_url
@ -565,9 +565,9 @@ class TestLimitOffset:
max_limit = self.pagination.max_limit max_limit = self.pagination.max_limit
next_offset = offset + max_limit next_offset = offset + max_limit
prev_offset = offset - max_limit prev_offset = offset - max_limit
base_url = 'http://testserver/?limit={}'.format(max_limit) base_url = f'http://testserver/?limit={max_limit}'
next_url = base_url + '&offset={}'.format(next_offset) next_url = base_url + f'&offset={next_offset}'
prev_url = base_url + '&offset={}'.format(prev_offset) prev_url = base_url + f'&offset={prev_offset}'
assert queryset == list(range(51, 66)) assert queryset == list(range(51, 66))
assert content.get('next') == next_url assert content.get('next') == next_url
assert content.get('previous') == prev_url assert content.get('previous') == prev_url

View File

@ -353,7 +353,7 @@ class ObjectPermissionsIntegrationTests(TestCase):
'delete': f('delete', model_name) 'delete': f('delete', model_name)
} }
for perm in perms.values(): for perm in perms.values():
perm = '{}.{}'.format(app_label, perm) perm = f'{app_label}.{perm}'
assign_perm(perm, everyone) assign_perm(perm, everyone)
everyone.user_set.add(*users.values()) everyone.user_set.add(*users.values())
@ -718,7 +718,7 @@ class PermissionsCompositionTests(TestCase):
assert hasperm is False assert hasperm is False
def test_operand_holder_is_hashable(self): 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): def test_operand_holder_hash_same_for_same_operands_and_operator(self):
first_operand_holder = ( first_operand_holder = (

View File

@ -586,7 +586,7 @@ class OneToOnePrimaryKeyTests(TestCase):
source = OneToOnePKSourceSerializer(data={'name': 'source-2', 'target': target_pk}) source = OneToOnePKSourceSerializer(data={'name': 'source-2', 'target': target_pk})
# Then: The source is valid with the serializer # Then: The source is valid with the serializer
if not source.is_valid(): 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 # Then: Saving the serializer creates a new object
new_source = source.save() new_source = source.save()
# Then: The new object has the same pk as the target object # Then: The new object has the same pk as the target object

View File

@ -408,7 +408,7 @@ class UnicodeJSONRendererTests(TestCase):
obj = {'should_escape': '\u2028\u2029'} obj = {'should_escape': '\u2028\u2029'}
renderer = JSONRenderer() renderer = JSONRenderer()
content = renderer.render(obj, 'application/json') 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): class AsciiJSONRendererTests(TestCase):
@ -421,7 +421,7 @@ class AsciiJSONRendererTests(TestCase):
obj = {'countries': ['United Kingdom', 'France', 'España']} obj = {'countries': ['United Kingdom', 'France', 'España']}
renderer = AsciiJSONRenderer() renderer = AsciiJSONRenderer()
content = renderer.render(obj, 'application/json') 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 # Tests for caching issue, #346

View File

@ -267,7 +267,7 @@ class Issue807Tests(TestCase):
""" """
headers = {"HTTP_ACCEPT": RendererC.media_type} headers = {"HTTP_ACCEPT": RendererC.media_type}
resp = self.client.get('/', **headers) 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']) self.assertEqual(expected, resp['Content-Type'])
def test_content_type_set_explicitly_on_response(self): def test_content_type_set_explicitly_on_response(self):

View File

@ -447,9 +447,9 @@ class TestDynamicListAndDetailRouter(TestCase):
url_path = endpoint.url_path url_path = endpoint.url_path
if method_name.startswith('list_'): 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: 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 # check method to function mapping
if method_name.endswith('_post'): if method_name.endswith('_post'):
method_map = 'post' method_map = 'post'
@ -488,14 +488,14 @@ class TestRegexUrlPath(URLPatternsTestCase, TestCase):
def test_regex_url_path_list(self): def test_regex_url_path_list(self):
kwarg = '1234' kwarg = '1234'
response = self.client.get('/regex/list/{}/'.format(kwarg)) response = self.client.get(f'/regex/list/{kwarg}/')
assert response.status_code == 200 assert response.status_code == 200
assert json.loads(response.content.decode()) == {'kwarg': kwarg} assert json.loads(response.content.decode()) == {'kwarg': kwarg}
def test_regex_url_path_detail(self): def test_regex_url_path_detail(self):
pk = '1' pk = '1'
kwarg = '1234' 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 response.status_code == 200
assert json.loads(response.content.decode()) == {'pk': pk, 'kwarg': kwarg} assert json.loads(response.content.decode()) == {'pk': pk, 'kwarg': kwarg}
@ -557,14 +557,14 @@ class TestUrlPath(URLPatternsTestCase, TestCase):
def test_list_extra_action(self): def test_list_extra_action(self):
kwarg = 1234 kwarg = 1234
response = self.client.get('/path/list/{}/'.format(kwarg)) response = self.client.get(f'/path/list/{kwarg}/')
assert response.status_code == 200 assert response.status_code == 200
assert json.loads(response.content.decode()) == {'kwarg': kwarg} assert json.loads(response.content.decode()) == {'kwarg': kwarg}
def test_detail_extra_action(self): def test_detail_extra_action(self):
pk = '1' pk = '1'
kwarg = 1234 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 response.status_code == 200
assert json.loads(response.content.decode()) == {'pk': pk, 'kwarg': kwarg} assert json.loads(response.content.decode()) == {'pk': pk, 'kwarg': kwarg}

View File

@ -148,14 +148,14 @@ class TestMaxValueValidatorValidation(TestCase):
def test_max_value_validation_success(self): def test_max_value_validation_success(self):
obj = ValidationMaxValueValidatorModel.objects.create(number_value=100) 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() view = UpdateMaxValueValidationModel().as_view()
response = view(request, pk=obj.pk).render() response = view(request, pk=obj.pk).render()
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
def test_max_value_validation_fail(self): def test_max_value_validation_fail(self):
obj = ValidationMaxValueValidatorModel.objects.create(number_value=100) 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() view = UpdateMaxValueValidationModel().as_view()
response = view(request, pk=obj.pk).render() response = view(request, pk=obj.pk).render()
assert response.content == b'{"number_value":["Ensure this value is less than or equal to 100."]}' assert response.content == b'{"number_value":["Ensure this value is less than or equal to 100."]}'