python: Merge concatenated string literals that Black would uglify.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2021-02-11 18:52:14 -08:00 committed by Tim Abbott
parent d8d0e7dfff
commit 5028c081cb
42 changed files with 91 additions and 174 deletions

View File

@ -46,8 +46,7 @@ def generate_time_series_data(days: int=100, business_hours_base: float=10,
else: else:
raise AssertionError(f"Unknown frequency: {frequency}") raise AssertionError(f"Unknown frequency: {frequency}")
if length < 2: if length < 2:
raise AssertionError("Must be generating at least 2 data points. " raise AssertionError(f"Must be generating at least 2 data points. Currently generating {length}")
f"Currently generating {length}")
growth_base = growth ** (1. / (length-1)) growth_base = growth ** (1. / (length-1))
values_no_noise = [seasonality[i % len(seasonality)] * (growth_base**i) for i in range(length)] values_no_noise = [seasonality[i % len(seasonality)] * (growth_base**i) for i in range(length)]

View File

@ -93,8 +93,7 @@ if replication_info:
else: else:
replication_info = run_sql_query( replication_info = run_sql_query(
'client_addr, state, sent_lsn, write_lsn, flush_lsn, replay_lsn' 'client_addr, state, sent_lsn, write_lsn, flush_lsn, replay_lsn from pg_stat_replication'
' from pg_stat_replication'
) )
if replication_info == 0: if replication_info == 0:
report('CRITICAL', 'No replicas!') report('CRITICAL', 'No replicas!')

View File

@ -17,16 +17,15 @@ def parse_args() -> argparse.Namespace:
"examined and removed.") "examined and removed.")
parser.add_argument( parser.add_argument(
"--threshold", dest="threshold_days", type=int, default=14, "--threshold", dest="threshold_days", type=int, default=14,
metavar="<days>", help="Deployments older than " metavar="<days>",
"threshold days will be deleted. (defaults to 14)") help="Deployments older than threshold days will be deleted. (defaults to 14)")
parser.add_argument( parser.add_argument(
"--dry-run", action="store_true", "--dry-run", action="store_true",
help="If specified then script will only print the deployments and " help="If specified then script will only print the deployments and "
"caches that it will delete/keep back. It will not delete anything.") "caches that it will delete/keep back. It will not delete anything.")
parser.add_argument( parser.add_argument(
"--verbose", action="store_true", "--verbose", action="store_true",
help="If specified then script will print a detailed report " help="If specified then script will print a detailed report of what is going on.")
"of what is going on.")
args = parser.parse_args() args = parser.parse_args()
args.verbose |= args.dry_run # Always print a detailed report in case of dry run. args.verbose |= args.dry_run # Always print a detailed report in case of dry run.

View File

@ -22,8 +22,7 @@ if __name__ == '__main__':
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('--show-ignored', parser.add_argument('--show-ignored',
action='store_true', action='store_true',
help='Show strings that passed the check because they ' help='Show strings that passed the check because they contained ignored phrases.')
'contained ignored phrases.')
parser.add_argument('--no-generate', parser.add_argument('--no-generate',
action='store_true', action='store_true',
help="Don't run makemessages command.") help="Don't run makemessages command.")

View File

@ -30,8 +30,7 @@ class UnusedImagesLinterSpider(BaseDocumentationSpider):
def closed(self, *args: Any, **kwargs: Any) -> None: def closed(self, *args: Any, **kwargs: Any) -> None:
unused_images = set(os.listdir(self.images_static_dir)) - self.static_images unused_images = set(os.listdir(self.images_static_dir)) - self.static_images
if unused_images: if unused_images:
exception_message = "The following images are not used in documentation " \ exception_message = "The following images are not used in documentation and can be removed: {}"
"and can be removed: {}"
self._set_error_state() self._set_error_state()
unused_images_relatedpath = [ unused_images_relatedpath = [
os.path.join(self.images_path, img) for img in unused_images] os.path.join(self.images_path, img) for img in unused_images]

View File

@ -79,8 +79,7 @@ if platform.architecture()[0] == '64bit':
elif platform.architecture()[0] == '32bit': elif platform.architecture()[0] == '32bit':
arch = "i386" arch = "i386"
else: else:
logging.critical("Only x86 is supported;" logging.critical("Only x86 is supported; ask on chat.zulip.org if you want another architecture.")
" ask on chat.zulip.org if you want another architecture.")
# Note: It's probably actually not hard to add additional # Note: It's probably actually not hard to add additional
# architectures. # architectures.
sys.exit(1) sys.exit(1)

View File

@ -110,8 +110,7 @@ def setup_bash_profile() -> None:
BASH_PROFILE = BASH_PROFILES[0] BASH_PROFILE = BASH_PROFILES[0]
DOT_PROFILE = BASH_PROFILES[2] DOT_PROFILE = BASH_PROFILES[2]
OLD_PROFILE_TEXT = "source /srv/zulip-py3-venv/bin/activate\n" + \ OLD_PROFILE_TEXT = "source /srv/zulip-py3-venv/bin/activate\ncd /srv/zulip\n"
"cd /srv/zulip\n"
if os.path.exists(DOT_PROFILE): if os.path.exists(DOT_PROFILE):
try: try:

View File

@ -50,25 +50,20 @@ def run() -> None:
linter_config.external_linter('css', ['node', 'node_modules/.bin/stylelint'], ['css'], linter_config.external_linter('css', ['node', 'node_modules/.bin/stylelint'], ['css'],
fix_arg='--fix', fix_arg='--fix',
description="Standard CSS style and formatting linter " description="Standard CSS style and formatting linter (config: stylelint.config.js)")
"(config: stylelint.config.js)")
linter_config.external_linter('eslint', ['node', 'node_modules/.bin/eslint', linter_config.external_linter('eslint', ['node', 'node_modules/.bin/eslint',
'--max-warnings=0', '--cache', '--ext', '.js,.ts'], ['js', 'ts'], '--max-warnings=0', '--cache', '--ext', '.js,.ts'], ['js', 'ts'],
fix_arg='--fix', fix_arg='--fix',
description="Standard JavaScript style and formatting linter " description="Standard JavaScript style and formatting linter (config: .eslintrc).")
"(config: .eslintrc).")
linter_config.external_linter('puppet', ['puppet', 'parser', 'validate'], ['pp'], linter_config.external_linter('puppet', ['puppet', 'parser', 'validate'], ['pp'],
description="Runs the puppet parser validator, " description="Runs the puppet parser validator, checking for syntax errors.")
"checking for syntax errors.")
linter_config.external_linter('puppet-lint', linter_config.external_linter('puppet-lint',
['puppet-lint', '--fail-on-warnings', *PUPPET_CHECK_RULES_TO_EXCLUDE], ['puppet-lint', '--fail-on-warnings', *PUPPET_CHECK_RULES_TO_EXCLUDE],
['pp'], ['pp'],
fix_arg='--fix', fix_arg='--fix',
description="Standard puppet linter " description="Standard puppet linter (config: tools/linter_lib/exclude.py)")
"(config: tools/linter_lib/exclude.py)")
linter_config.external_linter('templates', ['tools/check-templates'], ['hbs', 'html'], linter_config.external_linter('templates', ['tools/check-templates'], ['hbs', 'html'],
description="Custom linter checks whitespace formatting " description="Custom linter checks whitespace formatting of HTML templates",
"of HTML templates",
fix_arg='--fix') fix_arg='--fix')
linter_config.external_linter('openapi', ['node', 'tools/check-openapi'], ['yaml'], linter_config.external_linter('openapi', ['node', 'tools/check-openapi'], ['yaml'],
description="Validates our OpenAPI/Swagger API documentation " description="Validates our OpenAPI/Swagger API documentation "
@ -89,8 +84,7 @@ def run() -> None:
pass_targets=False, pass_targets=False,
description="Shares duplicate packages in yarn.lock") description="Shares duplicate packages in yarn.lock")
linter_config.external_linter('gitlint', ['tools/commit-message-lint'], linter_config.external_linter('gitlint', ['tools/commit-message-lint'],
description="Checks commit messages for common formatting errors " description="Checks commit messages for common formatting errors (config: .gitlint)")
"(config: .gitlint)")
linter_config.external_linter('isort', ['isort'], ['py'], linter_config.external_linter('isort', ['isort'], ['py'],
description="Sorts Python import statements", description="Sorts Python import statements",
check_arg=['--check-only', '--diff']) check_arg=['--check-only', '--diff'])
@ -112,8 +106,7 @@ def run() -> None:
"--dangerously-allow-arbitrary-code-execution-from-rules"] "--dangerously-allow-arbitrary-code-execution-from-rules"]
linter_config.external_linter('semgrep-py', [*semgrep_command, "--lang=python"], ['py'], linter_config.external_linter('semgrep-py', [*semgrep_command, "--lang=python"], ['py'],
fix_arg='--autofix', fix_arg='--autofix',
description="Syntactic Grep (semgrep) Code Search Tool " description="Syntactic Grep (semgrep) Code Search Tool (config: ./tools/semgrep.yml)")
"(config: ./tools/semgrep.yml)")
linter_config.external_linter('thirdparty', ['tools/check-thirdparty'], linter_config.external_linter('thirdparty', ['tools/check-thirdparty'],
description="Check docs/THIRDPARTY copyright file syntax") description="Check docs/THIRDPARTY copyright file syntax")

View File

@ -382,8 +382,7 @@ def main() -> None:
TestRunner = get_runner(settings) TestRunner = get_runner(settings)
if parallel > 1: if parallel > 1:
print("-- Running tests in parallel mode with {} " print(f"-- Running tests in parallel mode with {parallel} processes.", flush=True)
"processes.".format(parallel), flush=True)
else: else:
print("-- Running tests in serial mode.", flush=True) print("-- Running tests in serial mode.", flush=True)

View File

@ -7,11 +7,9 @@ from tools.lib.capitalization import check_capitalization, get_safe_text, is_cap
class GetSafeTextTestCase(TestCase): class GetSafeTextTestCase(TestCase):
def test_get_safe_text(self) -> None: def test_get_safe_text(self) -> None:
string = ('Messages in __page_params.product_name__ go to a ' string = ('Messages in __page_params.product_name__ go to a stream and have a topic.')
'stream and have a topic.')
safe_text = get_safe_text(string) safe_text = get_safe_text(string)
self.assertEqual(safe_text, 'Messages in __page_params_product_name__ ' self.assertEqual(safe_text, 'Messages in __page_params_product_name__ go to a stream and have a topic.')
'go to a stream and have a topic.')
string = "Zulip Zulip. Zulip some text!" string = "Zulip Zulip. Zulip some text!"
safe_text = get_safe_text(string) safe_text = get_safe_text(string)

View File

@ -156,9 +156,7 @@ class HomepageForm(forms.Form):
from_multiuse_invite = self.from_multiuse_invite from_multiuse_invite = self.from_multiuse_invite
if realm is None: if realm is None:
raise ValidationError(_("The organization you are trying to " raise ValidationError(_("The organization you are trying to join using {email} does not exist.").format(email=email))
"join using {email} does not "
"exist.").format(email=email))
if not from_multiuse_invite and realm.invite_required: if not from_multiuse_invite and realm.invite_required:
raise ValidationError(_("Please request an invite for {email} " raise ValidationError(_("Please request an invite for {email} "

View File

@ -236,8 +236,7 @@ def notify_bot_owner(event: Dict[str, Any],
if status_code: if status_code:
notification_message += f"\nThe webhook got a response with status code *{status_code}*." notification_message += f"\nThe webhook got a response with status code *{status_code}*."
if response_content: if response_content:
notification_message += "\nThe response contains the following payload:\n" \ notification_message += f"\nThe response contains the following payload:\n```\n{response_content!r}\n```"
f"```\n{response_content!r}\n```"
if exception: if exception:
notification_message += "\nWhen trying to send a request to the webhook service, an exception " \ notification_message += "\nWhen trying to send a request to the webhook service, an exception " \
f"of type {type(exception).__name__} occurred:\n```\n{exception}\n```" f"of type {type(exception).__name__} occurred:\n```\n{exception}\n```"

View File

@ -26,13 +26,11 @@ PUSH_COMMITS_MESSAGE_TEMPLATE_WITHOUT_COMMITTERS = PUSH_COMMITS_BASE + """
{commits_data} {commits_data}
""" """
PUSH_DELETE_BRANCH_MESSAGE_TEMPLATE = "{user_name} [deleted]({compare_url}) the branch {branch_name}." PUSH_DELETE_BRANCH_MESSAGE_TEMPLATE = "{user_name} [deleted]({compare_url}) the branch {branch_name}."
PUSH_LOCAL_BRANCH_WITHOUT_COMMITS_MESSAGE_TEMPLATE = ("{user_name} [pushed]({compare_url}) " PUSH_LOCAL_BRANCH_WITHOUT_COMMITS_MESSAGE_TEMPLATE = "{user_name} [pushed]({compare_url}) the branch {branch_name}."
"the branch {branch_name}.")
PUSH_COMMITS_MESSAGE_EXTENSION = "Commits by {}" PUSH_COMMITS_MESSAGE_EXTENSION = "Commits by {}"
PUSH_COMMITTERS_LIMIT_INFO = 3 PUSH_COMMITTERS_LIMIT_INFO = 3
FORCE_PUSH_COMMITS_MESSAGE_TEMPLATE = ("{user_name} [force pushed]({url}) " FORCE_PUSH_COMMITS_MESSAGE_TEMPLATE = "{user_name} [force pushed]({url}) to branch {branch_name}. Head is now {head}."
"to branch {branch_name}. Head is now {head}.")
CREATE_BRANCH_MESSAGE_TEMPLATE = "{user_name} created [{branch_name}]({url}) branch." CREATE_BRANCH_MESSAGE_TEMPLATE = "{user_name} created [{branch_name}]({url}) branch."
CREATE_BRANCH_WITHOUT_URL_MESSAGE_TEMPLATE = "{user_name} created {branch_name} branch." CREATE_BRANCH_WITHOUT_URL_MESSAGE_TEMPLATE = "{user_name} created {branch_name} branch."
REMOVE_BRANCH_MESSAGE_TEMPLATE = "{user_name} deleted branch {branch_name}." REMOVE_BRANCH_MESSAGE_TEMPLATE = "{user_name} deleted branch {branch_name}."

View File

@ -21,12 +21,10 @@ class Command(ZulipBaseCommand):
# first check if the db has been initialized # first check if the db has been initialized
Realm.objects.first() Realm.objects.first()
except ProgrammingError: except ProgrammingError:
raise CommandError("The Zulip database does not appear to exist. " raise CommandError("The Zulip database does not appear to exist. Have you run initialize-database?")
"Have you run initialize-database?")
url = generate_realm_creation_url(by_admin=True) url = generate_realm_creation_url(by_admin=True)
self.stdout.write(self.style.SUCCESS("Please visit the following " self.stdout.write(self.style.SUCCESS("Please visit the following secure single-use link to register your "))
"secure single-use link to register your "))
self.stdout.write(self.style.SUCCESS("new Zulip organization:\033[0m")) self.stdout.write(self.style.SUCCESS("new Zulip organization:\033[0m"))
self.stdout.write("") self.stdout.write("")
self.stdout.write(self.style.SUCCESS(f" \033[1;92m{url}\033[0m")) self.stdout.write(self.style.SUCCESS(f" \033[1;92m{url}\033[0m"))

View File

@ -76,8 +76,7 @@ import a database dump from one or more JSON files."""
if not os.path.exists(path): if not os.path.exists(path):
raise CommandError(f"Directory not found: '{path}'") raise CommandError(f"Directory not found: '{path}'")
if not os.path.isdir(path): if not os.path.isdir(path):
raise CommandError("Export file should be folder; if it's a " raise CommandError("Export file should be folder; if it's a tarball, please unpack it first.")
"tarball, please unpack it first.")
paths.append(path) paths.append(path)
for path in paths: for path in paths:

View File

@ -47,8 +47,7 @@ class Command(ZulipBaseCommand):
allow_subdomains=options["allow_subdomains"]) allow_subdomains=options["allow_subdomains"])
sys.exit(0) sys.exit(0)
except IntegrityError: except IntegrityError:
raise CommandError(f"The domain {domain} is already a part " raise CommandError(f"The domain {domain} is already a part of your organization.")
"of your organization.")
elif options["op"] == "remove": elif options["op"] == "remove":
try: try:
RealmDomain.objects.get(realm=realm, domain=domain).delete() RealmDomain.objects.get(realm=realm, domain=domain).delete()

View File

@ -36,12 +36,10 @@ approach shown above.
'into Zulip') 'into Zulip')
parser.add_argument('-u', '--url', parser.add_argument('-u', '--url',
help='The URL on your Zulip server that you want ' help='The URL on your Zulip server that you want to post the fixture to')
'to post the fixture to')
parser.add_argument('-H', '--custom-headers', parser.add_argument('-H', '--custom-headers',
help='The headers you want to provide along with ' help='The headers you want to provide along with your mock request to Zulip.')
'your mock request to Zulip.')
self.add_realm_args(parser, help="Specify which realm/subdomain to connect to; default is zulip") self.add_realm_args(parser, help="Specify which realm/subdomain to connect to; default is zulip")

View File

@ -11,8 +11,7 @@ class Command(ZulipBaseCommand):
self.add_realm_args(parser) self.add_realm_args(parser)
self.add_user_list_args(parser, self.add_user_list_args(parser,
help='Turn off digests for this comma-separated ' help='Turn off digests for this comma-separated list of email addresses.',
'list of email addresses.',
all_users_help="Turn off digests for everyone in realm.") all_users_help="Turn off digests for everyone in realm.")
def handle(self, **options: str) -> None: def handle(self, **options: str) -> None:

View File

@ -1486,8 +1486,7 @@ class TestAuthenticatedJsonPostViewDecorator(ZulipTestCase):
with self.assertLogs(level="WARNING") as m, \ with self.assertLogs(level="WARNING") as m, \
mock.patch('zerver.decorator.get_subdomain', return_value=''): mock.patch('zerver.decorator.get_subdomain', return_value=''):
self.assert_json_error_contains(self._do_test(user), self.assert_json_error_contains(self._do_test(user),
"Account is not associated with this " "Account is not associated with this subdomain")
"subdomain")
self.assertEqual( self.assertEqual(
m.output, m.output,
["WARNING:root:User {} ({}) attempted to access API on wrong subdomain ({})".format(email, 'zulip', ''), ["WARNING:root:User {} ({}) attempted to access API on wrong subdomain ({})".format(email, 'zulip', ''),
@ -1497,8 +1496,7 @@ class TestAuthenticatedJsonPostViewDecorator(ZulipTestCase):
with self.assertLogs(level="WARNING") as m, \ with self.assertLogs(level="WARNING") as m, \
mock.patch('zerver.decorator.get_subdomain', return_value='acme'): mock.patch('zerver.decorator.get_subdomain', return_value='acme'):
self.assert_json_error_contains(self._do_test(user), self.assert_json_error_contains(self._do_test(user),
"Account is not associated with this " "Account is not associated with this subdomain")
"subdomain")
self.assertEqual( self.assertEqual(
m.output, m.output,
["WARNING:root:User {} ({}) attempted to access API on wrong subdomain ({})".format(email, 'zulip', 'acme'), ["WARNING:root:User {} ({}) attempted to access API on wrong subdomain ({})".format(email, 'zulip', 'acme'),
@ -1545,8 +1543,7 @@ class TestAuthenticatedJsonViewDecorator(ZulipTestCase):
with self.assertLogs(level="WARNING") as m, \ with self.assertLogs(level="WARNING") as m, \
mock.patch('zerver.decorator.get_subdomain', return_value=''): mock.patch('zerver.decorator.get_subdomain', return_value=''):
self.assert_json_error_contains(self._do_test(email), self.assert_json_error_contains(self._do_test(email),
"Account is not associated with this " "Account is not associated with this subdomain")
"subdomain")
self.assertEqual( self.assertEqual(
m.output, m.output,
["WARNING:root:User {} ({}) attempted to access API on wrong subdomain ({})".format(email, "zulip", "")] ["WARNING:root:User {} ({}) attempted to access API on wrong subdomain ({})".format(email, "zulip", "")]
@ -1555,8 +1552,7 @@ class TestAuthenticatedJsonViewDecorator(ZulipTestCase):
with self.assertLogs(level="WARNING") as m, \ with self.assertLogs(level="WARNING") as m, \
mock.patch('zerver.decorator.get_subdomain', return_value='acme'): mock.patch('zerver.decorator.get_subdomain', return_value='acme'):
self.assert_json_error_contains(self._do_test(email), self.assert_json_error_contains(self._do_test(email),
"Account is not associated with this " "Account is not associated with this subdomain")
"subdomain")
self.assertEqual( self.assertEqual(
m.output, m.output,
["WARNING:root:User {} ({}) attempted to access API on wrong subdomain ({})".format(email, "zulip", "acme")] ["WARNING:root:User {} ({}) attempted to access API on wrong subdomain ({})".format(email, "zulip", "acme")]

View File

@ -490,8 +490,7 @@ class PrivacyTermsTest(ZulipTestCase):
response) response)
def test_custom_terms_of_service_template(self) -> None: def test_custom_terms_of_service_template(self) -> None:
not_configured_message = 'This installation of Zulip does not have a configured ' \ not_configured_message = 'This installation of Zulip does not have a configured terms of service'
'terms of service'
with self.settings(TERMS_OF_SERVICE=None): with self.settings(TERMS_OF_SERVICE=None):
response = self.client_get('/terms/') response = self.client_get('/terms/')
self.assert_in_success_response([not_configured_message], response) self.assert_in_success_response([not_configured_message], response)
@ -501,8 +500,7 @@ class PrivacyTermsTest(ZulipTestCase):
self.assert_not_in_success_response([not_configured_message], response) self.assert_not_in_success_response([not_configured_message], response)
def test_custom_privacy_policy_template(self) -> None: def test_custom_privacy_policy_template(self) -> None:
not_configured_message = 'This installation of Zulip does not have a configured ' \ not_configured_message = 'This installation of Zulip does not have a configured privacy policy'
'privacy policy'
with self.settings(PRIVACY_POLICY=None): with self.settings(PRIVACY_POLICY=None):
response = self.client_get('/privacy/') response = self.client_get('/privacy/')
self.assert_in_success_response([not_configured_message], response) self.assert_in_success_response([not_configured_message], response)

View File

@ -1009,8 +1009,7 @@ class MarkdownTest(ZulipTestCase):
realm_filter.save() realm_filter.save()
self.assertEqual( self.assertEqual(
realm_filter.__str__(), realm_filter.__str__(),
'<RealmFilter(zulip): #(?P<id>[0-9]{2,8})' '<RealmFilter(zulip): #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>')
' https://trac.example.com/ticket/%(id)s>')
msg = Message(sender=self.example_user('othello')) msg = Message(sender=self.example_user('othello'))
msg.set_topic_name("#444") msg.set_topic_name("#444")
@ -1679,8 +1678,7 @@ class MarkdownTest(ZulipTestCase):
realm_filter.save() realm_filter.save()
self.assertEqual( self.assertEqual(
realm_filter.__str__(), realm_filter.__str__(),
'<RealmFilter(zulip): #(?P<id>[0-9]{2,8})' '<RealmFilter(zulip): #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>')
' https://trac.example.com/ticket/%(id)s>')
# Create a user that potentially interferes with the pattern. # Create a user that potentially interferes with the pattern.
test_user = create_user( test_user = create_user(
email='atomic@example.com', email='atomic@example.com',
@ -1736,8 +1734,7 @@ class MarkdownTest(ZulipTestCase):
realm_filter.save() realm_filter.save()
self.assertEqual( self.assertEqual(
realm_filter.__str__(), realm_filter.__str__(),
'<RealmFilter(zulip): #(?P<id>[0-9]{2,8})' '<RealmFilter(zulip): #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>')
' https://trac.example.com/ticket/%(id)s>')
# Create a user-group that potentially interferes with the pattern. # Create a user-group that potentially interferes with the pattern.
user_id = user_profile.id user_id = user_profile.id
user_group = self.create_user_group_for_test('support #123') user_group = self.create_user_group_for_test('support #123')
@ -1908,8 +1905,7 @@ class MarkdownTest(ZulipTestCase):
realm_filter.save() realm_filter.save()
self.assertEqual( self.assertEqual(
realm_filter.__str__(), realm_filter.__str__(),
'<RealmFilter(zulip): #(?P<id>[0-9]{2,8})' '<RealmFilter(zulip): #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>')
' https://trac.example.com/ticket/%(id)s>')
# Create a topic link that potentially interferes with the pattern. # Create a topic link that potentially interferes with the pattern.
denmark = get_stream('Denmark', realm) denmark = get_stream('Denmark', realm)
msg = Message(sender=sender_user_profile, sending_client=get_client("test")) msg = Message(sender=sender_user_profile, sending_client=get_client("test"))
@ -1974,8 +1970,7 @@ class MarkdownTest(ZulipTestCase):
realm_filter.save() realm_filter.save()
self.assertEqual( self.assertEqual(
realm_filter.__str__(), realm_filter.__str__(),
'<RealmFilter(zulip): #(?P<id>[0-9]{2,8})' '<RealmFilter(zulip): #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>')
' https://trac.example.com/ticket/%(id)s>')
# Create a stream that potentially interferes with the pattern. # Create a stream that potentially interferes with the pattern.
stream = Stream.objects.create(name='Stream #1234', realm=realm) stream = Stream.objects.create(name='Stream #1234', realm=realm)
msg = Message(sender=sender_user_profile, sending_client=get_client("test")) msg = Message(sender=sender_user_profile, sending_client=get_client("test"))

View File

@ -256,8 +256,7 @@ class MessageDictTest(ZulipTestCase):
url_format_string=url_format_string) url_format_string=url_format_string)
self.assertEqual( self.assertEqual(
realm_filter.__str__(), realm_filter.__str__(),
'<RealmFilter(zulip): #(?P<id>[0-9]{2,8})' '<RealmFilter(zulip): #(?P<id>[0-9]{2,8}) https://trac.example.com/ticket/%(id)s>')
' https://trac.example.com/ticket/%(id)s>')
def get_message(sender: UserProfile) -> Message: def get_message(sender: UserProfile) -> Message:
msg_id = self.send_stream_message(sender, 'Denmark', 'hello world', topic_name, msg_id = self.send_stream_message(sender, 'Denmark', 'hello world', topic_name,

View File

@ -293,9 +293,7 @@ class EditMessageTest(ZulipTestCase):
self.example_user("hamlet"), self.example_user("hamlet"),
"Scotland", "Scotland",
topic_name="editing", topic_name="editing",
content=('content before edit, line 1\n' content='content before edit, line 1\n\ncontent before edit, line 3')
'\n'
'content before edit, line 3'))
new_content_2 = ('content before edit, line 1\n' new_content_2 = ('content before edit, line 1\n'
'content after edit, line 2\n' 'content after edit, line 2\n'
'content before edit, line 3') 'content before edit, line 3')
@ -310,8 +308,7 @@ class EditMessageTest(ZulipTestCase):
message_history_2 = json_response_2['message_history'] message_history_2 = json_response_2['message_history']
self.assertEqual(message_history_2[0]['rendered_content'], self.assertEqual(message_history_2[0]['rendered_content'],
('<p>content before edit, line 1</p>\n' '<p>content before edit, line 1</p>\n<p>content before edit, line 3</p>')
'<p>content before edit, line 3</p>'))
self.assertEqual(message_history_2[1]['rendered_content'], self.assertEqual(message_history_2[1]['rendered_content'],
('<p>content before edit, line 1<br>\n' ('<p>content before edit, line 1<br>\n'
'content after edit, line 2<br>\n' 'content after edit, line 2<br>\n'
@ -321,8 +318,7 @@ class EditMessageTest(ZulipTestCase):
'content <span class="highlight_text_inserted">after edit, line 2<br> ' 'content <span class="highlight_text_inserted">after edit, line 2<br> '
'content</span> before edit, line 3</p>')) 'content</span> before edit, line 3</p>'))
self.assertEqual(message_history_2[1]['prev_rendered_content'], self.assertEqual(message_history_2[1]['prev_rendered_content'],
('<p>content before edit, line 1</p>\n' '<p>content before edit, line 1</p>\n<p>content before edit, line 3</p>')
'<p>content before edit, line 3</p>'))
def test_edit_link(self) -> None: def test_edit_link(self) -> None:
# Link editing # Link editing

View File

@ -3248,9 +3248,9 @@ class MessageHasKeywordsTest(ZulipTestCase):
# This message should claim attachments 1 only because attachment 2 # This message should claim attachments 1 only because attachment 2
# is not being parsed as a link by Markdown. # is not being parsed as a link by Markdown.
body = ("Some files here ...[zulip.txt]({})" + body = (f"Some files here ...[zulip.txt]({dummy_urls[0]})"
"{}.... Some more...." + f"{dummy_urls[1]}.... Some more...."
"{}").format(dummy_urls[0], dummy_urls[1], dummy_urls[1]) f"{dummy_urls[1]}")
self.send_stream_message(user_profile, "Denmark", body, "test") self.send_stream_message(user_profile, "Denmark", body, "test")
assert_attachment_claimed(dummy_path_ids[0], True) assert_attachment_claimed(dummy_path_ids[0], True)
assert_attachment_claimed(dummy_path_ids[1], False) assert_attachment_claimed(dummy_path_ids[1], False)

View File

@ -123,12 +123,9 @@ class TestBrowserAndOsUserAgentStrings(ZulipTestCase):
'Chrome/54.0.2840.59 Safari/537.36', 'Chrome', 'Linux'), 'Chrome/54.0.2840.59 Safari/537.36', 'Chrome', 'Linux'),
('mozilla/5.0 (windows nt 6.1; win64; x64) applewebkit/537.36 (khtml, like gecko) ' + ('mozilla/5.0 (windows nt 6.1; win64; x64) applewebkit/537.36 (khtml, like gecko) ' +
'chrome/56.0.2924.87 safari/537.36', 'Chrome', 'Windows'), 'chrome/56.0.2924.87 safari/537.36', 'Chrome', 'Windows'),
('mozilla/5.0 (windows nt 6.1; wow64; rv:51.0) ' + ('mozilla/5.0 (windows nt 6.1; wow64; rv:51.0) gecko/20100101 firefox/51.0', 'Firefox', 'Windows'),
'gecko/20100101 firefox/51.0', 'Firefox', 'Windows'), ('mozilla/5.0 (windows nt 6.1; wow64; trident/7.0; rv:11.0) like gecko', 'Internet Explorer', 'Windows'),
('mozilla/5.0 (windows nt 6.1; wow64; trident/7.0; rv:11.0) ' + ('Mozilla/5.0 (Android; Mobile; rv:27.0) Gecko/27.0 Firefox/27.0', 'Firefox', 'Android'),
'like gecko', 'Internet Explorer', 'Windows'),
('Mozilla/5.0 (Android; Mobile; rv:27.0) ' +
'Gecko/27.0 Firefox/27.0', 'Firefox', 'Android'),
('Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) ' ('Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) '
'AppleWebKit/602.1.50 (KHTML, like Gecko) ' 'AppleWebKit/602.1.50 (KHTML, like Gecko) '
'CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1', 'Chrome', 'iOS'), 'CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1', 'Chrome', 'iOS'),

View File

@ -102,8 +102,7 @@ class OpenAPIToolsTest(ZulipTestCase):
def test_validate_against_openapi_schema(self) -> None: def test_validate_against_openapi_schema(self) -> None:
with self.assertRaises(ValidationError, with self.assertRaises(ValidationError,
msg=("Additional properties are not" + msg="Additional properties are not allowed ('foo' was unexpected)"):
" allowed ('foo' was unexpected)")):
bad_content: Dict[str, object] = { bad_content: Dict[str, object] = {
'msg': '', 'msg': '',
'result': 'success', 'result': 'success',

View File

@ -923,8 +923,7 @@ class HandlePushNotificationTest(PushNotificationTest):
return_value={'apns': True}), \ return_value={'apns': True}), \
mock.patch('zerver.lib.push_notifications.get_message_payload_gcm', mock.patch('zerver.lib.push_notifications.get_message_payload_gcm',
return_value=({'gcm': True}, {})), \ return_value=({'gcm': True}, {})), \
mock.patch('zerver.lib.push_notifications' mock.patch('zerver.lib.push_notifications.send_notifications_to_bouncer') as mock_send:
'.send_notifications_to_bouncer') as mock_send:
handle_push_notification(user_profile.id, missed_message) handle_push_notification(user_profile.id, missed_message)
mock_send.assert_called_with(user_profile.id, mock_send.assert_called_with(user_profile.id,
{'apns': True}, {'apns': True},
@ -957,10 +956,8 @@ class HandlePushNotificationTest(PushNotificationTest):
return_value={'apns': True}), \ return_value={'apns': True}), \
mock.patch('zerver.lib.push_notifications.get_message_payload_gcm', mock.patch('zerver.lib.push_notifications.get_message_payload_gcm',
return_value=({'gcm': True}, {})), \ return_value=({'gcm': True}, {})), \
mock.patch('zerver.lib.push_notifications' mock.patch('zerver.lib.push_notifications.send_apple_push_notification') as mock_send_apple, \
'.send_apple_push_notification') as mock_send_apple, \ mock.patch('zerver.lib.push_notifications.send_android_push_notification') as mock_send_android, \
mock.patch('zerver.lib.push_notifications'
'.send_android_push_notification') as mock_send_android, \
mock.patch('zerver.lib.push_notifications.push_notifications_enabled', return_value = True) as mock_push_notifications: mock.patch('zerver.lib.push_notifications.push_notifications_enabled', return_value = True) as mock_push_notifications:
handle_push_notification(self.user_profile.id, missed_message) handle_push_notification(self.user_profile.id, missed_message)
@ -980,8 +977,7 @@ class HandlePushNotificationTest(PushNotificationTest):
) )
with self.settings(PUSH_NOTIFICATION_BOUNCER_URL=True), \ with self.settings(PUSH_NOTIFICATION_BOUNCER_URL=True), \
mock.patch('zerver.lib.push_notifications' mock.patch('zerver.lib.push_notifications.send_notifications_to_bouncer') as mock_send:
'.send_notifications_to_bouncer') as mock_send:
handle_remove_push_notification(user_profile.id, [message.id]) handle_remove_push_notification(user_profile.id, [message.id])
mock_send.assert_called_with( mock_send.assert_called_with(
user_profile.id, user_profile.id,
@ -1030,10 +1026,8 @@ class HandlePushNotificationTest(PushNotificationTest):
PushDeviceToken.objects.filter(user=self.user_profile, PushDeviceToken.objects.filter(user=self.user_profile,
kind=PushDeviceToken.APNS)) kind=PushDeviceToken.APNS))
with mock.patch('zerver.lib.push_notifications' with mock.patch('zerver.lib.push_notifications.send_android_push_notification') as mock_send_android, \
'.send_android_push_notification') as mock_send_android, \ mock.patch('zerver.lib.push_notifications.send_apple_push_notification') as mock_send_apple:
mock.patch('zerver.lib.push_notifications'
'.send_apple_push_notification') as mock_send_apple:
handle_remove_push_notification(self.user_profile.id, [message.id]) handle_remove_push_notification(self.user_profile.id, [message.id])
mock_send_android.assert_called_with( mock_send_android.assert_called_with(
android_devices, android_devices,
@ -1116,10 +1110,8 @@ class HandlePushNotificationTest(PushNotificationTest):
return_value={'apns': True}), \ return_value={'apns': True}), \
mock.patch('zerver.lib.push_notifications.get_message_payload_gcm', mock.patch('zerver.lib.push_notifications.get_message_payload_gcm',
return_value=({'gcm': True}, {})), \ return_value=({'gcm': True}, {})), \
mock.patch('zerver.lib.push_notifications' mock.patch('zerver.lib.push_notifications.send_apple_push_notification') as mock_send_apple, \
'.send_apple_push_notification') as mock_send_apple, \ mock.patch('zerver.lib.push_notifications.send_android_push_notification') as mock_send_android, \
mock.patch('zerver.lib.push_notifications'
'.send_android_push_notification') as mock_send_android, \
mock.patch('zerver.lib.push_notifications.logger.error') as mock_logger, \ mock.patch('zerver.lib.push_notifications.logger.error') as mock_logger, \
mock.patch('zerver.lib.push_notifications.push_notifications_enabled', return_value = True) as mock_push_notifications: mock.patch('zerver.lib.push_notifications.push_notifications_enabled', return_value = True) as mock_push_notifications:
handle_push_notification(self.user_profile.id, missed_message) handle_push_notification(self.user_profile.id, missed_message)
@ -1914,9 +1906,7 @@ class GCMSendTest(PushNotificationTest):
data = self.get_gcm_data() data = self.get_gcm_data()
send_android_push_notification_to_user(self.user_profile, data, {}) send_android_push_notification_to_user(self.user_profile, data, {})
msg = ("GCM: Got canonical ref %s " msg = "GCM: Got canonical ref %s replacing %s but new ID not registered! Updating."
"replacing %s but new ID not "
"registered! Updating.")
mock_warning.assert_called_once_with(msg, t2, t1) mock_warning.assert_called_once_with(msg, t2, t1)
self.assertEqual(get_count('1111'), 0) self.assertEqual(get_count('1111'), 0)

View File

@ -646,9 +646,7 @@ class DefaultEmojiReactionTests(EmojiReactionBase):
def test_delete_insufficient_arguments_reaction(self) -> None: def test_delete_insufficient_arguments_reaction(self) -> None:
result = self.delete_reaction({}) result = self.delete_reaction({})
self.assert_json_error(result, 'At least one of the following ' self.assert_json_error(result, 'At least one of the following arguments must be present: emoji_name, emoji_code')
'arguments must be present: emoji_name, '
'emoji_code')
def test_delete_non_existing_emoji_reaction(self) -> None: def test_delete_non_existing_emoji_reaction(self) -> None:
reaction_info = { reaction_info = {

View File

@ -217,8 +217,7 @@ class TestServiceBotStateHandler(ZulipTestCase):
key = 'capacity-filling entry' key = 'capacity-filling entry'
storage.put(key, 'x' * (settings.USER_STATE_SIZE_LIMIT - len(key))) storage.put(key, 'x' * (settings.USER_STATE_SIZE_LIMIT - len(key)))
with self.assertRaisesMessage(StateError, "Request exceeds storage limit by 32 characters. " with self.assertRaisesMessage(StateError, "Request exceeds storage limit by 32 characters. The limit is 100 characters."):
"The limit is 100 characters."):
storage.put('too much data', 'a few bits too long') storage.put('too much data', 'a few bits too long')
second_storage = StateHandler(self.second_bot_profile) second_storage = StateHandler(self.second_bot_profile)

View File

@ -1603,8 +1603,7 @@ so we didn't send them an invitation. We did send invitations to everyone else!"
email_change_key = email_change_url.split('/')[-1] email_change_key = email_change_url.split('/')[-1]
url = '/accounts/do_confirm/' + email_change_key url = '/accounts/do_confirm/' + email_change_key
result = self.client_get(url) result = self.client_get(url)
self.assert_in_success_response(["Whoops. We couldn't find your " self.assert_in_success_response(["Whoops. We couldn't find your confirmation link in the system."], result)
"confirmation link in the system."], result)
def test_confirmation_expired(self) -> None: def test_confirmation_expired(self) -> None:
email = self.nonreg_email("alice") email = self.nonreg_email("alice")
@ -1621,8 +1620,7 @@ so we didn't send them an invitation. We did send invitations to everyone else!"
target_url = '/' + url.split('/', 3)[3] target_url = '/' + url.split('/', 3)[3]
result = self.client_get(target_url) result = self.client_get(target_url)
self.assert_in_success_response(["Whoops. The confirmation link has expired " self.assert_in_success_response(["Whoops. The confirmation link has expired or been deactivated."], result)
"or been deactivated."], result)
def test_send_more_than_one_invite_to_same_user(self) -> None: def test_send_more_than_one_invite_to_same_user(self) -> None:
self.user_profile = self.example_user('iago') self.user_profile = self.example_user('iago')
@ -3281,8 +3279,7 @@ class UserSignUpTest(InviteUserBase):
def test_failed_signup_due_to_nonexistent_realm(self) -> None: def test_failed_signup_due_to_nonexistent_realm(self) -> None:
email = 'user@acme.com' email = 'user@acme.com'
form = HomepageForm({'email': email}, realm=None) form = HomepageForm({'email': email}, realm=None)
self.assertIn("organization you are trying to join using {} does " self.assertIn(f"organization you are trying to join using {email} does not exist", form.errors['email'][0])
"not exist".format(email), form.errors['email'][0])
def test_access_signup_page_in_root_domain_without_realm(self) -> None: def test_access_signup_page_in_root_domain_without_realm(self) -> None:
result = self.client_get('/register', subdomain="", follow=True) result = self.client_get('/register', subdomain="", follow=True)

View File

@ -26,8 +26,7 @@ def create_realm_domain(request: HttpRequest, user_profile: UserProfile,
except ValidationError as e: except ValidationError as e:
return json_error(_('Invalid domain: {}').format(e.messages[0])) return json_error(_('Invalid domain: {}').format(e.messages[0]))
if RealmDomain.objects.filter(realm=user_profile.realm, domain=domain).exists(): if RealmDomain.objects.filter(realm=user_profile.realm, domain=domain).exists():
return json_error(_("The domain {domain} is already" return json_error(_("The domain {domain} is already a part of your organization.").format(domain=domain))
" a part of your organization.").format(domain=domain))
realm_domain = do_add_realm_domain(user_profile.realm, domain, allow_subdomains) realm_domain = do_add_realm_domain(user_profile.realm, domain, allow_subdomains)
return json_success({'new_domain': [realm_domain.id, realm_domain.domain]}) return json_success({'new_domain': [realm_domain.id, realm_domain.domain]})

View File

@ -17,8 +17,7 @@ DOCUMENT_TEMPLATE = "{user_name} {verb} the document [{title}]({url})"
QUESTION_TEMPLATE = "{user_name} {verb} the question [{title}]({url})" QUESTION_TEMPLATE = "{user_name} {verb} the question [{title}]({url})"
QUESTIONS_ANSWER_TEMPLATE = ("{user_name} {verb} the [answer]({answer_url}) " + QUESTIONS_ANSWER_TEMPLATE = ("{user_name} {verb} the [answer]({answer_url}) " +
"of the question [{question_title}]({question_url})") "of the question [{question_title}]({question_url})")
COMMENT_TEMPLATE = ("{user_name} {verb} the [comment]({answer_url}) " COMMENT_TEMPLATE = "{user_name} {verb} the [comment]({answer_url}) of the task [{task_title}]({task_url})"
"of the task [{task_title}]({task_url})")
MESSAGE_TEMPLATE = "{user_name} {verb} the message [{title}]({url})" MESSAGE_TEMPLATE = "{user_name} {verb} the message [{title}]({url})"
TODO_LIST_TEMPLATE = "{user_name} {verb} the todo list [{title}]({url})" TODO_LIST_TEMPLATE = "{user_name} {verb} the todo list [{title}]({url})"
TODO_TEMPLATE = "{user_name} {verb} the todo task [{title}]({url})" TODO_TEMPLATE = "{user_name} {verb} the todo task [{title}]({url})"

View File

@ -31,10 +31,8 @@ from zerver.models import UserProfile
BITBUCKET_TOPIC_TEMPLATE = '{repository_name}' BITBUCKET_TOPIC_TEMPLATE = '{repository_name}'
BITBUCKET_FORK_BODY = "{actor} forked the repository into [{fork_name}]({fork_url})." BITBUCKET_FORK_BODY = "{actor} forked the repository into [{fork_name}]({fork_url})."
BITBUCKET_COMMIT_STATUS_CHANGED_BODY = ('[System {key}]({system_url}) changed status of' BITBUCKET_COMMIT_STATUS_CHANGED_BODY = '[System {key}]({system_url}) changed status of {commit_info} to {status}.'
' {commit_info} to {status}.') BITBUCKET_REPO_UPDATED_CHANGED = '{actor} changed the {change} of the **{repo_name}** repo from **{old}** to **{new}**'
BITBUCKET_REPO_UPDATED_CHANGED = ('{actor} changed the {change} of the **{repo_name}**'
' repo from **{old}** to **{new}**')
BITBUCKET_REPO_UPDATED_ADDED = '{actor} changed the {change} of the **{repo_name}** repo to **{new}**' BITBUCKET_REPO_UPDATED_ADDED = '{actor} changed the {change} of the **{repo_name}** repo to **{new}**'
PULL_REQUEST_SUPPORTED_ACTIONS = [ PULL_REQUEST_SUPPORTED_ACTIONS = [

View File

@ -23,23 +23,17 @@ NAME_CHANGED_TEMPLATE = ("The name of the {entity} {name_template} was changed f
ARCHIVED_TEMPLATE = "The {entity} {name_template} was {action}." ARCHIVED_TEMPLATE = "The {entity} {name_template} was {action}."
STORY_TASK_TEMPLATE = "Task **{task_description}** was {action} the story {name_template}." STORY_TASK_TEMPLATE = "Task **{task_description}** was {action} the story {name_template}."
STORY_TASK_COMPLETED_TEMPLATE = "Task **{task_description}** ({name_template}) was completed. :tada:" STORY_TASK_COMPLETED_TEMPLATE = "Task **{task_description}** ({name_template}) was completed. :tada:"
STORY_ADDED_REMOVED_EPIC_TEMPLATE = ("The story {story_name_template} was {action} the" STORY_ADDED_REMOVED_EPIC_TEMPLATE = "The story {story_name_template} was {action} the epic {epic_name_template}."
" epic {epic_name_template}.") STORY_EPIC_CHANGED_TEMPLATE = "The story {story_name_template} was moved from {old_epic_name_template} to {new_epic_name_template}."
STORY_EPIC_CHANGED_TEMPLATE = ("The story {story_name_template} was moved from {old_epic_name_template}"
" to {new_epic_name_template}.")
STORY_ESTIMATE_TEMPLATE = "The estimate for the story {story_name_template} was set to {estimate}." STORY_ESTIMATE_TEMPLATE = "The estimate for the story {story_name_template} was set to {estimate}."
FILE_ATTACHMENT_TEMPLATE = "A {type} attachment `{file_name}` was added to the story {name_template}." FILE_ATTACHMENT_TEMPLATE = "A {type} attachment `{file_name}` was added to the story {name_template}."
STORY_LABEL_TEMPLATE = "The label **{label_name}** was added to the story {name_template}." STORY_LABEL_TEMPLATE = "The label **{label_name}** was added to the story {name_template}."
STORY_UPDATE_PROJECT_TEMPLATE = ("The story {name_template} was moved from" STORY_UPDATE_PROJECT_TEMPLATE = "The story {name_template} was moved from the **{old}** project to **{new}**."
" the **{old}** project to **{new}**.") STORY_UPDATE_TYPE_TEMPLATE = "The type of the story {name_template} was changed from **{old_type}** to **{new_type}**."
STORY_UPDATE_TYPE_TEMPLATE = ("The type of the story {name_template} was changed"
" from **{old_type}** to **{new_type}**.")
DELETE_TEMPLATE = "The {entity_type} **{name}** was deleted." DELETE_TEMPLATE = "The {entity_type} **{name}** was deleted."
STORY_UPDATE_OWNER_TEMPLATE = "New owner added to the story {name_template}." STORY_UPDATE_OWNER_TEMPLATE = "New owner added to the story {name_template}."
STORY_GITHUB_PR_TEMPLATE = ("New GitHub PR [#{name}]({url}) opened for story" STORY_GITHUB_PR_TEMPLATE = "New GitHub PR [#{name}]({url}) opened for story {name_template} ({old} -> {new})."
" {name_template} ({old} -> {new}).") STORY_GITHUB_BRANCH_TEMPLATE = "New GitHub branch [{name}]({url}) associated with story {name_template} ({old} -> {new})."
STORY_GITHUB_BRANCH_TEMPLATE = ("New GitHub branch [{name}]({url})"
" associated with story {name_template} ({old} -> {new}).")
def get_action_with_primary_id(payload: Dict[str, Any]) -> Dict[str, Any]: def get_action_with_primary_id(payload: Dict[str, Any]) -> Dict[str, Any]:

View File

@ -180,8 +180,7 @@ class FrontHookTests(WebhookTestCase):
def test_comment(self) -> None: def test_comment(self) -> None:
expected_topic = 'cnv_keocka' expected_topic = 'cnv_keocka'
expected_message = "**Bender Rodriguez** left a comment:\n" \ expected_message = "**Bender Rodriguez** left a comment:\n```quote\nSure.\n```"
"```quote\nSure.\n```"
self.check_webhook( self.check_webhook(
"comment", "comment",

View File

@ -414,8 +414,7 @@ def get_pull_request_review_requested_body(helper: Helper) -> str:
pr_number = payload['pull_request']['number'] pr_number = payload['pull_request']['number']
pr_url = payload['pull_request']['html_url'] pr_url = payload['pull_request']['html_url']
message = "**{sender}** requested {reviewers} for a review on [PR #{pr_number}]({pr_url})." message = "**{sender}** requested {reviewers} for a review on [PR #{pr_number}]({pr_url})."
message_with_title = ("**{sender}** requested {reviewers} for a review on " message_with_title = "**{sender}** requested {reviewers} for a review on [PR #{pr_number} {title}]({pr_url})."
"[PR #{pr_number} {title}]({pr_url}).")
body = message_with_title if include_title else message body = message_with_title if include_title else message
all_reviewers = [] all_reviewers = []

View File

@ -11,12 +11,11 @@ from zerver.lib.response import json_success
from zerver.lib.webhooks.common import check_send_webhook_message from zerver.lib.webhooks.common import check_send_webhook_message
from zerver.models import UserProfile from zerver.models import UserProfile
MESSAGE_TEMPLATE = ( MESSAGE_TEMPLATE = """\
'Author: {}\n' Author: {}
'Build status: {} {}\n' Build status: {} {}
'Details: [build log]({})\n' Details: [build log]({})
'Comment: {}' Comment: {}"""
)
@webhook_view('Gocd') @webhook_view('Gocd')
@has_request_variables @has_request_variables

View File

@ -130,8 +130,7 @@ class LibratoWebhookHandler(LibratoWebhookParser):
condition: Dict[str, Any]) -> str: condition: Dict[str, Any]) -> str:
summary_function, threshold, condition_type, duration = self.parse_condition(condition) summary_function, threshold, condition_type, duration = self.parse_condition(condition)
metric_name, recorded_at = self.parse_violation(violation) metric_name, recorded_at = self.parse_violation(violation)
metric_condition_template = ("\n * Metric `{metric_name}`, {summary_function} " metric_condition_template = "\n * Metric `{metric_name}`, {summary_function} was {condition_type} {threshold}"
"was {condition_type} {threshold}")
content = metric_condition_template.format( content = metric_condition_template.format(
metric_name=metric_name, summary_function=summary_function, condition_type=condition_type, metric_name=metric_name, summary_function=summary_function, condition_type=condition_type,
threshold=threshold) threshold=threshold)

View File

@ -62,8 +62,7 @@ def body(message: Dict[str, Any]) -> str:
title = canary_kind(message).title() title = canary_kind(message).title()
name = canary_name(message) name = canary_name(message)
body = (f"**:alert: {title} *{name}* has been triggered!**\n\n" body = f"**:alert: {title} *{name}* has been triggered!**\n\n{message['Intro']}\n\n"
f"{message['Intro']}\n\n")
if 'IncidentHash' in message: if 'IncidentHash' in message:
body += f"**Incident Id:** `{message['IncidentHash']}`\n" body += f"**Incident Id:** `{message['IncidentHash']}`\n"

View File

@ -14,11 +14,10 @@ GOOD_STATUSES = ['Passed', 'Fixed']
BAD_STATUSES = ['Failed', 'Broken', 'Still Failing', 'Errored', 'Canceled'] BAD_STATUSES = ['Failed', 'Broken', 'Still Failing', 'Errored', 'Canceled']
PENDING_STATUSES = ['Pending'] PENDING_STATUSES = ['Pending']
MESSAGE_TEMPLATE = ( MESSAGE_TEMPLATE = """\
'Author: {}\n' Author: {}
'Build status: {} {}\n' Build status: {} {}
'Details: [changes]({}), [build log]({})' Details: [changes]({}), [build log]({})"""
)
@webhook_view('Travis') @webhook_view('Travis')
@has_request_variables @has_request_variables

View File

@ -635,8 +635,7 @@ class MirrorWorker(QueueProcessingWorker):
try: try:
rate_limit_mirror_by_realm(recipient_realm) rate_limit_mirror_by_realm(recipient_realm)
except RateLimited: except RateLimited:
logger.warning("MirrorWorker: Rejecting an email from: %s " logger.warning("MirrorWorker: Rejecting an email from: %s to realm: %s - rate limited.",
"to realm: %s - rate limited.",
msg['From'], recipient_realm.name) msg['From'], recipient_realm.name)
return return

View File

@ -987,8 +987,7 @@ class ExternalAuthResult:
data_dict = {} data_dict = {}
if login_token is not None: if login_token is not None:
assert (not data_dict) and (user_profile is None), ("Passing in data_dict or user_profile " + assert (not data_dict) and (user_profile is None), "Passing in data_dict or user_profile with login_token is disallowed."
"with login_token is disallowed.")
self.instantiate_with_token(login_token, delete_stored_data) self.instantiate_with_token(login_token, delete_stored_data)
else: else:
self.data_dict = data_dict.copy() self.data_dict = data_dict.copy()