stop ignoring ruff rule B904 (#22641)
This commit is contained in:
Родитель
dc4170d11f
Коммит
dd200ad058
|
@ -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
|
||||||
|
|
Загрузка…
Ссылка в новой задаче