From c10f2266222c434485889b08cc1463acdb8fa169 Mon Sep 17 00:00:00 2001 From: Ahzam Ahmed Date: Wed, 5 Oct 2022 15:02:00 +0500 Subject: [PATCH] Refactor: Replace try/except with contextlib.suppress() (#8676) --- rest_framework/fields.py | 20 +++++++------------- rest_framework/pagination.py | 17 +++++------------ rest_framework/parsers.py | 13 +++++-------- rest_framework/relations.py | 6 ++---- rest_framework/renderers.py | 12 ++++-------- rest_framework/serializers.py | 6 +++--- rest_framework/utils/encoders.py | 6 +++--- rest_framework/utils/serializer_helpers.py | 5 ++--- 8 files changed, 31 insertions(+), 54 deletions(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index a6924bf23..7f4c83b5d 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1,3 +1,4 @@ +import contextlib import copy import datetime import decimal @@ -690,15 +691,13 @@ class BooleanField(Field): NULL_VALUES = {'null', 'Null', 'NULL', '', None} def to_internal_value(self, data): - try: + with contextlib.suppress(TypeError): if data in self.TRUE_VALUES: return True elif data in self.FALSE_VALUES: return False elif data in self.NULL_VALUES and self.allow_null: return None - except TypeError: # Input is an unhashable type - pass self.fail('invalid', input=data) def to_representation(self, value): @@ -1158,19 +1157,14 @@ class DateTimeField(Field): return self.enforce_timezone(value) for input_format in input_formats: - if input_format.lower() == ISO_8601: - try: + with contextlib.suppress(ValueError, TypeError): + if input_format.lower() == ISO_8601: parsed = parse_datetime(value) if parsed is not None: return self.enforce_timezone(parsed) - except (ValueError, TypeError): - pass - else: - try: - parsed = self.datetime_parser(value, input_format) - return self.enforce_timezone(parsed) - except (ValueError, TypeError): - pass + + parsed = self.datetime_parser(value, input_format) + return self.enforce_timezone(parsed) humanized_format = humanize_datetime.datetime_formats(input_formats) self.fail('invalid', format=humanized_format) diff --git a/rest_framework/pagination.py b/rest_framework/pagination.py index e815d8d5c..186e61d9b 100644 --- a/rest_framework/pagination.py +++ b/rest_framework/pagination.py @@ -2,6 +2,8 @@ Pagination serializers determine the structure of the output that should be used for paginated responses. """ + +import contextlib from base64 import b64decode, b64encode from collections import OrderedDict, namedtuple from urllib import parse @@ -257,15 +259,12 @@ class PageNumberPagination(BasePagination): def get_page_size(self, request): if self.page_size_query_param: - try: + with contextlib.suppress(KeyError, ValueError): return _positive_int( request.query_params[self.page_size_query_param], strict=True, cutoff=self.max_page_size ) - except (KeyError, ValueError): - pass - return self.page_size def get_next_link(self): @@ -430,15 +429,12 @@ class LimitOffsetPagination(BasePagination): def get_limit(self, request): if self.limit_query_param: - try: + with contextlib.suppress(KeyError, ValueError): return _positive_int( request.query_params[self.limit_query_param], strict=True, cutoff=self.max_limit ) - except (KeyError, ValueError): - pass - return self.default_limit def get_offset(self, request): @@ -680,15 +676,12 @@ class CursorPagination(BasePagination): def get_page_size(self, request): if self.page_size_query_param: - try: + with contextlib.suppress(KeyError, ValueError): return _positive_int( request.query_params[self.page_size_query_param], strict=True, cutoff=self.max_page_size ) - except (KeyError, ValueError): - pass - return self.page_size def get_next_link(self): diff --git a/rest_framework/parsers.py b/rest_framework/parsers.py index 4ee8e578b..f0fd2b884 100644 --- a/rest_framework/parsers.py +++ b/rest_framework/parsers.py @@ -4,7 +4,9 @@ Parsers are used to parse the content of incoming HTTP requests. They give us a generic way of being able to handle various media types on the request, such as form content or json encoded data. """ + import codecs +import contextlib from django.conf import settings from django.core.files.uploadhandler import StopFutureHandlers @@ -193,17 +195,12 @@ class FileUploadParser(BaseParser): Detects the uploaded file name. First searches a 'filename' url kwarg. Then tries to parse Content-Disposition header. """ - try: + with contextlib.suppress(KeyError): return parser_context['kwargs']['filename'] - except KeyError: - pass - try: + with contextlib.suppress(AttributeError, KeyError, ValueError): meta = parser_context['request'].META disposition, params = parse_header_parameters(meta['HTTP_CONTENT_DISPOSITION']) if 'filename*' in params: return params['filename*'] - else: - return params['filename'] - except (AttributeError, KeyError, ValueError): - pass + return params['filename'] diff --git a/rest_framework/relations.py b/rest_framework/relations.py index bdedd43b8..62da685fb 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -1,3 +1,4 @@ +import contextlib import sys from collections import OrderedDict from urllib import parse @@ -170,7 +171,7 @@ class RelatedField(Field): def get_attribute(self, instance): if self.use_pk_only_optimization() and self.source_attrs: # Optimized case, return a mock object only containing the pk attribute. - try: + with contextlib.suppress(AttributeError): attribute_instance = get_attribute(instance, self.source_attrs[:-1]) value = attribute_instance.serializable_value(self.source_attrs[-1]) if is_simple_callable(value): @@ -183,9 +184,6 @@ class RelatedField(Field): value = getattr(value, 'pk', value) return PKOnlyObject(pk=value) - except AttributeError: - pass - # Standard case, return the object instance. return super().get_attribute(instance) diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index b74df9a0b..3f47580f1 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -6,7 +6,9 @@ on the response, such as JSON encoded data or HTML output. REST framework also provides an HTML renderer that renders the browsable API. """ + import base64 +import contextlib from collections import OrderedDict from urllib import parse @@ -72,11 +74,8 @@ class JSONRenderer(BaseRenderer): # then pretty print the result. # Note that we coerce `indent=0` into `indent=None`. base_media_type, params = parse_header_parameters(accepted_media_type) - try: + with contextlib.suppress(KeyError, ValueError, TypeError): return zero_as_none(max(min(int(params['indent']), 8), 0)) - except (KeyError, ValueError, TypeError): - pass - # If 'indent' is provided in the context, then pretty print the result. # E.g. If we're being called by the BrowsableAPIRenderer. return renderer_context.get('indent', None) @@ -488,11 +487,8 @@ class BrowsableAPIRenderer(BaseRenderer): return if existing_serializer is not None: - try: + with contextlib.suppress(TypeError): return self.render_form_for_serializer(existing_serializer) - except TypeError: - pass - if has_serializer: if method in ('PUT', 'PATCH'): serializer = view.get_serializer(instance=instance, **kwargs) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 083910174..7037c07cd 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -10,6 +10,8 @@ python primitives. 2. The process of marshalling between python primitives and request and response content is handled by parsers and renderers. """ + +import contextlib import copy import inspect import traceback @@ -1496,12 +1498,10 @@ class ModelSerializer(Serializer): # they can't be nested attribute lookups. continue - try: + with contextlib.suppress(FieldDoesNotExist): field = model._meta.get_field(source) if isinstance(field, DjangoModelField): model_fields[source] = field - except FieldDoesNotExist: - pass return model_fields diff --git a/rest_framework/utils/encoders.py b/rest_framework/utils/encoders.py index 27293b725..35a89eb09 100644 --- a/rest_framework/utils/encoders.py +++ b/rest_framework/utils/encoders.py @@ -1,6 +1,8 @@ """ Helper classes for parsers. """ + +import contextlib import datetime import decimal import json # noqa @@ -58,10 +60,8 @@ class JSONEncoder(json.JSONEncoder): ) elif hasattr(obj, '__getitem__'): cls = (list if isinstance(obj, (list, tuple)) else dict) - try: + with contextlib.suppress(Exception): return cls(obj) - except Exception: - pass elif hasattr(obj, '__iter__'): return tuple(item for item in obj) return super().default(obj) diff --git a/rest_framework/utils/serializer_helpers.py b/rest_framework/utils/serializer_helpers.py index 54068f5fb..6ca794584 100644 --- a/rest_framework/utils/serializer_helpers.py +++ b/rest_framework/utils/serializer_helpers.py @@ -1,3 +1,4 @@ +import contextlib import sys from collections import OrderedDict from collections.abc import Mapping, MutableMapping @@ -103,15 +104,13 @@ class JSONBoundField(BoundField): # When HTML form input is used and the input is not valid # value will be a JSONString, rather than a JSON primitive. if not getattr(value, 'is_json_string', False): - try: + with contextlib.suppress(TypeError, ValueError): value = json.dumps( self.value, sort_keys=True, indent=4, separators=(',', ': '), ) - except (TypeError, ValueError): - pass return self.__class__(self._field, value, self.errors, self._prefix)