This commit is contained in:
Andrew Williamson 2024-09-05 12:07:00 +01:00 коммит произвёл GitHub
Родитель dc4170d11f
Коммит dd200ad058
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
42 изменённых файлов: 216 добавлений и 191 удалений

Просмотреть файл

@ -35,9 +35,7 @@ exclude = [
line-length = 88 line-length = 88
[tool.ruff.lint] [tool.ruff.lint]
ignore = [ ignore = []
"B904", # Within an `except` clause, raise exceptions with `raise ... from err|None`
]
select = [ select = [
"B", # flake8-bugbear "B", # flake8-bugbear
"E", # pycodestyle errors "E", # pycodestyle errors

Просмотреть файл

@ -239,14 +239,14 @@ class AddonAbuseReportSerializer(BaseAbuseReportSerializer):
try: try:
is_value_unknown = value not in reversed_choices is_value_unknown = value not in reversed_choices
except TypeError: except TypeError as exc:
# Log the invalid type and raise a validation error. # Log the invalid type and raise a validation error.
log.warning( log.warning(
'Invalid type for abuse report %s value submitted: %s', 'Invalid type for abuse report %s value submitted: %s',
field_name, field_name,
str(data[field_name])[:255], str(data[field_name])[:255],
) )
raise serializers.ValidationError({field_name: _('Invalid value')}) raise serializers.ValidationError({field_name: _('Invalid value')}) from exc
if is_value_unknown: if is_value_unknown:
log.warning( log.warning(

Просмотреть файл

@ -225,9 +225,9 @@ def cinder_webhook(request):
try: try:
cinder_job = CinderJob.objects.get(job_id=job_id) cinder_job = CinderJob.objects.get(job_id=job_id)
except CinderJob.DoesNotExist: except CinderJob.DoesNotExist as exc:
log.debug('CinderJob instance not found for job id %s', job_id) log.debug('CinderJob instance not found for job id %s', job_id)
raise ValidationError('No matching job id found') raise ValidationError('No matching job id found') from exc
if cinder_job.resolvable_in_reviewer_tools: if cinder_job.resolvable_in_reviewer_tools:
log.debug('Cinder webhook decision for reviewer resolvable job skipped.') log.debug('Cinder webhook decision for reviewer resolvable job skipped.')

Просмотреть файл

@ -141,12 +141,12 @@ def add_email_to_activity_log(parser):
uuid = parser.get_uuid() uuid = parser.get_uuid()
try: try:
token = ActivityLogToken.objects.get(uuid=uuid) token = ActivityLogToken.objects.get(uuid=uuid)
except (ActivityLogToken.DoesNotExist, ValidationError): except (ActivityLogToken.DoesNotExist, ValidationError) as exc:
log.warning('An email was skipped with non-existing uuid %s.', uuid) log.warning('An email was skipped with non-existing uuid %s.', uuid)
raise ActivityEmailUUIDError( raise ActivityEmailUUIDError(
'UUID found in email address TO: header but is not a valid token ' 'UUID found in email address TO: header but is not a valid token '
'(%s).' % uuid '(%s).' % uuid
) ) from exc
version = token.version version = token.version
user = token.user user = token.user

Просмотреть файл

@ -465,8 +465,8 @@ class AddonAdmin(AMOModelAdmin):
try: try:
if lookup_field in ('slug', 'guid'): if lookup_field in ('slug', 'guid'):
addon = self.get_queryset(request).get(**{lookup_field: object_id}) addon = self.get_queryset(request).get(**{lookup_field: object_id})
except Addon.DoesNotExist: except Addon.DoesNotExist as exc:
raise http.Http404 raise http.Http404 from exc
# Don't get in an infinite loop if addon.slug.isdigit(). # Don't get in an infinite loop if addon.slug.isdigit().
if addon and addon.id and addon.id != object_id: if addon and addon.id and addon.id != object_id:
url = request.path.replace(object_id, str(addon.id), 1) url = request.path.replace(object_id, str(addon.id), 1)
@ -596,8 +596,8 @@ class ReplacementAddonForm(AMOModelForm):
except forms.ValidationError as validation_error: except forms.ValidationError as validation_error:
# Re-raise the ValidationError about full paths for SITE_URL. # Re-raise the ValidationError about full paths for SITE_URL.
raise validation_error raise validation_error
except Exception: except Exception as exc:
raise forms.ValidationError('Path [%s] is not valid' % path) raise forms.ValidationError('Path [%s] is not valid' % path) from exc
return path return path

Просмотреть файл

@ -23,8 +23,8 @@ def addon_view(f, qs=Addon.objects.all, include_deleted_when_checking_versions=F
addon = qs().get(id=addon_id) addon = qs().get(id=addon_id)
elif lookup_field == 'guid': elif lookup_field == 'guid':
addon = qs().get(guid=addon_id) addon = qs().get(guid=addon_id)
except Addon.DoesNotExist: except Addon.DoesNotExist as exc:
raise http.Http404 raise http.Http404 from exc
# Don't get in an infinite loop if addon.slug.isdigit(). # Don't get in an infinite loop if addon.slug.isdigit().
if addon.slug and addon.slug != addon_id: if addon.slug and addon.slug != addon_id:
url = request.path.replace(addon_id, addon.slug, 1) url = request.path.replace(addon_id, addon.slug, 1)

Просмотреть файл

@ -230,8 +230,10 @@ class SourceFileField(serializers.FileField):
mode = 'r:bz2' if ext == '.bz2' else 'r:gz' mode = 'r:bz2' if ext == '.bz2' else 'r:gz'
with SafeTar.open(mode=mode, fileobj=data): with SafeTar.open(mode=mode, fileobj=data):
pass pass
except (zipfile.BadZipFile, tarfile.ReadError, OSError, EOFError): except (zipfile.BadZipFile, tarfile.ReadError, OSError, EOFError) as exc:
raise exceptions.ValidationError(gettext('Invalid or broken archive.')) raise exceptions.ValidationError(
gettext('Invalid or broken archive.')
) from exc
return data return data
@ -262,8 +264,10 @@ class VersionCompatibilityField(serializers.Field):
for app_name, min_max in data.items(): for app_name, min_max in data.items():
try: try:
app = amo.APPS[app_name] app = amo.APPS[app_name]
except KeyError: except KeyError as exc:
raise exceptions.ValidationError(gettext('Invalid app specified')) raise exceptions.ValidationError(
gettext('Invalid app specified')
) from exc
existing_app = existing.get(app) existing_app = existing.get(app)
# we need to copy() to avoid changing the instance before save # we need to copy() to avoid changing the instance before save
@ -278,10 +282,10 @@ class VersionCompatibilityField(serializers.Field):
elif version: elif version:
apps_versions.max = apps_versions.get_default_maximum_appversion() apps_versions.max = apps_versions.get_default_maximum_appversion()
except AppVersion.DoesNotExist: except AppVersion.DoesNotExist as exc:
raise exceptions.ValidationError( raise exceptions.ValidationError(
gettext('Unknown max app version specified') gettext('Unknown max app version specified')
) ) from exc
try: try:
app_version_qs = app_version_qs.filter(~Q(version__contains='*')) app_version_qs = app_version_qs.filter(~Q(version__contains='*'))
@ -290,10 +294,10 @@ class VersionCompatibilityField(serializers.Field):
apps_versions.min_or_max_explicitly_set = True apps_versions.min_or_max_explicitly_set = True
elif version: elif version:
apps_versions.min = apps_versions.get_default_minimum_appversion() apps_versions.min = apps_versions.get_default_minimum_appversion()
except AppVersion.DoesNotExist: except AppVersion.DoesNotExist as exc:
raise exceptions.ValidationError( raise exceptions.ValidationError(
gettext('Unknown min app version specified') gettext('Unknown min app version specified')
) ) from exc
if existing_app and existing_app.locked_from_manifest: if existing_app and existing_app.locked_from_manifest:
if ( if (

Просмотреть файл

@ -500,7 +500,7 @@ class DeveloperVersionSerializer(VersionSerializer):
try: try:
self.parsed_data = parse_addon(value, addon=self.addon, user=request.user) self.parsed_data = parse_addon(value, addon=self.addon, user=request.user)
except DuplicateAddonID as exc: except DuplicateAddonID as exc:
raise Conflict({self.field_name: exc.messages}) raise Conflict({self.field_name: exc.messages}) from exc
return value return value
def validate_is_disabled(self, disable): def validate_is_disabled(self, disable):
@ -562,13 +562,13 @@ class DeveloperVersionSerializer(VersionSerializer):
try: try:
ReviewedSourceFileValidator()(data['source'], self.fields['source']) ReviewedSourceFileValidator()(data['source'], self.fields['source'])
except exceptions.ValidationError as exc: except exceptions.ValidationError as exc:
raise exceptions.ValidationError({'source': exc.detail}) raise exceptions.ValidationError({'source': exc.detail}) from exc
if 'compatible_apps' in data: if 'compatible_apps' in data:
try: try:
self._post_validate_compatibility(data['compatible_apps']) self._post_validate_compatibility(data['compatible_apps'])
except exceptions.ValidationError as exc: except exceptions.ValidationError as exc:
raise exceptions.ValidationError({'compatibility': exc.detail}) raise exceptions.ValidationError({'compatibility': exc.detail}) from exc
return data return data
@ -793,7 +793,7 @@ class CurrentVersionSerializer(SimpleVersionSerializer):
application = value[0] application = value[0]
appversions = dict(zip(('min', 'max'), value[1:], strict=True)) appversions = dict(zip(('min', 'max'), value[1:], strict=True))
except ValueError as exc: except ValueError as exc:
raise exceptions.ParseError(str(exc)) raise exceptions.ParseError(str(exc)) from exc
version_qs = Version.objects.latest_public_compatible_with( version_qs = Version.objects.latest_public_compatible_with(
application, appversions application, appversions
@ -928,8 +928,8 @@ class AddonPendingAuthorSerializer(AddonAuthorSerializer):
def validate_user_id(self, value): def validate_user_id(self, value):
try: try:
user = UserProfile.objects.get(id=value) user = UserProfile.objects.get(id=value)
except UserProfile.DoesNotExist: except UserProfile.DoesNotExist as exc:
raise exceptions.ValidationError(gettext('Account not found.')) raise exceptions.ValidationError(gettext('Account not found.')) from exc
if not EmailUserRestriction.allow_email( if not EmailUserRestriction.allow_email(
user.email, restriction_type=RESTRICTION_TYPES.ADDON_SUBMISSION user.email, restriction_type=RESTRICTION_TYPES.ADDON_SUBMISSION
@ -950,13 +950,13 @@ class AddonPendingAuthorSerializer(AddonAuthorSerializer):
raise DjangoValidationError('') # raise so we can catch below. raise DjangoValidationError('') # raise so we can catch below.
for validator in user._meta.get_field('display_name').validators: for validator in user._meta.get_field('display_name').validators:
validator(user.display_name) validator(user.display_name)
except DjangoValidationError: except DjangoValidationError as exc:
raise exceptions.ValidationError( raise exceptions.ValidationError(
gettext( gettext(
'The account needs a display name before it can be added as an ' 'The account needs a display name before it can be added as an '
'author.' 'author.'
) )
) ) from exc
return value return value

Просмотреть файл

@ -20,7 +20,7 @@ class VerifyMozillaTrademark:
try: try:
verify_mozilla_trademark(value, user) verify_mozilla_trademark(value, user)
except forms.ValidationError as exc: except forms.ValidationError as exc:
raise exceptions.ValidationError(exc.message) raise exceptions.ValidationError(exc.message) from exc
class VersionLicenseValidator: class VersionLicenseValidator:
@ -159,7 +159,7 @@ class VersionAddonMetadataValidator(AddonMetadataValidator):
'version: {missing_addon_metadata}.' 'version: {missing_addon_metadata}.'
).format(missing_addon_metadata=list(exc.detail)), ).format(missing_addon_metadata=list(exc.detail)),
code='required', code='required',
) ) from exc
class AddonDefaultLocaleValidator: class AddonDefaultLocaleValidator:

Просмотреть файл

@ -865,8 +865,8 @@ class AddonPendingAuthorViewSet(CreateModelMixin, AddonAuthorViewSet):
def get_object_for_request(self, request): def get_object_for_request(self, request):
try: try:
return self.get_queryset().get(user=request.user) return self.get_queryset().get(user=request.user)
except AddonUserPendingConfirmation.DoesNotExist: except AddonUserPendingConfirmation.DoesNotExist as exc:
raise exceptions.PermissionDenied() raise exceptions.PermissionDenied() from exc
def perform_create(self, serializer): def perform_create(self, serializer):
instance = serializer.save() instance = serializer.save()
@ -995,8 +995,8 @@ class AddonFeaturedView(AddonSearchView):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
try: try:
page_size = int(self.request.GET.get('page_size', api_settings.PAGE_SIZE)) page_size = int(self.request.GET.get('page_size', api_settings.PAGE_SIZE))
except ValueError: except ValueError as exc:
raise exceptions.ParseError('Invalid page_size parameter') raise exceptions.ParseError('Invalid page_size parameter') from exc
# Simulate pagination-like results, without actual pagination. # Simulate pagination-like results, without actual pagination.
queryset = self.filter_queryset(self.get_queryset()[:page_size]) queryset = self.filter_queryset(self.get_queryset()[:page_size])
@ -1061,16 +1061,16 @@ class LanguageToolsView(ListAPIView):
# app parameter is mandatory with appversion # app parameter is mandatory with appversion
try: try:
application = AddonAppQueryParam(self.request.GET).get_value() application = AddonAppQueryParam(self.request.GET).get_value()
except ValueError: except ValueError as exc:
raise exceptions.ParseError( raise exceptions.ParseError(
'Invalid or missing app parameter while appversion parameter is ' 'Invalid or missing app parameter while appversion parameter is '
'set.' 'set.'
) ) from exc
try: try:
value = AddonAppVersionQueryParam(self.request.GET).get_values() value = AddonAppVersionQueryParam(self.request.GET).get_values()
appversions = {'min': value[1], 'max': value[2]} appversions = {'min': value[1], 'max': value[2]}
except ValueError: except ValueError as exc:
raise exceptions.ParseError('Invalid appversion parameter.') raise exceptions.ParseError('Invalid appversion parameter.') from exc
else: else:
appversions = None appversions = None
application = None application = None
@ -1082,11 +1082,11 @@ class LanguageToolsView(ListAPIView):
if AddonTypeQueryParam.query_param in self.request.GET or appversions: if AddonTypeQueryParam.query_param in self.request.GET or appversions:
try: try:
addon_types = tuple(AddonTypeQueryParam(self.request.GET).get_values()) addon_types = tuple(AddonTypeQueryParam(self.request.GET).get_values())
except ValueError: except ValueError as exc:
raise exceptions.ParseError( raise exceptions.ParseError(
'Invalid or missing type parameter while appversion ' 'Invalid or missing type parameter while appversion '
'parameter is set.' 'parameter is set.'
) ) from exc
else: else:
addon_types = (amo.ADDON_LPAPP, amo.ADDON_DICT) addon_types = (amo.ADDON_LPAPP, amo.ADDON_DICT)

Просмотреть файл

@ -118,8 +118,8 @@ class AMOModelAdminChangeList(ChangeList):
else: else:
try: try:
result_list = paginator.page(self.page_num).object_list result_list = paginator.page(self.page_num).object_list
except InvalidPage: except InvalidPage as exc:
raise IncorrectLookupParameters raise IncorrectLookupParameters from exc
self.result_count = result_count self.result_count = result_count
self.show_full_result_count = self.model_admin.show_full_result_count self.show_full_result_count = self.model_admin.show_full_result_count

Просмотреть файл

@ -56,7 +56,7 @@ class IPAddressBinaryField(VarBinaryField):
# bytestring - i.e. what's stored in the db; or an IPv4Address|IPv6Address. # bytestring - i.e. what's stored in the db; or an IPv4Address|IPv6Address.
return ipaddress.ip_address(value) if value is not None else None return ipaddress.ip_address(value) if value is not None else None
except Exception as exc: except Exception as exc:
raise exceptions.ValidationError(exc) raise exceptions.ValidationError(exc) from exc
def get_prep_value(self, value): def get_prep_value(self, value):
return self.to_python(value).packed if value is not None else None return self.to_python(value).packed if value is not None else None
@ -85,10 +85,10 @@ class ReCaptchaField(UpstreamReCaptchaField):
def validate_cidr(value): def validate_cidr(value):
try: try:
ipaddress.ip_network(value) ipaddress.ip_network(value)
except ValueError: except ValueError as exc:
raise exceptions.ValidationError( raise exceptions.ValidationError(
_('Enter a valid IP4 or IP6 network.'), code='invalid' _('Enter a valid IP4 or IP6 network.'), code='invalid'
) ) from exc
class CIDRField(models.Field): class CIDRField(models.Field):
@ -122,7 +122,7 @@ class CIDRField(models.Field):
try: try:
return ipaddress.ip_network(value) return ipaddress.ip_network(value)
except Exception as exc: except Exception as exc:
raise exceptions.ValidationError(exc) raise exceptions.ValidationError(exc) from exc
def get_prep_lookup(self, lookup_type, value): def get_prep_lookup(self, lookup_type, value):
if lookup_type == 'exact': if lookup_type == 'exact':

Просмотреть файл

@ -20,8 +20,8 @@ class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
try: try:
do_addnewversion(options['application_name'], options['version']) do_addnewversion(options['application_name'], options['version'])
except IndexError: except IndexError as exc:
raise CommandError(self.help) raise CommandError(self.help) from exc
msg = 'Adding version {!r} to application {!r}\n'.format( msg = 'Adding version {!r} to application {!r}\n'.format(
options['version'], options['version'],
@ -36,5 +36,5 @@ def do_addnewversion(application, version):
raise CommandError('Application %r does not exist.' % application) raise CommandError('Application %r does not exist.' % application)
try: try:
AppVersion.objects.create(application=amo.APPS[application].id, version=version) AppVersion.objects.create(application=amo.APPS[application].id, version=version)
except IntegrityError as e: except IntegrityError as exc:
raise CommandError(f'Version {version!r} already exists: {e!r}') raise CommandError(f'Version {version!r} already exists: {exc!r}') from exc

Просмотреть файл

@ -330,10 +330,10 @@ class SetRemoteAddrFromForwardedFor(MiddlewareMixin):
if not value: if not value:
raise IndexError raise IndexError
request.META['REMOTE_ADDR'] = value request.META['REMOTE_ADDR'] = value
except IndexError: except IndexError as exc:
# Shouldn't happen, must be a misconfiguration, raise an error # Shouldn't happen, must be a misconfiguration, raise an error
# rather than potentially use/record incorrect IPs. # rather than potentially use/record incorrect IPs.
raise ImproperlyConfigured('Invalid HTTP_X_FORWARDED_FOR') raise ImproperlyConfigured('Invalid HTTP_X_FORWARDED_FOR') from exc
class RequestIdMiddleware(MiddlewareMixin): class RequestIdMiddleware(MiddlewareMixin):

Просмотреть файл

@ -44,8 +44,8 @@ class ESPaginator(Paginator):
""" """
try: try:
number = int(number) number = int(number)
except (TypeError, ValueError): except (TypeError, ValueError) as exc:
raise PageNotAnInteger('That page number is not an integer') raise PageNotAnInteger('That page number is not an integer') from exc
if number < 1: if number < 1:
raise EmptyPage('That page number is less than 1') raise EmptyPage('That page number is less than 1')
return number return number

Просмотреть файл

@ -479,8 +479,8 @@ def get_sitemap_path(section, app, page=1):
raise InvalidSection raise InvalidSection
try: try:
page = int(page) page = int(page)
except ValueError: except ValueError as exc:
raise PageNotAnInteger raise PageNotAnInteger from exc
if app is None: if app is None:
# If we don't have a section or app, we don't need a complex directory # If we don't have a section or app, we don't need a complex directory
# structure and we can call the first page 'sitemap' for convenience # structure and we can call the first page 'sitemap' for convenience

Просмотреть файл

@ -1209,13 +1209,13 @@ def safe_exec(string, value=None, globals_=None, locals_=None):
locals_ = locals_ or {} locals_ = locals_ or {}
try: try:
exec(force_str(string), globals_ or globals(), locals_) exec(force_str(string), globals_ or globals(), locals_)
except Exception as e: except Exception as exc:
if value: if value:
raise AssertionError( raise AssertionError(
f'Could not exec {string.strip()!r} (from value {value!r}): {e}' f'Could not exec {string.strip()!r} (from value {value!r}): {exc}'
) ) from exc
else: else:
raise AssertionError(f'Could not exec {string.strip()!r}: {e}') raise AssertionError(f'Could not exec {string.strip()!r}: {exc}') from exc
return locals_ return locals_

Просмотреть файл

@ -245,11 +245,11 @@ def sitemap(request):
) )
patch_cache_control(response, max_age=60 * 60) patch_cache_control(response, max_age=60 * 60)
except EmptyPage: except EmptyPage as exc:
raise Http404('Page %s empty' % page) raise Http404('Page %s empty' % page) from exc
except PageNotAnInteger: except PageNotAnInteger as exc:
raise Http404('No page "%s"' % page) raise Http404('No page "%s"' % page) from exc
except InvalidSection: except InvalidSection as exc:
raise Http404('No sitemap available for section: %r' % section) raise Http404('No sitemap available for section: %r' % section) from exc
return response return response

Просмотреть файл

@ -113,7 +113,7 @@ class SessionIDAuthentication(BaseAuthentication):
try: try:
check_and_update_fxa_access_token(request) check_and_update_fxa_access_token(request)
except IdentificationError: except IdentificationError as exc:
log.info( log.info(
'User access token refresh failed; user needs to login to FxA again' 'User access token refresh failed; user needs to login to FxA again'
) )
@ -123,7 +123,7 @@ class SessionIDAuthentication(BaseAuthentication):
), ),
'code': 'ERROR_AUTHENTICATION_EXPIRED', 'code': 'ERROR_AUTHENTICATION_EXPIRED',
} }
raise exceptions.AuthenticationFailed(msg) raise exceptions.AuthenticationFailed(msg) from exc
# Set user in thread like UserAndAddrMiddleware does. # Set user in thread like UserAndAddrMiddleware does.
core.set_user(user) core.set_user(user)
@ -183,18 +183,18 @@ class JWTKeyAuthentication(BaseAuthentication):
) )
# Re-raise to deal with them properly. # Re-raise to deal with them properly.
raise exc raise exc
except TypeError: except TypeError as exc:
msg = gettext('Wrong type for one or more keys in payload') msg = gettext('Wrong type for one or more keys in payload')
raise exceptions.AuthenticationFailed(msg) raise exceptions.AuthenticationFailed(msg) from exc
except jwt.ExpiredSignatureError: except jwt.ExpiredSignatureError as exc:
msg = gettext('Signature has expired.') msg = gettext('Signature has expired.')
raise exceptions.AuthenticationFailed(msg) raise exceptions.AuthenticationFailed(msg) from exc
except jwt.DecodeError: except jwt.DecodeError as exc:
msg = gettext('Error decoding signature.') msg = gettext('Error decoding signature.')
raise exceptions.AuthenticationFailed(msg) raise exceptions.AuthenticationFailed(msg) from exc
except jwt.InvalidTokenError: except jwt.InvalidTokenError as exc:
msg = gettext('Invalid JWT Token.') msg = gettext('Invalid JWT Token.')
raise exceptions.AuthenticationFailed(msg) raise exceptions.AuthenticationFailed(msg) from exc
# Note: AuthenticationFailed can also be raised directly from our # Note: AuthenticationFailed can also be raised directly from our
# jwt_decode_handler. # jwt_decode_handler.
@ -220,9 +220,9 @@ class JWTKeyAuthentication(BaseAuthentication):
raise exceptions.AuthenticationFailed(msg) raise exceptions.AuthenticationFailed(msg)
try: try:
api_key = APIKey.get_jwt_key(key=payload['iss']) api_key = APIKey.get_jwt_key(key=payload['iss'])
except APIKey.DoesNotExist: except APIKey.DoesNotExist as exc:
msg = 'Invalid API Key.' msg = 'Invalid API Key.'
raise exceptions.AuthenticationFailed(msg) raise exceptions.AuthenticationFailed(msg) from exc
if api_key.user.deleted: if api_key.user.deleted:
msg = 'User account is disabled.' msg = 'User account is disabled.'
@ -269,8 +269,12 @@ class UnsubscribeTokenAuthentication(BaseAuthentication):
request.data.get('token'), request.data.get('hash') request.data.get('token'), request.data.get('hash')
) )
user = UserProfile.objects.get(email=email) user = UserProfile.objects.get(email=email)
except ValueError: except ValueError as exc:
raise exceptions.AuthenticationFailed(gettext('Invalid token or hash.')) raise exceptions.AuthenticationFailed(
except UserProfile.DoesNotExist: gettext('Invalid token or hash.')
raise exceptions.AuthenticationFailed(gettext('Email address not found.')) ) from exc
except UserProfile.DoesNotExist as exc:
raise exceptions.AuthenticationFailed(
gettext('Email address not found.')
) from exc
return (user, None) return (user, None)

Просмотреть файл

@ -374,11 +374,11 @@ class SlugOrPrimaryKeyRelatedField(serializers.RelatedField):
except Exception: except Exception:
try: try:
return self.queryset.get(**{self.slug_field: data}) return self.queryset.get(**{self.slug_field: data})
except ObjectDoesNotExist: except ObjectDoesNotExist as exc:
msg = _('Invalid pk or slug "%s" - object does not exist.') % smart_str( msg = _('Invalid pk or slug "%s" - object does not exist.') % smart_str(
data data
) )
raise exceptions.ValidationError(msg) raise exceptions.ValidationError(msg) from exc
class OutgoingSerializerMixin: class OutgoingSerializerMixin:

Просмотреть файл

@ -55,9 +55,11 @@ def jwt_decode_handler(token, get_api_key=APIKey.get_jwt_key):
try: try:
api_key = get_api_key(key=token_data['iss']) api_key = get_api_key(key=token_data['iss'])
except ObjectDoesNotExist: except ObjectDoesNotExist as exc:
log.info('No API key for JWT issuer: {}'.format(token_data['iss'])) log.info('No API key for JWT issuer: {}'.format(token_data['iss']))
raise exceptions.AuthenticationFailed(detail='Unknown JWT iss (issuer).') raise exceptions.AuthenticationFailed(
detail='Unknown JWT iss (issuer).'
) from exc
# TODO: add nonce checking to prevent replays. bug 1213354. # TODO: add nonce checking to prevent replays. bug 1213354.
@ -94,7 +96,7 @@ def jwt_decode_handler(token, get_api_key=APIKey.get_jwt_key):
'Missing required claim during JWT authentication: ' 'Missing required claim during JWT authentication: '
'{e.__class__.__name__}: {e}'.format(e=exc) '{e.__class__.__name__}: {e}'.format(e=exc)
) )
raise exceptions.AuthenticationFailed(detail=f'Invalid JWT: {exc}.') raise exceptions.AuthenticationFailed(detail=f'Invalid JWT: {exc}.') from exc
except (jwt.exceptions.ImmatureSignatureError, jwt.InvalidIssuedAtError) as exc: except (jwt.exceptions.ImmatureSignatureError, jwt.InvalidIssuedAtError) as exc:
log.info( log.info(
'Invalid iat during JWT authentication: ' 'Invalid iat during JWT authentication: '
@ -103,7 +105,7 @@ def jwt_decode_handler(token, get_api_key=APIKey.get_jwt_key):
raise exceptions.AuthenticationFailed( raise exceptions.AuthenticationFailed(
detail='JWT iat (issued at time) is invalid. Make sure your ' detail='JWT iat (issued at time) is invalid. Make sure your '
'system clock is synchronized with something like TLSdate.' 'system clock is synchronized with something like TLSdate.'
) ) from exc
except Exception as exc: except Exception as exc:
log.warning( log.warning(
'Unhandled exception during JWT authentication: ' 'Unhandled exception during JWT authentication: '

Просмотреть файл

@ -300,8 +300,8 @@ class ByHttpMethod(BasePermission):
def has_permission(self, request, view): def has_permission(self, request, view):
try: try:
perm = self.method_permissions[request.method.lower()] perm = self.method_permissions[request.method.lower()]
except KeyError: except KeyError as exc:
raise MethodNotAllowed(request.method) raise MethodNotAllowed(request.method) from exc
result = perm.has_permission(request, view) result = perm.has_permission(request, view)
if not result and hasattr(perm, 'message'): if not result and hasattr(perm, 'message'):
self.message = perm.message self.message = perm.message
@ -310,8 +310,8 @@ class ByHttpMethod(BasePermission):
def has_object_permission(self, request, view, obj): def has_object_permission(self, request, view, obj):
try: try:
perm = self.method_permissions[request.method.lower()] perm = self.method_permissions[request.method.lower()]
except KeyError: except KeyError as exc:
raise MethodNotAllowed(request.method) raise MethodNotAllowed(request.method) from exc
result = perm.has_object_permission(request, view, obj) result = perm.has_object_permission(request, view, obj)
if not result and hasattr(perm, 'message'): if not result and hasattr(perm, 'message'):
self.message = perm.message self.message = perm.message

Просмотреть файл

@ -13,8 +13,8 @@ class OneOrMorePrintableCharacterAPIValidator(OneOrMorePrintableCharacterValidat
def __call__(self, value): def __call__(self, value):
try: try:
return super().__call__(value) return super().__call__(value)
except DjangoValidationError: except DjangoValidationError as exc:
raise exceptions.ValidationError(self.message) raise exceptions.ValidationError(self.message) from exc
class NoURLsValidator: class NoURLsValidator:
@ -22,4 +22,4 @@ class NoURLsValidator:
try: try:
verify_no_urls(value) verify_no_urls(value)
except DjangoValidationError as exc: except DjangoValidationError as exc:
raise exceptions.ValidationError(exc.message) raise exceptions.ValidationError(exc.message) from exc

Просмотреть файл

@ -22,8 +22,8 @@ class ActivityFeedRSS(Feed):
try: try:
rsskey = request.GET.get('privaterss') rsskey = request.GET.get('privaterss')
rsskey = uuid.UUID(rsskey) rsskey = uuid.UUID(rsskey)
except ValueError: except ValueError as exc:
raise http.Http404 raise http.Http404 from exc
key = get_object_or_404(RssKey, key=rsskey.hex) key = get_object_or_404(RssKey, key=rsskey.hex)
return key return key

Просмотреть файл

@ -413,13 +413,13 @@ class AuthorWaitingConfirmationForm(AuthorForm):
raise forms.ValidationError('') # Caught below. raise forms.ValidationError('') # Caught below.
for validator in name_validators: for validator in name_validators:
validator(user.display_name) validator(user.display_name)
except forms.ValidationError: except forms.ValidationError as exc:
raise forms.ValidationError( raise forms.ValidationError(
gettext( gettext(
'The account needs a display name before it can be added ' 'The account needs a display name before it can be added '
'as an author.' 'as an author.'
) )
) ) from exc
return user return user
@ -738,8 +738,10 @@ class WithSourceMixin:
raise forms.ValidationError( raise forms.ValidationError(
self.get_invalid_source_file_type_message() self.get_invalid_source_file_type_message()
) )
except (zipfile.BadZipFile, tarfile.ReadError, OSError, EOFError): except (zipfile.BadZipFile, tarfile.ReadError, OSError, EOFError) as exc:
raise forms.ValidationError(gettext('Invalid or broken archive.')) raise forms.ValidationError(
gettext('Invalid or broken archive.')
) from exc
return source return source

Просмотреть файл

@ -101,8 +101,8 @@ MDN_BASE = 'https://developer.mozilla.org/en-US/Add-ons'
def get_fileupload_by_uuid_or_40x(value, *, user): def get_fileupload_by_uuid_or_40x(value, *, user):
try: try:
UUID(value) UUID(value)
except ValueError: except ValueError as exc:
raise http.Http404() raise http.Http404() from exc
upload = get_object_or_404(FileUpload, uuid=value) upload = get_object_or_404(FileUpload, uuid=value)
if upload.user != user: if upload.user != user:
raise PermissionDenied raise PermissionDenied
@ -731,8 +731,8 @@ def json_file_validation(request, addon_id, addon, file_id):
file = get_object_or_404(File, version__addon=addon, id=file_id) file = get_object_or_404(File, version__addon=addon, id=file_id)
try: try:
result = file.validation result = file.validation
except File.validation.RelatedObjectDoesNotExist: except File.validation.RelatedObjectDoesNotExist as exc:
raise http.Http404 raise http.Http404 from exc
return JsonResponse( return JsonResponse(
{ {
'validation': result.processed_validation, 'validation': result.processed_validation,

Просмотреть файл

@ -181,8 +181,10 @@ class ManifestJSONExtractor:
self.data = json.loads(json_string) self.data = json.loads(json_string)
if not isinstance(self.data, dict): if not isinstance(self.data, dict):
raise TypeError() raise TypeError()
except Exception: except Exception as exc:
raise InvalidManifest(gettext('Could not parse the manifest file.')) raise InvalidManifest(
gettext('Could not parse the manifest file.')
) from exc
def get(self, key, default=None): def get(self, key, default=None):
return self.data.get(key, default) return self.data.get(key, default)
@ -343,17 +345,17 @@ class ManifestJSONExtractor:
qs = AppVersion.objects.filter(application=app.id) qs = AppVersion.objects.filter(application=app.id)
try: try:
min_appver = qs.get(version=strict_min_version) min_appver = qs.get(version=strict_min_version)
except AppVersion.DoesNotExist: except AppVersion.DoesNotExist as exc:
msg = gettext( msg = gettext(
'Unknown "strict_min_version" {appver} for {app}'.format( 'Unknown "strict_min_version" {appver} for {app}'.format(
app=app.pretty, appver=strict_min_version app=app.pretty, appver=strict_min_version
) )
) )
raise forms.ValidationError(msg) raise forms.ValidationError(msg) from exc
try: try:
max_appver = qs.get(version=strict_max_version) max_appver = qs.get(version=strict_max_version)
except AppVersion.DoesNotExist: except AppVersion.DoesNotExist as exc:
# If the specified strict_max_version can't be found, raise an # If the specified strict_max_version can't be found, raise an
# error: we used to use '*' instead but this caused more # error: we used to use '*' instead but this caused more
# problems, especially with langpacks that are really specific # problems, especially with langpacks that are really specific
@ -363,7 +365,7 @@ class ManifestJSONExtractor:
app=app.pretty, appver=strict_max_version app=app.pretty, appver=strict_max_version
) )
) )
raise forms.ValidationError(msg) raise forms.ValidationError(msg) from exc
if app == amo.ANDROID and self.gecko_android is not EMPTY_FALLBACK_DICT: if app == amo.ANDROID and self.gecko_android is not EMPTY_FALLBACK_DICT:
originated_from = amo.APPVERSIONS_ORIGINATED_FROM_MANIFEST_GECKO_ANDROID originated_from = amo.APPVERSIONS_ORIGINATED_FROM_MANIFEST_GECKO_ANDROID
@ -389,11 +391,13 @@ class ManifestJSONExtractor:
dictionaries = self.get('dictionaries', EMPTY_FALLBACK_DICT) dictionaries = self.get('dictionaries', EMPTY_FALLBACK_DICT)
key = force_str(list(dictionaries.keys())[0]) key = force_str(list(dictionaries.keys())[0])
return key[:255] return key[:255]
except (IndexError, UnicodeDecodeError): except (IndexError, UnicodeDecodeError) as exc:
# This shouldn't happen: the linter should prevent it, but # This shouldn't happen: the linter should prevent it, but
# just in case, handle the error (without bothering with # just in case, handle the error (without bothering with
# translations as users should never see this). # translations as users should never see this).
raise forms.ValidationError('Invalid dictionaries object or langpack_id.') raise forms.ValidationError(
'Invalid dictionaries object or langpack_id.'
) from exc
def parse(self, minimal=False): def parse(self, minimal=False):
data = { data = {
@ -542,7 +546,7 @@ def archive_member_validator(member, ignore_filename_errors=False):
try: try:
force_str(filename) force_str(filename)
except UnicodeDecodeError: except UnicodeDecodeError as exc:
# We can't log the filename unfortunately since it's encoding # We can't log the filename unfortunately since it's encoding
# is obviously broken :-/ # is obviously broken :-/
log.warning('Extraction error, invalid file name encoding') log.warning('Extraction error, invalid file name encoding')
@ -550,7 +554,7 @@ def archive_member_validator(member, ignore_filename_errors=False):
'Invalid file name in archive. Please make sure ' 'Invalid file name in archive. Please make sure '
'all filenames are utf-8 or latin1 encoded.' 'all filenames are utf-8 or latin1 encoded.'
) )
raise InvalidArchiveFile(msg) raise InvalidArchiveFile(msg) from exc
if not ignore_filename_errors: if not ignore_filename_errors:
if ( if (
@ -733,17 +737,22 @@ def extract_extension_to_dest(source, dest=None, force_fsync=False):
archive.extractall(target) archive.extractall(target)
else: else:
raise FileNotFoundError # Unsupported file, shouldn't be reached raise FileNotFoundError # Unsupported file, shouldn't be reached
except (zipfile.BadZipFile, tarfile.ReadError, OSError, forms.ValidationError) as e: except (
zipfile.BadZipFile,
tarfile.ReadError,
OSError,
forms.ValidationError,
) as exc:
if tempdir is not None: if tempdir is not None:
rm_local_tmp_dir(tempdir) rm_local_tmp_dir(tempdir)
if isinstance(e, (FileNotFoundError, forms.ValidationError)): if isinstance(exc, (FileNotFoundError, forms.ValidationError)):
# We let FileNotFoundError (which are a subclass of IOError, or # We let FileNotFoundError (which are a subclass of IOError, or
# rather OSError but that's an alias) and ValidationError be # rather OSError but that's an alias) and ValidationError be
# raised, the caller will have to deal with it. # raised, the caller will have to deal with it.
raise raise
# Any other exceptions we caught, we raise a generic ValidationError # Any other exceptions we caught, we raise a generic ValidationError
# instead. # instead.
raise forms.ValidationError(gettext('Invalid or broken archive.')) raise forms.ValidationError(gettext('Invalid or broken archive.')) from exc
return target return target
@ -844,14 +853,16 @@ def parse_xpi(
except forms.ValidationError: except forms.ValidationError:
raise raise
except zipfile.BadZipFile: except zipfile.BadZipFile as exc:
raise forms.ValidationError(gettext('Invalid or corrupted file.')) raise forms.ValidationError(gettext('Invalid or corrupted file.')) from exc
except Exception as exception: except Exception as exc:
# We don't really know what happened, so even though we return a # We don't really know what happened, so even though we return a
# generic message about the manifest, don't raise InvalidManifest: it's # generic message about the manifest, don't raise InvalidManifest: it's
# not just invalid, it's worse... We want the validation to stop there. # not just invalid, it's worse... We want the validation to stop there.
log.exception(f'XPI parse error ({exception.__class__})') log.exception(f'XPI parse error ({exc.__class__})')
raise forms.ValidationError(gettext('Could not parse the manifest file.')) raise forms.ValidationError(
gettext('Could not parse the manifest file.')
) from exc
if minimal: if minimal:
return xpi_info return xpi_info
@ -1078,8 +1089,8 @@ def write_crx_as_xpi(chunks, target):
start_position = 12 + header_length start_position = 12 + header_length
else: else:
raise InvalidOrUnsupportedCrx('Unsupported CRX version') raise InvalidOrUnsupportedCrx('Unsupported CRX version')
except struct.error: except struct.error as exc:
raise InvalidOrUnsupportedCrx('Invalid or corrupt CRX file') raise InvalidOrUnsupportedCrx('Invalid or corrupt CRX file') from exc
# We can start reading the zip to write it where it needs to live on # We can start reading the zip to write it where it needs to live on
# the filesystem and then return the hash to the caller. If we somehow # the filesystem and then return the hash to the caller. If we somehow

Просмотреть файл

@ -255,10 +255,10 @@ class AddonGitRepository:
try: try:
master_ref = 'refs/heads/master' master_ref = 'refs/heads/master'
git_repository.lookup_reference(master_ref) git_repository.lookup_reference(master_ref)
except KeyError: except KeyError as exc:
message = f'Reference "{master_ref}" not found' message = f'Reference "{master_ref}" not found'
log.exception(message) log.exception(message)
raise MissingMasterBranchError(message) raise MissingMasterBranchError(message) from exc
return git_repository return git_repository
@ -393,10 +393,10 @@ class AddonGitRepository:
"""Lookup or create the branch named `name`""" """Lookup or create the branch named `name`"""
try: try:
branch = self.git_repository.branches.get(name) branch = self.git_repository.branches.get(name)
except pygit2.GitError: except pygit2.GitError as exc:
message = f'Reference for branch "{name}" is broken' message = f'Reference for branch "{name}" is broken'
log.exception(message) log.exception(message)
raise BrokenRefError(message) raise BrokenRefError(message) from exc
if branch is None: if branch is None:
branch = self.git_repository.create_branch( branch = self.git_repository.create_branch(

Просмотреть файл

@ -10,8 +10,10 @@ def get_grouped_ratings(request, addon):
show_grouped_ratings = serializers.BooleanField().to_internal_value( show_grouped_ratings = serializers.BooleanField().to_internal_value(
request.GET['show_grouped_ratings'] request.GET['show_grouped_ratings']
) )
except serializers.ValidationError: except serializers.ValidationError as exc:
raise ParseError('show_grouped_ratings parameter should be a boolean') raise ParseError(
'show_grouped_ratings parameter should be a boolean'
) from exc
if show_grouped_ratings and addon: if show_grouped_ratings and addon:
try: try:
aggregate = addon.ratingaggregate aggregate = addon.ratingaggregate

Просмотреть файл

@ -199,11 +199,11 @@ class RatingViewSet(AddonChildMixin, ModelViewSet):
) )
if show_flags_for != request.user.pk: if show_flags_for != request.user.pk:
raise serializers.ValidationError raise serializers.ValidationError
except serializers.ValidationError: except serializers.ValidationError as exc:
raise ParseError( raise ParseError(
'show_flags_for parameter value should be equal to ' 'show_flags_for parameter value should be equal to '
'the user id of the authenticated user' 'the user id of the authenticated user'
) ) from exc
return self._should_include_flags return self._should_include_flags
def check_permissions(self, request): def check_permissions(self, request):
@ -242,14 +242,14 @@ class RatingViewSet(AddonChildMixin, ModelViewSet):
if user_identifier: if user_identifier:
try: try:
user_identifier = int(user_identifier) user_identifier = int(user_identifier)
except ValueError: except ValueError as exc:
raise ParseError('user parameter should be an integer.') raise ParseError('user parameter should be an integer.') from exc
qs = qs.filter(user=user_identifier) qs = qs.filter(user=user_identifier)
if version_identifier: if version_identifier:
try: try:
version_identifier = int(version_identifier) version_identifier = int(version_identifier)
except ValueError: except ValueError as exc:
raise ParseError('version parameter should be an integer.') raise ParseError('version parameter should be an integer.') from exc
qs = qs.filter(version=version_identifier) qs = qs.filter(version=version_identifier)
elif addon_identifier: elif addon_identifier:
# When filtering on addon but not on version, only return the # When filtering on addon but not on version, only return the
@ -270,23 +270,23 @@ class RatingViewSet(AddonChildMixin, ModelViewSet):
if score_filter: if score_filter:
try: try:
scores = [int(score) for score in score_filter.split(',')] scores = [int(score) for score in score_filter.split(',')]
except ValueError: except ValueError as exc:
raise ParseError( raise ParseError(
'score parameter should be an integer or a list of ' 'score parameter should be an integer or a list of '
'integers (separated by a comma).' 'integers (separated by a comma).'
) ) from exc
qs = qs.filter(rating__in=scores) qs = qs.filter(rating__in=scores)
if exclude_ratings: if exclude_ratings:
try: try:
exclude_ratings = [ exclude_ratings = [
int(rating) for rating in exclude_ratings.split(',') int(rating) for rating in exclude_ratings.split(',')
] ]
except ValueError: except ValueError as exc:
raise ParseError( raise ParseError(
'exclude_ratings parameter should be an ' 'exclude_ratings parameter should be an '
'integer or a list of integers ' 'integer or a list of integers '
'(separated by a comma).' '(separated by a comma).'
) ) from exc
qs = qs.exclude(pk__in=exclude_ratings) qs = qs.exclude(pk__in=exclude_ratings)
if not addon_identifier: if not addon_identifier:
@ -316,11 +316,11 @@ class RatingViewSet(AddonChildMixin, ModelViewSet):
) )
if show_permissions_for != request.user.pk: if show_permissions_for != request.user.pk:
raise serializers.ValidationError raise serializers.ValidationError
except serializers.ValidationError: except serializers.ValidationError as exc:
raise ParseError( raise ParseError(
'show_permissions_for parameter value should be equal to ' 'show_permissions_for parameter value should be equal to '
'the user id of the authenticated user' 'the user id of the authenticated user'
) ) from exc
extra_data['can_reply'] = self.check_can_reply_permission_for_ratings_list() extra_data['can_reply'] = self.check_can_reply_permission_for_ratings_list()
# Call this here so the validation checks on the `show_flags_for` are # Call this here so the validation checks on the `show_flags_for` are
# carried out even when there are no results to serialize. # carried out even when there are no results to serialize.

Просмотреть файл

@ -472,8 +472,8 @@ class AutoApprovalSummary(ModelBase):
old_version = self.find_previous_confirmed_version() old_version = self.find_previous_confirmed_version()
old_size = find_code_size(old_version) if old_version else 0 old_size = find_code_size(old_version) if old_version else 0
new_size = find_code_size(self.version) new_size = find_code_size(self.version)
except FileValidation.DoesNotExist: except FileValidation.DoesNotExist as exc:
raise AutoApprovalNoValidationResultError() raise AutoApprovalNoValidationResultError() from exc
# We don't really care about whether it's a negative or positive change # We don't really care about whether it's a negative or positive change
# in size, we just need the absolute value (if there is no current # in size, we just need the absolute value (if there is no current
# public version, that value ends up being the total code size of the # public version, that value ends up being the total code size of the
@ -520,8 +520,8 @@ class AutoApprovalSummary(ModelBase):
def _count_linter_flag(cls, version, flag): def _count_linter_flag(cls, version, flag):
try: try:
validation = version.file.validation validation = version.file.validation
except FileValidation.DoesNotExist: except FileValidation.DoesNotExist as exc:
raise AutoApprovalNoValidationResultError() raise AutoApprovalNoValidationResultError() from exc
validation_data = json.loads(validation.validation) validation_data = json.loads(validation.validation)
return sum( return sum(
flag in message['id'] for message in validation_data.get('messages', []) flag in message['id'] for message in validation_data.get('messages', [])
@ -531,8 +531,8 @@ class AutoApprovalSummary(ModelBase):
def _count_metadata_property(cls, version, prop): def _count_metadata_property(cls, version, prop):
try: try:
validation = version.file.validation validation = version.file.validation
except FileValidation.DoesNotExist: except FileValidation.DoesNotExist as exc:
raise AutoApprovalNoValidationResultError() raise AutoApprovalNoValidationResultError() from exc
validation_data = json.loads(validation.validation) validation_data = json.loads(validation.validation)
return len(validation_data.get('metadata', {}).get(prop, [])) return len(validation_data.get('metadata', {}).get(prop, []))

Просмотреть файл

@ -90,8 +90,10 @@ class FileEntriesMixin:
# Caching the commit to avoid calling revparse_single many times. # Caching the commit to avoid calling revparse_single many times.
try: try:
return self.git_repo.revparse_single(self._get_version().git_hash) return self.git_repo.revparse_single(self._get_version().git_hash)
except pygit2.InvalidSpecError: except pygit2.InvalidSpecError as exc:
raise NotFound("Couldn't find the requested version in git-repository") raise NotFound(
"Couldn't find the requested version in git-repository"
) from exc
@cached_property @cached_property
def tree(self): def tree(self):

Просмотреть файл

@ -1019,8 +1019,8 @@ def download_git_stored_file(request, version_id, filename):
try: try:
addon = version.addon addon = version.addon
except Addon.DoesNotExist: except Addon.DoesNotExist as exc:
raise http.Http404 raise http.Http404 from exc
if version.channel == amo.CHANNEL_LISTED: if version.channel == amo.CHANNEL_LISTED:
is_owner = acl.check_addon_ownership(request.user, addon, allow_developer=True) is_owner = acl.check_addon_ownership(request.user, addon, allow_developer=True)
@ -1045,8 +1045,8 @@ def download_git_stored_file(request, version_id, filename):
if blob_or_tree.type == pygit2.GIT_OBJ_TREE: if blob_or_tree.type == pygit2.GIT_OBJ_TREE:
return http.HttpResponseBadRequest("Can't serve directories") return http.HttpResponseBadRequest("Can't serve directories")
selected_file = serializer._get_entries()[filename] selected_file = serializer._get_entries()[filename]
except (KeyError, NotFound): except (KeyError, NotFound) as exc:
raise http.Http404() raise http.Http404() from exc
actual_blob = serializer.git_repo[blob_or_tree.oid] actual_blob = serializer.git_repo[blob_or_tree.oid]
@ -1225,8 +1225,8 @@ class AddonReviewerViewSet(GenericViewSet):
raise PermissionDenied raise PermissionDenied
try: try:
result = file.validation result = file.validation
except File.validation.RelatedObjectDoesNotExist: except File.validation.RelatedObjectDoesNotExist as exc:
raise http.Http404 raise http.Http404 from exc
return JsonResponse( return JsonResponse(
{ {
'validation': result.processed_validation, 'validation': result.processed_validation,

Просмотреть файл

@ -195,11 +195,11 @@ class AbstractScannerRule(ModelBase):
'definition': _('The definition is not valid: %(error)s') 'definition': _('The definition is not valid: %(error)s')
% {'error': syntaxError} % {'error': syntaxError}
} }
) ) from syntaxError
except Exception: except Exception as exc:
raise ValidationError( raise ValidationError(
{'definition': _('An error occurred when compiling the definition')} {'definition': _('An error occurred when compiling the definition')}
) ) from exc
class ScannerRule(AbstractScannerRule): class ScannerRule(AbstractScannerRule):

Просмотреть файл

@ -122,9 +122,9 @@ def _run_scanner_for_url(scanner_result, url, scanner, api_url, api_key):
try: try:
data = response.json() data = response.json()
except ValueError: except ValueError as exc:
# Log the response body when JSON decoding has failed. # Log the response body when JSON decoding has failed.
raise ValueError(response.text) raise ValueError(response.text) from exc
if response.status_code != 200 or 'error' in data: if response.status_code != 200 or 'error' in data:
raise ValueError(data) raise ValueError(data)
@ -446,9 +446,9 @@ def call_mad_api(all_results, upload_pk):
try: try:
data = response.json() data = response.json()
except ValueError: except ValueError as exc:
# Log the response body when JSON decoding has failed. # Log the response body when JSON decoding has failed.
raise ValueError(response.text) raise ValueError(response.text) from exc
if response.status_code != 200: if response.status_code != 200:
raise ValueError(data) raise ValueError(data)

Просмотреть файл

@ -265,10 +265,10 @@ class AddonGuidQueryParam(AddonQueryMultiParam):
value = force_str(urlsafe_base64_decode(force_str(value[4:]))) value = force_str(urlsafe_base64_decode(force_str(value[4:])))
if not amo.ADDON_GUID_PATTERN.match(value): if not amo.ADDON_GUID_PATTERN.match(value):
raise ValueError() raise ValueError()
except (TypeError, ValueError): except (TypeError, ValueError) as exc:
raise ValueError( raise ValueError(
gettext('Invalid Return To AMO guid (not in base64url format?)') gettext('Invalid Return To AMO guid (not in base64url format?)')
) ) from exc
# Filter on the now decoded guid param as normal... # Filter on the now decoded guid param as normal...
filters = super().get_es_query([value]) filters = super().get_es_query([value])
# If the switch to enable all listed add-ons for RTAMO is on, we # If the switch to enable all listed add-ons for RTAMO is on, we
@ -310,7 +310,7 @@ class AddonCategoryQueryParam(AddonQueryParam):
try: try:
types = AddonTypeQueryParam(self.query_data).get_values() types = AddonTypeQueryParam(self.query_data).get_values()
self.reverse_dict = [CATEGORIES[type_] for type_ in types] self.reverse_dict = [CATEGORIES[type_] for type_ in types]
except KeyError: except KeyError as exc:
raise ValueError( raise ValueError(
gettext( gettext(
'Invalid combination of "%s" and "%s" parameters.' 'Invalid combination of "%s" and "%s" parameters.'
@ -319,7 +319,7 @@ class AddonCategoryQueryParam(AddonQueryParam):
self.query_param, self.query_param,
) )
) )
) ) from exc
def get_value(self): def get_value(self):
value = super().get_value() value = super().get_value()
@ -938,7 +938,7 @@ class SearchParameterFilter(BaseFilterBackend):
if param_class.query_param in request.GET: if param_class.query_param in request.GET:
clauses.extend(param_class(request.GET).get_es_query()) clauses.extend(param_class(request.GET).get_es_query())
except ValueError as exc: except ValueError as exc:
raise serializers.ValidationError(*exc.args) raise serializers.ValidationError(*exc.args) from exc
return clauses return clauses
def filter_queryset(self, request, qs, view): def filter_queryset(self, request, qs, view):
@ -1061,8 +1061,8 @@ class SortingFilter(BaseFilterBackend):
try: try:
order_by = [self.SORTING_PARAMS[name] for name in split_sort_params] order_by = [self.SORTING_PARAMS[name] for name in split_sort_params]
except KeyError: except KeyError as exc:
raise serializers.ValidationError('Invalid "sort" parameter.') raise serializers.ValidationError('Invalid "sort" parameter.') from exc
return qs.sort(*order_by) return qs.sort(*order_by)

Просмотреть файл

@ -267,8 +267,8 @@ class UserAdmin(AMOModelAdmin):
try: try:
if lookup_field == 'email': if lookup_field == 'email':
user = UserProfile.objects.get(email=object_id) user = UserProfile.objects.get(email=object_id)
except UserProfile.DoesNotExist: except UserProfile.DoesNotExist as exc:
raise http.Http404 raise http.Http404 from exc
url = request.path.replace(object_id, str(user.id), 1) url = request.path.replace(object_id, str(user.id), 1)
if request.GET: if request.GET:
url += '?' + request.GET.urlencode() url += '?' + request.GET.urlencode()

Просмотреть файл

@ -26,8 +26,8 @@ class Command(BaseCommand):
try: try:
profile = UserProfile.objects.get(email=email) profile = UserProfile.objects.get(email=email)
except UserProfile.DoesNotExist: except UserProfile.DoesNotExist as exc:
raise CommandError('User with email %s not found' % email) raise CommandError('User with email %s not found' % email) from exc
admin_msg = '' admin_msg = ''
if set_admin: if set_admin:

Просмотреть файл

@ -73,7 +73,7 @@ and email address and that's it.
'You must use --%s with --noinput.' % field_name 'You must use --%s with --noinput.' % field_name
) )
except exceptions.ValidationError as exc: except exceptions.ValidationError as exc:
raise CommandError('; '.join(exc.messages)) raise CommandError('; '.join(exc.messages)) from exc
else: else:
user_data = { user_data = {
field_name: self.get_value(field_name) field_name: self.get_value(field_name)

Просмотреть файл

@ -37,9 +37,9 @@ class UnsubscribeCode:
try: try:
decoded = base64.urlsafe_b64decode(force_bytes(code)) decoded = base64.urlsafe_b64decode(force_bytes(code))
email = decoded email = decoded
except (ValueError, TypeError): except (ValueError, TypeError) as exc:
# Data is broken # Data is broken
raise ValueError raise ValueError from exc
if cls.make_secret(decoded) != hash: if cls.make_secret(decoded) != hash:
log.info('[Tampering] Unsubscribe link data does not match hash') log.info('[Tampering] Unsubscribe link data does not match hash')

Просмотреть файл

@ -38,9 +38,9 @@ def do_adduser(user, group):
GroupUser.objects.create(user=user, group=group) GroupUser.objects.create(user=user, group=group)
except IntegrityError as e: except IntegrityError as exc:
raise CommandError('User is already in that group? %s' % e) raise CommandError('User is already in that group? %s' % exc) from exc
except UserProfile.DoesNotExist: except UserProfile.DoesNotExist as exc:
raise CommandError(f'User ({user}) does not exist.') raise CommandError(f'User ({user}) does not exist.') from exc
except Group.DoesNotExist: except Group.DoesNotExist as exc:
raise CommandError(f'Group ({group}) does not exist.') raise CommandError(f'Group ({group}) does not exist.') from exc

Просмотреть файл

@ -37,7 +37,7 @@ def do_removeuser(user, group):
# Doesn't actually check if the user was in the group or not. # Doesn't actually check if the user was in the group or not.
GroupUser.objects.filter(user=user, group=group).delete() GroupUser.objects.filter(user=user, group=group).delete()
except UserProfile.DoesNotExist: except UserProfile.DoesNotExist as exc:
raise CommandError(f'User ({user}) does not exist.') raise CommandError(f'User ({user}) does not exist.') from exc
except Group.DoesNotExist: except Group.DoesNotExist as exc:
raise CommandError(f'Group ({group}) does not exist.') raise CommandError(f'Group ({group}) does not exist.') from exc