From ffe3dbb1b15f35295924f5c2f0513fc4c81d5e6e Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Mon, 8 Jan 2018 01:49:46 -0800 Subject: [PATCH] Perfer iter(dict) over iter(dict.keys()) (#5736) Calling dict.keys() is unnecessary. The two are functionally equivalent on modern Pythons. Inspired by Lennart Regebro's talk "Prehistoric Patterns in Python" from PyCon 2017. https://www.youtube.com/watch?v=V5-JH23Vk0I --- docs/api-guide/serializers.md | 2 +- rest_framework/fields.py | 2 +- rest_framework/filters.py | 2 +- rest_framework/relations.py | 2 +- rest_framework/renderers.py | 4 ++-- rest_framework/schemas/generators.py | 2 +- rest_framework/schemas/inspectors.py | 4 ++-- rest_framework/serializers.py | 18 +++++++++--------- rest_framework/test.py | 2 +- rest_framework/utils/html.py | 2 +- rest_framework/utils/mediatypes.py | 4 ++-- tests/test_bound_fields.py | 2 +- tests/test_fields.py | 4 ++-- tests/test_metadata.py | 2 +- tests/test_multitable_inheritance.py | 4 ++-- tests/test_one_to_one_with_inheritance.py | 2 +- tests/test_permissions.py | 6 +++--- tests/test_request.py | 4 ++-- tests/test_serializer_lists.py | 2 +- 19 files changed, 35 insertions(+), 35 deletions(-) diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 140de0fe2..3c560d829 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -1083,7 +1083,7 @@ For example, if you wanted to be able to set which fields should be used by a se if fields is not None: # Drop any fields that are not specified in the `fields` argument. allowed = set(fields) - existing = set(self.fields.keys()) + existing = set(self.fields) for field_name in existing - allowed: self.fields.pop(field_name) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 9b88784c8..c8f189ed1 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1420,7 +1420,7 @@ class ChoiceField(Field): # Allows us to deal with eg. integer choices while supporting either # integer or string input, but still get the correct datatype out. self.choice_strings_to_values = { - six.text_type(key): key for key in self.choices.keys() + six.text_type(key): key for key in self.choices } choices = property(_get_choices, _set_choices) diff --git a/rest_framework/filters.py b/rest_framework/filters.py index d30135d2e..830d0a616 100644 --- a/rest_framework/filters.py +++ b/rest_framework/filters.py @@ -218,7 +218,7 @@ class OrderingFilter(BaseFilterBackend): ] valid_fields += [ (key, key.title().split('__')) - for key in queryset.query.annotations.keys() + for key in queryset.query.annotations ] else: valid_fields = [ diff --git a/rest_framework/relations.py b/rest_framework/relations.py index 22078e64a..c87b9299a 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -133,7 +133,7 @@ class RelatedField(Field): return CustomManyRelatedField(*args, **kwargs) """ list_kwargs = {'child_relation': cls(*args, **kwargs)} - for key in kwargs.keys(): + for key in kwargs: if key in MANY_RELATION_KWARGS: list_kwargs[key] = kwargs[key] return ManyRelatedField(**list_kwargs) diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index f071e7b4d..a2db9f228 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -805,8 +805,8 @@ class AdminRenderer(BrowsableAPIRenderer): header = results style = 'detail' - columns = [key for key in header.keys() if key != 'url'] - details = [key for key in header.keys() if key != 'url'] + columns = [key for key in header if key != 'url'] + details = [key for key in header if key != 'url'] context['style'] = style context['columns'] = columns diff --git a/rest_framework/schemas/generators.py b/rest_framework/schemas/generators.py index 10af6ee04..880777918 100644 --- a/rest_framework/schemas/generators.py +++ b/rest_framework/schemas/generators.py @@ -228,7 +228,7 @@ class EndpointEnumerator(object): Return a list of the valid HTTP methods for this endpoint. """ if hasattr(callback, 'actions'): - actions = set(callback.actions.keys()) + actions = set(callback.actions) http_method_names = set(callback.cls.http_method_names) methods = [method.upper() for method in actions & http_method_names] else: diff --git a/rest_framework/schemas/inspectors.py b/rest_framework/schemas/inspectors.py index b2a5320bd..2afef7a04 100644 --- a/rest_framework/schemas/inspectors.py +++ b/rest_framework/schemas/inspectors.py @@ -54,13 +54,13 @@ def field_to_schema(field): return coreschema.String(title=title, description=description) elif isinstance(field, serializers.MultipleChoiceField): return coreschema.Array( - items=coreschema.Enum(enum=list(field.choices.keys())), + items=coreschema.Enum(enum=list(field.choices)), title=title, description=description ) elif isinstance(field, serializers.ChoiceField): return coreschema.Enum( - enum=list(field.choices.keys()), + enum=list(field.choices), title=title, description=description ) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index e2ea0d744..57f916a17 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -1136,9 +1136,9 @@ class ModelSerializer(Serializer): """ return ( [model_info.pk.name] + - list(declared_fields.keys()) + - list(model_info.fields.keys()) + - list(model_info.forward_relations.keys()) + list(declared_fields) + + list(model_info.fields) + + list(model_info.forward_relations) ) # Methods for constructing serializer fields... @@ -1194,7 +1194,7 @@ class ModelSerializer(Serializer): 'error_messages', 'validators', 'allow_null', 'allow_blank', 'choices' } - for key in list(field_kwargs.keys()): + for key in list(field_kwargs): if key not in valid_kwargs: field_kwargs.pop(key) @@ -1364,7 +1364,7 @@ class ModelSerializer(Serializer): # Include each of the `unique_together` field names, # so long as all the field names are included on the serializer. - for parent_class in [model] + list(model._meta.parents.keys()): + for parent_class in [model] + list(model._meta.parents): for unique_together_list in parent_class._meta.unique_together: if set(field_names).issuperset(set(unique_together_list)): unique_constraint_names |= set(unique_together_list) @@ -1466,7 +1466,7 @@ class ModelSerializer(Serializer): """ model_class_inheritance_tree = ( [self.Meta.model] + - list(self.Meta.model._meta.parents.keys()) + list(self.Meta.model._meta.parents) ) # The field names we're passing though here only include fields @@ -1566,9 +1566,9 @@ class HyperlinkedModelSerializer(ModelSerializer): """ return ( [self.url_field_name] + - list(declared_fields.keys()) + - list(model_info.fields.keys()) + - list(model_info.forward_relations.keys()) + list(declared_fields) + + list(model_info.fields) + + list(model_info.forward_relations) ) def build_nested_field(self, field_name, relation_info, nested_depth): diff --git a/rest_framework/test.py b/rest_framework/test.py index 3b745bd62..c58df34c6 100644 --- a/rest_framework/test.py +++ b/rest_framework/test.py @@ -175,7 +175,7 @@ class APIRequestFactory(DjangoRequestFactory): "Set TEST_REQUEST_RENDERER_CLASSES to enable " "extra request formats.".format( format, - ', '.join(["'" + fmt + "'" for fmt in self.renderer_classes.keys()]) + ', '.join(["'" + fmt + "'" for fmt in self.renderer_classes]) ) ) diff --git a/rest_framework/utils/html.py b/rest_framework/utils/html.py index ca062c9fc..77167e470 100644 --- a/rest_framework/utils/html.py +++ b/rest_framework/utils/html.py @@ -59,7 +59,7 @@ def parse_html_list(dictionary, prefix=''): ret[index][key] = value else: ret[index] = MultiValueDict({key: [value]}) - return [ret[item] for item in sorted(ret.keys())] + return [ret[item] for item in sorted(ret)] def parse_html_dict(dictionary, prefix=''): diff --git a/rest_framework/utils/mediatypes.py b/rest_framework/utils/mediatypes.py index 9fe3da05b..7d9d24f2b 100644 --- a/rest_framework/utils/mediatypes.py +++ b/rest_framework/utils/mediatypes.py @@ -55,7 +55,7 @@ class _MediaType(object): def match(self, other): """Return true if this MediaType satisfies the given MediaType.""" - for key in self.params.keys(): + for key in self.params: if key != 'q' and other.params.get(key, None) != self.params.get(key, None): return False @@ -76,7 +76,7 @@ class _MediaType(object): return 0 elif self.sub_type == '*': return 1 - elif not self.params or list(self.params.keys()) == ['q']: + elif not self.params or list(self.params) == ['q']: return 2 return 3 diff --git a/tests/test_bound_fields.py b/tests/test_bound_fields.py index e90e65edf..4cb75dc2c 100644 --- a/tests/test_bound_fields.py +++ b/tests/test_bound_fields.py @@ -54,7 +54,7 @@ class TestSimpleBoundField: serializer = ExampleSerializer() del serializer.fields['text'] - assert 'text' not in serializer.fields.keys() + assert 'text' not in serializer.fields def test_as_form_fields(self): class ExampleSerializer(serializers.Serializer): diff --git a/tests/test_fields.py b/tests/test_fields.py index bc11cd133..fd12a33f9 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -401,7 +401,7 @@ class TestHTMLInput: serializer = TestSerializer(data=QueryDict('message=')) assert serializer.is_valid() - assert list(serializer.validated_data.keys()) == ['message'] + assert list(serializer.validated_data) == ['message'] def test_empty_html_uuidfield_with_optional(self): class TestSerializer(serializers.Serializer): @@ -409,7 +409,7 @@ class TestHTMLInput: serializer = TestSerializer(data=QueryDict('message=')) assert serializer.is_valid() - assert list(serializer.validated_data.keys()) == [] + assert list(serializer.validated_data) == [] def test_empty_html_charfield_allow_null(self): class TestSerializer(serializers.Serializer): diff --git a/tests/test_metadata.py b/tests/test_metadata.py index b9db36e81..647a30dbd 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -207,7 +207,7 @@ class TestMetadata: view = ExampleView.as_view() response = view(request=request) assert response.status_code == status.HTTP_200_OK - assert list(response.data['actions'].keys()) == ['PUT'] + assert list(response.data['actions']) == ['PUT'] def test_object_permissions(self): """ diff --git a/tests/test_multitable_inheritance.py b/tests/test_multitable_inheritance.py index c406fceda..2ddd37ebb 100644 --- a/tests/test_multitable_inheritance.py +++ b/tests/test_multitable_inheritance.py @@ -44,7 +44,7 @@ class InheritedModelSerializationTests(TestCase): """ child = ChildModel(name1='parent name', name2='child name') serializer = DerivedModelSerializer(child) - assert set(serializer.data.keys()) == {'name1', 'name2', 'id'} + assert set(serializer.data) == {'name1', 'name2', 'id'} def test_onetoone_primary_key_model_fields_as_expected(self): """ @@ -54,7 +54,7 @@ class InheritedModelSerializationTests(TestCase): parent = ParentModel.objects.create(name1='parent name') associate = AssociatedModel.objects.create(name='hello', ref=parent) serializer = AssociatedModelSerializer(associate) - assert set(serializer.data.keys()) == {'name', 'ref'} + assert set(serializer.data) == {'name', 'ref'} def test_data_is_valid_without_parent_ptr(self): """ diff --git a/tests/test_one_to_one_with_inheritance.py b/tests/test_one_to_one_with_inheritance.py index 4bc9cec0b..789c7fcb9 100644 --- a/tests/test_one_to_one_with_inheritance.py +++ b/tests/test_one_to_one_with_inheritance.py @@ -39,5 +39,5 @@ class InheritedModelSerializationTests(TestCase): """ child = ChildModel(name1='parent name', name2='child name') serializer = DerivedModelSerializer(child) - self.assertEqual(set(serializer.data.keys()), + self.assertEqual(set(serializer.data), {'name1', 'name2', 'id', 'childassociatedmodel'}) diff --git a/tests/test_permissions.py b/tests/test_permissions.py index 5d7cb20ea..80b666180 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -151,7 +151,7 @@ class ModelPermissionsIntegrationTests(TestCase): response = root_view(request, pk='1') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIn('actions', response.data) - self.assertEqual(list(response.data['actions'].keys()), ['POST']) + self.assertEqual(list(response.data['actions']), ['POST']) request = factory.options( '/1', @@ -160,7 +160,7 @@ class ModelPermissionsIntegrationTests(TestCase): response = instance_view(request, pk='1') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIn('actions', response.data) - self.assertEqual(list(response.data['actions'].keys()), ['PUT']) + self.assertEqual(list(response.data['actions']), ['PUT']) def test_options_disallowed(self): request = factory.options( @@ -195,7 +195,7 @@ class ModelPermissionsIntegrationTests(TestCase): response = instance_view(request, pk='1') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIn('actions', response.data) - self.assertEqual(list(response.data['actions'].keys()), ['PUT']) + self.assertEqual(list(response.data['actions']), ['PUT']) def test_empty_view_does_not_assert(self): request = factory.get('/1', HTTP_AUTHORIZATION=self.permitted_credentials) diff --git a/tests/test_request.py b/tests/test_request.py index 76589a440..8c680baa0 100644 --- a/tests/test_request.py +++ b/tests/test_request.py @@ -103,8 +103,8 @@ class TestContentParsing(TestCase): upload = SimpleUploadedFile("file.txt", b"file_content") request = Request(factory.post('/', {'upload': upload})) request.parsers = (FormParser(), MultiPartParser()) - assert list(request.POST.keys()) == [] - assert list(request.FILES.keys()) == ['upload'] + assert list(request.POST) == [] + assert list(request.FILES) == ['upload'] def test_standard_behaviour_determines_form_content_PUT(self): """ diff --git a/tests/test_serializer_lists.py b/tests/test_serializer_lists.py index a7955d83c..34c3d100b 100644 --- a/tests/test_serializer_lists.py +++ b/tests/test_serializer_lists.py @@ -15,7 +15,7 @@ class BasicObject: def __eq__(self, other): if self._data.keys() != other._data.keys(): return False - for key in self._data.keys(): + for key in self._data: if self._data[key] != other._data[key]: return False return True