diff --git a/analytics/management/commands/check_analytics_state.py b/analytics/management/commands/check_analytics_state.py index d34aa27fdc..66bb7694e8 100644 --- a/analytics/management/commands/check_analytics_state.py +++ b/analytics/management/commands/check_analytics_state.py @@ -8,7 +8,7 @@ from django.utils.timezone import now as timezone_now from analytics.lib.counts import COUNT_STATS, CountStat from analytics.models import installation_epoch -from zerver.lib.timestamp import TimeZoneNotUTCException, floor_to_day, floor_to_hour, verify_UTC +from zerver.lib.timestamp import TimeZoneNotUTCError, floor_to_day, floor_to_hour, verify_UTC from zerver.models import Realm states = { @@ -48,7 +48,7 @@ class Command(BaseCommand): last_fill = installation_epoch() try: verify_UTC(last_fill) - except TimeZoneNotUTCException: + except TimeZoneNotUTCError: return {"status": 2, "message": f"FillState not in UTC for {property}"} if stat.frequency == CountStat.DAY: diff --git a/analytics/tests/test_counts.py b/analytics/tests/test_counts.py index 2c71b9fbe9..ff714ebcee 100644 --- a/analytics/tests/test_counts.py +++ b/analytics/tests/test_counts.py @@ -53,7 +53,7 @@ from zerver.actions.users import do_deactivate_user from zerver.lib.create_user import create_user from zerver.lib.exceptions import InvitationError from zerver.lib.test_classes import ZulipTestCase -from zerver.lib.timestamp import TimeZoneNotUTCException, floor_to_day +from zerver.lib.timestamp import TimeZoneNotUTCError, floor_to_day from zerver.lib.topic import DB_TOPIC_NAME from zerver.lib.utils import assert_is_not_none from zerver.models import ( @@ -290,7 +290,7 @@ class TestProcessCountStat(AnalyticsTestCase): stat = self.make_dummy_count_stat("test stat") with self.assertRaises(ValueError): process_count_stat(stat, installation_epoch() + 65 * self.MINUTE) - with self.assertRaises(TimeZoneNotUTCException): + with self.assertRaises(TimeZoneNotUTCError): process_count_stat(stat, installation_epoch().replace(tzinfo=None)) # This tests the LoggingCountStat branch of the code in do_delete_counts_at_hour. diff --git a/confirmation/models.py b/confirmation/models.py index 40130dbd21..16df5d9ef7 100644 --- a/confirmation/models.py +++ b/confirmation/models.py @@ -29,7 +29,7 @@ from zerver.models import ( ) -class ConfirmationKeyException(Exception): +class ConfirmationKeyError(Exception): WRONG_LENGTH = 1 EXPIRED = 2 DOES_NOT_EXIST = 3 @@ -40,11 +40,11 @@ class ConfirmationKeyException(Exception): def render_confirmation_key_error( - request: HttpRequest, exception: ConfirmationKeyException + request: HttpRequest, exception: ConfirmationKeyError ) -> HttpResponse: - if exception.error_type == ConfirmationKeyException.WRONG_LENGTH: + if exception.error_type == ConfirmationKeyError.WRONG_LENGTH: return render(request, "confirmation/link_malformed.html", status=404) - if exception.error_type == ConfirmationKeyException.EXPIRED: + if exception.error_type == ConfirmationKeyError.EXPIRED: return render(request, "confirmation/link_expired.html", status=404) return render(request, "confirmation/link_does_not_exist.html", status=404) @@ -77,16 +77,16 @@ def get_object_from_key( # Confirmation keys used to be 40 characters if len(confirmation_key) not in (24, 40): - raise ConfirmationKeyException(ConfirmationKeyException.WRONG_LENGTH) + raise ConfirmationKeyError(ConfirmationKeyError.WRONG_LENGTH) try: confirmation = Confirmation.objects.get( confirmation_key=confirmation_key, type__in=confirmation_types ) except Confirmation.DoesNotExist: - raise ConfirmationKeyException(ConfirmationKeyException.DOES_NOT_EXIST) + raise ConfirmationKeyError(ConfirmationKeyError.DOES_NOT_EXIST) if confirmation.expiry_date is not None and timezone_now() > confirmation.expiry_date: - raise ConfirmationKeyException(ConfirmationKeyException.EXPIRED) + raise ConfirmationKeyError(ConfirmationKeyError.EXPIRED) obj = confirmation.content_object assert obj is not None @@ -96,7 +96,7 @@ def get_object_from_key( if hasattr(obj, "status") and obj.status in [used_value, revoked_value]: # Confirmations where the object has the status attribute are one-time use # and are marked after being used (or revoked). - raise ConfirmationKeyException(ConfirmationKeyException.EXPIRED) + raise ConfirmationKeyError(ConfirmationKeyError.EXPIRED) if mark_object_used: # MultiuseInvite objects do not use the STATUS_USED status, since they are @@ -240,10 +240,10 @@ def validate_key(creation_key: Optional[str]) -> Optional["RealmCreationKey"]: try: key_record = RealmCreationKey.objects.get(creation_key=creation_key) except RealmCreationKey.DoesNotExist: - raise RealmCreationKey.Invalid() + raise RealmCreationKey.InvalidError() time_elapsed = timezone_now() - key_record.date_created if time_elapsed.total_seconds() > settings.REALM_CREATION_LINK_VALIDITY_DAYS * 24 * 3600: - raise RealmCreationKey.Invalid() + raise RealmCreationKey.InvalidError() return key_record @@ -266,5 +266,5 @@ class RealmCreationKey(models.Model): # is theirs, and skip sending mail to it to confirm that. presume_email_valid = models.BooleanField(default=False) - class Invalid(Exception): + class InvalidError(Exception): pass diff --git a/corporate/lib/stripe.py b/corporate/lib/stripe.py index eb32515c45..a420197d57 100644 --- a/corporate/lib/stripe.py +++ b/corporate/lib/stripe.py @@ -248,13 +248,13 @@ class UpgradeWithExistingPlanError(BillingError): ) -class InvalidBillingSchedule(Exception): +class InvalidBillingScheduleError(Exception): def __init__(self, billing_schedule: int) -> None: self.message = f"Unknown billing_schedule: {billing_schedule}" super().__init__(self.message) -class InvalidTier(Exception): +class InvalidTierError(Exception): def __init__(self, tier: int) -> None: self.message = f"Unknown tier: {tier}" super().__init__(self.message) @@ -570,16 +570,16 @@ def get_price_per_license( elif billing_schedule == CustomerPlan.MONTHLY: price_per_license = 800 else: # nocoverage - raise InvalidBillingSchedule(billing_schedule) + raise InvalidBillingScheduleError(billing_schedule) elif tier == CustomerPlan.PLUS: if billing_schedule == CustomerPlan.ANNUAL: price_per_license = 16000 elif billing_schedule == CustomerPlan.MONTHLY: price_per_license = 1600 else: # nocoverage - raise InvalidBillingSchedule(billing_schedule) + raise InvalidBillingScheduleError(billing_schedule) else: - raise InvalidTier(tier) + raise InvalidTierError(tier) if discount is not None: price_per_license = calculate_discounted_price_per_license(price_per_license, discount) @@ -602,7 +602,7 @@ def compute_plan_parameters( elif billing_schedule == CustomerPlan.MONTHLY: period_end = add_months(billing_cycle_anchor, 1) else: # nocoverage - raise InvalidBillingSchedule(billing_schedule) + raise InvalidBillingScheduleError(billing_schedule) price_per_license = get_price_per_license(tier, billing_schedule, discount) diff --git a/corporate/tests/test_stripe.py b/corporate/tests/test_stripe.py index 34413a5a2d..901507c6f0 100644 --- a/corporate/tests/test_stripe.py +++ b/corporate/tests/test_stripe.py @@ -40,8 +40,8 @@ from corporate.lib.stripe import ( MIN_INVOICED_LICENSES, STRIPE_API_VERSION, BillingError, - InvalidBillingSchedule, - InvalidTier, + InvalidBillingScheduleError, + InvalidTierError, StripeCardError, add_months, approve_sponsorship, @@ -4302,10 +4302,10 @@ class BillingHelpersTest(ZulipTestCase): 800, ) - with self.assertRaisesRegex(InvalidBillingSchedule, "Unknown billing_schedule: 1000"): + with self.assertRaisesRegex(InvalidBillingScheduleError, "Unknown billing_schedule: 1000"): get_price_per_license(CustomerPlan.STANDARD, 1000) - with self.assertRaisesRegex(InvalidTier, "Unknown tier: 10"): + with self.assertRaisesRegex(InvalidTierError, "Unknown tier: 10"): get_price_per_license(CustomerPlan.ENTERPRISE, CustomerPlan.ANNUAL) def test_get_plan_renewal_or_end_date(self) -> None: diff --git a/corporate/views/portico.py b/corporate/views/portico.py index 1011d9f15f..697194f30f 100644 --- a/corporate/views/portico.py +++ b/corporate/views/portico.py @@ -9,7 +9,10 @@ from django.template.response import TemplateResponse from zerver.context_processors import get_realm_from_request, latest_info_context from zerver.decorator import add_google_analytics -from zerver.lib.github import InvalidPlatform, get_latest_github_release_download_link_for_platform +from zerver.lib.github import ( + InvalidPlatformError, + get_latest_github_release_download_link_for_platform, +) from zerver.lib.realm_description import get_realm_text_description from zerver.lib.realm_icon import get_realm_icon_url from zerver.lib.subdomains import is_subdomain_root_or_alias @@ -30,7 +33,7 @@ def app_download_link_redirect(request: HttpRequest, platform: str) -> HttpRespo try: download_link = get_latest_github_release_download_link_for_platform(platform) return HttpResponseRedirect(download_link, status=302) - except InvalidPlatform: + except InvalidPlatformError: return TemplateResponse(request, "404.html", status=404) diff --git a/pyproject.toml b/pyproject.toml index f8f27066dd..8ebb35fad8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -125,7 +125,6 @@ ignore = [ "E731", # Do not assign a lambda expression, use a def "N802", # Function name should be lowercase "N806", # Variable in function should be lowercase - "N818", # Exception name should be named with an Error suffix ] line-length = 100 src = [".", "tools", "tools/setup/emoji"] diff --git a/templates/zerver/api/incoming-webhooks-walkthrough.md b/templates/zerver/api/incoming-webhooks-walkthrough.md index 1f86fef77d..bbeba13f71 100644 --- a/templates/zerver/api/incoming-webhooks-walkthrough.md +++ b/templates/zerver/api/incoming-webhooks-walkthrough.md @@ -628,9 +628,9 @@ Many third-party services have dozens of different event types. In some cases, we may choose to explicitly ignore specific events. In other cases, there may be events that are new or events that we don't know about. In such cases, we recommend raising -`UnsupportedWebhookEventType` (found in `zerver/lib/exceptions.py`), +`UnsupportedWebhookEventTypeError` (found in `zerver/lib/exceptions.py`), with a string describing the unsupported event type, like so: ``` -raise UnsupportedWebhookEventType(event_type) +raise UnsupportedWebhookEventTypeError(event_type) ``` diff --git a/tools/coveragerc b/tools/coveragerc index d651f31ba4..3ed6968a54 100644 --- a/tools/coveragerc +++ b/tools/coveragerc @@ -12,7 +12,7 @@ exclude_lines = # Don't require coverage for __str__ statements just used for printing def __str__[(]self[)] -> .*: # Don't require coverage for errors about unsupported webhook event types - raise UnsupportedWebhookEventType + raise UnsupportedWebhookEventTypeError # Don't require coverage for blocks only run when type-checking if TYPE_CHECKING: # Don't require coverage for abstract methods; they're never called. diff --git a/tools/lib/html_branches.py b/tools/lib/html_branches.py index 4eecf45324..5f34987b7b 100644 --- a/tools/lib/html_branches.py +++ b/tools/lib/html_branches.py @@ -2,7 +2,7 @@ import re from collections import defaultdict from typing import Dict, List -from .template_parser import FormattedException, Token, tokenize +from .template_parser import FormattedError, Token, tokenize class TagInfo: @@ -83,7 +83,7 @@ def build_id_dict(templates: List[str]) -> (Dict[str, List[str]]): try: list_tags = tokenize(text) - except FormattedException as e: + except FormattedError as e: raise Exception( f""" fn: {fn} diff --git a/tools/lib/template_parser.py b/tools/lib/template_parser.py index 1bd78e48a8..0ebed88ada 100644 --- a/tools/lib/template_parser.py +++ b/tools/lib/template_parser.py @@ -1,11 +1,11 @@ from typing import Callable, List, Optional -class FormattedException(Exception): +class FormattedError(Exception): pass -class TemplateParserException(Exception): +class TemplateParserError(Exception): def __init__(self, message: str) -> None: self.message = message @@ -13,7 +13,7 @@ class TemplateParserException(Exception): return self.message -class TokenizationException(Exception): +class TokenizationError(Exception): def __init__(self, message: str, line_content: Optional[str] = None) -> None: self.message = message self.line_content = line_content @@ -149,7 +149,7 @@ def tokenize(text: str) -> List[Token]: tag_parts = s[1:end_offset].split() if not tag_parts: - raise TemplateParserException("Tag name missing") + raise TemplateParserError("Tag name missing") tag = tag_parts[0] @@ -228,8 +228,8 @@ def tokenize(text: str) -> List[Token]: continue tag = "" kind = "text" - except TokenizationException as e: - raise FormattedException( + except TokenizationError as e: + raise FormattedError( f'''{e.message} at line {state.line} col {state.col}:"{e.line_content}"''', ) @@ -350,8 +350,8 @@ def validate(fn: Optional[str] = None, text: Optional[str] = None) -> List[Token try: tokens = tokenize(text) - except FormattedException as e: - raise TemplateParserException( + except FormattedError as e: + raise TemplateParserError( f""" fn: {fn} {e}""" @@ -367,7 +367,7 @@ def validate(fn: Optional[str] = None, text: Optional[str] = None) -> List[Token def no_start_tag(token: Optional[Token]) -> None: assert token - raise TemplateParserException( + raise TemplateParserError( f""" No start tag fn: {fn} @@ -393,7 +393,7 @@ def validate(fn: Optional[str] = None, text: Optional[str] = None) -> List[Token def f(end_token: Optional[Token]) -> None: if end_token is None: - raise TemplateParserException( + raise TemplateParserError( f""" Problem with {fn} @@ -429,7 +429,7 @@ def validate(fn: Optional[str] = None, text: Optional[str] = None) -> List[Token problem = report_problem() if problem: - raise TemplateParserException( + raise TemplateParserError( f""" fn: {fn} {problem} @@ -460,12 +460,12 @@ def validate(fn: Optional[str] = None, text: Optional[str] = None) -> List[Token if not state.foreign: if kind == "html_start": if tag in HTML_VOID_TAGS: - raise TemplateParserException( + raise TemplateParserError( f"Tag must be self-closing: {tag} at {fn} line {token.line}, col {token.col}" ) elif kind == "html_singleton": if tag not in HTML_VOID_TAGS: - raise TemplateParserException( + raise TemplateParserError( f"Tag must not be self-closing: {tag} at {fn} line {token.line}, col {token.col}" ) @@ -514,7 +514,7 @@ def ensure_matching_indentation(fn: str, tokens: List[Token], lines: List[str]) return False if has_bad_indentation(): - raise TemplateParserException( + raise TemplateParserError( f""" fn: {fn} Indentation for start/end tags does not match. @@ -539,14 +539,14 @@ def prevent_extra_newlines(fn: str, tokens: List[Token]) -> None: count += 1 if count >= 4: - raise TemplateParserException( + raise TemplateParserError( f"""Please avoid so many blank lines near row {token.line} in {fn}.""" ) def prevent_whitespace_violations(fn: str, tokens: List[Token]) -> None: if tokens[0].kind in ("indent", "whitespace"): - raise TemplateParserException(f" Please remove the whitespace at the beginning of {fn}.") + raise TemplateParserError(f" Please remove the whitespace at the beginning of {fn}.") prevent_extra_newlines(fn, tokens) @@ -559,12 +559,12 @@ def prevent_whitespace_violations(fn: str, tokens: List[Token]) -> None: raise AssertionError("programming error parsing indents") if next_token.kind == "newline": - raise TemplateParserException( + raise TemplateParserError( f"""Please just make row {token.line} in {fn} a truly blank line (no spaces).""" ) if len(token.s) % 4 != 0: - raise TemplateParserException( + raise TemplateParserError( f""" Please use 4-space indents for template files. Most of our codebase (including Python and JavaScript) uses 4-space indents, @@ -578,13 +578,13 @@ def prevent_whitespace_violations(fn: str, tokens: List[Token]) -> None: if token.kind == "whitespace": if len(token.s) > 1: - raise TemplateParserException( + raise TemplateParserError( f""" We did not expect this much whitespace at row {token.line} column {token.col} in {fn}. """ ) if next_token.kind == "newline": - raise TemplateParserException( + raise TemplateParserError( f""" Unexpected trailing whitespace at row {token.line} column {token.col} in {fn}. """ @@ -613,7 +613,7 @@ def get_handlebars_tag(text: str, i: int) -> str: while end < len(text) - 1 and text[end] != "}": end += 1 if text[end] != "}" or text[end + 1] != "}": - raise TokenizationException('Tag missing "}}"', text[i : end + 2]) + raise TokenizationError('Tag missing "}}"', text[i : end + 2]) s = text[i : end + 2] return s @@ -649,7 +649,7 @@ def get_django_tag(text: str, i: int, stripped: bool = False) -> str: while end < len(text) - 1 and text[end] != "%": end += 1 if text[end] != "%" or text[end + 1] != "}": - raise TokenizationException('Tag missing "%}"', text[i : end + 2]) + raise TokenizationError('Tag missing "%}"', text[i : end + 2]) s = text[i : end + 2] return s @@ -666,11 +666,11 @@ def get_html_tag(text: str, i: int) -> str: end += 1 if quote_count % 2 != 0: if unclosed_end: - raise TokenizationException("Unbalanced quotes", text[i:unclosed_end]) + raise TokenizationError("Unbalanced quotes", text[i:unclosed_end]) else: - raise TokenizationException("Unbalanced quotes", text[i : end + 1]) + raise TokenizationError("Unbalanced quotes", text[i : end + 1]) if end == len(text) or text[end] != ">": - raise TokenizationException('Tag missing ">"', text[i : end + 1]) + raise TokenizationError('Tag missing ">"', text[i : end + 1]) s = text[i : end + 1] return s @@ -684,7 +684,7 @@ def get_html_comment(text: str, i: int) -> str: if not unclosed_end and text[end] == "<": unclosed_end = end end += 1 - raise TokenizationException("Unclosed comment", text[i:unclosed_end]) + raise TokenizationError("Unclosed comment", text[i:unclosed_end]) def get_handlebars_comment(text: str, i: int) -> str: @@ -696,7 +696,7 @@ def get_handlebars_comment(text: str, i: int) -> str: if not unclosed_end and text[end] == "<": unclosed_end = end end += 1 - raise TokenizationException("Unclosed comment", text[i:unclosed_end]) + raise TokenizationError("Unclosed comment", text[i:unclosed_end]) def get_template_var(text: str, i: int) -> str: @@ -710,7 +710,7 @@ def get_template_var(text: str, i: int) -> str: if not unclosed_end and text[end] == "<": unclosed_end = end end += 1 - raise TokenizationException("Unclosed var", text[i:unclosed_end]) + raise TokenizationError("Unclosed var", text[i:unclosed_end]) def get_django_comment(text: str, i: int) -> str: @@ -722,7 +722,7 @@ def get_django_comment(text: str, i: int) -> str: if not unclosed_end and text[end] == "<": unclosed_end = end end += 1 - raise TokenizationException("Unclosed comment", text[i:unclosed_end]) + raise TokenizationError("Unclosed comment", text[i:unclosed_end]) def get_handlebars_partial(text: str, i: int) -> str: @@ -734,4 +734,4 @@ def get_handlebars_partial(text: str, i: int) -> str: if not unclosed_end and text[end] == "<": unclosed_end = end end += 1 - raise TokenizationException("Unclosed partial", text[i:unclosed_end]) + raise TokenizationError("Unclosed partial", text[i:unclosed_end]) diff --git a/tools/tests/test_template_parser.py b/tools/tests/test_template_parser.py index 8ad7c3433f..e3db01540f 100644 --- a/tools/tests/test_template_parser.py +++ b/tools/tests/test_template_parser.py @@ -4,7 +4,7 @@ from typing import Optional try: from tools.lib.template_parser import ( - TemplateParserException, + TemplateParserError, is_django_block_tag, tokenize, validate, @@ -21,7 +21,7 @@ class ParserTest(unittest.TestCase): fn: Optional[str] = None, text: Optional[str] = None, ) -> None: - with self.assertRaisesRegex(TemplateParserException, error): + with self.assertRaisesRegex(TemplateParserError, error): validate(fn=fn, text=text) def test_is_django_block_tag(self) -> None: diff --git a/zerver/actions/message_send.py b/zerver/actions/message_send.py index c624d439d9..d707183200 100644 --- a/zerver/actions/message_send.py +++ b/zerver/actions/message_send.py @@ -35,10 +35,10 @@ from zerver.lib.cache import cache_with_key, user_profile_delivery_email_cache_k from zerver.lib.create_user import create_user from zerver.lib.exceptions import ( JsonableError, - MarkdownRenderingException, + MarkdownRenderingError, StreamDoesNotExistError, StreamWithIDDoesNotExistError, - ZephyrMessageAlreadySentException, + ZephyrMessageAlreadySentError, ) from zerver.lib.markdown import MessageRenderingResult from zerver.lib.markdown import version as markdown_version @@ -148,7 +148,7 @@ def render_incoming_message( url_embed_data=url_embed_data, email_gateway=email_gateway, ) - except MarkdownRenderingException: + except MarkdownRenderingError: raise JsonableError(_("Unable to render message")) return rendering_result @@ -1173,7 +1173,7 @@ def check_send_message( widget_content, skip_stream_access_check=skip_stream_access_check, ) - except ZephyrMessageAlreadySentException as e: + except ZephyrMessageAlreadySentError as e: return e.message_id return do_send_messages([message])[0] @@ -1460,7 +1460,7 @@ def check_message( if client.name == "zephyr_mirror": id = already_sent_mirrored_message_id(message) if id is not None: - raise ZephyrMessageAlreadySentException(id) + raise ZephyrMessageAlreadySentError(id) widget_content_dict = None if widget_content is not None: diff --git a/zerver/decorator.py b/zerver/decorator.py index 4a8238959a..2496bd5919 100644 --- a/zerver/decorator.py +++ b/zerver/decorator.py @@ -38,17 +38,17 @@ from typing_extensions import Concatenate, ParamSpec from zerver.lib.exceptions import ( AccessDeniedError, - AnomalousWebhookPayload, + AnomalousWebhookPayloadError, InvalidAPIKeyError, InvalidAPIKeyFormatError, InvalidJSONError, JsonableError, - OrganizationAdministratorRequired, - OrganizationMemberRequired, - OrganizationOwnerRequired, + OrganizationAdministratorRequiredError, + OrganizationMemberRequiredError, + OrganizationOwnerRequiredError, RealmDeactivatedError, UnauthorizedError, - UnsupportedWebhookEventType, + UnsupportedWebhookEventTypeError, UserDeactivatedError, WebhookError, ) @@ -139,7 +139,7 @@ def require_realm_owner( **kwargs: ParamT.kwargs, ) -> HttpResponse: if not user_profile.is_realm_owner: - raise OrganizationOwnerRequired() + raise OrganizationOwnerRequiredError() return func(request, user_profile, *args, **kwargs) return wrapper @@ -157,7 +157,7 @@ def require_realm_admin( **kwargs: ParamT.kwargs, ) -> HttpResponse: if not user_profile.is_realm_admin: - raise OrganizationAdministratorRequired() + raise OrganizationAdministratorRequiredError() return func(request, user_profile, *args, **kwargs) return wrapper @@ -175,7 +175,7 @@ def require_organization_member( **kwargs: ParamT.kwargs, ) -> HttpResponse: if user_profile.role > UserProfile.ROLE_MEMBER: - raise OrganizationMemberRequired() + raise OrganizationMemberRequiredError() return func(request, user_profile, *args, **kwargs) return wrapper @@ -303,15 +303,15 @@ def log_unsupported_webhook_event(summary: str) -> None: # webhook integrations (e.g. GitHub) that need to log an unsupported # event based on attributes nested deep within a complicated JSON # payload. In such cases, the error message we want to log may not - # really fit what a regular UnsupportedWebhookEventType exception + # really fit what a regular UnsupportedWebhookEventTypeError exception # represents. webhook_unsupported_events_logger.exception(summary, stack_info=True) def log_exception_to_webhook_logger(err: Exception) -> None: - if isinstance(err, AnomalousWebhookPayload): + if isinstance(err, AnomalousWebhookPayloadError): webhook_anomalous_payloads_logger.exception(str(err), stack_info=True) - elif isinstance(err, UnsupportedWebhookEventType): + elif isinstance(err, UnsupportedWebhookEventTypeError): webhook_unsupported_events_logger.exception(str(err), stack_info=True) else: webhook_logger.exception(str(err), stack_info=True) diff --git a/zerver/forms.py b/zerver/forms.py index f7ae6bfa3d..cf72ea25aa 100644 --- a/zerver/forms.py +++ b/zerver/forms.py @@ -26,7 +26,7 @@ from zerver.lib.email_validation import ( email_allowed_for_realm, email_reserved_for_system_bots_error, ) -from zerver.lib.exceptions import JsonableError, RateLimited +from zerver.lib.exceptions import JsonableError, RateLimitedError from zerver.lib.name_restrictions import is_disposable_domain, is_reserved_subdomain from zerver.lib.rate_limiter import RateLimitedObject, rate_limit_request_by_ip from zerver.lib.send_email import FromAddress, send_email @@ -344,7 +344,7 @@ class ZulipPasswordResetForm(PasswordResetForm): try: rate_limit_password_reset_form_by_email(email) rate_limit_request_by_ip(request, domain="sends_email_by_ip") - except RateLimited: + except RateLimitedError: logging.info( "Too many password reset attempts for email %s from %s", email, @@ -418,7 +418,7 @@ class RateLimitedPasswordResetByEmail(RateLimitedObject): def rate_limit_password_reset_form_by_email(email: str) -> None: ratelimited, secs_to_freedom = RateLimitedPasswordResetByEmail(email).rate_limit() if ratelimited: - raise RateLimited(secs_to_freedom) + raise RateLimitedError(secs_to_freedom) class CreateUserForm(forms.Form): @@ -447,7 +447,7 @@ class OurAuthenticationForm(AuthenticationForm): realm=realm, return_data=return_data, ) - except RateLimited as e: + except RateLimitedError as e: assert e.secs_to_freedom is not None secs_to_freedom = int(e.secs_to_freedom) error_message = _( diff --git a/zerver/lib/bot_lib.py b/zerver/lib/bot_lib.py index 47750d9e2b..f9e4fe1da0 100644 --- a/zerver/lib/bot_lib.py +++ b/zerver/lib/bot_lib.py @@ -58,11 +58,11 @@ class StateHandler: return is_key_in_bot_storage(self.user_profile, key) -class EmbeddedBotQuitException(Exception): +class EmbeddedBotQuitError(Exception): pass -class EmbeddedBotEmptyRecipientsList(Exception): +class EmbeddedBotEmptyRecipientsListError(Exception): pass @@ -102,7 +102,7 @@ class EmbeddedBotHandler: recipients = ",".join(message["to"]).split(",") if len(message["to"]) == 0: - raise EmbeddedBotEmptyRecipientsList(_("Message must have recipients!")) + raise EmbeddedBotEmptyRecipientsListError(_("Message must have recipients!")) elif len(message["to"]) == 1: recipient_user = get_active_user(recipients[0], self.user_profile.realm) message_id = internal_send_private_message( @@ -151,4 +151,4 @@ class EmbeddedBotHandler: raise def quit(self, message: str = "") -> None: - raise EmbeddedBotQuitException(message) + raise EmbeddedBotQuitError(message) diff --git a/zerver/lib/cache.py b/zerver/lib/cache.py index f2f8c3c8b9..b05e2b3fa5 100644 --- a/zerver/lib/cache.py +++ b/zerver/lib/cache.py @@ -44,11 +44,6 @@ ReturnT = TypeVar("ReturnT") logger = logging.getLogger() - -class NotFoundInCache(Exception): - pass - - remote_cache_time_start = 0.0 remote_cache_total_time = 0.0 remote_cache_total_requests = 0 @@ -151,7 +146,7 @@ def cache_with_key( try: val = cache_get(key, cache_name=cache_name) - except InvalidCacheKeyException: + except InvalidCacheKeyError: stack_trace = traceback.format_exc() log_invalid_cache_keys(stack_trace, [key]) return func(*args, **kwargs) @@ -190,7 +185,7 @@ def cache_with_key( return decorator -class InvalidCacheKeyException(Exception): +class InvalidCacheKeyError(Exception): pass @@ -215,9 +210,9 @@ def validate_cache_key(key: str) -> None: # The regex checks "all characters between ! and ~ in the ascii table", # which happens to be the set of all "nice" ascii characters. if not bool(re.fullmatch(r"([!-~])+", key)): - raise InvalidCacheKeyException("Invalid characters in the cache key: " + key) + raise InvalidCacheKeyError("Invalid characters in the cache key: " + key) if len(key) > MEMCACHED_MAX_KEY_LENGTH: - raise InvalidCacheKeyException(f"Cache key too long: {key} Length: {len(key)}") + raise InvalidCacheKeyError(f"Cache key too long: {key} Length: {len(key)}") def cache_set( @@ -262,7 +257,7 @@ def safe_cache_get_many(keys: List[str], cache_name: Optional[str] = None) -> Di # to do normal cache_get_many to avoid the overhead of # validating all the keys here. return cache_get_many(keys, cache_name) - except InvalidCacheKeyException: + except InvalidCacheKeyError: stack_trace = traceback.format_exc() good_keys, bad_keys = filter_good_and_bad_keys(keys) @@ -295,7 +290,7 @@ def safe_cache_set_many( # to do normal cache_set_many to avoid the overhead of # validating all the keys here. return cache_set_many(items, cache_name, timeout) - except InvalidCacheKeyException: + except InvalidCacheKeyError: stack_trace = traceback.format_exc() good_keys, bad_keys = filter_good_and_bad_keys(list(items.keys())) @@ -330,7 +325,7 @@ def filter_good_and_bad_keys(keys: List[str]) -> Tuple[List[str], List[str]]: try: validate_cache_key(key) good_keys.append(key) - except InvalidCacheKeyException: + except InvalidCacheKeyError: bad_keys.append(key) return good_keys, bad_keys diff --git a/zerver/lib/email_mirror.py b/zerver/lib/email_mirror.py index 4988e0f566..f89e0679ad 100644 --- a/zerver/lib/email_mirror.py +++ b/zerver/lib/email_mirror.py @@ -20,7 +20,7 @@ from zerver.lib.email_mirror_helpers import ( get_email_gateway_message_string_from_address, ) from zerver.lib.email_notifications import convert_html_to_markdown -from zerver.lib.exceptions import JsonableError, RateLimited +from zerver.lib.exceptions import JsonableError, RateLimitedError from zerver.lib.message import normalize_body, truncate_topic from zerver.lib.queue import queue_json_publish from zerver.lib.rate_limiter import RateLimitedObject @@ -534,4 +534,4 @@ def rate_limit_mirror_by_realm(recipient_realm: Realm) -> None: ratelimited, secs_to_freedom = RateLimitedRealmMirror(recipient_realm).rate_limit() if ratelimited: - raise RateLimited(secs_to_freedom) + raise RateLimitedError(secs_to_freedom) diff --git a/zerver/lib/events.py b/zerver/lib/events.py index 99e90ca0ee..c36a588ac6 100644 --- a/zerver/lib/events.py +++ b/zerver/lib/events.py @@ -76,7 +76,7 @@ from zerver.tornado.django_api import get_user_events, request_event_queue from zproject.backends import email_auth_enabled, password_auth_enabled -class RestartEventException(Exception): +class RestartEventError(Exception): """ Special error for handling restart events in apply_events. """ @@ -646,7 +646,7 @@ def apply_events( ) -> None: for event in events: if event["type"] == "restart": - raise RestartEventException() + raise RestartEventError() if fetch_event_types is not None and event["type"] not in fetch_event_types: # TODO: continuing here is not, most precisely, correct. # In theory, an event of one type, e.g. `realm_user`, @@ -1483,7 +1483,7 @@ def do_events_register( slim_presence=slim_presence, include_subscribers=include_subscribers, ) - except RestartEventException: + except RestartEventError: # This represents a rare race condition, where Tornado # restarted (and sent `restart` events) while we were waiting # for fetch_initial_state_data to return. To avoid the client diff --git a/zerver/lib/exceptions.py b/zerver/lib/exceptions.py index de49e31f79..ffa356da42 100644 --- a/zerver/lib/exceptions.py +++ b/zerver/lib/exceptions.py @@ -185,7 +185,7 @@ class CannotDeactivateLastUserError(JsonableError): return _("Cannot deactivate the only {entity}.") -class InvalidMarkdownIncludeStatement(JsonableError): +class InvalidMarkdownIncludeStatementError(JsonableError): code = ErrorCode.INVALID_MARKDOWN_INCLUDE_STATEMENT data_fields = ["include_statement"] @@ -197,7 +197,7 @@ class InvalidMarkdownIncludeStatement(JsonableError): return _("Invalid Markdown include statement: {include_statement}") -class RateLimited(JsonableError): +class RateLimitedError(JsonableError): code = ErrorCode.RATE_LIMIT_HIT http_status_code = 429 @@ -232,7 +232,7 @@ class InvalidJSONError(JsonableError): return _("Malformed JSON") -class OrganizationMemberRequired(JsonableError): +class OrganizationMemberRequiredError(JsonableError): code: ErrorCode = ErrorCode.UNAUTHORIZED_PRINCIPAL def __init__(self) -> None: @@ -243,7 +243,7 @@ class OrganizationMemberRequired(JsonableError): return _("Must be an organization member") -class OrganizationAdministratorRequired(JsonableError): +class OrganizationAdministratorRequiredError(JsonableError): code: ErrorCode = ErrorCode.UNAUTHORIZED_PRINCIPAL def __init__(self) -> None: @@ -254,7 +254,7 @@ class OrganizationAdministratorRequired(JsonableError): return _("Must be an organization administrator") -class OrganizationOwnerRequired(JsonableError): +class OrganizationOwnerRequiredError(JsonableError): code: ErrorCode = ErrorCode.UNAUTHORIZED_PRINCIPAL def __init__(self) -> None: @@ -320,7 +320,7 @@ class PasswordResetRequiredError(AuthenticationFailedError): return _("Your password has been disabled and needs to be reset") -class MarkdownRenderingException(Exception): +class MarkdownRenderingError(Exception): pass @@ -346,7 +346,7 @@ class WebhookError(JsonableError): """ Intended as a generic exception raised by specific webhook integrations. This class is subclassed by more specific exceptions - such as UnsupportedWebhookEventType and AnomalousWebhookPayload. + such as UnsupportedWebhookEventTypeError and AnomalousWebhookPayloadError. """ data_fields = ["webhook_name"] @@ -357,14 +357,14 @@ class WebhookError(JsonableError): self.webhook_name = "(unknown)" -class UnsupportedWebhookEventType(WebhookError): +class UnsupportedWebhookEventTypeError(WebhookError): """Intended as an exception for event formats that we know the third-party service generates but which Zulip doesn't support / generate a message for. Exceptions where we cannot parse the event type, possibly because the event isn't actually from the service in question, should - raise AnomalousWebhookPayload. + raise AnomalousWebhookPayloadError. """ code = ErrorCode.UNSUPPORTED_WEBHOOK_EVENT_TYPE @@ -379,14 +379,14 @@ class UnsupportedWebhookEventType(WebhookError): return _("The '{event_type}' event isn't currently supported by the {webhook_name} webhook") -class AnomalousWebhookPayload(WebhookError): +class AnomalousWebhookPayloadError(WebhookError): """Intended as an exception for incoming webhook requests that we cannot recognize as having been generated by the service in question. (E.g. because someone pointed a Jira server at the GitHub integration URL). If we can parse the event but don't support it, use - UnsupportedWebhookEventType. + UnsupportedWebhookEventTypeError. """ @@ -420,7 +420,7 @@ class InvalidSubdomainError(JsonableError): return _("Invalid subdomain") -class ZephyrMessageAlreadySentException(Exception): +class ZephyrMessageAlreadySentError(Exception): def __init__(self, message_id: int) -> None: self.message_id = message_id diff --git a/zerver/lib/github.py b/zerver/lib/github.py index 08397c3ff3..8ed20b6542 100644 --- a/zerver/lib/github.py +++ b/zerver/lib/github.py @@ -43,14 +43,14 @@ PLATFORM_TO_SETUP_FILE = { } -class InvalidPlatform(Exception): +class InvalidPlatformError(Exception): pass @cache_with_key(lambda platform: f"download_link:{platform}", timeout=60 * 30) def get_latest_github_release_download_link_for_platform(platform: str) -> str: if platform not in PLATFORM_TO_SETUP_FILE: - raise InvalidPlatform() + raise InvalidPlatformError() latest_version = get_latest_github_release_version_for_repo("zulip-desktop") if latest_version: diff --git a/zerver/lib/markdown/__init__.py b/zerver/lib/markdown/__init__.py index c35b0582c3..97ff461160 100644 --- a/zerver/lib/markdown/__init__.py +++ b/zerver/lib/markdown/__init__.py @@ -50,7 +50,7 @@ from zerver.lib import mention as mention from zerver.lib.cache import cache_with_key from zerver.lib.camo import get_camo_url from zerver.lib.emoji import EMOTICON_RE, codepoint_to_name, name_to_codepoint, translate_emoticons -from zerver.lib.exceptions import MarkdownRenderingException +from zerver.lib.exceptions import MarkdownRenderingError from zerver.lib.markdown import fenced_code from zerver.lib.markdown.fenced_code import FENCE_RE from zerver.lib.mention import ( @@ -63,7 +63,7 @@ from zerver.lib.outgoing_http import OutgoingSession from zerver.lib.subdomains import is_static_or_current_realm_url from zerver.lib.tex import render_tex from zerver.lib.thumbnail import user_uploads_or_external -from zerver.lib.timeout import TimeoutExpired, timeout +from zerver.lib.timeout import TimeoutExpiredError, timeout from zerver.lib.timezone import common_timezones from zerver.lib.types import LinkifierDict from zerver.lib.url_encoding import encode_stream, hash_util_encode @@ -474,7 +474,7 @@ def fetch_tweet_data(tweet_id: str) -> Optional[Dict[str, Any]]: # formatting timeout. tweet = timeout(3, lambda: api.GetStatus(tweet_id)) res = tweet.AsDict() - except TimeoutExpired: + except TimeoutExpiredError: # We'd like to try again later and not cache the bad result, # so we need to re-raise the exception (just as though # we were being rate-limited) @@ -2581,7 +2581,7 @@ def do_convert( # something huge. MAX_MESSAGE_LENGTH = settings.MAX_MESSAGE_LENGTH if len(rendering_result.rendered_content) > MAX_MESSAGE_LENGTH * 100: - raise MarkdownRenderingException( + raise MarkdownRenderingError( f"Rendered content exceeds {MAX_MESSAGE_LENGTH * 100} characters (message {logging_message_id})" ) return rendering_result @@ -2596,7 +2596,7 @@ def do_convert( logging_message_id, ) - raise MarkdownRenderingException() + raise MarkdownRenderingError() finally: # These next three lines are slightly paranoid, since # we always set these right before actually using the diff --git a/zerver/lib/markdown/fenced_code.py b/zerver/lib/markdown/fenced_code.py index d50078e49a..6c9a288b75 100644 --- a/zerver/lib/markdown/fenced_code.py +++ b/zerver/lib/markdown/fenced_code.py @@ -87,7 +87,7 @@ from markdown.preprocessors import Preprocessor from pygments.lexers import find_lexer_class_by_name from pygments.util import ClassNotFound -from zerver.lib.exceptions import MarkdownRenderingException +from zerver.lib.exceptions import MarkdownRenderingError from zerver.lib.markdown.priorities import PREPROCESSOR_PRIORITES from zerver.lib.tex import render_tex @@ -137,7 +137,7 @@ Missing required -X argument in curl command: regex = r'curl [-](sS)?X "?(GET|DELETE|PATCH|POST)"?' if line.startswith("curl"): if re.search(regex, line) is None: - raise MarkdownRenderingException(error_msg.format(command=line.strip())) + raise MarkdownRenderingError(error_msg.format(command=line.strip())) CODE_VALIDATORS: Dict[Optional[str], Callable[[List[str]], None]] = { diff --git a/zerver/lib/markdown/include.py b/zerver/lib/markdown/include.py index deab46f44f..f694e751ef 100644 --- a/zerver/lib/markdown/include.py +++ b/zerver/lib/markdown/include.py @@ -7,7 +7,7 @@ from markdown import Extension, Markdown from markdown.blockparser import BlockParser from markdown.blockprocessors import BlockProcessor -from zerver.lib.exceptions import InvalidMarkdownIncludeStatement +from zerver.lib.exceptions import InvalidMarkdownIncludeStatementError from zerver.lib.markdown.priorities import BLOCK_PROCESSOR_PRIORITIES @@ -39,7 +39,7 @@ class IncludeBlockProcessor(BlockProcessor): with open(os.path.normpath(os.path.join(self.base_path, m[1]))) as f: lines = f.read().splitlines() except OSError as e: - raise InvalidMarkdownIncludeStatement(m[0].strip()) from e + raise InvalidMarkdownIncludeStatementError(m[0].strip()) from e for prep in self.parser.md.preprocessors: lines = prep.run(lines) diff --git a/zerver/lib/mdiff.py b/zerver/lib/mdiff.py index ccd58c521b..5163112c47 100755 --- a/zerver/lib/mdiff.py +++ b/zerver/lib/mdiff.py @@ -3,7 +3,7 @@ import os import subprocess -class DiffException(Exception): +class DiffError(Exception): pass @@ -13,7 +13,7 @@ def diff_strings(output: str, expected_output: str) -> str: if not os.path.isfile(mdiff_path): # nocoverage msg = "Cannot find mdiff for Markdown diff rendering" logging.error(msg) - raise DiffException(msg) + raise DiffError(msg) command = ["node", mdiff_path, output, expected_output] diff = subprocess.check_output(command, text=True) diff --git a/zerver/lib/narrow.py b/zerver/lib/narrow.py index 697de10d9b..41077bd116 100644 --- a/zerver/lib/narrow.py +++ b/zerver/lib/narrow.py @@ -186,7 +186,7 @@ def build_narrow_filter(narrow: Collection[Sequence[str]]) -> Callable[[Mapping[ LARGER_THAN_MAX_MESSAGE_ID = 10000000000000000 -class BadNarrowOperator(JsonableError): +class BadNarrowOperatorError(JsonableError): code = ErrorCode.BAD_NARROW data_fields = ["desc"] @@ -284,7 +284,7 @@ class NarrowBuilder: method_name = "by_" + operator.replace("-", "_") method = getattr(self, method_name, None) if method is None: - raise BadNarrowOperator("unknown operator " + operator) + raise BadNarrowOperatorError("unknown operator " + operator) if negated: maybe_negate = not_ @@ -295,7 +295,7 @@ class NarrowBuilder: def by_has(self, query: Select, operand: str, maybe_negate: ConditionTransform) -> Select: if operand not in ["attachment", "image", "link"]: - raise BadNarrowOperator("unknown 'has' operand " + operand) + raise BadNarrowOperatorError("unknown 'has' operand " + operand) col_name = "has_" + operand cond = column(col_name, Boolean) return query.where(maybe_negate(cond)) @@ -311,7 +311,7 @@ class NarrowBuilder: elif operand == "all": return query - raise BadNarrowOperator("unknown 'in' operand " + operand) + raise BadNarrowOperatorError("unknown 'in' operand " + operand) def by_is(self, query: Select, operand: str, maybe_negate: ConditionTransform) -> Select: # This operator class does not support is_web_public_query. @@ -338,7 +338,7 @@ class NarrowBuilder: elif operand == "resolved": cond = get_resolved_topic_condition_sa() return query.where(maybe_negate(cond)) - raise BadNarrowOperator("unknown 'is' operand " + operand) + raise BadNarrowOperatorError("unknown 'is' operand " + operand) _alphanum = frozenset("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") @@ -371,9 +371,9 @@ class NarrowBuilder: stream = get_stream_by_narrow_operand_access_unchecked(operand, self.realm) if self.is_web_public_query and not stream.is_web_public: - raise BadNarrowOperator("unknown web-public stream " + str(operand)) + raise BadNarrowOperatorError("unknown web-public stream " + str(operand)) except Stream.DoesNotExist: - raise BadNarrowOperator("unknown stream " + str(operand)) + raise BadNarrowOperatorError("unknown stream " + str(operand)) if self.realm.is_zephyr_mirror_realm: # MIT users expect narrowing to "social" to also show messages to @@ -412,7 +412,7 @@ class NarrowBuilder: elif operand == "web-public": recipient_queryset = get_web_public_streams_queryset(self.realm) else: - raise BadNarrowOperator("unknown streams operand " + operand) + raise BadNarrowOperatorError("unknown streams operand " + operand) recipient_ids = recipient_queryset.values_list("recipient_id", flat=True).order_by("id") cond = column("recipient_id", Integer).in_(recipient_ids) @@ -472,7 +472,7 @@ class NarrowBuilder: else: sender = get_user_by_id_in_realm_including_cross_realm(operand, self.realm) except UserProfile.DoesNotExist: - raise BadNarrowOperator("unknown user " + str(operand)) + raise BadNarrowOperatorError("unknown user " + str(operand)) cond = column("sender_id", Integer) == literal(sender.id) return query.where(maybe_negate(cond)) @@ -484,7 +484,7 @@ class NarrowBuilder: self, query: Select, operand: Union[int, str], maybe_negate: ConditionTransform ) -> Select: if not str(operand).isdigit(): - raise BadNarrowOperator("Invalid message ID") + raise BadNarrowOperatorError("Invalid message ID") cond = self.msg_id_column == literal(operand) return query.where(maybe_negate(cond)) @@ -520,7 +520,7 @@ class NarrowBuilder: allow_deactivated=True, ) except (JsonableError, ValidationError): - raise BadNarrowOperator("unknown user in " + str(operand)) + raise BadNarrowOperatorError("unknown user in " + str(operand)) # Group DM if recipient.type == Recipient.HUDDLE: @@ -576,7 +576,7 @@ class NarrowBuilder: else: narrow_profile = get_user_by_id_in_realm_including_cross_realm(operand, self.realm) except UserProfile.DoesNotExist: - raise BadNarrowOperator("unknown user " + str(operand)) + raise BadNarrowOperatorError("unknown user " + str(operand)) self_recipient_ids = [ recipient_tuple["recipient_id"] diff --git a/zerver/lib/rate_limiter.py b/zerver/lib/rate_limiter.py index fcf6753e35..3b824563cb 100644 --- a/zerver/lib/rate_limiter.py +++ b/zerver/lib/rate_limiter.py @@ -11,7 +11,7 @@ from django.conf import settings from django.http import HttpRequest from zerver.lib.cache import cache_with_key -from zerver.lib.exceptions import RateLimited +from zerver.lib.exceptions import RateLimitedError from zerver.lib.redis_utils import get_redis_client from zerver.lib.utils import statsd from zerver.models import UserProfile @@ -27,7 +27,7 @@ KEY_PREFIX = "" logger = logging.getLogger(__name__) -class RateLimiterLockingException(Exception): +class RateLimiterLockingError(Exception): pass @@ -61,7 +61,7 @@ class RateLimitedObject(ABC): # Abort this request if the user is over their rate limits if ratelimited: # Pass information about what kind of entity got limited in the exception: - raise RateLimited(time) + raise RateLimitedError(time) calls_remaining, seconds_until_reset = self.api_calls_left() @@ -483,7 +483,7 @@ class RedisRateLimiterBackend(RateLimiterBackend): break except redis.WatchError: # nocoverage # Ideally we'd have a test for this. if count > 10: - raise RateLimiterLockingException() + raise RateLimiterLockingError() count += 1 continue @@ -500,7 +500,7 @@ class RedisRateLimiterBackend(RateLimiterBackend): else: try: cls.incr_ratelimit(entity_key, max_api_calls, max_api_window) - except RateLimiterLockingException: + except RateLimiterLockingError: logger.warning("Deadlock trying to incr_ratelimit for %s", entity_key) # rate-limit users who are hitting the API so hard we can't update our stats. ratelimited = True @@ -536,7 +536,7 @@ class RateLimitedSpectatorAttachmentAccessByFile(RateLimitedObject): def rate_limit_spectator_attachment_access_by_file(path_id: str) -> None: ratelimited, _ = RateLimitedSpectatorAttachmentAccessByFile(path_id).rate_limit() if ratelimited: - raise RateLimited + raise RateLimitedError def is_local_addr(addr: str) -> bool: @@ -579,7 +579,7 @@ def client_is_exempt_from_rate_limiting(request: HttpRequest) -> bool: def rate_limit_user(request: HttpRequest, user: UserProfile, domain: str) -> None: - """Returns whether or not a user was rate limited. Will raise a RateLimited exception + """Returns whether or not a user was rate limited. Will raise a RateLimitedError exception if the user has been rate limited, otherwise returns and modifies request to contain the rate limit information""" if not should_rate_limit(request): diff --git a/zerver/lib/remote_server.py b/zerver/lib/remote_server.py index 62fa3df145..4f04d62952 100644 --- a/zerver/lib/remote_server.py +++ b/zerver/lib/remote_server.py @@ -21,7 +21,7 @@ class PushBouncerSession(OutgoingSession): super().__init__(role="push_bouncer", timeout=30) -class PushNotificationBouncerException(Exception): +class PushNotificationBouncerError(Exception): pass @@ -87,7 +87,7 @@ def send_to_push_bouncer( msg = result_dict["msg"] if "code" in result_dict and result_dict["code"] == "INVALID_ZULIP_SERVER": # Invalid Zulip server credentials should email this server's admins - raise PushNotificationBouncerException( + raise PushNotificationBouncerError( _("Push notifications bouncer error: {}").format(msg) ) else: @@ -99,7 +99,7 @@ def send_to_push_bouncer( # Anything else is unexpected and likely suggests a bug in # this version of Zulip, so we throw an exception that will # email the server admins. - raise PushNotificationBouncerException( + raise PushNotificationBouncerError( f"Push notification bouncer returned unexpected status code {res.status_code}" ) diff --git a/zerver/lib/send_email.py b/zerver/lib/send_email.py index ed067594d5..3187cf73af 100644 --- a/zerver/lib/send_email.py +++ b/zerver/lib/send_email.py @@ -206,11 +206,11 @@ def build_email( return mail -class EmailNotDeliveredException(Exception): +class EmailNotDeliveredError(Exception): pass -class DoubledEmailArgumentException(CommandError): +class DoubledEmailArgumentError(CommandError): def __init__(self, argument_name: str) -> None: msg = ( f"Argument '{argument_name}' is ambiguously present in both options and email template." @@ -218,7 +218,7 @@ class DoubledEmailArgumentException(CommandError): super().__init__(msg) -class NoEmailArgumentException(CommandError): +class NoEmailArgumentError(CommandError): def __init__(self, argument_name: str) -> None: msg = f"Argument '{argument_name}' is required in either options or email template." super().__init__(msg) @@ -277,7 +277,7 @@ def send_email( # it will only call .close() if it was not open to begin with if connection.send_messages([mail]) == 0: logger.error("Unknown error sending %s email to %s", template, mail.to) - raise EmailNotDeliveredException + raise EmailNotDeliveredError except smtplib.SMTPResponseException as e: logger.exception( "Error sending %s email to %s with error code %s: %s", @@ -287,10 +287,10 @@ def send_email( e.smtp_error, stack_info=True, ) - raise EmailNotDeliveredException + raise EmailNotDeliveredError except smtplib.SMTPException as e: logger.exception("Error sending %s email to %s: %s", template, mail.to, e, stack_info=True) - raise EmailNotDeliveredException + raise EmailNotDeliveredError @backoff.on_exception(backoff.expo, OSError, max_tries=MAX_CONNECTION_TRIES, logger=None) @@ -488,9 +488,9 @@ def deliver_scheduled_emails(email: ScheduledEmail) -> None: def get_header(option: Optional[str], header: Optional[str], name: str) -> str: if option and header: - raise DoubledEmailArgumentException(name) + raise DoubledEmailArgumentError(name) if not option and not header: - raise NoEmailArgumentException(name) + raise NoEmailArgumentError(name) return str(option or header) @@ -564,7 +564,7 @@ def send_custom_email( context=context, dry_run=options["dry_run"], ) - except EmailNotDeliveredException: + except EmailNotDeliveredError: pass if options["dry_run"]: diff --git a/zerver/lib/streams.py b/zerver/lib/streams.py index 3df07eeb21..e7934a5596 100644 --- a/zerver/lib/streams.py +++ b/zerver/lib/streams.py @@ -9,8 +9,8 @@ from django.utils.translation import gettext as _ from zerver.actions.default_streams import get_default_streams_for_realm from zerver.lib.exceptions import ( JsonableError, - OrganizationAdministratorRequired, - OrganizationOwnerRequired, + OrganizationAdministratorRequiredError, + OrganizationOwnerRequiredError, ) from zerver.lib.markdown import markdown_convert from zerver.lib.stream_subscription import ( @@ -318,7 +318,7 @@ def check_stream_access_for_delete_or_update( if sub is None and stream.invite_only: raise JsonableError(error) - raise OrganizationAdministratorRequired() + raise OrganizationAdministratorRequiredError() def access_stream_for_delete_or_update( @@ -739,7 +739,7 @@ def list_to_streams( if message_retention_days_not_none: if not user_profile.is_realm_owner: - raise OrganizationOwnerRequired() + raise OrganizationOwnerRequiredError() user_profile.realm.ensure_not_on_limited_plan() diff --git a/zerver/lib/test_classes.py b/zerver/lib/test_classes.py index 54434473ce..d85fc4f4ca 100644 --- a/zerver/lib/test_classes.py +++ b/zerver/lib/test_classes.py @@ -66,7 +66,7 @@ from zerver.lib.streams import ( from zerver.lib.subscription_info import gather_subscriptions from zerver.lib.test_console_output import ( ExtraConsoleOutputFinder, - ExtraConsoleOutputInTestException, + ExtraConsoleOutputInTestError, tee_stderr_and_find_extra_console_output, tee_stdout_and_find_extra_console_output, ) @@ -192,7 +192,7 @@ Output: {extra_output_finder.full_extra_output.decode(errors="replace")} -------------------------------------------- """ - raise ExtraConsoleOutputInTestException(exception_message) + raise ExtraConsoleOutputInTestError(exception_message) return test_result """ diff --git a/zerver/lib/test_console_output.py b/zerver/lib/test_console_output.py index a12117cea5..e6119fa621 100644 --- a/zerver/lib/test_console_output.py +++ b/zerver/lib/test_console_output.py @@ -7,7 +7,7 @@ from types import TracebackType from typing import IO, Iterable, Iterator, List, Optional, Type -class ExtraConsoleOutputInTestException(Exception): +class ExtraConsoleOutputInTestError(Exception): pass diff --git a/zerver/lib/timeout.py b/zerver/lib/timeout.py index 2514ce4158..591e07c52a 100644 --- a/zerver/lib/timeout.py +++ b/zerver/lib/timeout.py @@ -9,7 +9,7 @@ from typing import Callable, Optional, Tuple, Type, TypeVar # Based on https://code.activestate.com/recipes/483752/ -class TimeoutExpired(Exception): +class TimeoutExpiredError(Exception): """Exception raised when a function times out.""" def __str__(self) -> str: @@ -24,7 +24,7 @@ def timeout(timeout: float, func: Callable[[], ResultT]) -> ResultT: Return its return value, or raise an exception, within approximately 'timeout' seconds. - The function may receive a TimeoutExpired exception + The function may receive a TimeoutExpiredError exception anywhere in its code, which could have arbitrary unsafe effects (resources not released, etc.). It might also fail to receive the exception and @@ -57,11 +57,11 @@ def timeout(timeout: float, func: Callable[[], ResultT]) -> ResultT: def raise_async_timeout(self) -> None: # This function is called from another thread; we attempt - # to raise a TimeoutExpired in _this_ thread. + # to raise a TimeoutExpiredError in _this_ thread. assert self.ident is not None ctypes.pythonapi.PyThreadState_SetAsyncExc( ctypes.c_ulong(self.ident), - ctypes.py_object(TimeoutExpired), + ctypes.py_object(TimeoutExpiredError), ) thread = TimeoutThread() @@ -86,7 +86,7 @@ def timeout(timeout: float, func: Callable[[], ResultT]) -> ResultT: # we just ignore it. if thread.is_alive(): logging.warning("Failed to time out backend thread") - raise TimeoutExpired + raise TimeoutExpiredError if thread.exc_info[1] is not None: # Died with some other exception; re-raise it diff --git a/zerver/lib/timestamp.py b/zerver/lib/timestamp.py index 3c54d5003f..f636d9a553 100644 --- a/zerver/lib/timestamp.py +++ b/zerver/lib/timestamp.py @@ -2,13 +2,13 @@ import calendar import datetime -class TimeZoneNotUTCException(Exception): +class TimeZoneNotUTCError(Exception): pass def verify_UTC(dt: datetime.datetime) -> None: if dt.tzinfo is None or dt.tzinfo.utcoffset(dt) != datetime.timezone.utc.utcoffset(dt): - raise TimeZoneNotUTCException(f"Datetime {dt} does not have a UTC time zone.") + raise TimeZoneNotUTCError(f"Datetime {dt} does not have a UTC time zone.") def convert_to_UTC(dt: datetime.datetime) -> datetime.datetime: diff --git a/zerver/lib/users.py b/zerver/lib/users.py index 94071ef739..81714fd3b1 100644 --- a/zerver/lib/users.py +++ b/zerver/lib/users.py @@ -21,8 +21,8 @@ from zerver.lib.cache import ( ) from zerver.lib.exceptions import ( JsonableError, - OrganizationAdministratorRequired, - OrganizationOwnerRequired, + OrganizationAdministratorRequiredError, + OrganizationOwnerRequiredError, ) from zerver.lib.timezone import canonicalize_timezone from zerver.lib.types import ProfileDataElementUpdateDict, ProfileDataElementValue @@ -145,12 +145,12 @@ def check_bot_creation_policy(user_profile: UserProfile, bot_type: int) -> None: if user_profile.realm.bot_creation_policy == Realm.BOT_CREATION_EVERYONE: return if user_profile.realm.bot_creation_policy == Realm.BOT_CREATION_ADMINS_ONLY: - raise OrganizationAdministratorRequired() + raise OrganizationAdministratorRequiredError() if ( user_profile.realm.bot_creation_policy == Realm.BOT_CREATION_LIMIT_GENERIC_BOTS and bot_type == UserProfile.DEFAULT_BOT ): - raise OrganizationAdministratorRequired() + raise OrganizationAdministratorRequiredError() def check_valid_bot_type(user_profile: UserProfile, bot_type: int) -> None: @@ -255,7 +255,7 @@ def access_bot_by_id(user_profile: UserProfile, user_id: int) -> UserProfile: # default, because it can be abused to send spam. Requiring an # owner is intended to ensure organizational responsibility # for use of this permission. - raise OrganizationOwnerRequired() + raise OrganizationOwnerRequiredError() return target diff --git a/zerver/lib/webhooks/common.py b/zerver/lib/webhooks/common.py index cb711606b4..985a81f768 100644 --- a/zerver/lib/webhooks/common.py +++ b/zerver/lib/webhooks/common.py @@ -57,7 +57,7 @@ def notify_bot_owner_about_invalid_json( ) -class MissingHTTPEventHeader(JsonableError): +class MissingHTTPEventHeaderError(JsonableError): code = ErrorCode.MISSING_HTTP_EVENT_HEADER data_fields = ["header"] @@ -176,7 +176,7 @@ def validate_extract_webhook_http_header( request.user, request.user.realm, message_body ) - raise MissingHTTPEventHeader(header) + raise MissingHTTPEventHeaderError(header) return extracted_header diff --git a/zerver/management/commands/deliver_scheduled_emails.py b/zerver/management/commands/deliver_scheduled_emails.py index ef22981ac3..503aa5d4a4 100644 --- a/zerver/management/commands/deliver_scheduled_emails.py +++ b/zerver/management/commands/deliver_scheduled_emails.py @@ -15,7 +15,7 @@ from django.db import transaction from django.utils.timezone import now as timezone_now from zerver.lib.logging_util import log_to_file -from zerver.lib.send_email import EmailNotDeliveredException, deliver_scheduled_emails +from zerver.lib.send_email import EmailNotDeliveredError, deliver_scheduled_emails from zerver.models import ScheduledEmail ## Setup ## @@ -46,7 +46,7 @@ Usage: ./manage.py deliver_scheduled_emails if job: try: deliver_scheduled_emails(job) - except EmailNotDeliveredException: + except EmailNotDeliveredError: logger.warning("%r not delivered", job) else: time.sleep(10) diff --git a/zerver/management/commands/sync_ldap_user_data.py b/zerver/management/commands/sync_ldap_user_data.py index 5c8a957d84..1b419f1ed6 100644 --- a/zerver/management/commands/sync_ldap_user_data.py +++ b/zerver/management/commands/sync_ldap_user_data.py @@ -9,7 +9,7 @@ from django.db import transaction from zerver.lib.logging_util import log_to_file from zerver.lib.management import ZulipBaseCommand from zerver.models import UserProfile -from zproject.backends import ZulipLDAPException, sync_user_from_ldap +from zproject.backends import ZulipLDAPError, sync_user_from_ldap ## Setup ## logger = logging.getLogger("zulip.sync_ldap_user_data") @@ -29,7 +29,7 @@ def sync_ldap_user_data( # does not exist. try: sync_user_from_ldap(u, logger) - except ZulipLDAPException as e: + except ZulipLDAPError as e: logger.error("Error attempting to update user %s:", u.delivery_email) logger.error(e.args[0]) diff --git a/zerver/models.py b/zerver/models.py index 84bedce234..58f9d60c64 100644 --- a/zerver/models.py +++ b/zerver/models.py @@ -81,7 +81,7 @@ from zerver.lib.cache import ( user_profile_by_id_cache_key, user_profile_cache_key, ) -from zerver.lib.exceptions import JsonableError, RateLimited +from zerver.lib.exceptions import JsonableError, RateLimitedError from zerver.lib.pysa import mark_sanitized from zerver.lib.timestamp import datetime_to_timestamp from zerver.lib.types import ( @@ -3506,7 +3506,7 @@ def validate_attachment_request_for_spectator_access( from zerver.lib.rate_limiter import rate_limit_spectator_attachment_access_by_file rate_limit_spectator_attachment_access_by_file(attachment.path_id) - except RateLimited: + except RateLimitedError: return False return True @@ -4672,7 +4672,7 @@ class BotConfigData(models.Model): unique_together = ("bot_profile", "key") -class InvalidFakeEmailDomain(Exception): +class InvalidFakeEmailDomainError(Exception): pass @@ -4688,7 +4688,7 @@ def get_fake_email_domain(realm: Realm) -> str: # Check that the fake email domain can be used to form valid email addresses. validate_email(Address(username="bot", domain=settings.FAKE_EMAIL_DOMAIN).addr_spec) except ValidationError: - raise InvalidFakeEmailDomain( + raise InvalidFakeEmailDomainError( settings.FAKE_EMAIL_DOMAIN + " is not a valid domain. " "Consider setting the FAKE_EMAIL_DOMAIN setting." ) diff --git a/zerver/tests/test_auth_backends.py b/zerver/tests/test_auth_backends.py index dcdb58d9f5..244ee28a2c 100644 --- a/zerver/tests/test_auth_backends.py +++ b/zerver/tests/test_auth_backends.py @@ -71,7 +71,7 @@ from zerver.lib.email_validation import ( get_realm_email_validator, validate_email_is_valid, ) -from zerver.lib.exceptions import JsonableError, RateLimited +from zerver.lib.exceptions import JsonableError, RateLimitedError from zerver.lib.initial_password import initial_password from zerver.lib.mobile_auth_otp import otp_decrypt_api_key from zerver.lib.rate_limiter import add_ratelimit_rule, remove_ratelimit_rule @@ -127,6 +127,8 @@ from zproject.backends import ( GitHubAuthBackend, GitLabAuthBackend, GoogleAuthBackend, + NoMatchingLDAPUserError, + OutsideLDAPDomainError, PopulateUserLDAPError, RateLimitedAuthenticationByUsername, SAMLAuthBackend, @@ -136,9 +138,7 @@ from zproject.backends import ( ZulipDummyBackend, ZulipLDAPAuthBackend, ZulipLDAPConfigurationError, - ZulipLDAPException, - ZulipLDAPExceptionNoMatchingLDAPUser, - ZulipLDAPExceptionOutsideDomain, + ZulipLDAPError, ZulipLDAPUser, ZulipLDAPUserPopulator, ZulipRemoteUserBackend, @@ -672,9 +672,9 @@ class RateLimitAuthenticationTests(ZulipTestCase): self.assertIsNone(attempt_authentication(username, wrong_password)) # 2 failed attempts is the limit, so the next ones should get blocked, # even with the correct password. - with self.assertRaises(RateLimited): + with self.assertRaises(RateLimitedError): attempt_authentication(username, correct_password) - with self.assertRaises(RateLimited): + with self.assertRaises(RateLimitedError): attempt_authentication(username, wrong_password) # After enough time passes, more authentication attempts can be made: @@ -690,7 +690,7 @@ class RateLimitAuthenticationTests(ZulipTestCase): self.assertIsNone(attempt_authentication(username, wrong_password)) self.assertIsNone(attempt_authentication(username, wrong_password)) # But the third attempt goes over the limit: - with self.assertRaises(RateLimited): + with self.assertRaises(RateLimitedError): attempt_authentication(username, wrong_password) # Resetting the password also clears the rate-limit @@ -5529,7 +5529,7 @@ class DjangoToLDAPUsernameTests(ZulipTestCase): self.assertEqual(self.backend.django_to_ldap_username("hamlet"), "hamlet") self.assertEqual(self.backend.django_to_ldap_username("hamlet@zulip.com"), "hamlet") with self.assertRaisesRegex( - ZulipLDAPExceptionOutsideDomain, + OutsideLDAPDomainError, "Email hamlet@example.com does not match LDAP domain zulip.com.", ): self.backend.django_to_ldap_username("hamlet@example.com") @@ -5556,7 +5556,7 @@ class DjangoToLDAPUsernameTests(ZulipTestCase): self.backend.django_to_ldap_username("hamlet@zulip.com"), self.ldap_username("hamlet") ) # If there are no matches through the email search, raise exception: - with self.assertRaises(ZulipLDAPExceptionNoMatchingLDAPUser): + with self.assertRaises(NoMatchingLDAPUserError): self.backend.django_to_ldap_username("no_such_email@example.com") self.assertEqual( @@ -5564,7 +5564,7 @@ class DjangoToLDAPUsernameTests(ZulipTestCase): ) with self.assertLogs(level="WARNING") as m: - with self.assertRaises(ZulipLDAPExceptionNoMatchingLDAPUser): + with self.assertRaises(NoMatchingLDAPUserError): self.backend.django_to_ldap_username("shared_email@zulip.com") self.assertEqual( m.output, @@ -5938,19 +5938,19 @@ class TestLDAP(ZulipLDAPTestCase): realm.save() email = "spam@mailnator.com" - with self.assertRaisesRegex(ZulipLDAPException, "Email validation failed."): + with self.assertRaisesRegex(ZulipLDAPError, "Email validation failed."): self.backend.get_or_build_user(email, _LDAPUser()) realm.emails_restricted_to_domains = True realm.save(update_fields=["emails_restricted_to_domains"]) email = "spam+spam@mailnator.com" - with self.assertRaisesRegex(ZulipLDAPException, "Email validation failed."): + with self.assertRaisesRegex(ZulipLDAPError, "Email validation failed."): self.backend.get_or_build_user(email, _LDAPUser()) email = "spam@acme.com" with self.assertRaisesRegex( - ZulipLDAPException, "This email domain isn't allowed in this organization." + ZulipLDAPError, "This email domain isn't allowed in this organization." ): self.backend.get_or_build_user(email, _LDAPUser()) @@ -6167,7 +6167,7 @@ class TestZulipLDAPUserPopulator(ZulipLDAPTestCase): def test_too_short_name(self) -> None: self.change_ldap_user_attr("hamlet", "cn", "a") - with self.assertRaises(ZulipLDAPException), self.assertLogs( + with self.assertRaises(ZulipLDAPError), self.assertLogs( "django_auth_ldap", "WARNING" ) as warn_log: self.perform_ldap_sync(self.example_user("hamlet")) @@ -6417,7 +6417,7 @@ class TestZulipLDAPUserPopulator(ZulipLDAPTestCase): } ): with self.assertRaisesRegex( - ZulipLDAPException, "Custom profile field with name non_existent not found" + ZulipLDAPError, "Custom profile field with name non_existent not found" ), self.assertLogs("django_auth_ldap", "WARNING") as warn_log: self.perform_ldap_sync(self.example_user("hamlet")) self.assertEqual( @@ -6437,7 +6437,7 @@ class TestZulipLDAPUserPopulator(ZulipLDAPTestCase): } ): with self.assertRaisesRegex( - ZulipLDAPException, "Invalid data for birthday field" + ZulipLDAPError, "Invalid data for birthday field" ), self.assertLogs("django_auth_ldap", "WARNING") as warn_log: self.perform_ldap_sync(self.example_user("hamlet")) self.assertEqual( diff --git a/zerver/tests/test_cache.py b/zerver/tests/test_cache.py index baf1b96ba3..f1743cd054 100644 --- a/zerver/tests/test_cache.py +++ b/zerver/tests/test_cache.py @@ -6,7 +6,7 @@ from django.conf import settings from zerver.apps import flush_cache from zerver.lib.cache import ( MEMCACHED_MAX_KEY_LENGTH, - InvalidCacheKeyException, + InvalidCacheKeyError, bulk_cached_fetch, cache_delete, cache_delete_many, @@ -38,18 +38,18 @@ class AppsTest(ZulipTestCase): class CacheKeyValidationTest(ZulipTestCase): def test_validate_cache_key(self) -> None: validate_cache_key("nice_Ascii:string!~") - with self.assertRaises(InvalidCacheKeyException): + with self.assertRaises(InvalidCacheKeyError): validate_cache_key("utf8_character:Ä…") - with self.assertRaises(InvalidCacheKeyException): + with self.assertRaises(InvalidCacheKeyError): validate_cache_key("new_line_character:\n") - with self.assertRaises(InvalidCacheKeyException): + with self.assertRaises(InvalidCacheKeyError): validate_cache_key("control_character:\r") - with self.assertRaises(InvalidCacheKeyException): + with self.assertRaises(InvalidCacheKeyError): validate_cache_key("whitespace_character: ") - with self.assertRaises(InvalidCacheKeyException): + with self.assertRaises(InvalidCacheKeyError): validate_cache_key("too_long:" + "X" * MEMCACHED_MAX_KEY_LENGTH) - with self.assertRaises(InvalidCacheKeyException): + with self.assertRaises(InvalidCacheKeyError): # validate_cache_key does validation on a key with the # KEY_PREFIX appended to the start, so even though we're # passing something "short enough" here, it becomes too @@ -59,18 +59,18 @@ class CacheKeyValidationTest(ZulipTestCase): def test_cache_functions_raise_exception(self) -> None: invalid_key = "invalid_character:\n" good_key = "good_key" - with self.assertRaises(InvalidCacheKeyException): + with self.assertRaises(InvalidCacheKeyError): cache_get(invalid_key) - with self.assertRaises(InvalidCacheKeyException): + with self.assertRaises(InvalidCacheKeyError): cache_set(invalid_key, 0) - with self.assertRaises(InvalidCacheKeyException): + with self.assertRaises(InvalidCacheKeyError): cache_delete(invalid_key) - with self.assertRaises(InvalidCacheKeyException): + with self.assertRaises(InvalidCacheKeyError): cache_get_many([good_key, invalid_key]) - with self.assertRaises(InvalidCacheKeyException): + with self.assertRaises(InvalidCacheKeyError): cache_set_many({good_key: 0, invalid_key: 1}) - with self.assertRaises(InvalidCacheKeyException): + with self.assertRaises(InvalidCacheKeyError): cache_delete_many([good_key, invalid_key]) @@ -248,11 +248,11 @@ class GenericBulkCachedFetchTest(ZulipTestCase): # Get the user cached: get_user_profile_by_id(hamlet.id) - class CustomException(Exception): + class CustomError(Exception): pass def query_function(ids: List[int]) -> List[UserProfile]: - raise CustomException("The query function was called") + raise CustomError("The query function was called") # query_function shouldn't be called, because the only requested object # is already cached: @@ -268,7 +268,7 @@ class GenericBulkCachedFetchTest(ZulipTestCase): self.assertEqual(info_log.output, ["INFO:root:Clearing memcached cache after migrations"]) # With the cache flushed, the query_function should get called: - with self.assertRaises(CustomException): + with self.assertRaises(CustomError): result = bulk_cached_fetch( cache_key_function=user_profile_by_id_cache_key, query_function=query_function, @@ -277,18 +277,18 @@ class GenericBulkCachedFetchTest(ZulipTestCase): ) def test_empty_object_ids_list(self) -> None: - class CustomException(Exception): + class CustomError(Exception): pass def cache_key_function( email: str, ) -> str: # nocoverage -- this is just here to make sure it's not called - raise CustomException("The cache key function was called") + raise CustomError("The cache key function was called") def query_function( emails: List[str], ) -> List[UserProfile]: # nocoverage -- this is just here to make sure it's not called - raise CustomException("The query function was called") + raise CustomError("The query function was called") # query_function and cache_key_function shouldn't be called, because # objects_ids is empty, so there's nothing to do. diff --git a/zerver/tests/test_decorators.py b/zerver/tests/test_decorators.py index de2088c1ab..c1bfd818ee 100644 --- a/zerver/tests/test_decorators.py +++ b/zerver/tests/test_decorators.py @@ -43,7 +43,7 @@ from zerver.lib.exceptions import ( InvalidAPIKeyFormatError, InvalidJSONError, JsonableError, - UnsupportedWebhookEventType, + UnsupportedWebhookEventTypeError, ) from zerver.lib.initial_password import initial_password from zerver.lib.rate_limiter import is_local_addr @@ -315,7 +315,7 @@ class DecoratorTestCase(ZulipTestCase): def my_webhook_raises_exception_unsupported_event( request: HttpRequest, user_profile: UserProfile ) -> HttpResponse: - raise UnsupportedWebhookEventType("test_event") + raise UnsupportedWebhookEventTypeError("test_event") webhook_bot_email = "webhook-bot@zulip.com" webhook_bot_realm = get_realm("zulip") @@ -410,7 +410,7 @@ class DecoratorTestCase(ZulipTestCase): request.POST["api_key"] = webhook_bot_api_key exception_msg = "The 'test_event' event isn't currently supported by the ClientName webhook" with self.assertLogs("zulip.zerver.webhooks.unsupported", level="ERROR") as log: - with self.assertRaisesRegex(UnsupportedWebhookEventType, exception_msg): + with self.assertRaisesRegex(UnsupportedWebhookEventTypeError, exception_msg): request.body = b"invalidjson" request.content_type = "application/json" request.META["HTTP_X_CUSTOM_HEADER"] = "custom_value" @@ -564,7 +564,7 @@ class DecoratorLoggingTestCase(ZulipTestCase): def my_webhook_raises_exception( request: HttpRequest, user_profile: UserProfile ) -> HttpResponse: - raise UnsupportedWebhookEventType("test_event") + raise UnsupportedWebhookEventTypeError("test_event") webhook_bot_email = "webhook-bot@zulip.com" @@ -582,7 +582,7 @@ class DecoratorLoggingTestCase(ZulipTestCase): exception_msg = ( "The 'test_event' event isn't currently supported by the ClientName webhook" ) - with self.assertRaisesRegex(UnsupportedWebhookEventType, exception_msg): + with self.assertRaisesRegex(UnsupportedWebhookEventTypeError, exception_msg): my_webhook_raises_exception(request) mock_exception.assert_called_with(exception_msg, stack_info=True) diff --git a/zerver/tests/test_email_notifications.py b/zerver/tests/test_email_notifications.py index 8c0e9712ee..a37eca3751 100644 --- a/zerver/tests/test_email_notifications.py +++ b/zerver/tests/test_email_notifications.py @@ -110,10 +110,10 @@ class TestCustomEmails(ZulipTestCase): email_subject = "subject_test" markdown_template_path = "zerver/tests/fixtures/email/custom_emails/email_base_headers_no_headers_test.source.html" - from zerver.lib.send_email import NoEmailArgumentException + from zerver.lib.send_email import NoEmailArgumentError self.assertRaises( - NoEmailArgumentException, + NoEmailArgumentError, send_custom_email, [hamlet], options={ @@ -124,7 +124,7 @@ class TestCustomEmails(ZulipTestCase): ) self.assertRaises( - NoEmailArgumentException, + NoEmailArgumentError, send_custom_email, [hamlet], options={ @@ -142,10 +142,10 @@ class TestCustomEmails(ZulipTestCase): "zerver/tests/fixtures/email/custom_emails/email_base_headers_test.source.html" ) - from zerver.lib.send_email import DoubledEmailArgumentException + from zerver.lib.send_email import DoubledEmailArgumentError self.assertRaises( - DoubledEmailArgumentException, + DoubledEmailArgumentError, send_custom_email, [hamlet], options={ @@ -156,7 +156,7 @@ class TestCustomEmails(ZulipTestCase): ) self.assertRaises( - DoubledEmailArgumentException, + DoubledEmailArgumentError, send_custom_email, [hamlet], options={ diff --git a/zerver/tests/test_embedded_bot_system.py b/zerver/tests/test_embedded_bot_system.py index 964328b400..b0b0b37809 100644 --- a/zerver/tests/test_embedded_bot_system.py +++ b/zerver/tests/test_embedded_bot_system.py @@ -2,7 +2,7 @@ from unittest.mock import patch import orjson -from zerver.lib.bot_lib import EmbeddedBotQuitException +from zerver.lib.bot_lib import EmbeddedBotQuitError from zerver.lib.test_classes import ZulipTestCase from zerver.models import ( UserProfile, @@ -75,7 +75,7 @@ class TestEmbeddedBotMessaging(ZulipTestCase): assert self.bot_profile is not None with patch( "zulip_bots.bots.helloworld.helloworld.HelloWorldHandler.handle_message", - side_effect=EmbeddedBotQuitException("I'm quitting!"), + side_effect=EmbeddedBotQuitError("I'm quitting!"), ): with self.assertLogs(level="WARNING") as m: self.send_stream_message( diff --git a/zerver/tests/test_events.py b/zerver/tests/test_events.py index 91585e4147..3edf6d49d1 100644 --- a/zerver/tests/test_events.py +++ b/zerver/tests/test_events.py @@ -182,7 +182,7 @@ from zerver.lib.event_schema import ( check_user_topic, ) from zerver.lib.events import ( - RestartEventException, + RestartEventError, apply_events, fetch_initial_state_data, post_process_state, @@ -2499,7 +2499,7 @@ class NormalActionsTest(BaseAction): check_has_zoom_token("events[0]", events[0], value=False) def test_restart_event(self) -> None: - with self.assertRaises(RestartEventException): + with self.assertRaises(RestartEventError): self.verify_action(lambda: send_restart_events(immediate=True)) def test_display_setting_event_not_sent(self) -> None: diff --git a/zerver/tests/test_external.py b/zerver/tests/test_external.py index 2b4bbe2c15..4ab4c14b69 100644 --- a/zerver/tests/test_external.py +++ b/zerver/tests/test_external.py @@ -17,7 +17,7 @@ from zerver.lib.cache import cache_delete from zerver.lib.rate_limiter import ( RateLimitedIPAddr, RateLimitedUser, - RateLimiterLockingException, + RateLimiterLockingError, add_ratelimit_rule, get_tor_ips, remove_ratelimit_rule, @@ -447,7 +447,7 @@ class RateLimitTests(ZulipTestCase): with mock.patch( "zerver.lib.rate_limiter.RedisRateLimiterBackend.incr_ratelimit", - side_effect=RateLimiterLockingException, + side_effect=RateLimiterLockingError, ): with self.assertLogs("zerver.lib.rate_limiter", level="WARNING") as m: result = self.send_api_message(user, "some stuff") diff --git a/zerver/tests/test_github.py b/zerver/tests/test_github.py index 4c0c29bff0..de6567047e 100644 --- a/zerver/tests/test_github.py +++ b/zerver/tests/test_github.py @@ -2,7 +2,10 @@ import requests import responses from zerver.lib.cache import cache_delete -from zerver.lib.github import InvalidPlatform, get_latest_github_release_download_link_for_platform +from zerver.lib.github import ( + InvalidPlatformError, + get_latest_github_release_download_link_for_platform, +) from zerver.lib.test_classes import ZulipTestCase logger_string = "zerver.lib.github" @@ -81,5 +84,5 @@ class GitHubTestCase(ZulipTestCase): [f"ERROR:{logger_string}:App download link is broken {download_link}"], ) - with self.assertRaises(InvalidPlatform): + with self.assertRaises(InvalidPlatformError): get_latest_github_release_download_link_for_platform("plan9") diff --git a/zerver/tests/test_markdown.py b/zerver/tests/test_markdown.py index 483083d447..60587cf0c0 100644 --- a/zerver/tests/test_markdown.py +++ b/zerver/tests/test_markdown.py @@ -21,7 +21,7 @@ from zerver.lib.alert_words import get_alert_word_automaton from zerver.lib.camo import get_camo_url from zerver.lib.create_user import create_user from zerver.lib.emoji import get_emoji_url -from zerver.lib.exceptions import JsonableError, MarkdownRenderingException +from zerver.lib.exceptions import JsonableError, MarkdownRenderingError from zerver.lib.markdown import ( MarkdownListPreprocessor, MessageRenderingResult, @@ -2900,7 +2900,7 @@ class MarkdownApiTests(ZulipTestCase): class MarkdownErrorTests(ZulipTestCase): def test_markdown_error_handling(self) -> None: with self.simulated_markdown_failure(): - with self.assertRaises(MarkdownRenderingException): + with self.assertRaises(MarkdownRenderingError): markdown_convert_wrapper("") def test_send_message_errors(self) -> None: @@ -2921,7 +2921,7 @@ class MarkdownErrorTests(ZulipTestCase): with mock.patch("zerver.lib.markdown.timeout", return_value=msg), mock.patch( "zerver.lib.markdown.markdown_logger" ): - with self.assertRaises(MarkdownRenderingException): + with self.assertRaises(MarkdownRenderingError): markdown_convert_wrapper(msg) def test_curl_code_block_validation(self) -> None: @@ -2936,7 +2936,7 @@ class MarkdownErrorTests(ZulipTestCase): "```", ] - with self.assertRaises(MarkdownRenderingException): + with self.assertRaises(MarkdownRenderingError): processor.run(markdown_input) def test_curl_code_block_without_validation(self) -> None: diff --git a/zerver/tests/test_message_fetch.py b/zerver/tests/test_message_fetch.py index 904aa152ce..c5bbc8aa64 100644 --- a/zerver/tests/test_message_fetch.py +++ b/zerver/tests/test_message_fetch.py @@ -28,7 +28,7 @@ from zerver.lib.message import ( ) from zerver.lib.narrow import ( LARGER_THAN_MAX_MESSAGE_ID, - BadNarrowOperator, + BadNarrowOperatorError, NarrowBuilder, build_narrow_filter, exclude_muting_conditions, @@ -109,7 +109,7 @@ class NarrowBuilderTest(ZulipTestCase): def test_add_term_using_not_defined_operator(self) -> None: term = dict(operator="not-defined", operand="any") - self.assertRaises(BadNarrowOperator, self._build_query, term) + self.assertRaises(BadNarrowOperatorError, self._build_query, term) def test_add_term_using_stream_operator(self) -> None: term = dict(operator="stream", operand="Scotland") @@ -123,7 +123,7 @@ class NarrowBuilderTest(ZulipTestCase): self, ) -> None: # NEGATED term = dict(operator="stream", operand="NonExistingStream") - self.assertRaises(BadNarrowOperator, self._build_query, term) + self.assertRaises(BadNarrowOperatorError, self._build_query, term) def test_add_term_using_is_operator_and_private_operand(self) -> None: term = dict(operator="is", operand="private") @@ -133,7 +133,7 @@ class NarrowBuilderTest(ZulipTestCase): self, ) -> None: # NEGATED term = dict(operator="streams", operand="invalid_operands") - self.assertRaises(BadNarrowOperator, self._build_query, term) + self.assertRaises(BadNarrowOperatorError, self._build_query, term) def test_add_term_using_streams_operator_and_public_stream_operand(self) -> None: term = dict(operator="streams", operand="public") @@ -261,7 +261,7 @@ class NarrowBuilderTest(ZulipTestCase): def test_add_term_using_non_supported_operator_should_raise_error(self) -> None: term = dict(operator="is", operand="non_supported") - self.assertRaises(BadNarrowOperator, self._build_query, term) + self.assertRaises(BadNarrowOperatorError, self._build_query, term) def test_add_term_using_topic_operator_and_lunch_operand(self) -> None: term = dict(operator="topic", operand="lunch") @@ -291,7 +291,7 @@ class NarrowBuilderTest(ZulipTestCase): self, ) -> None: # NEGATED term = dict(operator="sender", operand="non-existing@zulip.com") - self.assertRaises(BadNarrowOperator, self._build_query, term) + self.assertRaises(BadNarrowOperatorError, self._build_query, term) def test_add_term_using_pm_with_operator_and_not_the_same_user_as_operand(self) -> None: term = dict(operator="pm-with", operand=self.othello_email) @@ -375,13 +375,13 @@ class NarrowBuilderTest(ZulipTestCase): def test_add_term_using_pm_with_operator_with_comma_noise(self) -> None: term = dict(operator="pm-with", operand=" ,,, ,,, ,") - self.assertRaises(BadNarrowOperator, self._build_query, term) + self.assertRaises(BadNarrowOperatorError, self._build_query, term) def test_add_term_using_pm_with_operator_with_existing_and_non_existing_user_as_operand( self, ) -> None: term = dict(operator="pm-with", operand=self.othello_email + ",non-existing@zulip.com") - self.assertRaises(BadNarrowOperator, self._build_query, term) + self.assertRaises(BadNarrowOperatorError, self._build_query, term) def test_add_term_using_id_operator(self) -> None: term = dict(operator="id", operand=555) @@ -389,10 +389,10 @@ class NarrowBuilderTest(ZulipTestCase): def test_add_term_using_id_operator_invalid(self) -> None: term = dict(operator="id", operand="") - self.assertRaises(BadNarrowOperator, self._build_query, term) + self.assertRaises(BadNarrowOperatorError, self._build_query, term) term = dict(operator="id", operand="notanint") - self.assertRaises(BadNarrowOperator, self._build_query, term) + self.assertRaises(BadNarrowOperatorError, self._build_query, term) def test_add_term_using_id_operator_and_negated(self) -> None: # NEGATED term = dict(operator="id", operand=555, negated=True) @@ -419,7 +419,7 @@ class NarrowBuilderTest(ZulipTestCase): def test_add_term_using_group_pm_operator_with_non_existing_user_as_operand(self) -> None: term = dict(operator="group-pm-with", operand="non-existing@zulip.com") - self.assertRaises(BadNarrowOperator, self._build_query, term) + self.assertRaises(BadNarrowOperatorError, self._build_query, term) @override_settings(USING_PGROONGA=False) def test_add_term_using_search_operator(self) -> None: @@ -475,7 +475,7 @@ class NarrowBuilderTest(ZulipTestCase): def test_add_term_using_has_operator_non_supported_operand_should_raise_error(self) -> None: term = dict(operator="has", operand="non_supported") - self.assertRaises(BadNarrowOperator, self._build_query, term) + self.assertRaises(BadNarrowOperatorError, self._build_query, term) def test_add_term_using_in_operator(self) -> None: mute_stream(self.realm, self.user_profile, "Verona") @@ -503,7 +503,7 @@ class NarrowBuilderTest(ZulipTestCase): def test_add_term_using_in_operator_and_not_defined_operand(self) -> None: term = dict(operator="in", operand="not_defined") - self.assertRaises(BadNarrowOperator, self._build_query, term) + self.assertRaises(BadNarrowOperatorError, self._build_query, term) def test_add_term_using_near_operator(self) -> None: term = dict(operator="near", operand="operand") @@ -518,7 +518,7 @@ class NarrowBuilderTest(ZulipTestCase): def _build_query(term: Dict[str, Any]) -> Select: return builder.add_term(self.raw_query, term) - self.assertRaises(BadNarrowOperator, _build_query, term) + self.assertRaises(BadNarrowOperatorError, _build_query, term) def _do_add_term_test( self, term: Dict[str, Any], where_clause: str, params: Optional[Dict[str, Any]] = None diff --git a/zerver/tests/test_message_flags.py b/zerver/tests/test_message_flags.py index f8f423ee80..2bb78a3dc9 100644 --- a/zerver/tests/test_message_flags.py +++ b/zerver/tests/test_message_flags.py @@ -22,7 +22,7 @@ from zerver.lib.message import ( ) from zerver.lib.test_classes import ZulipTestCase from zerver.lib.test_helpers import get_subscription, timeout_mock -from zerver.lib.timeout import TimeoutExpired +from zerver.lib.timeout import TimeoutExpiredError from zerver.lib.user_topics import add_topic_mute from zerver.models import ( Message, @@ -688,7 +688,7 @@ class MarkAllAsReadEndpointTest(ZulipTestCase): def test_mark_all_as_read_timeout_response(self) -> None: self.login("hamlet") - with mock.patch("zerver.views.message_flags.timeout", side_effect=TimeoutExpired): + with mock.patch("zerver.views.message_flags.timeout", side_effect=TimeoutExpiredError): result = self.client_post("/json/mark_all_as_read", {}) self.assertEqual(result.status_code, 200) diff --git a/zerver/tests/test_message_send.py b/zerver/tests/test_message_send.py index f338c5d57f..2eadb19018 100644 --- a/zerver/tests/test_message_send.py +++ b/zerver/tests/test_message_send.py @@ -63,7 +63,7 @@ from zerver.models import ( get_system_bot, get_user, ) -from zerver.views.message_send import InvalidMirrorInput +from zerver.views.message_send import InvalidMirrorInputError if sys.version_info < (3, 9): # nocoverage from backports import zoneinfo @@ -1098,7 +1098,7 @@ class MessagePOSTTest(ZulipTestCase): def test_send_message_create_mirrored_message_user_returns_invalid_input( self, create_mirrored_message_users_mock: Any ) -> None: - create_mirrored_message_users_mock.side_effect = InvalidMirrorInput() + create_mirrored_message_users_mock.side_effect = InvalidMirrorInputError() result = self.api_post( self.mit_user("starnine"), "/api/v1/messages", diff --git a/zerver/tests/test_message_topics.py b/zerver/tests/test_message_topics.py index 34806c5787..45ec739b72 100644 --- a/zerver/tests/test_message_topics.py +++ b/zerver/tests/test_message_topics.py @@ -6,7 +6,7 @@ from django.utils.timezone import now as timezone_now from zerver.actions.streams import do_change_stream_permission from zerver.lib.test_classes import ZulipTestCase from zerver.lib.test_helpers import timeout_mock -from zerver.lib.timeout import TimeoutExpired +from zerver.lib.timeout import TimeoutExpiredError from zerver.models import Message, UserMessage, get_client, get_realm, get_stream @@ -322,7 +322,7 @@ class TopicDeleteTest(ZulipTestCase): self.login_user(user_profile) endpoint = "/json/streams/" + str(stream.id) + "/delete_topic" - with mock.patch("zerver.views.streams.timeout", side_effect=TimeoutExpired): + with mock.patch("zerver.views.streams.timeout", side_effect=TimeoutExpiredError): result = self.client_post( endpoint, { diff --git a/zerver/tests/test_mirror_users.py b/zerver/tests/test_mirror_users.py index dc2390d891..8f20fcc377 100644 --- a/zerver/tests/test_mirror_users.py +++ b/zerver/tests/test_mirror_users.py @@ -9,7 +9,7 @@ from zerver.lib.create_user import create_user_profile from zerver.lib.test_classes import ZulipTestCase from zerver.lib.test_helpers import reset_emails_in_zulip_realm from zerver.models import UserProfile, get_client, get_realm, get_user -from zerver.views.message_send import InvalidMirrorInput, create_mirrored_message_users +from zerver.views.message_send import InvalidMirrorInputError, create_mirrored_message_users class MirroredMessageUsersTest(ZulipTestCase): @@ -22,7 +22,7 @@ class MirroredMessageUsersTest(ZulipTestCase): message_type = "private" client = get_client("banned_mirror") - with self.assertRaises(InvalidMirrorInput): + with self.assertRaises(InvalidMirrorInputError): create_mirrored_message_users(client, user, recipients, sender.email, message_type) def test_invalid_email(self) -> None: @@ -38,7 +38,7 @@ class MirroredMessageUsersTest(ZulipTestCase): for client_name in ["zephyr_mirror", "irc_mirror", "jabber_mirror"]: client = get_client(client_name) - with self.assertRaises(InvalidMirrorInput): + with self.assertRaises(InvalidMirrorInputError): create_mirrored_message_users(client, user, recipients, sender.email, message_type) @mock.patch( diff --git a/zerver/tests/test_push_notifications.py b/zerver/tests/test_push_notifications.py index 06585644d9..b641b1761d 100644 --- a/zerver/tests/test_push_notifications.py +++ b/zerver/tests/test_push_notifications.py @@ -49,7 +49,7 @@ from zerver.lib.push_notifications import ( send_notifications_to_bouncer, ) from zerver.lib.remote_server import ( - PushNotificationBouncerException, + PushNotificationBouncerError, PushNotificationBouncerRetryLaterError, build_analytics_data, send_analytics_to_remote_server, @@ -2220,7 +2220,7 @@ class TestSendToPushBouncer(ZulipTestCase): # This is the exception our decorator uses for an invalid Zulip server error_response = json_response_from_error(InvalidZulipServerError("testRole")) self.add_mock_response(body=error_response.content, status=error_response.status_code) - with self.assertRaises(PushNotificationBouncerException) as exc: + with self.assertRaises(PushNotificationBouncerError) as exc: send_to_push_bouncer("POST", "register", {"msg": "true"}) self.assertEqual( str(exc.exception), @@ -2237,7 +2237,7 @@ class TestSendToPushBouncer(ZulipTestCase): @responses.activate def test_300_error(self) -> None: self.add_mock_response(body=b"/", status=300) - with self.assertRaises(PushNotificationBouncerException) as exc: + with self.assertRaises(PushNotificationBouncerError) as exc: send_to_push_bouncer("POST", "register", {"msg": "true"}) self.assertEqual( str(exc.exception), "Push notification bouncer returned unexpected status code 300" diff --git a/zerver/tests/test_queue_worker.py b/zerver/tests/test_queue_worker.py index 88bf7ab0a8..5e44cd88a8 100644 --- a/zerver/tests/test_queue_worker.py +++ b/zerver/tests/test_queue_worker.py @@ -17,9 +17,9 @@ from django.test import override_settings from zerver.lib.email_mirror import RateLimitedRealmMirror from zerver.lib.email_mirror_helpers import encode_email_address from zerver.lib.queue import MAX_REQUEST_RETRIES -from zerver.lib.rate_limiter import RateLimiterLockingException +from zerver.lib.rate_limiter import RateLimiterLockingError from zerver.lib.remote_server import PushNotificationBouncerRetryLaterError -from zerver.lib.send_email import EmailNotDeliveredException, FromAddress +from zerver.lib.send_email import EmailNotDeliveredError, FromAddress from zerver.lib.test_classes import ZulipTestCase from zerver.lib.test_helpers import mock_queue_publish from zerver.models import ( @@ -507,10 +507,10 @@ class WorkerTest(ZulipTestCase): worker.start() self.assertEqual(mock_mirror_email.call_count, 4) - # If RateLimiterLockingException is thrown, we rate-limit the new message: + # If RateLimiterLockingError is thrown, we rate-limit the new message: with patch( "zerver.lib.rate_limiter.RedisRateLimiterBackend.incr_ratelimit", - side_effect=RateLimiterLockingException, + side_effect=RateLimiterLockingError, ): with self.assertLogs("zerver.lib.rate_limiter", "WARNING") as mock_warn: fake_client.enqueue("email_mirror", data[0]) @@ -553,14 +553,14 @@ class WorkerTest(ZulipTestCase): worker = queue_processors.EmailSendingWorker() worker.setup() with patch( - "zerver.lib.send_email.build_email", side_effect=EmailNotDeliveredException + "zerver.lib.send_email.build_email", side_effect=EmailNotDeliveredError ), mock_queue_publish( "zerver.lib.queue.queue_json_publish", side_effect=fake_publish ), self.assertLogs( level="ERROR" ) as m: worker.start() - self.assertIn("failed due to exception EmailNotDeliveredException", m.output[0]) + self.assertIn("failed due to exception EmailNotDeliveredError", m.output[0]) self.assertEqual(data["failed_tries"], 1 + MAX_REQUEST_RETRIES) @@ -764,7 +764,7 @@ class WorkerTest(ZulipTestCase): def consume(self, data: Mapping[str, Any]) -> None: pass # nocoverage # this is intentionally not called - with self.assertRaises(queue_processors.WorkerDeclarationException): + with self.assertRaises(queue_processors.WorkerDeclarationError): TestWorker() def test_get_active_worker_queues(self) -> None: diff --git a/zerver/tests/test_send_email.py b/zerver/tests/test_send_email.py index 95cfb71dc1..3006e36cea 100644 --- a/zerver/tests/test_send_email.py +++ b/zerver/tests/test_send_email.py @@ -6,7 +6,7 @@ from django.core.mail.backends.smtp import EmailBackend as SMTPBackend from django.core.mail.message import sanitize_address from zerver.lib.send_email import ( - EmailNotDeliveredException, + EmailNotDeliveredError, FromAddress, build_email, initialize_connection, @@ -118,7 +118,7 @@ class TestSendEmail(ZulipTestCase): ) self.assertEqual(mail.extra_headers["From"], f"{from_name} <{FromAddress.NOREPLY}>") - # We test the cases that should raise an EmailNotDeliveredException + # We test the cases that should raise an EmailNotDeliveredError errors = { f"Unknown error sending password_reset email to {mail.to}": [0], f"Error sending password_reset email to {mail.to}": [SMTPException()], @@ -133,7 +133,7 @@ class TestSendEmail(ZulipTestCase): for message, side_effect in errors.items(): with mock.patch.object(EmailBackend, "send_messages", side_effect=side_effect): with self.assertLogs(logger=logger) as info_log: - with self.assertRaises(EmailNotDeliveredException): + with self.assertRaises(EmailNotDeliveredError): send_email( "zerver/emails/password_reset", to_emails=[hamlet.email], diff --git a/zerver/tests/test_service_bot_system.py b/zerver/tests/test_service_bot_system.py index 7c31d6a139..da80808791 100644 --- a/zerver/tests/test_service_bot_system.py +++ b/zerver/tests/test_service_bot_system.py @@ -10,7 +10,7 @@ from typing_extensions import Concatenate, ParamSpec from zerver.actions.create_user import do_create_user from zerver.actions.message_send import get_service_bot_events from zerver.lib.bot_config import ConfigError, load_bot_config_template, set_bot_config -from zerver.lib.bot_lib import EmbeddedBotEmptyRecipientsList, EmbeddedBotHandler, StateHandler +from zerver.lib.bot_lib import EmbeddedBotEmptyRecipientsListError, EmbeddedBotHandler, StateHandler from zerver.lib.bot_storage import StateError from zerver.lib.test_classes import ZulipTestCase from zerver.lib.test_helpers import mock_queue_publish @@ -409,7 +409,7 @@ class TestServiceBotConfigHandler(ZulipTestCase): def test_bot_send_pm_with_empty_recipients_list(self) -> None: with self.assertRaisesRegex( - EmbeddedBotEmptyRecipientsList, "Message must have recipients!" + EmbeddedBotEmptyRecipientsListError, "Message must have recipients!" ): self.bot_handler.send_message(message={"type": "private", "to": []}) diff --git a/zerver/tests/test_signup.py b/zerver/tests/test_signup.py index c9ab94a941..1047ccbb3f 100644 --- a/zerver/tests/test_signup.py +++ b/zerver/tests/test_signup.py @@ -23,7 +23,7 @@ from django.utils.translation import gettext as _ from confirmation import settings as confirmation_settings from confirmation.models import ( Confirmation, - ConfirmationKeyException, + ConfirmationKeyError, create_confirmation_link, get_object_from_key, one_click_unsubscribe_link, @@ -67,7 +67,7 @@ from zerver.lib.mobile_auth_otp import ( from zerver.lib.name_restrictions import is_disposable_domain from zerver.lib.rate_limiter import add_ratelimit_rule, remove_ratelimit_rule from zerver.lib.send_email import ( - EmailNotDeliveredException, + EmailNotDeliveredError, FromAddress, deliver_scheduled_emails, send_future_email, @@ -2160,9 +2160,9 @@ so we didn't send them an invitation. We did send invitations to everyone else!" registration_key = url.split("/")[-1] # Mainly a test of get_object_from_key, rather than of the invitation pathway - with self.assertRaises(ConfirmationKeyException) as cm: + with self.assertRaises(ConfirmationKeyError) as cm: get_object_from_key(registration_key, [Confirmation.INVITATION], mark_object_used=True) - self.assertEqual(cm.exception.error_type, ConfirmationKeyException.DOES_NOT_EXIST) + self.assertEqual(cm.exception.error_type, ConfirmationKeyError.DOES_NOT_EXIST) # Verify that using the wrong type doesn't work in the main confirm code path email_change_url = create_confirmation_link(prereg_user, Confirmation.EMAIL_CHANGE) @@ -4093,13 +4093,13 @@ class UserSignUpTest(InviteUserBase): def test_bad_email_configuration_for_accounts_home(self) -> None: """ - Make sure we redirect for EmailNotDeliveredException. + Make sure we redirect for EmailNotDeliveredError. """ email = self.nonreg_email("newguy") smtp_mock = patch( "zerver.views.registration.send_confirm_registration_email", - side_effect=EmailNotDeliveredException, + side_effect=EmailNotDeliveredError, ) with smtp_mock, self.assertLogs(level="ERROR") as m: @@ -4110,13 +4110,13 @@ class UserSignUpTest(InviteUserBase): def test_bad_email_configuration_for_create_realm(self) -> None: """ - Make sure we redirect for EmailNotDeliveredException. + Make sure we redirect for EmailNotDeliveredError. """ email = self.nonreg_email("newguy") smtp_mock = patch( "zerver.views.registration.send_confirm_registration_email", - side_effect=EmailNotDeliveredException, + side_effect=EmailNotDeliveredError, ) with smtp_mock, self.assertLogs(level="ERROR") as m: diff --git a/zerver/tests/test_templates.py b/zerver/tests/test_templates.py index 400a31e58d..a920baafe2 100644 --- a/zerver/tests/test_templates.py +++ b/zerver/tests/test_templates.py @@ -1,6 +1,6 @@ from django.template.loader import get_template -from zerver.lib.exceptions import InvalidMarkdownIncludeStatement +from zerver.lib.exceptions import InvalidMarkdownIncludeStatementError from zerver.lib.test_classes import ZulipTestCase @@ -123,7 +123,7 @@ footer } with self.assertRaisesRegex( - InvalidMarkdownIncludeStatement, "Invalid Markdown include statement" + InvalidMarkdownIncludeStatementError, "Invalid Markdown include statement" ): template.render(context) diff --git a/zerver/tests/test_timeout.py b/zerver/tests/test_timeout.py index 8593d85d13..fe2eac8f1d 100644 --- a/zerver/tests/test_timeout.py +++ b/zerver/tests/test_timeout.py @@ -2,7 +2,7 @@ import time import traceback from zerver.lib.test_classes import ZulipTestCase -from zerver.lib.timeout import TimeoutExpired, timeout +from zerver.lib.timeout import TimeoutExpiredError, timeout class TimeoutTestCase(ZulipTestCase): @@ -25,7 +25,7 @@ class TimeoutTestCase(ZulipTestCase): try: timeout(1, lambda: self.sleep_x_seconds_y_times(0.1, 50)) raise AssertionError("Failed to raise a timeout") - except TimeoutExpired as exc: + except TimeoutExpiredError as exc: tb = traceback.format_tb(exc.__traceback__) self.assertIn("in sleep_x_seconds_y_times", tb[-1]) self.assertIn("time.sleep(x)", tb[-1]) @@ -46,8 +46,8 @@ class TimeoutTestCase(ZulipTestCase): try: timeout(1, lambda: self.sleep_x_seconds_y_times(5, 1)) raise AssertionError("Failed to raise a timeout") - except TimeoutExpired as exc: + except TimeoutExpiredError as exc: tb = traceback.format_tb(exc.__traceback__) self.assertNotIn("in sleep_x_seconds_y_times", tb[-1]) - self.assertIn("raise TimeoutExpired", tb[-1]) + self.assertIn("raise TimeoutExpiredError", tb[-1]) self.assertEqual(m.output, ["WARNING:root:Failed to time out backend thread"]) diff --git a/zerver/tests/test_timestamp.py b/zerver/tests/test_timestamp.py index d4e20f5216..a2b5e981a2 100644 --- a/zerver/tests/test_timestamp.py +++ b/zerver/tests/test_timestamp.py @@ -4,7 +4,7 @@ from dateutil import parser from zerver.lib.test_classes import ZulipTestCase from zerver.lib.timestamp import ( - TimeZoneNotUTCException, + TimeZoneNotUTCError, ceiling_to_hour, convert_to_UTC, datetime_to_timestamp, @@ -28,7 +28,7 @@ class TestTimestamp(ZulipTestCase): parser.parse("2017-01-01 00:00:00.123+01:00"), parser.parse("2017-01-01 00:00:00.123"), ]: - with self.assertRaises(TimeZoneNotUTCException): + with self.assertRaises(TimeZoneNotUTCError): datetime_to_timestamp(dt) def test_convert_to_UTC(self) -> None: @@ -43,5 +43,5 @@ class TestTimestamp(ZulipTestCase): def test_enforce_UTC(self) -> None: non_utc_datetime = parser.parse("2017-01-01 00:00:00.123") for function in [floor_to_hour, floor_to_day, ceiling_to_hour, ceiling_to_hour]: - with self.assertRaises(TimeZoneNotUTCException): + with self.assertRaises(TimeZoneNotUTCError): function(non_utc_datetime) diff --git a/zerver/tests/test_users.py b/zerver/tests/test_users.py index ad31eca791..68da24f968 100644 --- a/zerver/tests/test_users.py +++ b/zerver/tests/test_users.py @@ -51,7 +51,7 @@ from zerver.lib.users import Accounts, access_user_by_id, get_accounts_for_email from zerver.lib.utils import assert_is_not_none from zerver.models import ( CustomProfileField, - InvalidFakeEmailDomain, + InvalidFakeEmailDomainError, Message, PreregistrationUser, Realm, @@ -2304,12 +2304,12 @@ class FakeEmailDomainTest(ZulipTestCase): @override_settings(FAKE_EMAIL_DOMAIN="invaliddomain", REALM_HOSTS={"zulip": "127.0.0.1"}) def test_invalid_fake_email_domain(self) -> None: realm = get_realm("zulip") - with self.assertRaises(InvalidFakeEmailDomain): + with self.assertRaises(InvalidFakeEmailDomainError): get_fake_email_domain(realm) @override_settings(FAKE_EMAIL_DOMAIN="127.0.0.1", REALM_HOSTS={"zulip": "127.0.0.1"}) def test_invalid_fake_email_domain_ip(self) -> None: - with self.assertRaises(InvalidFakeEmailDomain): + with self.assertRaises(InvalidFakeEmailDomainError): realm = get_realm("zulip") get_fake_email_domain(realm) diff --git a/zerver/tests/test_webhooks_common.py b/zerver/tests/test_webhooks_common.py index 90e3c6fc2c..1112c4d5c0 100644 --- a/zerver/tests/test_webhooks_common.py +++ b/zerver/tests/test_webhooks_common.py @@ -15,7 +15,7 @@ from zerver.lib.users import get_api_key from zerver.lib.webhooks.common import ( INVALID_JSON_MESSAGE, MISSING_EVENT_HEADER_MESSAGE, - MissingHTTPEventHeader, + MissingHTTPEventHeaderError, get_fixture_http_headers, standardize_headers, validate_extract_webhook_http_header, @@ -46,7 +46,7 @@ class WebhooksCommonTestCase(ZulipTestCase): request.path = "some/random/path" exception_msg = "Missing the HTTP event header 'X-Custom-Header'" - with self.assertRaisesRegex(MissingHTTPEventHeader, exception_msg): + with self.assertRaisesRegex(MissingHTTPEventHeaderError, exception_msg): validate_extract_webhook_http_header(request, "X-Custom-Header", "test_webhook") msg = self.get_last_message() diff --git a/zerver/views/auth.py b/zerver/views/auth.py index 8d0668f093..aa3c946ce5 100644 --- a/zerver/views/auth.py +++ b/zerver/views/auth.py @@ -33,7 +33,7 @@ from typing_extensions import Concatenate, ParamSpec from confirmation.models import ( Confirmation, - ConfirmationKeyException, + ConfirmationKeyError, create_confirmation_link, get_object_from_key, render_confirmation_key_error, @@ -54,7 +54,7 @@ from zerver.lib.exceptions import ( JsonableError, PasswordAuthDisabledError, PasswordResetRequiredError, - RateLimited, + RateLimitedError, RealmDeactivatedError, UserDeactivatedError, ) @@ -200,7 +200,7 @@ def maybe_send_to_registration( confirmation_obj = get_object_from_key( multiuse_object_key, [Confirmation.MULTIUSE_INVITE], mark_object_used=False ) - except ConfirmationKeyException as exception: + except ConfirmationKeyError as exception: return render_confirmation_key_error(request, exception) assert isinstance(confirmation_obj, MultiuseInvite) @@ -1037,7 +1037,7 @@ def password_reset(request: HttpRequest) -> HttpResponse: form_class=ZulipPasswordResetForm, success_url="/accounts/password/reset/done/", )(request) - except RateLimited as e: + except RateLimitedError as e: assert e.secs_to_freedom is not None return render( request, diff --git a/zerver/views/invite.py b/zerver/views/invite.py index e2145af639..c3a214d1b6 100644 --- a/zerver/views/invite.py +++ b/zerver/views/invite.py @@ -15,7 +15,7 @@ from zerver.actions.invites import ( do_revoke_user_invite, ) from zerver.decorator import require_member_or_admin, require_realm_admin -from zerver.lib.exceptions import JsonableError, OrganizationOwnerRequired +from zerver.lib.exceptions import JsonableError, OrganizationOwnerRequiredError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.streams import access_stream_by_id @@ -34,7 +34,7 @@ def check_if_owner_required(invited_as: int, user_profile: UserProfile) -> None: invited_as == PreregistrationUser.INVITE_AS["REALM_OWNER"] and not user_profile.is_realm_owner ): - raise OrganizationOwnerRequired() + raise OrganizationOwnerRequiredError() @require_member_or_admin diff --git a/zerver/views/message_flags.py b/zerver/views/message_flags.py index 739a7c0fd0..a641ba630f 100644 --- a/zerver/views/message_flags.py +++ b/zerver/views/message_flags.py @@ -18,7 +18,7 @@ from zerver.lib.narrow import ( from zerver.lib.request import REQ, RequestNotes, has_request_variables from zerver.lib.response import json_partial_success, json_success from zerver.lib.streams import access_stream_by_id -from zerver.lib.timeout import TimeoutExpired, timeout +from zerver.lib.timeout import TimeoutExpiredError, timeout from zerver.lib.topic import user_message_exists_for_topic from zerver.lib.validator import check_bool, check_int, check_list, to_non_negative_int from zerver.models import UserActivity, UserProfile @@ -121,7 +121,7 @@ def mark_all_as_read(request: HttpRequest, user_profile: UserProfile) -> HttpRes request_notes = RequestNotes.get_notes(request) try: count = timeout(50, lambda: do_mark_all_as_read(user_profile)) - except TimeoutExpired: + except TimeoutExpiredError: return json_partial_success(request, data={"code": ErrorCode.REQUEST_TIMEOUT.name}) log_data_str = f"[{count} updated]" diff --git a/zerver/views/message_send.py b/zerver/views/message_send.py index 548a7d8811..759cdcccac 100644 --- a/zerver/views/message_send.py +++ b/zerver/views/message_send.py @@ -42,7 +42,7 @@ else: # nocoverage import zoneinfo -class InvalidMirrorInput(Exception): +class InvalidMirrorInputError(Exception): pass @@ -70,12 +70,12 @@ def create_mirrored_message_users( user_check = same_realm_jabber_user fullname_function = compute_jabber_user_fullname else: - raise InvalidMirrorInput("Unrecognized mirroring client") + raise InvalidMirrorInputError("Unrecognized mirroring client") for email in referenced_users: # Check that all referenced users are in our realm: if not user_check(user_profile, email): - raise InvalidMirrorInput("At least one user cannot be mirrored") + raise InvalidMirrorInputError("At least one user cannot be mirrored") # Create users for the referenced users, if needed. for email in referenced_users: @@ -278,7 +278,7 @@ def send_message_backend( mirror_sender = create_mirrored_message_users( client, user_profile, message_to, req_sender, message_type_name ) - except InvalidMirrorInput: + except InvalidMirrorInputError: raise JsonableError(_("Invalid mirrored message")) if client.name == "zephyr_mirror" and not user_profile.realm.is_zephyr_mirror_realm: diff --git a/zerver/views/realm.py b/zerver/views/realm.py index f3046aa002..1375c57f78 100644 --- a/zerver/views/realm.py +++ b/zerver/views/realm.py @@ -6,7 +6,7 @@ from django.shortcuts import render from django.utils.translation import gettext as _ from django.views.decorators.http import require_safe -from confirmation.models import Confirmation, ConfirmationKeyException, get_object_from_key +from confirmation.models import Confirmation, ConfirmationKeyError, get_object_from_key from zerver.actions.create_realm import do_change_realm_subdomain from zerver.actions.realm_settings import ( do_change_realm_org_type, @@ -20,7 +20,7 @@ from zerver.actions.realm_settings import ( ) from zerver.decorator import require_realm_admin, require_realm_owner from zerver.forms import check_subdomain_available as check_subdomain -from zerver.lib.exceptions import JsonableError, OrganizationOwnerRequired +from zerver.lib.exceptions import JsonableError, OrganizationOwnerRequiredError from zerver.lib.i18n import get_available_language_codes from zerver.lib.message import parse_message_content_edit_or_delete_limit from zerver.lib.request import REQ, has_request_variables @@ -155,7 +155,7 @@ def update_realm( raise JsonableError(_("Invalid language '{}'").format(default_language)) if authentication_methods is not None: if not user_profile.is_realm_owner: - raise OrganizationOwnerRequired() + raise OrganizationOwnerRequiredError() if True not in list(authentication_methods.values()): raise JsonableError(_("At least one authentication method must be enabled.")) if video_chat_provider is not None and video_chat_provider not in { @@ -170,7 +170,7 @@ def update_realm( message_retention_days: Optional[int] = None if message_retention_days_raw is not None: if not user_profile.is_realm_owner: - raise OrganizationOwnerRequired() + raise OrganizationOwnerRequiredError() realm.ensure_not_on_limited_plan() message_retention_days = parse_message_retention_days( message_retention_days_raw, Realm.MESSAGE_RETENTION_SPECIAL_VALUES_MAP @@ -180,15 +180,15 @@ def update_realm( if ( invite_to_realm_policy is not None or invite_required is not None ) and not user_profile.is_realm_owner: - raise OrganizationOwnerRequired() + raise OrganizationOwnerRequiredError() if ( emails_restricted_to_domains is not None or disallow_disposable_email_addresses is not None ) and not user_profile.is_realm_owner: - raise OrganizationOwnerRequired() + raise OrganizationOwnerRequiredError() if waiting_period_threshold is not None and not user_profile.is_realm_owner: - raise OrganizationOwnerRequired() + raise OrganizationOwnerRequiredError() if enable_spectator_access: realm.ensure_not_on_limited_plan() @@ -307,7 +307,7 @@ def update_realm( if string_id is not None: if not user_profile.is_realm_owner: - raise OrganizationOwnerRequired() + raise OrganizationOwnerRequiredError() if realm.demo_organization_scheduled_deletion_date is None: raise JsonableError(_("Must be a demo organization.")) @@ -349,7 +349,7 @@ def realm_reactivation(request: HttpRequest, confirmation_key: str) -> HttpRespo obj = get_object_from_key( confirmation_key, [Confirmation.REALM_REACTIVATION], mark_object_used=True ) - except ConfirmationKeyException: + except ConfirmationKeyError: return render(request, "zerver/realm_reactivation_link_error.html", status=404) assert isinstance(obj, RealmReactivationStatus) diff --git a/zerver/views/registration.py b/zerver/views/registration.py index 5ff05bf420..aebfd85eaa 100644 --- a/zerver/views/registration.py +++ b/zerver/views/registration.py @@ -17,7 +17,7 @@ from django_auth_ldap.backend import LDAPBackend, _LDAPUser from confirmation.models import ( Confirmation, - ConfirmationKeyException, + ConfirmationKeyError, RealmCreationKey, create_confirmation_link, get_object_from_key, @@ -42,12 +42,12 @@ from zerver.forms import ( RegistrationForm, ) from zerver.lib.email_validation import email_allowed_for_realm, validate_email_not_already_in_realm -from zerver.lib.exceptions import RateLimited +from zerver.lib.exceptions import RateLimitedError from zerver.lib.i18n import get_default_language_for_new_user from zerver.lib.pysa import mark_sanitized from zerver.lib.rate_limiter import rate_limit_request_by_ip from zerver.lib.request import REQ, has_request_variables -from zerver.lib.send_email import EmailNotDeliveredException, FromAddress, send_email +from zerver.lib.send_email import EmailNotDeliveredError, FromAddress, send_email from zerver.lib.sessions import get_expirable_session_var from zerver.lib.subdomains import get_subdomain, is_root_domain_available from zerver.lib.url_encoding import append_url_query_string @@ -79,8 +79,8 @@ from zerver.views.auth import ( ) from zproject.backends import ( ExternalAuthResult, + NoMatchingLDAPUserError, ZulipLDAPAuthBackend, - ZulipLDAPExceptionNoMatchingLDAPUser, email_auth_enabled, email_belongs_to_ldap, get_external_method_dicts, @@ -114,7 +114,7 @@ def get_prereg_key_and_redirect( """ try: check_prereg_key(request, confirmation_key) - except ConfirmationKeyException as e: + except ConfirmationKeyError as e: return render_confirmation_key_error(request, e) return render( @@ -127,7 +127,7 @@ def get_prereg_key_and_redirect( def check_prereg_key(request: HttpRequest, confirmation_key: str) -> PreregistrationUser: """ Checks if the Confirmation key is valid, returning the PreregistrationUser object in case of success - and raising an appropriate ConfirmationKeyException otherwise. + and raising an appropriate ConfirmationKeyError otherwise. """ confirmation_types = [ Confirmation.USER_REGISTRATION, @@ -159,7 +159,7 @@ def accounts_register( ) -> HttpResponse: try: prereg_user = check_prereg_key(request, key) - except ConfirmationKeyException as e: + except ConfirmationKeyError as e: return render_confirmation_key_error(request, e) email = prereg_user.email @@ -182,7 +182,7 @@ def accounts_register( assert prereg_user.realm is not None if get_subdomain(request) != prereg_user.realm.string_id: return render_confirmation_key_error( - request, ConfirmationKeyException(ConfirmationKeyException.DOES_NOT_EXIST) + request, ConfirmationKeyError(ConfirmationKeyError.DOES_NOT_EXIST) ) realm = prereg_user.realm try: @@ -239,7 +239,7 @@ def accounts_register( if isinstance(backend, LDAPBackend): try: ldap_username = backend.django_to_ldap_username(email) - except ZulipLDAPExceptionNoMatchingLDAPUser: + except NoMatchingLDAPUserError: logging.warning("New account email %s could not be found in LDAP", email) break @@ -607,7 +607,7 @@ def redirect_to_email_login_url(email: str) -> HttpResponseRedirect: def create_realm(request: HttpRequest, creation_key: Optional[str] = None) -> HttpResponse: try: key_record = validate_key(creation_key) - except RealmCreationKey.Invalid: + except RealmCreationKey.InvalidError: return render( request, "zerver/realm_creation_link_invalid.html", @@ -626,7 +626,7 @@ def create_realm(request: HttpRequest, creation_key: Optional[str] = None) -> Ht if form.is_valid(): try: rate_limit_request_by_ip(request, domain="sends_email_by_ip") - except RateLimited as e: + except RateLimitedError as e: assert e.secs_to_freedom is not None return render( request, @@ -649,7 +649,7 @@ def create_realm(request: HttpRequest, creation_key: Optional[str] = None) -> Ht try: send_confirm_registration_email(email, activation_url, request=request) - except EmailNotDeliveredException: + except EmailNotDeliveredError: logging.error("Error in create_realm") return HttpResponseRedirect("/config-error/smtp") @@ -701,7 +701,7 @@ def accounts_home( if form.is_valid(): try: rate_limit_request_by_ip(request, domain="sends_email_by_ip") - except RateLimited as e: + except RateLimitedError as e: assert e.secs_to_freedom is not None return render( request, @@ -727,7 +727,7 @@ def accounts_home( ) try: send_confirm_registration_email(email, activation_url, request=request, realm=realm) - except EmailNotDeliveredException: + except EmailNotDeliveredError: logging.error("Error in accounts_home") return HttpResponseRedirect("/config-error/smtp") @@ -757,7 +757,7 @@ def accounts_home_from_multiuse_invite(request: HttpRequest, confirmation_key: s if realm != multiuse_object.realm: return render(request, "confirmation/link_does_not_exist.html", status=404) # Required for OAuth 2 - except ConfirmationKeyException as exception: + except ConfirmationKeyError as exception: if realm is None or realm.invite_required: return render_confirmation_key_error(request, exception) return accounts_home( @@ -779,7 +779,7 @@ def find_account( for i in range(len(emails)): try: rate_limit_request_by_ip(request, domain="sends_email_by_ip") - except RateLimited as e: + except RateLimitedError as e: assert e.secs_to_freedom is not None return render( request, diff --git a/zerver/views/streams.py b/zerver/views/streams.py index 8d528932bc..95956e7a4f 100644 --- a/zerver/views/streams.py +++ b/zerver/views/streams.py @@ -49,7 +49,7 @@ from zerver.decorator import ( from zerver.lib.exceptions import ( ErrorCode, JsonableError, - OrganizationOwnerRequired, + OrganizationOwnerRequiredError, ResourceNotFoundError, ) from zerver.lib.mention import MentionBackend, silent_mention_syntax_for_user @@ -72,7 +72,7 @@ from zerver.lib.streams import ( ) from zerver.lib.string_validation import check_stream_name from zerver.lib.subscription_info import gather_subscriptions -from zerver.lib.timeout import TimeoutExpired, timeout +from zerver.lib.timeout import TimeoutExpiredError, timeout from zerver.lib.topic import ( get_topic_history_for_public_stream, get_topic_history_for_stream, @@ -346,7 +346,7 @@ def update_stream_backend( if message_retention_days is not None: if not user_profile.is_realm_owner: - raise OrganizationOwnerRequired() + raise OrganizationOwnerRequiredError() user_profile.realm.ensure_not_on_limited_plan() new_message_retention_days_value = parse_message_retention_days( message_retention_days, Stream.MESSAGE_RETENTION_SPECIAL_VALUES_MAP @@ -889,7 +889,7 @@ def delete_in_topic( try: timeout(50, delete_in_batches) - except TimeoutExpired: + except TimeoutExpiredError: return json_partial_success(request, data={"code": ErrorCode.REQUEST_TIMEOUT.name}) return json_success(request) diff --git a/zerver/views/unsubscribe.py b/zerver/views/unsubscribe.py index 095237073a..b071bdc90d 100644 --- a/zerver/views/unsubscribe.py +++ b/zerver/views/unsubscribe.py @@ -4,7 +4,7 @@ from django.http import HttpRequest, HttpResponse from django.shortcuts import render from django.views.decorators.csrf import csrf_exempt -from confirmation.models import Confirmation, ConfirmationKeyException, get_object_from_key +from confirmation.models import Confirmation, ConfirmationKeyError, get_object_from_key from zerver.actions.user_settings import do_change_user_setting from zerver.context_processors import common_context from zerver.lib.send_email import clear_scheduled_emails @@ -21,7 +21,7 @@ def process_unsubscribe( user_profile = get_object_from_key( confirmation_key, [Confirmation.UNSUBSCRIBE], mark_object_used=False ) - except ConfirmationKeyException: + except ConfirmationKeyError: return render(request, "zerver/unsubscribe_link_error.html") assert isinstance(user_profile, UserProfile) diff --git a/zerver/views/user_settings.py b/zerver/views/user_settings.py index 87ee69e12d..0ecc0d8d62 100644 --- a/zerver/views/user_settings.py +++ b/zerver/views/user_settings.py @@ -13,7 +13,7 @@ from django.utils.translation import gettext_lazy from confirmation.models import ( Confirmation, - ConfirmationKeyException, + ConfirmationKeyError, get_object_from_key, render_confirmation_key_error, ) @@ -33,7 +33,7 @@ from zerver.lib.email_validation import ( validate_email_is_valid, validate_email_not_already_in_realm, ) -from zerver.lib.exceptions import JsonableError, RateLimited, UserDeactivatedError +from zerver.lib.exceptions import JsonableError, RateLimitedError, UserDeactivatedError from zerver.lib.i18n import get_available_language_codes from zerver.lib.rate_limiter import RateLimitedUser from zerver.lib.request import REQ, has_request_variables @@ -65,7 +65,7 @@ def confirm_email_change(request: HttpRequest, confirmation_key: str) -> HttpRes email_change_object = get_object_from_key( confirmation_key, [Confirmation.EMAIL_CHANGE], mark_object_used=True ) - except ConfirmationKeyException as exception: + except ConfirmationKeyError as exception: return render_confirmation_key_error(request, exception) assert isinstance(email_change_object, EmailChangeStatus) @@ -244,7 +244,7 @@ def json_change_settings( return_data=return_data, ): raise JsonableError(_("Wrong password!")) - except RateLimited as e: + except RateLimitedError as e: assert e.secs_to_freedom is not None secs_to_freedom = int(e.secs_to_freedom) raise JsonableError( @@ -300,7 +300,7 @@ def json_change_settings( user_profile, domain="email_change_by_user" ).rate_limit() if ratelimited: - raise RateLimited(time_until_free) + raise RateLimitedError(time_until_free) do_start_email_change_process(user_profile, new_email) diff --git a/zerver/views/users.py b/zerver/views/users.py index 9847a4b556..2509033509 100644 --- a/zerver/views/users.py +++ b/zerver/views/users.py @@ -41,8 +41,8 @@ from zerver.lib.exceptions import ( CannotDeactivateLastUserError, JsonableError, MissingAuthenticationError, - OrganizationAdministratorRequired, - OrganizationOwnerRequired, + OrganizationAdministratorRequiredError, + OrganizationOwnerRequiredError, ) from zerver.lib.integrations import EMBEDDED_BOTS from zerver.lib.rate_limiter import rate_limit_spectator_attachment_access_by_file @@ -87,7 +87,7 @@ from zerver.models import ( DisposableEmailError, DomainNotAllowedForRealmError, EmailContainsPlusError, - InvalidFakeEmailDomain, + InvalidFakeEmailDomainError, Message, Realm, Service, @@ -117,7 +117,7 @@ def deactivate_user_backend( ) -> HttpResponse: target = access_user_by_id(user_profile, user_id, for_admin=True) if target.is_realm_owner and not user_profile.is_realm_owner: - raise OrganizationOwnerRequired() + raise OrganizationOwnerRequiredError() if check_last_owner(target): raise JsonableError(_("Cannot deactivate the only organization owner")) if deactivation_notification_comment is not None: @@ -231,9 +231,9 @@ def update_user_backend( # # Logic replicated in patch_bot_backend. if UserProfile.ROLE_REALM_OWNER in [role, target.role] and not user_profile.is_realm_owner: - raise OrganizationOwnerRequired() + raise OrganizationOwnerRequiredError() elif not user_profile.is_realm_admin: - raise OrganizationAdministratorRequired() + raise OrganizationAdministratorRequiredError() if target.role == UserProfile.ROLE_REALM_OWNER and check_last_owner(target): raise JsonableError( @@ -367,9 +367,9 @@ def patch_bot_backend( if role is not None and bot.role != role: # Logic duplicated from update_user_backend. if UserProfile.ROLE_REALM_OWNER in [role, bot.role] and not user_profile.is_realm_owner: - raise OrganizationOwnerRequired() + raise OrganizationOwnerRequiredError() elif not user_profile.is_realm_admin: - raise OrganizationAdministratorRequired() + raise OrganizationAdministratorRequiredError() do_change_user_role(bot, role, acting_user=user_profile) @@ -484,7 +484,7 @@ def add_bot_backend( full_name = check_full_name(full_name_raw) try: email = Address(username=short_name, domain=user_profile.realm.get_bot_domain()).addr_spec - except InvalidFakeEmailDomain: + except InvalidFakeEmailDomainError: raise JsonableError( _( "Can't create bots until FAKE_EMAIL_DOMAIN is correctly configured.\n" diff --git a/zerver/webhooks/azuredevops/view.py b/zerver/webhooks/azuredevops/view.py index fd708331ad..bd37685cbe 100644 --- a/zerver/webhooks/azuredevops/view.py +++ b/zerver/webhooks/azuredevops/view.py @@ -3,7 +3,7 @@ from typing import Callable, Dict, Optional from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_int, check_string, to_wild_value @@ -148,7 +148,7 @@ def get_event_name(payload: WildValue, branches: Optional[str]) -> Optional[str] return None if event_name in EVENT_FUNCTION_MAPPER: return event_name - raise UnsupportedWebhookEventType(event_name) + raise UnsupportedWebhookEventTypeError(event_name) EVENT_FUNCTION_MAPPER: Dict[str, Callable[[WildValue], str]] = { diff --git a/zerver/webhooks/basecamp/view.py b/zerver/webhooks/basecamp/view.py index 91e24cea15..4626a25e60 100644 --- a/zerver/webhooks/basecamp/view.py +++ b/zerver/webhooks/basecamp/view.py @@ -4,7 +4,7 @@ import string from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_string, to_wild_value @@ -47,7 +47,7 @@ def api_basecamp_webhook( event = get_event_type(payload) if event not in SUPPORT_EVENTS: - raise UnsupportedWebhookEventType(event) + raise UnsupportedWebhookEventTypeError(event) subject = get_project_name(payload) if event.startswith("document_"): @@ -72,7 +72,7 @@ def api_basecamp_webhook( body = get_comment_body(event, payload) event = "comment" else: - raise UnsupportedWebhookEventType(event) + raise UnsupportedWebhookEventTypeError(event) check_send_webhook_message(request, user_profile, subject, body, event) return json_success(request) diff --git a/zerver/webhooks/bitbucket2/view.py b/zerver/webhooks/bitbucket2/view.py index 7483ed6575..acf8edbcbc 100644 --- a/zerver/webhooks/bitbucket2/view.py +++ b/zerver/webhooks/bitbucket2/view.py @@ -7,7 +7,7 @@ from typing import Dict, List, Optional, Protocol from django.http import HttpRequest, HttpResponse from zerver.decorator import log_unsupported_webhook_event, webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_bool, check_int, check_string, to_wild_value @@ -196,7 +196,7 @@ def get_type(request: HttpRequest, payload: WildValue) -> str: if event_key == "repo:updated": return event_key - raise UnsupportedWebhookEventType(event_key) + raise UnsupportedWebhookEventTypeError(event_key) class BodyGetter(Protocol): diff --git a/zerver/webhooks/bitbucket3/view.py b/zerver/webhooks/bitbucket3/view.py index 7eaf327db7..de29cfe695 100644 --- a/zerver/webhooks/bitbucket3/view.py +++ b/zerver/webhooks/bitbucket3/view.py @@ -5,7 +5,7 @@ from typing import Dict, List, Optional, Protocol from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_int, check_none_or, check_string, to_wild_value @@ -169,7 +169,7 @@ def repo_push_branch_data(payload: WildValue, change: WildValue) -> Dict[str, st body = get_remove_branch_event_message(user_name, branch_name) else: message = "{}.{}".format(payload["eventKey"].tame(check_string), event_type) # nocoverage - raise UnsupportedWebhookEventType(message) + raise UnsupportedWebhookEventTypeError(message) subject = TOPIC_WITH_BRANCH_TEMPLATE.format(repo=repo_name, branch=branch_name) return {"subject": subject, "body": body} @@ -186,7 +186,7 @@ def repo_push_tag_data(payload: WildValue, change: WildValue) -> Dict[str, str]: action = "removed" else: message = "{}.{}".format(payload["eventKey"].tame(check_string), event_type) # nocoverage - raise UnsupportedWebhookEventType(message) + raise UnsupportedWebhookEventTypeError(message) subject = BITBUCKET_TOPIC_TEMPLATE.format(repository_name=repo_name) body = get_push_tag_event_message(get_user_name(payload), tag_name, action=action) @@ -213,7 +213,7 @@ def repo_push_handler( message = "{}.{}".format( payload["eventKey"].tame(check_string), event_target_type ) # nocoverage - raise UnsupportedWebhookEventType(message) + raise UnsupportedWebhookEventTypeError(message) return data @@ -446,7 +446,7 @@ def api_bitbucket3_webhook( assert eventkey is not None handler = EVENT_HANDLER_MAP.get(eventkey) if handler is None: - raise UnsupportedWebhookEventType(eventkey) + raise UnsupportedWebhookEventTypeError(eventkey) data = handler(payload, branches=branches, include_title=user_specified_topic) for element in data: diff --git a/zerver/webhooks/clubhouse/view.py b/zerver/webhooks/clubhouse/view.py index f3cc98ab6b..f00c1da506 100644 --- a/zerver/webhooks/clubhouse/view.py +++ b/zerver/webhooks/clubhouse/view.py @@ -4,7 +4,7 @@ from typing import Callable, Dict, Iterable, Iterator, List, Optional from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import ( @@ -695,7 +695,7 @@ def send_stream_messages_for_actions( body_func = EVENT_BODY_FUNCTION_MAPPER.get(event) topic_func = get_topic_function_based_on_type(payload, action) if body_func is None or topic_func is None: - raise UnsupportedWebhookEventType(event) + raise UnsupportedWebhookEventTypeError(event) topic = topic_func(payload, action) body = body_func(payload, action) diff --git a/zerver/webhooks/freshping/view.py b/zerver/webhooks/freshping/view.py index 49bf659741..55bf4ff4e3 100644 --- a/zerver/webhooks/freshping/view.py +++ b/zerver/webhooks/freshping/view.py @@ -1,7 +1,7 @@ from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_int, check_string, to_wild_value @@ -32,7 +32,7 @@ def api_freshping_webhook( subject = get_subject_for_http_request(payload) check_state_name = payload["webhook_event_data"]["check_state_name"].tame(check_string) if check_state_name not in CHECK_STATE_NAME_TO_EVENT_TYPE: - raise UnsupportedWebhookEventType(check_state_name) + raise UnsupportedWebhookEventTypeError(check_state_name) check_send_webhook_message( request, diff --git a/zerver/webhooks/gci/view.py b/zerver/webhooks/gci/view.py index efd1a2d051..4c89f7c132 100644 --- a/zerver/webhooks/gci/view.py +++ b/zerver/webhooks/gci/view.py @@ -17,7 +17,7 @@ def build_instance_url(instance_id: int) -> str: return f"https://codein.withgoogle.com/dashboard/task-instances/{instance_id}/" -class UnknownEventType(Exception): +class UnknownEventTypeError(Exception): pass @@ -155,7 +155,7 @@ def get_event(payload: WildValue) -> Optional[str]: if event in EVENTS_FUNCTION_MAPPER: return event - raise UnknownEventType(f"Event '{event}' is unknown and cannot be handled") # nocoverage + raise UnknownEventTypeError(f"Event '{event}' is unknown and cannot be handled") # nocoverage def get_body_based_on_event(event: str) -> Callable[[WildValue], str]: diff --git a/zerver/webhooks/github/view.py b/zerver/webhooks/github/view.py index f7efdc92eb..48950120ee 100644 --- a/zerver/webhooks/github/view.py +++ b/zerver/webhooks/github/view.py @@ -5,7 +5,7 @@ from typing import Callable, Dict, Optional from django.http import HttpRequest, HttpResponse from zerver.decorator import log_unsupported_webhook_event, webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import ( @@ -759,7 +759,7 @@ def api_github_webhook( """ header_event = validate_extract_webhook_http_header(request, "X-GitHub-Event", "GitHub") if header_event is None: - raise UnsupportedWebhookEventType("no header provided") + raise UnsupportedWebhookEventTypeError("no header provided") event = get_zulip_event_name(header_event, payload, branches) if event is None: @@ -832,7 +832,7 @@ def get_zulip_event_name( else: # this means GH has actually added new actions since September 2020, # so it's a bit more cause for alarm - raise UnsupportedWebhookEventType(f"unsupported team action {action}") + raise UnsupportedWebhookEventTypeError(f"unsupported team action {action}") elif header_event in list(EVENT_FUNCTION_MAPPER.keys()): return header_event elif header_event in IGNORED_EVENTS: @@ -841,4 +841,4 @@ def get_zulip_event_name( complete_event = "{}:{}".format( header_event, payload.get("action", "???").tame(check_string) ) # nocoverage - raise UnsupportedWebhookEventType(complete_event) + raise UnsupportedWebhookEventTypeError(complete_event) diff --git a/zerver/webhooks/gitlab/view.py b/zerver/webhooks/gitlab/view.py index de911c2e67..676522c634 100644 --- a/zerver/webhooks/gitlab/view.py +++ b/zerver/webhooks/gitlab/view.py @@ -5,7 +5,7 @@ from typing import Dict, List, Optional, Protocol, Union from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_bool, check_int, check_string, to_wild_value @@ -517,4 +517,4 @@ def get_event(request: HttpRequest, payload: WildValue, branches: Optional[str]) if event in list(EVENT_FUNCTION_MAPPER.keys()): return event - raise UnsupportedWebhookEventType(event) + raise UnsupportedWebhookEventTypeError(event) diff --git a/zerver/webhooks/gogs/view.py b/zerver/webhooks/gogs/view.py index d39a4bcd1d..615452b8d7 100644 --- a/zerver/webhooks/gogs/view.py +++ b/zerver/webhooks/gogs/view.py @@ -4,7 +4,7 @@ from typing import Dict, List, Optional, Protocol from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_bool, check_int, check_string, to_wild_value @@ -247,7 +247,7 @@ def gogs_webhook_main( ) else: - raise UnsupportedWebhookEventType(event) + raise UnsupportedWebhookEventTypeError(event) check_send_webhook_message(request, user_profile, topic, body, event) return json_success(request) diff --git a/zerver/webhooks/gosquared/view.py b/zerver/webhooks/gosquared/view.py index e13932cee4..857f695e08 100644 --- a/zerver/webhooks/gosquared/view.py +++ b/zerver/webhooks/gosquared/view.py @@ -1,7 +1,7 @@ from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_bool, check_int, check_string, to_wild_value @@ -58,6 +58,6 @@ def api_gosquared_webhook( ) check_send_webhook_message(request, user_profile, topic, body, "chat_message") else: - raise UnsupportedWebhookEventType("unknown_event") + raise UnsupportedWebhookEventTypeError("unknown_event") return json_success(request) diff --git a/zerver/webhooks/groove/view.py b/zerver/webhooks/groove/view.py index 14c45ca70f..5f2afe21a3 100644 --- a/zerver/webhooks/groove/view.py +++ b/zerver/webhooks/groove/view.py @@ -5,7 +5,7 @@ from typing import Callable, Dict, Optional from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import ( @@ -121,7 +121,7 @@ def api_groove_webhook( assert event is not None handler = EVENTS_FUNCTION_MAPPER.get(event) if handler is None: - raise UnsupportedWebhookEventType(event) + raise UnsupportedWebhookEventTypeError(event) body = handler(payload) topic = "notifications" diff --git a/zerver/webhooks/harbor/view.py b/zerver/webhooks/harbor/view.py index 5a519dc1ca..2b9f0c3acf 100644 --- a/zerver/webhooks/harbor/view.py +++ b/zerver/webhooks/harbor/view.py @@ -5,7 +5,7 @@ from django.db.models import Q from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_int, check_string, to_wild_value @@ -59,7 +59,7 @@ def handle_scanning_completed_event( scan_results = "" scan_overview = payload["event_data"]["resources"][0]["scan_overview"] if "application/vnd.security.vulnerability.report; version=1.1" not in scan_overview: - raise UnsupportedWebhookEventType("Unsupported harbor scanning webhook payload") + raise UnsupportedWebhookEventTypeError("Unsupported harbor scanning webhook payload") scan_summaries = scan_overview["application/vnd.security.vulnerability.report; version=1.1"][ "summary" ]["summary"] @@ -109,7 +109,7 @@ def api_harbor_webhook( content_func = EVENT_FUNCTION_MAPPER.get(event) if content_func is None: - raise UnsupportedWebhookEventType(event) + raise UnsupportedWebhookEventTypeError(event) content: str = content_func(payload, user_profile, operator_username) diff --git a/zerver/webhooks/intercom/view.py b/zerver/webhooks/intercom/view.py index 53f79541ae..9eb2cccbfe 100644 --- a/zerver/webhooks/intercom/view.py +++ b/zerver/webhooks/intercom/view.py @@ -5,7 +5,7 @@ from typing import Callable, Dict, List, Tuple from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_int, check_none_or, check_string, to_wild_value @@ -337,7 +337,7 @@ def api_intercom_webhook( handler = EVENT_TO_FUNCTION_MAPPER.get(event_type) if handler is None: - raise UnsupportedWebhookEventType(event_type) + raise UnsupportedWebhookEventTypeError(event_type) topic, body = handler(payload) check_send_webhook_message(request, user_profile, topic, body, event_type) diff --git a/zerver/webhooks/jira/view.py b/zerver/webhooks/jira/view.py index af22a2de00..7252272585 100644 --- a/zerver/webhooks/jira/view.py +++ b/zerver/webhooks/jira/view.py @@ -8,7 +8,7 @@ from django.db.models import Q from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import AnomalousWebhookPayload, UnsupportedWebhookEventType +from zerver.lib.exceptions import AnomalousWebhookPayloadError, UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_none_or, check_string, to_wild_value @@ -363,13 +363,13 @@ def api_jira_webhook( return json_success(request) if event is None: - raise AnomalousWebhookPayload() + raise AnomalousWebhookPayloadError() if event is not None: content_func = JIRA_CONTENT_FUNCTION_MAPPER.get(event) if content_func is None: - raise UnsupportedWebhookEventType(event) + raise UnsupportedWebhookEventTypeError(event) subject = get_issue_subject(payload) content: str = content_func(payload, user_profile) diff --git a/zerver/webhooks/lidarr/view.py b/zerver/webhooks/lidarr/view.py index 8128a66383..b1ab5fe9f9 100644 --- a/zerver/webhooks/lidarr/view.py +++ b/zerver/webhooks/lidarr/view.py @@ -3,7 +3,7 @@ from typing import Dict, List from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_bool, check_string, to_wild_value @@ -141,4 +141,4 @@ def get_body_for_http_request(payload: WildValue) -> str: else: return get_body_for_tracks_imported_event(payload) else: - raise UnsupportedWebhookEventType(event_type) + raise UnsupportedWebhookEventTypeError(event_type) diff --git a/zerver/webhooks/netlify/view.py b/zerver/webhooks/netlify/view.py index db783a7bdc..5d9a2fac0a 100644 --- a/zerver/webhooks/netlify/view.py +++ b/zerver/webhooks/netlify/view.py @@ -3,7 +3,7 @@ from typing import Tuple from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_string, to_wild_value @@ -63,6 +63,6 @@ def get_template(request: HttpRequest, payload: WildValue) -> Tuple[str, str]: elif event in ALL_EVENT_TYPES: message_template += "is now {state}.".format(state=payload["state"].tame(check_string)) else: - raise UnsupportedWebhookEventType(event) + raise UnsupportedWebhookEventTypeError(event) return message_template, event diff --git a/zerver/webhooks/pagerduty/view.py b/zerver/webhooks/pagerduty/view.py index 4b88fb36a5..505afa453a 100644 --- a/zerver/webhooks/pagerduty/view.py +++ b/zerver/webhooks/pagerduty/view.py @@ -4,7 +4,7 @@ from typing import Dict, Union from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_int, check_none_or, check_string, to_wild_value @@ -250,7 +250,7 @@ def api_pagerduty_webhook( break if message_type not in PAGER_DUTY_EVENT_NAMES: - raise UnsupportedWebhookEventType(message_type) + raise UnsupportedWebhookEventTypeError(message_type) format_dict = build_pagerduty_formatdict(message) send_formated_pagerduty(request, user_profile, message_type, format_dict) @@ -264,7 +264,7 @@ def api_pagerduty_webhook( break if message_event not in PAGER_DUTY_EVENT_NAMES_V2: - raise UnsupportedWebhookEventType(message_event) + raise UnsupportedWebhookEventTypeError(message_event) format_dict = build_pagerduty_formatdict_v2(message) send_formated_pagerduty(request, user_profile, message_event, format_dict) @@ -275,7 +275,7 @@ def api_pagerduty_webhook( event_type = event.get("event_type").tame(check_none_or(check_string)) if event_type not in PAGER_DUTY_EVENT_NAMES_V3: - raise UnsupportedWebhookEventType(event_type) + raise UnsupportedWebhookEventTypeError(event_type) format_dict = build_pagerduty_formatdict_v3(event) send_formated_pagerduty(request, user_profile, event_type, format_dict) diff --git a/zerver/webhooks/pingdom/view.py b/zerver/webhooks/pingdom/view.py index befd8023d9..aabeabfb8d 100644 --- a/zerver/webhooks/pingdom/view.py +++ b/zerver/webhooks/pingdom/view.py @@ -2,7 +2,7 @@ from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_string, to_wild_value @@ -51,7 +51,7 @@ def api_pingdom_webhook( subject = get_subject_for_http_request(payload) body = get_body_for_http_request(payload) else: - raise UnsupportedWebhookEventType(check_type) + raise UnsupportedWebhookEventTypeError(check_type) check_send_webhook_message(request, user_profile, subject, body, check_type) return json_success(request) diff --git a/zerver/webhooks/pivotal/tests.py b/zerver/webhooks/pivotal/tests.py index 5ffa4c5288..f738194cef 100644 --- a/zerver/webhooks/pivotal/tests.py +++ b/zerver/webhooks/pivotal/tests.py @@ -2,7 +2,7 @@ from unittest import mock import orjson -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.test_classes import WebhookTestCase from zerver.webhooks.pivotal.view import api_pivotal_webhook_v5 @@ -218,7 +218,7 @@ Try again next time self.assertEqual(result[0], "#0: ") bad = orjson.loads(self.get_body("bad_kind")) - with self.assertRaisesRegex(UnsupportedWebhookEventType, "'unknown_kind'.* supported"): + with self.assertRaisesRegex(UnsupportedWebhookEventTypeError, "'unknown_kind'.* supported"): with mock.patch("zerver.webhooks.pivotal.view.orjson.loads", return_value=bad): api_pivotal_webhook_v5(request, hamlet) diff --git a/zerver/webhooks/pivotal/view.py b/zerver/webhooks/pivotal/view.py index 5c55925c60..95afb942ba 100644 --- a/zerver/webhooks/pivotal/view.py +++ b/zerver/webhooks/pivotal/view.py @@ -8,7 +8,7 @@ from django.http import HttpRequest, HttpResponse from django.utils.translation import gettext as _ from zerver.decorator import webhook_view -from zerver.lib.exceptions import JsonableError, UnsupportedWebhookEventType +from zerver.lib.exceptions import JsonableError, UnsupportedWebhookEventTypeError from zerver.lib.request import has_request_variables from zerver.lib.response import json_success from zerver.lib.webhooks.common import check_send_webhook_message @@ -170,7 +170,7 @@ def api_pivotal_webhook_v5(request: HttpRequest, user_profile: UserProfile) -> T # Known but unsupported Pivotal event types pass else: - raise UnsupportedWebhookEventType(event_type) + raise UnsupportedWebhookEventTypeError(event_type) return subject, content, f"{event_type}_v5" diff --git a/zerver/webhooks/radarr/view.py b/zerver/webhooks/radarr/view.py index c9ec8d8fcc..8d2bb91530 100644 --- a/zerver/webhooks/radarr/view.py +++ b/zerver/webhooks/radarr/view.py @@ -1,7 +1,7 @@ from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_string, to_wild_value @@ -103,4 +103,4 @@ def get_body_for_http_request(payload: WildValue) -> str: elif event_type == "Grab": return get_body_for_movie_grabbed_event(payload) else: - raise UnsupportedWebhookEventType(event_type) + raise UnsupportedWebhookEventTypeError(event_type) diff --git a/zerver/webhooks/raygun/view.py b/zerver/webhooks/raygun/view.py index 860e54d3b9..aa0dfaa281 100644 --- a/zerver/webhooks/raygun/view.py +++ b/zerver/webhooks/raygun/view.py @@ -3,7 +3,7 @@ import time from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import ( @@ -43,7 +43,7 @@ def api_raygun_webhook( elif event == "error_activity": message = compose_activity_message(payload) else: - raise UnsupportedWebhookEventType(event) + raise UnsupportedWebhookEventTypeError(event) topic = "test" @@ -232,7 +232,7 @@ def compose_notification_message(payload: WildValue) -> str: elif "FollowUp" in event_type: return notification_message_follow_up(payload) else: - raise UnsupportedWebhookEventType(event_type) + raise UnsupportedWebhookEventTypeError(event_type) def activity_message(payload: WildValue) -> str: @@ -292,7 +292,7 @@ def compose_activity_message(payload: WildValue) -> str: ): return activity_message(payload) else: - raise UnsupportedWebhookEventType(event_type) + raise UnsupportedWebhookEventTypeError(event_type) def parse_time(timestamp: str) -> str: diff --git a/zerver/webhooks/reviewboard/view.py b/zerver/webhooks/reviewboard/view.py index 2bd9eecb77..f017295c22 100644 --- a/zerver/webhooks/reviewboard/view.py +++ b/zerver/webhooks/reviewboard/view.py @@ -1,7 +1,7 @@ from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_int, check_none_or, check_string, to_wild_value @@ -194,6 +194,6 @@ def api_reviewboard_webhook( topic = get_review_request_repo_title(payload) check_send_webhook_message(request, user_profile, topic, body, event_type) else: - raise UnsupportedWebhookEventType(event_type) + raise UnsupportedWebhookEventTypeError(event_type) return json_success(request) diff --git a/zerver/webhooks/rhodecode/view.py b/zerver/webhooks/rhodecode/view.py index 17818e2564..84009063ac 100644 --- a/zerver/webhooks/rhodecode/view.py +++ b/zerver/webhooks/rhodecode/view.py @@ -4,7 +4,7 @@ from django.core.exceptions import ValidationError from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_string, to_wild_value @@ -55,7 +55,7 @@ def get_event_name(payload: WildValue, branches: Optional[str]) -> Optional[str] return None if event_name in EVENT_FUNCTION_MAPPER: return event_name - raise UnsupportedWebhookEventType(event_name) + raise UnsupportedWebhookEventTypeError(event_name) def get_repository_name(payload: WildValue) -> str: diff --git a/zerver/webhooks/sentry/view.py b/zerver/webhooks/sentry/view.py index 35c74f2690..06e8bccc10 100644 --- a/zerver/webhooks/sentry/view.py +++ b/zerver/webhooks/sentry/view.py @@ -6,7 +6,7 @@ from urllib.parse import urljoin from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.webhooks.common import check_send_webhook_message @@ -95,7 +95,7 @@ def handle_event_payload(event: Dict[str, Any]) -> Tuple[str, str]: """Handle either an exception type event or a message type event payload.""" # We shouldn't support the officially deprecated Raven series of SDKs. if int(event["version"]) < 7: - raise UnsupportedWebhookEventType("Raven SDK") + raise UnsupportedWebhookEventTypeError("Raven SDK") subject = event["title"] platform_name = event["platform"] @@ -159,7 +159,7 @@ def handle_event_payload(event: Dict[str, Any]) -> Tuple[str, str]: body = MESSAGE_EVENT_TEMPLATE.format(**context) else: - raise UnsupportedWebhookEventType("unknown-event type") + raise UnsupportedWebhookEventTypeError("unknown-event type") return (subject, body) @@ -211,7 +211,7 @@ def handle_issue_payload( body = ISSUE_IGNORED_MESSAGE_TEMPLATE.format(**context) else: - raise UnsupportedWebhookEventType("unknown-issue-action type") + raise UnsupportedWebhookEventTypeError("unknown-issue-action type") return (subject, body) @@ -266,7 +266,7 @@ def api_sentry_webhook( elif "issue" in data: subject, body = handle_issue_payload(payload["action"], data["issue"], payload["actor"]) else: - raise UnsupportedWebhookEventType(str(list(data.keys()))) + raise UnsupportedWebhookEventTypeError(str(list(data.keys()))) else: subject, body = handle_deprecated_payload(payload) diff --git a/zerver/webhooks/sonarr/view.py b/zerver/webhooks/sonarr/view.py index 5cfe904c28..9e1edccb63 100644 --- a/zerver/webhooks/sonarr/view.py +++ b/zerver/webhooks/sonarr/view.py @@ -1,7 +1,7 @@ from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_bool, check_int, check_string, to_wild_value @@ -167,4 +167,4 @@ def get_body_for_http_request(payload: WildValue) -> str: else: return get_body_for_episode_deleted_event(payload) else: - raise UnsupportedWebhookEventType(event_type) + raise UnsupportedWebhookEventTypeError(event_type) diff --git a/zerver/webhooks/statuspage/view.py b/zerver/webhooks/statuspage/view.py index 1530b207f8..ae02257031 100644 --- a/zerver/webhooks/statuspage/view.py +++ b/zerver/webhooks/statuspage/view.py @@ -2,7 +2,7 @@ from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_string, to_wild_value @@ -69,7 +69,7 @@ def api_statuspage_webhook( topic = get_component_topic(payload) body = get_components_update_body(payload) else: - raise UnsupportedWebhookEventType("unknown-event") + raise UnsupportedWebhookEventTypeError("unknown-event") check_send_webhook_message(request, user_profile, topic, body, event) return json_success(request) diff --git a/zerver/webhooks/stripe/view.py b/zerver/webhooks/stripe/view.py index beb3efc229..7c49a12ba2 100644 --- a/zerver/webhooks/stripe/view.py +++ b/zerver/webhooks/stripe/view.py @@ -5,7 +5,7 @@ from typing import Dict, Optional, Sequence, Tuple from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.timestamp import timestamp_to_datetime @@ -21,11 +21,11 @@ from zerver.lib.webhooks.common import check_send_webhook_message from zerver.models import UserProfile -class SuppressedEvent(Exception): +class SuppressedEventError(Exception): pass -class NotImplementedEventType(SuppressedEvent): +class NotImplementedEventTypeError(SuppressedEventError): pass @@ -63,7 +63,7 @@ def api_stripe_webhook( ) -> HttpResponse: try: topic, body = topic_and_body(payload) - except SuppressedEvent: # nocoverage + except SuppressedEventError: # nocoverage return json_success(request) check_send_webhook_message( request, user_profile, topic, body, payload["type"].tame(check_string) @@ -98,7 +98,7 @@ def topic_and_body(payload: WildValue) -> Tuple[str, str]: blacklist ) if not previous_attributes: # nocoverage - raise SuppressedEvent() + raise SuppressedEventError() return "".join( "\n* " + attribute.replace("_", " ").capitalize() @@ -119,18 +119,18 @@ def topic_and_body(payload: WildValue) -> Tuple[str, str]: if resource == "account": if event == "updated": if "previous_attributes" not in payload["data"]: - raise SuppressedEvent() + raise SuppressedEventError() topic = "account updates" body = update_string() else: # Part of Stripe Connect - raise NotImplementedEventType() + raise NotImplementedEventTypeError() if category == "application_fee": # nocoverage # Part of Stripe Connect - raise NotImplementedEventType() + raise NotImplementedEventTypeError() if category == "balance": # nocoverage # Not that interesting to most businesses, I think - raise NotImplementedEventType() + raise NotImplementedEventTypeError() if category == "charge": if resource == "charge": if not topic: # only in legacy fixtures @@ -160,10 +160,10 @@ def topic_and_body(payload: WildValue) -> Tuple[str, str]: ) if category == "checkout_beta": # nocoverage # Not sure what this is - raise NotImplementedEventType() + raise NotImplementedEventTypeError() if category == "coupon": # nocoverage # Not something that likely happens programmatically - raise NotImplementedEventType() + raise NotImplementedEventTypeError() if category == "customer": if resource == "customer": # Running into the 60 character topic limit. @@ -260,10 +260,10 @@ def topic_and_body(payload: WildValue) -> Tuple[str, str]: ) if category.startswith("issuing"): # nocoverage # Not implemented - raise NotImplementedEventType() + raise NotImplementedEventTypeError() if category.startswith("order"): # nocoverage # Not implemented - raise NotImplementedEventType() + raise NotImplementedEventTypeError() if category in [ "payment_intent", "payout", @@ -282,10 +282,10 @@ def topic_and_body(payload: WildValue) -> Tuple[str, str]: # Not implemented. In theory doing something like # body = default_body() # may not be hard for some of these - raise NotImplementedEventType() + raise NotImplementedEventTypeError() if body is None: - raise UnsupportedWebhookEventType(event_type) + raise UnsupportedWebhookEventTypeError(event_type) return (topic, body) diff --git a/zerver/webhooks/transifex/view.py b/zerver/webhooks/transifex/view.py index c123a8a2b1..42fa6c3132 100644 --- a/zerver/webhooks/transifex/view.py +++ b/zerver/webhooks/transifex/view.py @@ -4,7 +4,7 @@ from typing import Optional from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import check_int @@ -33,6 +33,6 @@ def api_transifex_webhook( event = "review" body = f"Resource {resource} fully reviewed." else: - raise UnsupportedWebhookEventType("Unknown Event Type") + raise UnsupportedWebhookEventTypeError("Unknown Event Type") check_send_webhook_message(request, user_profile, subject, body, event) return json_success(request) diff --git a/zerver/webhooks/trello/view/__init__.py b/zerver/webhooks/trello/view/__init__.py index 2fa7edc1c7..26d0aa82e8 100644 --- a/zerver/webhooks/trello/view/__init__.py +++ b/zerver/webhooks/trello/view/__init__.py @@ -4,7 +4,7 @@ from typing import Optional, Tuple from django.http import HttpRequest, HttpResponse from zerver.decorator import return_success_on_head_request, webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_string, to_wild_value @@ -42,4 +42,4 @@ def get_subject_and_body(payload: WildValue, action_type: str) -> Optional[Tuple if action_type in SUPPORTED_BOARD_ACTIONS: return process_board_action(payload, action_type) - raise UnsupportedWebhookEventType(action_type) + raise UnsupportedWebhookEventTypeError(action_type) diff --git a/zerver/webhooks/trello/view/board_actions.py b/zerver/webhooks/trello/view/board_actions.py index 7f3e623c95..87d04d3c32 100644 --- a/zerver/webhooks/trello/view/board_actions.py +++ b/zerver/webhooks/trello/view/board_actions.py @@ -1,6 +1,6 @@ from typing import Mapping, Optional, Tuple -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.validator import WildValue, check_string SUPPORTED_BOARD_ACTIONS = [ @@ -43,7 +43,7 @@ def get_proper_action(payload: WildValue, action_type: Optional[str]) -> Optiona return None elif data["old"]["name"].tame(check_string): return CHANGE_NAME - raise UnsupportedWebhookEventType(action_type) + raise UnsupportedWebhookEventTypeError(action_type) return action_type diff --git a/zerver/webhooks/trello/view/card_actions.py b/zerver/webhooks/trello/view/card_actions.py index 0f1444fe27..444951abe0 100644 --- a/zerver/webhooks/trello/view/card_actions.py +++ b/zerver/webhooks/trello/view/card_actions.py @@ -1,6 +1,6 @@ from typing import Mapping, Optional, Tuple -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.validator import WildValue, check_bool, check_none_or, check_string SUPPORTED_CARD_ACTIONS = [ @@ -126,7 +126,7 @@ def get_proper_action(payload: WildValue, action_type: str) -> Optional[str]: for field in ignored_fields: if field in old_data: return None - raise UnsupportedWebhookEventType(action_type) + raise UnsupportedWebhookEventTypeError(action_type) return action_type diff --git a/zerver/webhooks/updown/view.py b/zerver/webhooks/updown/view.py index bac7f7cfa6..38e66fd5ec 100644 --- a/zerver/webhooks/updown/view.py +++ b/zerver/webhooks/updown/view.py @@ -4,7 +4,7 @@ import re from django.http import HttpRequest, HttpResponse from zerver.decorator import webhook_view -from zerver.lib.exceptions import UnsupportedWebhookEventType +from zerver.lib.exceptions import UnsupportedWebhookEventTypeError from zerver.lib.request import REQ, has_request_variables from zerver.lib.response import json_success from zerver.lib.validator import WildValue, check_int, check_none_or, check_string, to_wild_value @@ -92,4 +92,4 @@ def get_event_type(event: WildValue) -> str: event_type = event_type_match.group(1) if event_type in EVENT_TYPE_BODY_MAPPER: return event_type - raise UnsupportedWebhookEventType(event["event"].tame(check_string)) + raise UnsupportedWebhookEventTypeError(event["event"].tame(check_string)) diff --git a/zerver/worker/queue_processors.py b/zerver/worker/queue_processors.py index c2aba93878..93109064fe 100644 --- a/zerver/worker/queue_processors.py +++ b/zerver/worker/queue_processors.py @@ -54,7 +54,7 @@ from zerver.actions.presence import do_update_user_presence from zerver.actions.realm_export import notify_realm_export from zerver.actions.user_activity import do_update_user_activity, do_update_user_activity_interval from zerver.context_processors import common_context -from zerver.lib.bot_lib import EmbeddedBotHandler, EmbeddedBotQuitException, get_bot_handler +from zerver.lib.bot_lib import EmbeddedBotHandler, EmbeddedBotQuitError, get_bot_handler from zerver.lib.context_managers import lockfile from zerver.lib.db import reset_queries from zerver.lib.digest import bulk_handle_digest_email @@ -66,7 +66,7 @@ from zerver.lib.email_mirror import ( from zerver.lib.email_mirror import process_message as mirror_email from zerver.lib.email_notifications import handle_missedmessage_emails from zerver.lib.error_notify import do_report_error -from zerver.lib.exceptions import RateLimited +from zerver.lib.exceptions import RateLimitedError from zerver.lib.export import export_realm_wrapper from zerver.lib.outgoing_webhook import do_rest_call, get_outgoing_webhook_service_handler from zerver.lib.push_notifications import ( @@ -79,7 +79,7 @@ from zerver.lib.pysa import mark_sanitized from zerver.lib.queue import SimpleQueueClient, retry_event from zerver.lib.remote_server import PushNotificationBouncerRetryLaterError from zerver.lib.send_email import ( - EmailNotDeliveredException, + EmailNotDeliveredError, FromAddress, handle_send_email_format_changes, initialize_connection, @@ -110,7 +110,7 @@ from zerver.models import ( logger = logging.getLogger(__name__) -class WorkerTimeoutException(Exception): +class WorkerTimeoutError(Exception): def __init__(self, queue_name: str, limit: int, event_count: int) -> None: self.queue_name = queue_name self.limit = limit @@ -120,7 +120,7 @@ class WorkerTimeoutException(Exception): return f"Timed out in {self.queue_name} after {self.limit * self.event_count} seconds processing {self.event_count} events" -class InterruptConsumeException(Exception): +class InterruptConsumeError(Exception): """ This exception is to be thrown inside event consume function if the intention is to simply interrupt the processing @@ -130,7 +130,7 @@ class InterruptConsumeException(Exception): pass -class WorkerDeclarationException(Exception): +class WorkerDeclarationError(Exception): pass @@ -198,7 +198,7 @@ def retry_send_email_failures( except ( socket.gaierror, socket.timeout, - EmailNotDeliveredException, + EmailNotDeliveredError, ) as e: error_class_name = type(e).__name__ @@ -230,7 +230,7 @@ class QueueProcessingWorker(ABC): def __init__(self) -> None: self.q: Optional[SimpleQueueClient] = None if not hasattr(self, "queue_name"): - raise WorkerDeclarationException("Queue worker declared without queue_name") + raise WorkerDeclarationError("Queue worker declared without queue_name") self.initialize_statistics() @@ -360,10 +360,10 @@ class QueueProcessingWorker(ABC): def timer_expired( self, limit: int, events: List[Dict[str, Any]], signal: int, frame: FrameType ) -> None: - raise WorkerTimeoutException(self.queue_name, limit, len(events)) + raise WorkerTimeoutError(self.queue_name, limit, len(events)) def _handle_consume_exception(self, events: List[Dict[str, Any]], exception: Exception) -> None: - if isinstance(exception, InterruptConsumeException): + if isinstance(exception, InterruptConsumeError): # The exception signals that no further error handling # is needed and the worker can proceed. return @@ -376,7 +376,7 @@ class QueueProcessingWorker(ABC): "queue_name": self.queue_name, }, ) - if isinstance(exception, WorkerTimeoutException): + if isinstance(exception, WorkerTimeoutError): with sentry_sdk.push_scope() as scope: scope.fingerprint = ["worker-timeout", self.queue_name] logging.exception(exception, stack_info=True) @@ -825,7 +825,7 @@ class MirrorWorker(QueueProcessingWorker): recipient_realm = decode_stream_email_address(rcpt_to)[0].realm try: rate_limit_mirror_by_realm(recipient_realm) - except RateLimited: + except RateLimitedError: logger.warning( "MirrorWorker: Rejecting an email from: %s to realm: %s - rate limited.", msg["From"], @@ -888,7 +888,7 @@ class FetchLinksEmbedData(QueueProcessingWorker): event["message_id"], event["urls"], ) - raise InterruptConsumeException + raise InterruptConsumeError @assign_queue("outgoing_webhooks") @@ -939,7 +939,7 @@ class EmbeddedBotWorker(QueueProcessingWorker): message=message, bot_handler=self.get_bot_api_client(user_profile), ) - except EmbeddedBotQuitException as e: + except EmbeddedBotQuitError as e: logging.warning("%s", e) diff --git a/zilencer/auth.py b/zilencer/auth.py index fe8b0e3fe6..2a95a60a12 100644 --- a/zilencer/auth.py +++ b/zilencer/auth.py @@ -14,7 +14,7 @@ from zerver.decorator import get_basic_credentials, process_client from zerver.lib.exceptions import ( ErrorCode, JsonableError, - RateLimited, + RateLimitedError, RemoteServerDeactivatedError, UnauthorizedError, ) @@ -60,7 +60,7 @@ def rate_limit_remote_server( try: RateLimitedRemoteZulipServer(remote_server, domain=domain).rate_limit_request(request) - except RateLimited as e: + except RateLimitedError as e: logger.warning("Remote server %s exceeded rate limits on domain %s", remote_server, domain) raise e diff --git a/zproject/backends.py b/zproject/backends.py index fe17746ae1..c5ed1d3ce5 100644 --- a/zproject/backends.py +++ b/zproject/backends.py @@ -299,7 +299,7 @@ def rate_limit_auth(auth_func: AuthFuncT, *args: Any, **kwargs: Any) -> Optional pass else: # Apply rate limiting. If this request is above the limit, - # RateLimited will be raised, interrupting the authentication process. + # RateLimitedError will be raised, interrupting the authentication process. # From there, the code calling authenticate() can either catch the exception # and handle it on its own, or it will be processed by RateLimitMiddleware. rate_limit_authentication_by_username(request, username) @@ -587,16 +587,16 @@ class LDAPReverseEmailSearch(_LDAPUser): return ldap_users -class ZulipLDAPException(_LDAPUser.AuthenticationFailed): +class ZulipLDAPError(_LDAPUser.AuthenticationFailed): """Since this inherits from _LDAPUser.AuthenticationFailed, these will be caught and logged at debug level inside django-auth-ldap's authenticate()""" -class ZulipLDAPExceptionNoMatchingLDAPUser(ZulipLDAPException): +class NoMatchingLDAPUserError(ZulipLDAPError): pass -class ZulipLDAPExceptionOutsideDomain(ZulipLDAPExceptionNoMatchingLDAPUser): +class OutsideLDAPDomainError(NoMatchingLDAPUserError): pass @@ -648,14 +648,14 @@ class ZulipLDAPAuthBackendBase(ZulipAuthMixin, LDAPBackend): Translates django username (user_profile.delivery_email or whatever the user typed in the login field when authenticating via the LDAP backend) into LDAP username. Guarantees that the username it returns actually has an entry in the LDAP directory. - Raises ZulipLDAPExceptionNoMatchingLDAPUser if that's not possible. + Raises NoMatchingLDAPUserError if that's not possible. """ result = username if settings.LDAP_APPEND_DOMAIN: if is_valid_email(username): address = Address(addr_spec=username) if address.domain != settings.LDAP_APPEND_DOMAIN: - raise ZulipLDAPExceptionOutsideDomain( + raise OutsideLDAPDomainError( f"Email {username} does not match LDAP domain {settings.LDAP_APPEND_DOMAIN}." ) result = address.username @@ -680,7 +680,7 @@ class ZulipLDAPAuthBackendBase(ZulipAuthMixin, LDAPBackend): error_message = ( "No LDAP user matching django_to_ldap_username result: {}. Input username: {}" ) - raise ZulipLDAPExceptionNoMatchingLDAPUser( + raise NoMatchingLDAPUserError( error_message.format(result, username), ) @@ -698,7 +698,7 @@ class ZulipLDAPAuthBackendBase(ZulipAuthMixin, LDAPBackend): if settings.LDAP_EMAIL_ATTR is not None: # Get email from LDAP attributes. if settings.LDAP_EMAIL_ATTR not in ldap_user.attrs: - raise ZulipLDAPException( + raise ZulipLDAPError( f"LDAP user doesn't have the needed {settings.LDAP_EMAIL_ATTR} attribute" ) else: @@ -831,7 +831,7 @@ class ZulipLDAPAuthBackendBase(ZulipAuthMixin, LDAPBackend): last_name = ldap_user.attrs[last_name_attr][0] full_name = f"{first_name} {last_name}" else: - raise ZulipLDAPException("Missing required mapping for user's full name") + raise ZulipLDAPError("Missing required mapping for user's full name") return full_name @@ -843,7 +843,7 @@ class ZulipLDAPAuthBackendBase(ZulipAuthMixin, LDAPBackend): try: full_name = check_full_name(full_name) except JsonableError as e: - raise ZulipLDAPException(e.msg) + raise ZulipLDAPError(e.msg) do_change_full_name(user_profile, full_name, None) def sync_custom_profile_fields_from_ldap( @@ -865,8 +865,8 @@ class ZulipLDAPAuthBackendBase(ZulipAuthMixin, LDAPBackend): try: sync_user_profile_custom_fields(user_profile, values_by_var_name) - except SyncUserException as e: - raise ZulipLDAPException(str(e)) from e + except SyncUserError as e: + raise ZulipLDAPError(str(e)) from e class ZulipLDAPAuthBackend(ZulipLDAPAuthBackendBase): @@ -897,7 +897,7 @@ class ZulipLDAPAuthBackend(ZulipLDAPAuthBackendBase): # to the user's LDAP username before calling the # django-auth-ldap authenticate(). username = self.django_to_ldap_username(username) - except ZulipLDAPExceptionNoMatchingLDAPUser as e: + except NoMatchingLDAPUserError as e: ldap_logger.debug("%s: %s", type(self).__name__, e) if return_data is not None: return_data["no_matching_ldap_user"] = True @@ -930,14 +930,14 @@ class ZulipLDAPAuthBackend(ZulipLDAPAuthBackendBase): username = self.user_email_from_ldapuser(username, ldap_user) if self.is_account_realm_access_forbidden(ldap_user, self._realm): - raise ZulipLDAPException("User not allowed to access realm") + raise ZulipLDAPError("User not allowed to access realm") if ldap_should_sync_active_status(): # nocoverage ldap_disabled = self.is_user_disabled_in_ldap(ldap_user) if ldap_disabled: # Treat disabled users as deactivated in Zulip. return_data["inactive_user"] = True - raise ZulipLDAPException("User has been deactivated") + raise ZulipLDAPError("User has been deactivated") user_profile = common_get_active_user(username, self._realm, return_data) if user_profile is not None: @@ -946,9 +946,9 @@ class ZulipLDAPAuthBackend(ZulipLDAPAuthBackendBase): if return_data.get("inactive_realm"): # This happens if there is a user account in a deactivated realm - raise ZulipLDAPException("Realm has been deactivated") + raise ZulipLDAPError("Realm has been deactivated") if return_data.get("inactive_user"): - raise ZulipLDAPException("User has been deactivated") + raise ZulipLDAPError("User has been deactivated") # An invalid_subdomain `return_data` value here is ignored, # since that just means we're trying to create an account in a # second realm on the server (`ldap_auth_enabled(realm)` would @@ -957,7 +957,7 @@ class ZulipLDAPAuthBackend(ZulipLDAPAuthBackendBase): if self._realm.deactivated: # This happens if no account exists, but the realm is # deactivated, so we shouldn't create a new user account - raise ZulipLDAPException("Realm has been deactivated") + raise ZulipLDAPError("Realm has been deactivated") try: validate_email(username) @@ -967,7 +967,7 @@ class ZulipLDAPAuthBackend(ZulipLDAPAuthBackendBase): # or a malformed email value in the ldap directory, # so we should log a warning about this before failing. self.logger.warning(error_message) - raise ZulipLDAPException(error_message) + raise ZulipLDAPError(error_message) # Makes sure that email domain hasn't be restricted for this # realm. The main thing here is email_allowed_for_realm; but @@ -977,16 +977,16 @@ class ZulipLDAPAuthBackend(ZulipLDAPAuthBackendBase): email_allowed_for_realm(username, self._realm) validate_email_not_already_in_realm(self._realm, username) except DomainNotAllowedForRealmError: - raise ZulipLDAPException("This email domain isn't allowed in this organization.") + raise ZulipLDAPError("This email domain isn't allowed in this organization.") except (DisposableEmailError, EmailContainsPlusError): - raise ZulipLDAPException("Email validation failed.") + raise ZulipLDAPError("Email validation failed.") # We have valid LDAP credentials; time to create an account. full_name = self.get_mapped_name(ldap_user) try: full_name = check_full_name(full_name) except JsonableError as e: - raise ZulipLDAPException(e.msg) + raise ZulipLDAPError(e.msg) opts: Dict[str, Any] = {} if self._prereg_user: @@ -1087,7 +1087,7 @@ class ZulipLDAPUserPopulator(ZulipLDAPAuthBackendBase): return (user, built) -class PopulateUserLDAPError(ZulipLDAPException): +class PopulateUserLDAPError(ZulipLDAPError): pass @@ -1111,7 +1111,7 @@ def sync_user_from_ldap(user_profile: UserProfile, logger: logging.Logger) -> bo backend = ZulipLDAPUserPopulator() try: ldap_username = backend.django_to_ldap_username(user_profile.delivery_email) - except ZulipLDAPExceptionNoMatchingLDAPUser: + except NoMatchingLDAPUserError: if ( settings.ONLY_LDAP if settings.LDAP_DEACTIVATE_NON_MATCHING_USERS is None @@ -1156,7 +1156,7 @@ def query_ldap(email: str) -> List[str]: if backend is not None: try: ldap_username = backend.django_to_ldap_username(email) - except ZulipLDAPExceptionNoMatchingLDAPUser as e: + except NoMatchingLDAPUserError as e: values.append(f"No such user found: {e}") return values @@ -1345,7 +1345,7 @@ class ExternalAuthResult: pass -class SyncUserException(Exception): +class SyncUserError(Exception): pass @@ -1368,13 +1368,13 @@ def sync_user_profile_custom_fields( try: field = fields_by_var_name[var_name] except KeyError: - raise SyncUserException(f"Custom profile field with name {var_name} not found.") + raise SyncUserError(f"Custom profile field with name {var_name} not found.") if existing_values.get(var_name) == value: continue try: validate_user_custom_profile_field(user_profile.realm.id, field, value) except ValidationError as error: - raise SyncUserException(f"Invalid data for {var_name} field: {error.message}") + raise SyncUserError(f"Invalid data for {var_name} field: {error.message}") profile_data.append( { "id": field.id, @@ -1723,7 +1723,7 @@ def social_auth_finish( custom_profile_field_name_to_value[field_name] = extra_attrs.get(attr_name) try: sync_user_profile_custom_fields(user_profile, custom_profile_field_name_to_value) - except SyncUserException as e: + except SyncUserError as e: backend.logger.warning( "Exception while syncing custom profile fields for user %s: %s", user_profile.id,