diff --git a/analytics/management/commands/clear_analytics_tables.py b/analytics/management/commands/clear_analytics_tables.py index cd1018af76..57c9ce0f2f 100644 --- a/analytics/management/commands/clear_analytics_tables.py +++ b/analytics/management/commands/clear_analytics_tables.py @@ -1,8 +1,7 @@ -import sys from argparse import ArgumentParser from typing import Any -from django.core.management.base import BaseCommand +from django.core.management.base import BaseCommand, CommandError from analytics.lib.counts import do_drop_all_analytics_tables @@ -18,5 +17,4 @@ class Command(BaseCommand): if options['force']: do_drop_all_analytics_tables() else: - print("Would delete all data from analytics tables (!); use --force to do so.") - sys.exit(1) + raise CommandError("Would delete all data from analytics tables (!); use --force to do so.") diff --git a/analytics/management/commands/clear_single_stat.py b/analytics/management/commands/clear_single_stat.py index 1e3dd33fda..f3a52c15ed 100644 --- a/analytics/management/commands/clear_single_stat.py +++ b/analytics/management/commands/clear_single_stat.py @@ -1,8 +1,7 @@ -import sys from argparse import ArgumentParser from typing import Any -from django.core.management.base import BaseCommand +from django.core.management.base import BaseCommand, CommandError from analytics.lib.counts import COUNT_STATS, do_drop_single_stat @@ -20,10 +19,8 @@ class Command(BaseCommand): def handle(self, *args: Any, **options: Any) -> None: property = options['property'] if property not in COUNT_STATS: - print("Invalid property: %s" % (property,)) - sys.exit(1) + raise CommandError("Invalid property: %s" % (property,)) if not options['force']: - print("No action taken. Use --force.") - sys.exit(1) + raise CommandError("No action taken. Use --force.") do_drop_single_stat(property) diff --git a/analytics/management/commands/realm_stats.py b/analytics/management/commands/realm_stats.py index 6ddcfce310..e9bb29cf3e 100644 --- a/analytics/management/commands/realm_stats.py +++ b/analytics/management/commands/realm_stats.py @@ -2,7 +2,7 @@ import datetime from argparse import ArgumentParser from typing import Any, List -from django.core.management.base import BaseCommand +from django.core.management.base import BaseCommand, CommandError from django.db.models import Count from django.utils.timezone import now as timezone_now @@ -73,8 +73,7 @@ class Command(BaseCommand): try: realms = [get_realm(string_id) for string_id in options['realms']] except Realm.DoesNotExist as e: - print(e) - exit(1) + raise CommandError(e) else: realms = Realm.objects.all() diff --git a/analytics/management/commands/stream_stats.py b/analytics/management/commands/stream_stats.py index 7e682f9607..d868bdbe78 100644 --- a/analytics/management/commands/stream_stats.py +++ b/analytics/management/commands/stream_stats.py @@ -1,7 +1,7 @@ from argparse import ArgumentParser from typing import Any -from django.core.management.base import BaseCommand +from django.core.management.base import BaseCommand, CommandError from django.db.models import Q from zerver.models import Message, Realm, \ @@ -19,8 +19,7 @@ class Command(BaseCommand): try: realms = [get_realm(string_id) for string_id in options['realms']] except Realm.DoesNotExist as e: - print(e) - exit(1) + raise CommandError(e) else: realms = Realm.objects.all() diff --git a/analytics/management/commands/user_stats.py b/analytics/management/commands/user_stats.py index 59d9a3c998..8cb7615425 100644 --- a/analytics/management/commands/user_stats.py +++ b/analytics/management/commands/user_stats.py @@ -2,7 +2,7 @@ import datetime from argparse import ArgumentParser from typing import Any -from django.core.management.base import BaseCommand +from django.core.management.base import BaseCommand, CommandError from django.utils.timezone import now as timezone_now from zerver.models import Message, Realm, Stream, UserProfile, get_realm @@ -24,8 +24,7 @@ class Command(BaseCommand): try: realms = [get_realm(string_id) for string_id in options['realms']] except Realm.DoesNotExist as e: - print(e) - exit(1) + raise CommandError(e) else: realms = Realm.objects.all() diff --git a/zerver/management/commands/add_users_to_mailing_list.py b/zerver/management/commands/add_users_to_mailing_list.py index baa6ce8aae..f2c9cf0add 100644 --- a/zerver/management/commands/add_users_to_mailing_list.py +++ b/zerver/management/commands/add_users_to_mailing_list.py @@ -6,7 +6,7 @@ from typing import Any import requests import ujson from django.conf import settings -from django.core.management.base import BaseCommand +from django.core.management.base import BaseCommand, CommandError from django.utils.timezone import now as timezone_now from zerver.models import UserProfile @@ -33,24 +33,20 @@ class Command(BaseCommand): if options['api_key'] is None: try: if settings.MAILCHIMP_API_KEY is None: - print('MAILCHIMP_API_KEY is None. Check your server settings file.') - exit(1) + raise CommandError('MAILCHIMP_API_KEY is None. Check your server settings file.') options['api_key'] = settings.MAILCHIMP_API_KEY except AttributeError: - print('Please supply a MailChimp API key to --api-key, or add a ' - 'MAILCHIMP_API_KEY to your server settings file.') - exit(1) + raise CommandError('Please supply a MailChimp API key to --api-key, or add a ' + 'MAILCHIMP_API_KEY to your server settings file.') if options['list_id'] is None: try: if settings.ZULIP_FRIENDS_LIST_ID is None: - print('ZULIP_FRIENDS_LIST_ID is None. Check your server settings file.') - exit(1) + raise CommandError('ZULIP_FRIENDS_LIST_ID is None. Check your server settings file.') options['list_id'] = settings.ZULIP_FRIENDS_LIST_ID except AttributeError: - print('Please supply a MailChimp List ID to --list-id, or add a ' - 'ZULIP_FRIENDS_LIST_ID to your server settings file.') - exit(1) + raise CommandError('Please supply a MailChimp List ID to --list-id, or add a ' + 'ZULIP_FRIENDS_LIST_ID to your server settings file.') endpoint = "https://%s.api.mailchimp.com/3.0/lists/%s/members" % \ (options['api_key'].split('-')[1], options['list_id']) diff --git a/zerver/management/commands/check_redis.py b/zerver/management/commands/check_redis.py index 96acd09daa..6e49ef2942 100644 --- a/zerver/management/commands/check_redis.py +++ b/zerver/management/commands/check_redis.py @@ -4,7 +4,7 @@ import time from typing import Any, Callable, Optional from django.conf import settings -from django.core.management.base import BaseCommand, CommandParser +from django.core.management.base import BaseCommand, CommandParser, CommandError from zerver.lib.rate_limiter import RateLimitedUser, \ client, max_api_calls, max_api_window @@ -44,8 +44,7 @@ than max_api_calls! (trying to trim) %s %s" % (key, count)) def handle(self, *args: Any, **options: Any) -> None: if not settings.RATE_LIMITING: - print("This machine is not using redis or rate limiting, aborting") - exit(1) + raise CommandError("This machine is not using redis or rate limiting, aborting") # Find all keys, and make sure they're all within size constraints wildcard_list = "ratelimit:*:*:list" diff --git a/zerver/management/commands/convert_gitter_data.py b/zerver/management/commands/convert_gitter_data.py index f10803e79a..92b10466be 100644 --- a/zerver/management/commands/convert_gitter_data.py +++ b/zerver/management/commands/convert_gitter_data.py @@ -41,8 +41,7 @@ class Command(BaseCommand): for path in options['gitter_data']: if not os.path.exists(path): - print("Gitter data file not found: '%s'" % (path,)) - exit(1) + raise CommandError("Gitter data file not found: '%s'" % (path,)) # TODO add json check print("Converting Data ...") do_convert_data(path, output_dir, num_threads) diff --git a/zerver/management/commands/convert_hipchat_data.py b/zerver/management/commands/convert_hipchat_data.py index b34e17b182..44f448a9b1 100644 --- a/zerver/management/commands/convert_hipchat_data.py +++ b/zerver/management/commands/convert_hipchat_data.py @@ -21,7 +21,7 @@ spec: exporting-from-hipchat-server-or-data-center-for-data-portability-950821555.html ''' -from django.core.management.base import BaseCommand, CommandParser +from django.core.management.base import BaseCommand, CommandParser, CommandError from zerver.data_import.hipchat import do_convert_data @@ -56,25 +56,21 @@ class Command(BaseCommand): output_dir = options["output_dir"] if output_dir is None: - print("You need to specify --output ") - exit(1) + raise CommandError("You need to specify --output ") if os.path.exists(output_dir) and not os.path.isdir(output_dir): - print(output_dir + " is not a directory") - exit(1) + raise CommandError(output_dir + " is not a directory") os.makedirs(output_dir, exist_ok=True) if os.listdir(output_dir): - print('Output directory should be empty!') - exit(1) + raise CommandError('Output directory should be empty!') output_dir = os.path.realpath(output_dir) for path in options['hipchat_tar']: if not os.path.exists(path): - print("Tar file not found: '%s'" % (path,)) - exit(1) + raise CommandError("Tar file not found: '%s'" % (path,)) print("Converting Data ...") do_convert_data( diff --git a/zerver/management/commands/convert_slack_data.py b/zerver/management/commands/convert_slack_data.py index 7457bf0eff..2cde1e280b 100644 --- a/zerver/management/commands/convert_slack_data.py +++ b/zerver/management/commands/convert_slack_data.py @@ -40,8 +40,7 @@ class Command(BaseCommand): token = options['token'] if token is None: - print("Enter slack legacy token!") - exit(1) + raise CommandError("Enter slack legacy token!") num_threads = int(options['threads']) if num_threads < 1: @@ -49,8 +48,7 @@ class Command(BaseCommand): for path in options['slack_data_zip']: if not os.path.exists(path): - print("Slack data directory not found: '%s'" % (path,)) - exit(1) + raise CommandError("Slack data directory not found: '%s'" % (path,)) print("Converting Data ...") do_convert_data(path, output_dir, token, threads=num_threads) diff --git a/zerver/management/commands/deactivate_user.py b/zerver/management/commands/deactivate_user.py index b1dcbc474c..5314be24b4 100644 --- a/zerver/management/commands/deactivate_user.py +++ b/zerver/management/commands/deactivate_user.py @@ -3,7 +3,7 @@ from argparse import ArgumentParser from typing import Any from zerver.lib.actions import do_deactivate_user -from zerver.lib.management import ZulipBaseCommand +from zerver.lib.management import ZulipBaseCommand, CommandError from zerver.lib.sessions import user_sessions from zerver.models import UserProfile @@ -39,8 +39,7 @@ class Command(ZulipBaseCommand): )) if not options["for_real"]: - print("This was a dry run. Pass -f to actually deactivate.") - exit(1) + raise CommandError("This was a dry run. Pass -f to actually deactivate.") do_deactivate_user(user_profile) print("Sessions deleted, user deactivated.") diff --git a/zerver/management/commands/delete_old_unclaimed_attachments.py b/zerver/management/commands/delete_old_unclaimed_attachments.py index 4e6004b37b..49f8e637ad 100644 --- a/zerver/management/commands/delete_old_unclaimed_attachments.py +++ b/zerver/management/commands/delete_old_unclaimed_attachments.py @@ -2,7 +2,7 @@ from argparse import ArgumentParser from typing import Any -from django.core.management.base import BaseCommand +from django.core.management.base import BaseCommand, CommandError from zerver.lib.actions import do_delete_old_unclaimed_attachments from zerver.models import get_old_unclaimed_attachments @@ -36,8 +36,7 @@ class Command(BaseCommand): print("") if not options["for_real"]: - print("This was a dry run. Pass -f to actually delete.") - exit(1) + raise CommandError("This was a dry run. Pass -f to actually delete.") do_delete_old_unclaimed_attachments(delta_weeks) print("") diff --git a/zerver/management/commands/email_mirror.py b/zerver/management/commands/email_mirror.py index bf5e7de4b1..d3577bb3eb 100644 --- a/zerver/management/commands/email_mirror.py +++ b/zerver/management/commands/email_mirror.py @@ -29,7 +29,7 @@ from imaplib import IMAP4_SSL from typing import Any, Generator from django.conf import settings -from django.core.management.base import BaseCommand +from django.core.management.base import BaseCommand, CommandError from zerver.lib.email_mirror import logger, process_message @@ -73,8 +73,7 @@ class Command(BaseCommand): if (not settings.EMAIL_GATEWAY_BOT or not settings.EMAIL_GATEWAY_LOGIN or not settings.EMAIL_GATEWAY_PASSWORD or not settings.EMAIL_GATEWAY_IMAP_SERVER or not settings.EMAIL_GATEWAY_IMAP_PORT or not settings.EMAIL_GATEWAY_IMAP_FOLDER): - print("Please configure the Email Mirror Gateway in /etc/zulip/, " - "or specify $ORIGINAL_RECIPIENT if piping a single mail.") - exit(1) + raise CommandError("Please configure the Email Mirror Gateway in /etc/zulip/, " + "or specify $ORIGINAL_RECIPIENT if piping a single mail.") for message in get_imap_messages(): process_message(message) diff --git a/zerver/management/commands/fix_unreads.py b/zerver/management/commands/fix_unreads.py index ba2db3e58f..ab6d86da18 100644 --- a/zerver/management/commands/fix_unreads.py +++ b/zerver/management/commands/fix_unreads.py @@ -1,14 +1,12 @@ import logging -import sys from argparse import ArgumentParser from typing import Any, List, Optional -from django.core.management.base import CommandError from django.db import connection from zerver.lib.fix_unreads import fix -from zerver.lib.management import ZulipBaseCommand +from zerver.lib.management import ZulipBaseCommand, CommandError from zerver.models import Realm, UserProfile logging.getLogger('zulip.fix_unreads').setLevel(logging.INFO) @@ -55,8 +53,7 @@ class Command(ZulipBaseCommand): if options['all']: if realm is None: - print('You must specify a realm if you choose the --all option.') - sys.exit(1) + raise CommandError('You must specify a realm if you choose the --all option.') self.fix_all_users(realm) return diff --git a/zerver/management/commands/generate_invite_links.py b/zerver/management/commands/generate_invite_links.py index 7cf5ee4945..03a6ec760b 100644 --- a/zerver/management/commands/generate_invite_links.py +++ b/zerver/management/commands/generate_invite_links.py @@ -29,7 +29,7 @@ class Command(ZulipBaseCommand): if not options['emails']: self.print_help("./manage.py", "generate_invite_links") - exit(1) + raise CommandError for email in options['emails']: try: @@ -48,10 +48,9 @@ class Command(ZulipBaseCommand): email_allowed_for_realm(email, realm) except DomainNotAllowedForRealmError: if not options["force"]: - print("You've asked to add an external user '%s' to a closed realm '%s'." % ( - email, realm.string_id)) - print("Are you sure? To do this, pass --force.") - exit(1) + raise CommandError("You've asked to add an external user '{}' to a " + "closed realm '{}'.\nAre you sure? To do this, " + "pass --force.".format(email, realm.string_id)) prereg_user = PreregistrationUser(email=email, realm=realm) prereg_user.save() diff --git a/zerver/management/commands/generate_realm_creation_link.py b/zerver/management/commands/generate_realm_creation_link.py index 4f15ad0420..e97cc196c6 100644 --- a/zerver/management/commands/generate_realm_creation_link.py +++ b/zerver/management/commands/generate_realm_creation_link.py @@ -1,11 +1,10 @@ -import sys from typing import Any from django.db import ProgrammingError from confirmation.models import generate_realm_creation_url -from zerver.lib.management import ZulipBaseCommand +from zerver.lib.management import ZulipBaseCommand, CommandError from zerver.models import Realm class Command(ZulipBaseCommand): @@ -22,8 +21,8 @@ class Command(ZulipBaseCommand): # first check if the db has been initalized Realm.objects.first() except ProgrammingError: - print("The Zulip database does not appear to exist. Have you run initialize-database?") - sys.exit(1) + raise CommandError("The Zulip database does not appear to exist. " + "Have you run initialize-database?") url = generate_realm_creation_url(by_admin=True) self.stdout.write(self.style.SUCCESS("Please visit the following " diff --git a/zerver/management/commands/import.py b/zerver/management/commands/import.py index a4fa051dcd..f2e2753788 100644 --- a/zerver/management/commands/import.py +++ b/zerver/management/commands/import.py @@ -67,11 +67,10 @@ import a database dump from one or more JSON files.""" for path in options['export_paths']: path = os.path.realpath(os.path.expanduser(path)) if not os.path.exists(path): - print("Directory not found: '%s'" % (path,)) - exit(1) + raise CommandError("Directory not found: '%s'" % (path,)) if not os.path.isdir(path): - print("Export file should be folder; if it's a tarball, please unpack it first.") - exit(1) + raise CommandError("Export file should be folder; if it's a " + "tarball, please unpack it first.") paths.append(path) for path in paths: diff --git a/zerver/management/commands/process_queue.py b/zerver/management/commands/process_queue.py index ad463540fa..c6d15555c4 100644 --- a/zerver/management/commands/process_queue.py +++ b/zerver/management/commands/process_queue.py @@ -8,7 +8,7 @@ from types import FrameType from typing import Any, List from django.conf import settings -from django.core.management.base import BaseCommand +from django.core.management.base import BaseCommand, CommandError from django.utils import autoreload from zerver.worker.queue_processors import get_active_worker_queues, get_worker @@ -46,7 +46,7 @@ class Command(BaseCommand): logger.info("Not using RabbitMQ queue workers in the test suite.") else: logger.error("Cannot run a queue processor when USING_RABBITMQ is False!") - sys.exit(1) + raise CommandError def run_threaded_workers(queues: List[str], logger: logging.Logger) -> None: cnt = 0 diff --git a/zerver/management/commands/rate_limit.py b/zerver/management/commands/rate_limit.py index 950631638a..35062244bb 100644 --- a/zerver/management/commands/rate_limit.py +++ b/zerver/management/commands/rate_limit.py @@ -2,7 +2,7 @@ from argparse import ArgumentParser from typing import Any -from zerver.lib.management import ZulipBaseCommand +from zerver.lib.management import ZulipBaseCommand, CommandError from zerver.lib.rate_limiter import RateLimitedUser, \ block_access, unblock_access from zerver.models import UserProfile, get_user_profile_by_api_key @@ -38,8 +38,7 @@ class Command(ZulipBaseCommand): def handle(self, *args: Any, **options: Any) -> None: if (not options['api_key'] and not options['email']) or \ (options['api_key'] and options['email']): - print("Please enter either an email or API key to manage") - exit(1) + raise CommandError("Please enter either an email or API key to manage") realm = self.get_realm(options) if options['email']: @@ -48,8 +47,7 @@ class Command(ZulipBaseCommand): try: user_profile = get_user_profile_by_api_key(options['api_key']) except UserProfile.DoesNotExist: - print("Unable to get user profile for api key %s" % (options['api_key'],)) - exit(1) + raise CommandError("Unable to get user profile for api key %s" % (options['api_key'],)) users = [user_profile] if options['bots']: diff --git a/zerver/management/commands/realm_domain.py b/zerver/management/commands/realm_domain.py index bd0ebe3581..f82d84c843 100644 --- a/zerver/management/commands/realm_domain.py +++ b/zerver/management/commands/realm_domain.py @@ -7,7 +7,7 @@ from django.core.exceptions import ValidationError from django.db.utils import IntegrityError from zerver.lib.domains import validate_domain -from zerver.lib.management import ZulipBaseCommand +from zerver.lib.management import ZulipBaseCommand, CommandError from zerver.models import RealmDomain, get_realm_domains class Command(ZulipBaseCommand): @@ -44,23 +44,21 @@ class Command(ZulipBaseCommand): try: validate_domain(domain) except ValidationError as e: - print(e.messages[0]) - sys.exit(1) + raise CommandError(e.messages[0]) if options["op"] == "add": try: RealmDomain.objects.create(realm=realm, domain=domain, allow_subdomains=options["allow_subdomains"]) sys.exit(0) except IntegrityError: - print("The domain %(domain)s is already a part of your organization." % {'domain': domain}) - sys.exit(1) + raise CommandError("The domain %(domain)s is already a part " + "of your organization." % {'domain': domain}) elif options["op"] == "remove": try: RealmDomain.objects.get(realm=realm, domain=domain).delete() sys.exit(0) except RealmDomain.DoesNotExist: - print("No such entry found!") - sys.exit(1) + raise CommandError("No such entry found!") else: self.print_help("./manage.py", "realm_domain") - sys.exit(1) + raise CommandError diff --git a/zerver/management/commands/realm_filters.py b/zerver/management/commands/realm_filters.py index 6759e94392..84eb3d16ba 100644 --- a/zerver/management/commands/realm_filters.py +++ b/zerver/management/commands/realm_filters.py @@ -4,7 +4,7 @@ from argparse import ArgumentParser from typing import Any from zerver.lib.actions import do_add_realm_filter, do_remove_realm_filter -from zerver.lib.management import ZulipBaseCommand +from zerver.lib.management import ZulipBaseCommand, CommandError from zerver.models import all_realm_filters class Command(ZulipBaseCommand): @@ -44,13 +44,13 @@ Example: ./manage.py realm_filters --realm=zulip --op=show pattern = options['pattern'] if not pattern: self.print_help("./manage.py", "realm_filters") - sys.exit(1) + raise CommandError if options["op"] == "add": url_format_string = options['url_format_string'] if not url_format_string: self.print_help("./manage.py", "realm_filters") - sys.exit(1) + raise CommandError do_add_realm_filter(realm, pattern, url_format_string) sys.exit(0) elif options["op"] == "remove": @@ -58,4 +58,4 @@ Example: ./manage.py realm_filters --realm=zulip --op=show sys.exit(0) else: self.print_help("./manage.py", "realm_filters") - sys.exit(1) + raise CommandError diff --git a/zerver/management/commands/send_to_email_mirror.py b/zerver/management/commands/send_to_email_mirror.py index 2c6fd376e2..54f42a3ed3 100644 --- a/zerver/management/commands/send_to_email_mirror.py +++ b/zerver/management/commands/send_to_email_mirror.py @@ -11,7 +11,7 @@ from django.core.management.base import CommandParser from zerver.lib.email_mirror import mirror_email_message from zerver.lib.email_mirror_helpers import encode_email_address -from zerver.lib.management import ZulipBaseCommand +from zerver.lib.management import ZulipBaseCommand, CommandError from zerver.models import Realm, get_stream, get_realm @@ -57,7 +57,7 @@ Example: def handle(self, **options: str) -> None: if options['fixture'] is None: self.print_help('./manage.py', 'send_to_email_mirror') - exit(1) + raise CommandError if options['stream'] is None: stream = "Denmark" @@ -93,8 +93,7 @@ Example: def _parse_email_fixture(self, fixture_path: str) -> Message: if not self._does_fixture_path_exist(fixture_path): - print('Fixture {} does not exist'.format(fixture_path)) - exit(1) + raise CommandError('Fixture {} does not exist'.format(fixture_path)) if fixture_path.endswith('.json'): message = self._parse_email_json_fixture(fixture_path) diff --git a/zerver/management/commands/send_webhook_fixture_message.py b/zerver/management/commands/send_webhook_fixture_message.py index e06d25327f..ba89fb2337 100644 --- a/zerver/management/commands/send_webhook_fixture_message.py +++ b/zerver/management/commands/send_webhook_fixture_message.py @@ -6,7 +6,7 @@ from django.conf import settings from django.core.management.base import CommandParser from django.test import Client -from zerver.lib.management import ZulipBaseCommand +from zerver.lib.management import ZulipBaseCommand, CommandError from zerver.models import get_realm class Command(ZulipBaseCommand): @@ -61,20 +61,18 @@ approach shown above. headers["HTTP_" + header.upper().replace("-", "_")] = str(custom_headers_dict[header]) return headers except ValueError as ve: - print('Encountered an error while attempting to parse custom headers: %s' % (ve,)) - print('Note: all strings must be enclosed within "" instead of \'\'') - exit(1) + raise CommandError('Encountered an error while attempting to parse custom headers: {}\n' + 'Note: all strings must be enclosed within "" instead of \'\''.format(ve)) def handle(self, **options: str) -> None: if options['fixture'] is None or options['url'] is None: self.print_help('./manage.py', 'send_webhook_fixture_message') - exit(1) + raise CommandError full_fixture_path = os.path.join(settings.DEPLOY_ROOT, options['fixture']) if not self._does_fixture_path_exist(full_fixture_path): - print('Fixture {} does not exist'.format(options['fixture'])) - exit(1) + raise CommandError('Fixture {} does not exist'.format(options['fixture'])) headers = self.parse_headers(options['custom-headers']) json = self._get_fixture_as_json(full_fixture_path) @@ -90,8 +88,7 @@ approach shown above. result = client.post(options['url'], json, content_type="application/json", HTTP_HOST=realm.host) if result.status_code != 200: - print('Error status %s: %s' % (result.status_code, result.content)) - exit(1) + raise CommandError('Error status %s: %s' % (result.status_code, result.content)) def _does_fixture_path_exist(self, fixture_path: str) -> bool: return os.path.exists(fixture_path) diff --git a/zerver/management/commands/set_message_flags.py b/zerver/management/commands/set_message_flags.py index 1b2f1f8467..fd8913f863 100644 --- a/zerver/management/commands/set_message_flags.py +++ b/zerver/management/commands/set_message_flags.py @@ -7,7 +7,7 @@ from django.core.management.base import CommandParser from django.db import models from zerver.lib import utils -from zerver.lib.management import ZulipBaseCommand +from zerver.lib.management import ZulipBaseCommand, CommandError from zerver.models import UserMessage class Command(ZulipBaseCommand): @@ -44,8 +44,7 @@ class Command(ZulipBaseCommand): def handle(self, *args: Any, **options: Any) -> None: if not options["flag"] or not options["op"] or not options["email"]: - print("Please specify an operation, a flag and an email") - exit(1) + raise CommandError("Please specify an operation, a flag and an email") op = options['op'] flag = getattr(UserMessage.flags, options['flag']) @@ -77,7 +76,7 @@ class Command(ZulipBaseCommand): if not options["for_real"]: logging.info("Updating %s by %s %s" % (mids, op, flag)) logging.info("Dry run completed. Run with --for-real to change message flags.") - exit(1) + raise CommandError utils.run_in_batches(mids, 400, do_update, sleep_time=3) exit(0) diff --git a/zerver/management/commands/soft_deactivate_users.py b/zerver/management/commands/soft_deactivate_users.py index e4cce1fa5e..e7a4983830 100644 --- a/zerver/management/commands/soft_deactivate_users.py +++ b/zerver/management/commands/soft_deactivate_users.py @@ -63,7 +63,7 @@ class Command(ZulipBaseCommand): if not user_emails: print('You need to specify at least one user to use the activate option.') self.print_help("./manage.py", "soft_deactivate_users") - sys.exit(1) + raise CommandError users_to_activate = get_users_from_emails(user_emails, filter_kwargs) users_activated = do_soft_activate_users(users_to_activate) @@ -81,4 +81,4 @@ class Command(ZulipBaseCommand): else: self.print_help("./manage.py", "soft_deactivate_users") - sys.exit(1) + raise CommandError diff --git a/zerver/tests/test_management_commands.py b/zerver/tests/test_management_commands.py index 580537e237..94f4453b80 100644 --- a/zerver/tests/test_management_commands.py +++ b/zerver/tests/test_management_commands.py @@ -169,14 +169,14 @@ class TestSendWebhookFixtureMessage(TestCase): @patch('zerver.management.commands.send_webhook_fixture_message.Command.print_help') def test_check_if_command_exits_when_fixture_param_is_empty(self, print_help_mock: MagicMock) -> None: - with self.assertRaises(SystemExit): + with self.assertRaises(CommandError): call_command(self.COMMAND_NAME, url=self.url) print_help_mock.assert_any_call('./manage.py', self.COMMAND_NAME) @patch('zerver.management.commands.send_webhook_fixture_message.Command.print_help') def test_check_if_command_exits_when_url_param_is_empty(self, print_help_mock: MagicMock) -> None: - with self.assertRaises(SystemExit): + with self.assertRaises(CommandError): call_command(self.COMMAND_NAME, fixture=self.fixture_path) print_help_mock.assert_any_call('./manage.py', self.COMMAND_NAME) @@ -186,7 +186,7 @@ class TestSendWebhookFixtureMessage(TestCase): self, os_path_exists_mock: MagicMock) -> None: os_path_exists_mock.return_value = False - with self.assertRaises(SystemExit): + with self.assertRaises(CommandError): call_command(self.COMMAND_NAME, fixture=self.fixture_path, url=self.url) os_path_exists_mock.assert_any_call(os.path.join(settings.DEPLOY_ROOT, self.fixture_path)) @@ -206,7 +206,7 @@ class TestSendWebhookFixtureMessage(TestCase): client = client_mock() - with self.assertRaises(SystemExit): + with self.assertRaises(CommandError): call_command(self.COMMAND_NAME, fixture=self.fixture_path, url=self.url) self.assertTrue(ujson_mock.dumps.called) self.assertTrue(ujson_mock.loads.called) @@ -225,7 +225,7 @@ class TestSendWebhookFixtureMessage(TestCase): get_fixture_as_json_mock.return_value = "{}" improper_headers = '{"X-Custom - Headers": "some_val"}' - with self.assertRaises(SystemExit): + with self.assertRaises(CommandError): call_command(self.COMMAND_NAME, fixture=self.fixture_path, url=self.url, custom_headers=improper_headers) @@ -235,7 +235,7 @@ class TestSendWebhookFixtureMessage(TestCase): command = Command() self.assertEqual(command.parse_headers(None), None) self.assertEqual(command.parse_headers('{"X-Custom-Header": "value"}'), {"HTTP_X_CUSTOM_HEADER": "value"}) - with self.assertRaises(SystemExit): + with self.assertRaises(CommandError): command.parse_headers('{"X-Custom - Headers": "some_val"}') class TestGenerateRealmCreationLink(ZulipTestCase):