From 8dd83228e79aa29bbced620e11fd50b5fe60f277 Mon Sep 17 00:00:00 2001 From: Anders Kaseorg Date: Mon, 8 Jun 2020 15:25:09 -0700 Subject: [PATCH] python: Convert "".format to Python 3.6 f-strings. Generated by pyupgrade --py36-plus --keep-percent-format, but with the NamedTuple changes reverted (see commit ba7906a3c657905fa35bbcfb4e97b053f050272d, #15132). Signed-off-by: Anders Kaseorg --- analytics/tests/test_views.py | 2 +- analytics/views.py | 14 ++-- corporate/lib/stripe.py | 8 +- corporate/tests/test_stripe.py | 14 ++-- corporate/views.py | 4 +- frontend_tests/run-casper | 8 +- scripts/lib/sharding.py | 2 +- tools/circleci/generate-dockerfiles | 2 +- .../spiders/check_help_documentation.py | 2 +- tools/droplets/add_mentor.py | 10 +-- tools/droplets/create.py | 42 +++++------ tools/fetch-contributor-data | 2 +- tools/generate-integration-docs-screenshot | 16 ++-- tools/i18n/process-mobile-i18n | 2 +- tools/lib/capitalization.py | 2 +- tools/lib/gitlint-rules.py | 4 +- tools/linter_lib/custom_check.py | 8 +- tools/setup/emoji/build_emoji | 8 +- tools/test-backend | 10 +-- tools/test-js-with-node | 4 +- tools/test-queue-worker-reload | 2 +- tools/test-run-dev | 2 +- tools/tests/test_zulint_custom_rules.py | 10 +-- tools/update-zuliprc-api-field | 2 +- zerver/data_import/hipchat.py | 4 +- zerver/data_import/hipchat_user.py | 2 +- zerver/data_import/slack.py | 2 +- zerver/decorator.py | 2 +- zerver/forms.py | 4 +- zerver/lib/actions.py | 4 +- zerver/lib/bot_config.py | 4 +- zerver/lib/bot_storage.py | 4 +- zerver/lib/bugdown/__init__.py | 14 ++-- .../bugdown/api_arguments_table_generator.py | 2 +- zerver/lib/bugdown/include.py | 2 +- zerver/lib/bugdown/tabbed_sections.py | 2 +- zerver/lib/cache.py | 2 +- zerver/lib/debug.py | 4 +- zerver/lib/email_mirror.py | 10 +-- zerver/lib/email_notifications.py | 4 +- zerver/lib/emoji.py | 4 +- zerver/lib/i18n.py | 2 +- zerver/lib/import_realm.py | 2 +- zerver/lib/integrations.py | 6 +- zerver/lib/logging_util.py | 2 +- zerver/lib/rate_limiter.py | 4 +- zerver/lib/remote_server.py | 2 +- zerver/lib/test_classes.py | 16 ++-- zerver/lib/test_fixtures.py | 2 +- zerver/lib/test_runner.py | 8 +- zerver/lib/users.py | 2 +- zerver/lib/webhooks/git.py | 16 ++-- zerver/management/commands/compilemessages.py | 8 +- zerver/management/commands/export.py | 4 +- zerver/management/commands/makemessages.py | 4 +- .../commands/send_to_email_mirror.py | 2 +- zerver/openapi/markdown_extension.py | 8 +- zerver/openapi/openapi.py | 2 +- zerver/openapi/python_examples.py | 10 +-- zerver/openapi/test_curl_examples.py | 2 +- zerver/signals.py | 2 +- zerver/tests/test_attachments.py | 8 +- zerver/tests/test_auth_backends.py | 16 ++-- zerver/tests/test_bots.py | 74 +++++++++---------- zerver/tests/test_bugdown.py | 8 +- zerver/tests/test_cache.py | 10 +-- zerver/tests/test_compatibility.py | 2 +- zerver/tests/test_custom_profile_data.py | 36 ++++----- zerver/tests/test_digest.py | 4 +- zerver/tests/test_docs.py | 8 +- zerver/tests/test_email_change.py | 2 +- zerver/tests/test_email_mirror.py | 18 ++--- zerver/tests/test_email_notifications.py | 4 +- zerver/tests/test_embedded_bot_system.py | 8 +- zerver/tests/test_events.py | 4 +- zerver/tests/test_i18n.py | 2 +- zerver/tests/test_import_export.py | 6 +- zerver/tests/test_integrations_dev_panel.py | 14 ++-- zerver/tests/test_link_embed.py | 16 ++-- zerver/tests/test_management_commands.py | 16 ++-- zerver/tests/test_messages.py | 46 ++++++------ zerver/tests/test_narrow.py | 4 +- zerver/tests/test_openapi.py | 4 +- zerver/tests/test_outgoing_webhook_system.py | 2 +- zerver/tests/test_presence.py | 2 +- zerver/tests/test_push_notifications.py | 6 +- zerver/tests/test_realm_export.py | 8 +- zerver/tests/test_realm_filters.py | 4 +- zerver/tests/test_signup.py | 32 ++++---- zerver/tests/test_slack_importer.py | 2 +- zerver/tests/test_subs.py | 38 +++++----- zerver/tests/test_tornado.py | 4 +- zerver/tests/test_upload.py | 30 ++++---- zerver/tests/test_user_groups.py | 58 +++++++-------- zerver/tests/test_users.py | 56 +++++++------- zerver/views/development/integrations.py | 2 +- zerver/views/documentation.py | 4 +- zerver/views/messages.py | 2 +- zerver/webhooks/alertmanager/view.py | 6 +- zerver/webhooks/basecamp/view.py | 2 +- zerver/webhooks/bitbucket/tests.py | 10 +-- zerver/webhooks/bitbucket2/tests.py | 12 +-- zerver/webhooks/bitbucket2/view.py | 2 +- zerver/webhooks/bitbucket3/view.py | 10 +-- zerver/webhooks/clubhouse/view.py | 2 +- zerver/webhooks/dialogflow/view.py | 2 +- zerver/webhooks/flock/view.py | 2 +- zerver/webhooks/front/view.py | 14 ++-- zerver/webhooks/gci/view.py | 4 +- zerver/webhooks/github/tests.py | 8 +- zerver/webhooks/github/view.py | 22 +++--- zerver/webhooks/gitlab/tests.py | 2 +- zerver/webhooks/gitlab/view.py | 10 +-- zerver/webhooks/gogs/tests.py | 4 +- zerver/webhooks/gogs/view.py | 4 +- zerver/webhooks/gosquared/view.py | 4 +- zerver/webhooks/greenhouse/view.py | 4 +- zerver/webhooks/harbor/view.py | 2 +- zerver/webhooks/hellosign/view.py | 6 +- zerver/webhooks/jira/view.py | 30 ++++---- zerver/webhooks/librato/view.py | 4 +- zerver/webhooks/opbeat/view.py | 14 ++-- zerver/webhooks/pingdom/view.py | 2 +- zerver/webhooks/pivotal/tests.py | 2 +- zerver/webhooks/raygun/view.py | 12 +-- zerver/webhooks/sentry/view.py | 2 +- zerver/webhooks/slack/view.py | 2 +- zerver/webhooks/slack_incoming/view.py | 2 +- zerver/webhooks/solano/view.py | 6 +- zerver/webhooks/splunk/view.py | 2 +- zerver/webhooks/stripe/view.py | 12 +-- zerver/webhooks/teamcity/view.py | 2 +- zerver/webhooks/transifex/tests.py | 8 +- zerver/webhooks/transifex/view.py | 6 +- zerver/webhooks/travis/tests.py | 2 +- zerver/webhooks/travis/view.py | 2 +- zerver/webhooks/trello/view/__init__.py | 2 +- zerver/webhooks/trello/view/board_actions.py | 2 +- zerver/webhooks/trello/view/card_actions.py | 2 +- zerver/webhooks/updown/view.py | 10 +-- zerver/worker/queue_processors.py | 2 +- .../management/commands/compare_messages.py | 4 +- .../management/commands/render_messages.py | 2 +- zproject/backends.py | 8 +- zproject/settings.py | 2 +- zproject/urls.py | 2 +- 146 files changed, 596 insertions(+), 596 deletions(-) diff --git a/analytics/tests/test_views.py b/analytics/tests/test_views.py index 21b129e02c..aec6e365d7 100644 --- a/analytics/tests/test_views.py +++ b/analytics/tests/test_views.py @@ -432,7 +432,7 @@ class TestSupportEndpoint(ZulipTestCase): def check_preregistration_user_query_result(result: HttpResponse, email: str, invite: Optional[bool]=False) -> None: self.assert_in_success_response(['preregistration user\n', - 'Email: {}'.format(email), + f'Email: {email}', ], result) if invite: self.assert_in_success_response(['invite'], result) diff --git a/analytics/views.py b/analytics/views.py index f0ed1a4b1c..3ff32d2017 100644 --- a/analytics/views.py +++ b/analytics/views.py @@ -1103,23 +1103,23 @@ def support(request: HttpRequest) -> HttpResponse: new_discount = Decimal(new_discount) current_discount = get_discount_for_realm(realm) attach_discount_to_realm(realm, new_discount) - msg = "Discount of {} changed to {} from {} ".format(realm.name, new_discount, current_discount) + msg = f"Discount of {realm.name} changed to {new_discount} from {current_discount} " context["message"] = msg status = request.POST.get("status", None) if status is not None: if status == "active": do_send_realm_reactivation_email(realm) - context["message"] = "Realm reactivation email sent to admins of {}.".format(realm.name) + context["message"] = f"Realm reactivation email sent to admins of {realm.name}." elif status == "deactivated": do_deactivate_realm(realm, request.user) - context["message"] = "{} deactivated.".format(realm.name) + context["message"] = f"{realm.name} deactivated." scrub_realm = request.POST.get("scrub_realm", None) if scrub_realm is not None: if scrub_realm == "scrub_realm": do_scrub_realm(realm) - context["message"] = "{} scrubbed.".format(realm.name) + context["message"] = f"{realm.name} scrubbed." query = request.GET.get("q", None) if query: @@ -1135,7 +1135,7 @@ def support(request: HttpRequest) -> HttpResponse: hostname = parse_result.hostname assert hostname is not None if parse_result.port: - hostname = "{}:{}".format(hostname, parse_result.port) + hostname = f"{hostname}:{parse_result.port}" subdomain = get_subdomain_from_hostname(hostname) try: realms.add(get_realm(subdomain)) @@ -1295,13 +1295,13 @@ def realm_activity_link(realm_str: str) -> mark_safe: def realm_stats_link(realm_str: str) -> mark_safe: url_name = 'analytics.views.stats_for_realm' url = reverse(url_name, kwargs=dict(realm_str=realm_str)) - stats_link = '{}'.format(url, realm_str) + stats_link = f'{realm_str}' return mark_safe(stats_link) def remote_installation_stats_link(server_id: int, hostname: str) -> mark_safe: url_name = 'analytics.views.stats_for_remote_installation' url = reverse(url_name, kwargs=dict(remote_server_id=server_id)) - stats_link = '{}'.format(url, hostname) + stats_link = f'{hostname}' return mark_safe(stats_link) def realm_client_table(user_summaries: Dict[str, Dict[str, Dict[str, Any]]]) -> str: diff --git a/corporate/lib/stripe.py b/corporate/lib/stripe.py index 5e4ad49ede..362e13b6be 100644 --- a/corporate/lib/stripe.py +++ b/corporate/lib/stripe.py @@ -283,7 +283,7 @@ def compute_plan_parameters( price_per_license = 800 period_end = add_months(billing_cycle_anchor, 1) else: - raise AssertionError('Unknown billing_schedule: {}'.format(billing_schedule)) + raise AssertionError(f'Unknown billing_schedule: {billing_schedule}') if discount is not None: # There are no fractional cents in Stripe, so round down to nearest integer. price_per_license = int(float(price_per_license * (1 - discount / 100)) + .00001) @@ -326,12 +326,12 @@ def process_initial_upgrade(user: UserProfile, licenses: int, automanage_license amount=price_per_license * licenses, currency='usd', customer=customer.stripe_customer_id, - description="Upgrade to Zulip Standard, ${} x {}".format(price_per_license/100, licenses), + description=f"Upgrade to Zulip Standard, ${price_per_license/100} x {licenses}", receipt_email=user.delivery_email, statement_descriptor='Zulip Standard') # Not setting a period start and end, but maybe we should? Unclear what will make things # most similar to the renewal case from an accounting perspective. - description = "Payment (Card ending in {})".format(cast(stripe.Card, stripe_charge.source).last4) + description = f"Payment (Card ending in {cast(stripe.Card, stripe_charge.source).last4})" stripe.InvoiceItem.create( amount=price_per_license * licenses * -1, currency='usd', @@ -454,7 +454,7 @@ def invoice_plan(plan: CustomerPlan, event_time: datetime) -> None: plan.invoiced_through = ledger_entry plan.invoicing_status = CustomerPlan.STARTED plan.save(update_fields=['invoicing_status', 'invoiced_through']) - idempotency_key: Optional[str] = 'ledger_entry:{}'.format(ledger_entry.id) + idempotency_key: Optional[str] = f'ledger_entry:{ledger_entry.id}' if settings.TEST_SUITE: idempotency_key = None stripe.InvoiceItem.create( diff --git a/corporate/tests/test_stripe.py b/corporate/tests/test_stripe.py index 94ec72b515..0e1dfbdbd1 100644 --- a/corporate/tests/test_stripe.py +++ b/corporate/tests/test_stripe.py @@ -71,7 +71,7 @@ def fixture_files_for_function(decorated_function: CallableT) -> List[str]: # n decorated_function_name = decorated_function.__name__ if decorated_function_name[:5] == 'test_': decorated_function_name = decorated_function_name[5:] - return sorted(['{}/{}'.format(STRIPE_FIXTURES_DIR, f) for f in os.listdir(STRIPE_FIXTURES_DIR) + return sorted([f'{STRIPE_FIXTURES_DIR}/{f}' for f in os.listdir(STRIPE_FIXTURES_DIR) if f.startswith(decorated_function_name + '--')]) def generate_and_save_stripe_fixture(decorated_function_name: str, mocked_function_name: str, @@ -174,7 +174,7 @@ def normalize_fixture_data(decorated_function: CallableT, with open(fixture_file, "w") as f: f.write(file_content) -MOCKED_STRIPE_FUNCTION_NAMES = ["stripe.{}".format(name) for name in [ +MOCKED_STRIPE_FUNCTION_NAMES = [f"stripe.{name}" for name in [ "Charge.create", "Charge.list", "Coupon.create", "Customer.create", "Customer.retrieve", "Customer.save", @@ -392,7 +392,7 @@ class StripeTest(StripeTestCase): self.assertEqual(stripe_charges[0].amount, 8000 * self.seat_count) # TODO: fix Decimal self.assertEqual(stripe_charges[0].description, - "Upgrade to Zulip Standard, $80.0 x {}".format(self.seat_count)) + f"Upgrade to Zulip Standard, $80.0 x {self.seat_count}") self.assertEqual(stripe_charges[0].receipt_email, user.email) self.assertEqual(stripe_charges[0].statement_descriptor, "Zulip Standard") # Check Invoices in Stripe @@ -775,7 +775,7 @@ class StripeTest(StripeTestCase): 'Zulip Standard', 'Free Trial', str(self.seat_count), 'You are using', '%s of %s licenses' % (self.seat_count, 123), 'Your plan will be upgraded to', 'March 2, 2012', - '{:,.2f}'.format(80 * 123), 'Billed by invoice' + f'{80 * 123:,.2f}', 'Billed by invoice' ]: self.assert_in_response(substring, response) @@ -983,13 +983,13 @@ class StripeTest(StripeTestCase): upgrade_params['licenses'] = licenses response = self.upgrade(invoice=invoice, talk_to_stripe=False, del_args=del_args, **upgrade_params) - self.assert_json_error_contains(response, "at least {} users".format(min_licenses_in_response)) + self.assert_json_error_contains(response, f"at least {min_licenses_in_response} users") self.assertEqual(ujson.loads(response.content)['error_description'], 'not enough licenses') def check_max_licenses_error(licenses: int) -> None: response = self.upgrade(invoice=True, talk_to_stripe=False, licenses=licenses) - self.assert_json_error_contains(response, "with more than {} licenses".format(MAX_INVOICED_LICENSES)) + self.assert_json_error_contains(response, f"with more than {MAX_INVOICED_LICENSES} licenses") self.assertEqual(ujson.loads(response.content)['error_description'], 'too many licenses') def check_success(invoice: bool, licenses: Optional[int], upgrade_params: Dict[str, Any]={}) -> None: @@ -1108,7 +1108,7 @@ class StripeTest(StripeTestCase): realm = Realm.objects.create(string_id='second', name='second') UserProfile.objects.create(realm=realm, email='member@second.com', pointer=-1) for i in range(5): - UserProfile.objects.create(realm=realm, email='guest{}@second.com'.format(i), + UserProfile.objects.create(realm=realm, email=f'guest{i}@second.com', pointer=-1, role=UserProfile.ROLE_GUEST) self.assertEqual(get_latest_seat_count(realm), 1) # Test 1 member and 6 guests diff --git a/corporate/views.py b/corporate/views.py index 1ee03762d7..3767a3b139 100644 --- a/corporate/views.py +++ b/corporate/views.py @@ -131,7 +131,7 @@ def initial_upgrade(request: HttpRequest) -> HttpResponse: if customer is not None and get_current_plan_by_customer(customer) is not None: billing_page_url = reverse('corporate.views.billing_home') if request.GET.get("onboarding") is not None: - billing_page_url = "{}?onboarding=true".format(billing_page_url) + billing_page_url = f"{billing_page_url}?onboarding=true" return HttpResponseRedirect(billing_page_url) percent_off = Decimal(0) @@ -210,7 +210,7 @@ def billing_home(request: HttpRequest) -> HttpResponse: 'licenses': licenses, 'licenses_used': licenses_used, 'renewal_date': renewal_date, - 'renewal_amount': '{:,.2f}'.format(renewal_cents / 100.), + 'renewal_amount': f'{renewal_cents / 100.:,.2f}', 'payment_method': payment_method, 'charge_automatically': charge_automatically, 'publishable_key': STRIPE_PUBLISHABLE_KEY, diff --git a/frontend_tests/run-casper b/frontend_tests/run-casper index df98d3da6a..72d972dd0f 100755 --- a/frontend_tests/run-casper +++ b/frontend_tests/run-casper @@ -99,7 +99,7 @@ def run_tests(files: Iterable[str], external_host: str) -> None: print('\n\nWe will use loop mode for these tests:\n') for test_file in test_files: print(' ' + os.path.basename(test_file)) - print('\nnumber of loops: {}\n'.format(loop_cnt)) + print(f'\nnumber of loops: {loop_cnt}\n') print() else: loop_cnt = None @@ -130,12 +130,12 @@ def run_tests(files: Iterable[str], external_host: str) -> None: def run_loops(loop_cnt: int) -> None: while True: for trial in range(1, loop_cnt + 1): - print('\n\n\nSTARTING TRIAL {} / {}\n'.format(trial, loop_cnt)) + print(f'\n\n\nSTARTING TRIAL {trial} / {loop_cnt}\n') ret = run_tests() if ret == 0: - print('`\n\nSUCCESS! trial #{}\n\n'.format(trial)) + print(f'`\n\nSUCCESS! trial #{trial}\n\n') else: - print('\n\nFAIL! trial #{}\n'.format(trial)) + print(f'\n\nFAIL! trial #{trial}\n') break while True: diff --git a/scripts/lib/sharding.py b/scripts/lib/sharding.py index 2b068910bc..694153f638 100755 --- a/scripts/lib/sharding.py +++ b/scripts/lib/sharding.py @@ -47,7 +47,7 @@ with open('/etc/zulip/nginx_sharding.conf.tmp', 'w') as nginx_sharding_conf_f, \ if '.' in shard: host = shard else: - host = "{}.{}".format(shard, external_host) + host = f"{shard}.{external_host}" assert host not in shard_map, "host %s duplicated" % (host,) shard_map[host] = int(port) write_realm_nginx_config_line(nginx_sharding_conf_f, host, port) diff --git a/tools/circleci/generate-dockerfiles b/tools/circleci/generate-dockerfiles index 4fe9adc3ef..fb4bf6974a 100755 --- a/tools/circleci/generate-dockerfiles +++ b/tools/circleci/generate-dockerfiles @@ -14,7 +14,7 @@ if __name__ == "__main__": dockerfile_settings = yaml.safe_load(f) for distro in dockerfile_settings: - dockerfile_path = "images/{}/Dockerfile".format(distro) + dockerfile_path = f"images/{distro}/Dockerfile" os.makedirs(os.path.dirname(dockerfile_path), exist_ok=True) with open(dockerfile_path, "w") as f: f.write("""\ diff --git a/tools/documentation_crawler/documentation_crawler/spiders/check_help_documentation.py b/tools/documentation_crawler/documentation_crawler/spiders/check_help_documentation.py index c831fa095e..475beb9587 100644 --- a/tools/documentation_crawler/documentation_crawler/spiders/check_help_documentation.py +++ b/tools/documentation_crawler/documentation_crawler/spiders/check_help_documentation.py @@ -25,7 +25,7 @@ class UnusedImagesLinterSpider(BaseDocumentationSpider): def _is_external_url(self, url: str) -> bool: is_external = url.startswith('http') and self.start_urls[0] not in url - if self._has_extension(url) and 'localhost:9981/{}'.format(self.images_path) in url: + if self._has_extension(url) and f'localhost:9981/{self.images_path}' in url: self.static_images.add(basename(urlparse(url).path)) return is_external or self._has_extension(url) diff --git a/tools/droplets/add_mentor.py b/tools/droplets/add_mentor.py index a7e0bd042d..f505828120 100644 --- a/tools/droplets/add_mentor.py +++ b/tools/droplets/add_mentor.py @@ -32,7 +32,7 @@ append_key = """\ """ def get_mentor_keys(username: str) -> List[str]: - url = 'https://api.github.com/users/{}/keys'.format(username) + url = f'https://api.github.com/users/{username}/keys' r = requests.get(url) if r.status_code != 200: @@ -41,7 +41,7 @@ def get_mentor_keys(username: str) -> List[str]: keys = r.json() if not keys: - print('Mentor "{}" has no public key.'.format(username)) + print(f'Mentor "{username}" has no public key.') sys.exit(1) return [key['key'] for key in keys] @@ -62,7 +62,7 @@ if __name__ == '__main__': f.write(new_content) f.truncate() - print('Successfully removed {}\' SSH key!'.format(args.username)) + print(f'Successfully removed {args.username}\' SSH key!') else: keys = get_mentor_keys(args.username) @@ -70,6 +70,6 @@ if __name__ == '__main__': for key in keys: f.write(append_key.format(username=args.username, key=key)) - print('Successfully added {}\'s SSH key!'.format(args.username)) + print(f'Successfully added {args.username}\'s SSH key!') print('Can you let your mentor know that they can connect to this machine with:\n') - print(' $ ssh zulipdev@{}\n'.format(socket.gethostname())) + print(f' $ ssh zulipdev@{socket.gethostname()}\n') diff --git a/tools/droplets/create.py b/tools/droplets/create.py index 75fdb815e6..0c2b8e6e2a 100644 --- a/tools/droplets/create.py +++ b/tools/droplets/create.py @@ -39,8 +39,8 @@ def get_config() -> configparser.ConfigParser: return config def user_exists(username: str) -> bool: - print("Checking to see if GitHub user {} exists...".format(username)) - user_api_url = "https://api.github.com/users/{}".format(username) + print(f"Checking to see if GitHub user {username} exists...") + user_api_url = f"https://api.github.com/users/{username}" try: response = urllib.request.urlopen(user_api_url) json.load(response) @@ -48,28 +48,28 @@ def user_exists(username: str) -> bool: return True except urllib.error.HTTPError as err: print(err) - print("Does the github user {} exist?".format(username)) + print(f"Does the github user {username} exist?") sys.exit(1) def get_keys(username: str) -> List[Dict[str, Any]]: print("Checking to see that GitHub user has available public keys...") - apiurl_keys = "https://api.github.com/users/{}/keys".format(username) + apiurl_keys = f"https://api.github.com/users/{username}/keys" try: response = urllib.request.urlopen(apiurl_keys) userkeys = json.load(response) if not userkeys: - print("No keys found. Has user {} added ssh keys to their github account?".format(username)) + print(f"No keys found. Has user {username} added ssh keys to their github account?") sys.exit(1) print("...public keys found!") return userkeys except urllib.error.HTTPError as err: print(err) - print("Has user {} added ssh keys to their github account?".format(username)) + print(f"Has user {username} added ssh keys to their github account?") sys.exit(1) def fork_exists(username: str) -> bool: print("Checking to see GitHub user has forked zulip/zulip...") - apiurl_fork = "https://api.github.com/repos/{}/zulip".format(username) + apiurl_fork = f"https://api.github.com/repos/{username}/zulip" try: response = urllib.request.urlopen(apiurl_fork) json.load(response) @@ -77,21 +77,21 @@ def fork_exists(username: str) -> bool: return True except urllib.error.HTTPError as err: print(err) - print("Has user {} forked zulip/zulip?".format(username)) + print(f"Has user {username} forked zulip/zulip?") sys.exit(1) def exit_if_droplet_exists(my_token: str, username: str, recreate: bool) -> None: - print("Checking to see if droplet for {} already exists...".format(username)) + print(f"Checking to see if droplet for {username} already exists...") manager = digitalocean.Manager(token=my_token) my_droplets = manager.get_all_droplets() for droplet in my_droplets: - if droplet.name.lower() == "{}.zulipdev.org".format(username): + if droplet.name.lower() == f"{username}.zulipdev.org": if not recreate: print("Droplet for user {} already exists. Pass --recreate if you " "need to recreate the droplet.".format(username)) sys.exit(1) else: - print("Deleting existing droplet for {}.".format(username)) + print(f"Deleting existing droplet for {username}.") droplet.destroy() return print("...No droplet found...proceeding.") @@ -101,13 +101,13 @@ def set_user_data(username: str, userkey_dicts: List[Dict[str, Any]]) -> str: userkeys = [userkey_dict["key"] for userkey_dict in userkey_dicts] ssh_keys = "\n".join(userkeys) - setup_root_ssh_keys = "printf '{keys}' > /root/.ssh/authorized_keys".format(keys=ssh_keys) - setup_zulipdev_ssh_keys = "printf '{keys}' > /home/zulipdev/.ssh/authorized_keys".format(keys=ssh_keys) + setup_root_ssh_keys = f"printf '{ssh_keys}' > /root/.ssh/authorized_keys" + setup_zulipdev_ssh_keys = f"printf '{ssh_keys}' > /home/zulipdev/.ssh/authorized_keys" # We pass the hostname as username.zulipdev.org to the DigitalOcean API. # But some droplets (eg on 18.04) are created with with hostname set to just username. # So we fix the hostname using cloud-init. - hostname_setup = "hostnamectl set-hostname {username}.zulipdev.org".format(username=username) + hostname_setup = f"hostnamectl set-hostname {username}.zulipdev.org" setup_repo = ( "cd /home/zulipdev/{1} && " @@ -141,7 +141,7 @@ su -c 'git config --global pull.rebase true' zulipdev def create_droplet(my_token: str, template_id: str, username: str, tags: List[str], user_data: str) -> str: droplet = digitalocean.Droplet( token=my_token, - name='{}.zulipdev.org'.format(username), + name=f'{username}.zulipdev.org', region='nyc3', image=template_id, size_slug='s-1vcpu-2gb', @@ -157,7 +157,7 @@ def create_droplet(my_token: str, template_id: str, username: str, tags: List[st actions = droplet.get_actions() for action in actions: action.load() - print("...[{}]: {}".format(action.type, action.status)) + print(f"...[{action.type}]: {action.status}") if action.type == 'create' and action.status == 'completed': incomplete = False break @@ -165,7 +165,7 @@ def create_droplet(my_token: str, template_id: str, username: str, tags: List[st time.sleep(15) print("...droplet created!") droplet.load() - print("...ip address for new droplet is: {}.".format(droplet.ip_address)) + print(f"...ip address for new droplet is: {droplet.ip_address}.") return droplet.ip_address def delete_existing_records(records: List[digitalocean.Record], record_name: str) -> None: @@ -175,7 +175,7 @@ def delete_existing_records(records: List[digitalocean.Record], record_name: str record.destroy() count = count + 1 if count: - print("Deleted {} existing A records for {}.zulipdev.org.".format(count, record_name)) + print(f"Deleted {count} existing A records for {record_name}.zulipdev.org.") def create_dns_record(my_token: str, username: str, ip_address: str) -> None: domain = digitalocean.Domain(token=my_token, name='zulipdev.org') @@ -186,9 +186,9 @@ def create_dns_record(my_token: str, username: str, ip_address: str) -> None: wildcard_name = "*." + username delete_existing_records(records, wildcard_name) - print("Creating new A record for {}.zulipdev.org that points to {}.".format(username, ip_address)) + print(f"Creating new A record for {username}.zulipdev.org that points to {ip_address}.") domain.create_new_domain_record(type='A', name=username, data=ip_address) - print("Creating new A record for *.{}.zulipdev.org that points to {}.".format(username, ip_address)) + print(f"Creating new A record for *.{username}.zulipdev.org that points to {ip_address}.") domain.create_new_domain_record(type='A', name=wildcard_name, data=ip_address) def print_completion(username: str) -> None: @@ -230,7 +230,7 @@ if __name__ == '__main__': # get command line arguments args = parser.parse_args() username = args.username.lower() - print("Creating Zulip developer environment for GitHub user {}...".format(username)) + print(f"Creating Zulip developer environment for GitHub user {username}...") # get config details config = get_config() diff --git a/tools/fetch-contributor-data b/tools/fetch-contributor-data index caf92492fa..40a82d06fd 100755 --- a/tools/fetch-contributor-data +++ b/tools/fetch-contributor-data @@ -49,7 +49,7 @@ def fetch_contributors(repo_link: str) -> Optional[List[Dict[str, Dict[str, Any] def write_to_disk(json_data: ContributorsJSON, out_file: str) -> None: with open(out_file, 'w') as f: try: - f.write("{}\n".format(json.dumps(json_data, indent=2, sort_keys=True))) + f.write(f"{json.dumps(json_data, indent=2, sort_keys=True)}\n") except OSError as e: logger.warning(e) sys.exit(1) diff --git a/tools/generate-integration-docs-screenshot b/tools/generate-integration-docs-screenshot index d64af84c96..0b28d3c122 100755 --- a/tools/generate-integration-docs-screenshot +++ b/tools/generate-integration-docs-screenshot @@ -47,9 +47,9 @@ from zerver.lib.storage import static_path def create_integration_bot(integration: WebhookIntegration, bot_name: Optional[str]=None) -> UserProfile: realm = get_realm('zulip') owner = get_user_by_delivery_email("iago@zulip.com", realm) - bot_email = "{}-bot@example.com".format(integration.name) + bot_email = f"{integration.name}-bot@example.com" if bot_name is None: - bot_name = "{} Bot".format(integration.name.capitalize()) + bot_name = f"{integration.name.capitalize()} Bot" try: bot = UserProfile.objects.get(email=bot_email) except UserProfile.DoesNotExist: @@ -123,13 +123,13 @@ def send_bot_payload_message(bot: UserProfile, integration: WebhookIntegration, if config.custom_headers: headers.update(config.custom_headers) if config.use_basic_auth: - credentials = base64.b64encode('{}:{}'.format(bot.email, bot.api_key).encode('utf8')).decode('utf8') - auth = 'basic {}'.format(credentials) + credentials = base64.b64encode(f'{bot.email}:{bot.api_key}'.encode('utf8')).decode('utf8') + auth = f'basic {credentials}' headers.update(dict(Authorization=auth)) assert isinstance(bot.bot_owner, UserProfile) stream = integration.stream_name or 'devel' - url = "{}/{}".format(bot.bot_owner.realm.uri, integration.url) + url = f"{bot.bot_owner.realm.uri}/{integration.url}" params = {'api_key': bot.api_key, 'stream': stream} if config.extra_params: params.update(config.extra_params) @@ -148,7 +148,7 @@ def send_bot_payload_message(bot: UserProfile, integration: WebhookIntegration, else: extra_args = {'json': data} - url = '{}?{}'.format(url, urlencode(params)) + url = f'{url}?{urlencode(params)}' try: response = requests.post(url=url, headers=headers, **extra_args) @@ -161,13 +161,13 @@ def send_bot_payload_message(bot: UserProfile, integration: WebhookIntegration, print('Failed to trigger webhook') return False else: - print('Triggered {} webhook'.format(integration.name)) + print(f'Triggered {integration.name} webhook') return True def capture_last_message_screenshot(bot: UserProfile, image_path: str) -> None: message = Message.objects.filter(sender=bot).last() if message is None: - print('No message found for {}'.format(bot.full_name)) + print(f'No message found for {bot.full_name}') return message_id = str(message.id) screenshot_script = os.path.join(TOOLS_DIR, 'message-screenshot.js') diff --git a/tools/i18n/process-mobile-i18n b/tools/i18n/process-mobile-i18n index d4764f2ae7..e8be13254d 100755 --- a/tools/i18n/process-mobile-i18n +++ b/tools/i18n/process-mobile-i18n @@ -6,7 +6,7 @@ from subprocess import check_output from typing import Dict, List def get_json_filename(locale: str) -> str: - return "locale/{}/mobile.json".format(locale) + return f"locale/{locale}/mobile.json" def get_locales() -> List[str]: output = check_output(['git', 'ls-files', 'locale']) diff --git a/tools/lib/capitalization.py b/tools/lib/capitalization.py index 3e078495db..49aaba7db8 100644 --- a/tools/lib/capitalization.py +++ b/tools/lib/capitalization.py @@ -167,7 +167,7 @@ COMPILED_IGNORED_PHRASES = [ ] SPLIT_BOUNDARY = '?.!' # Used to split string into sentences. -SPLIT_BOUNDARY_REGEX = re.compile(r'[{}]'.format(SPLIT_BOUNDARY)) +SPLIT_BOUNDARY_REGEX = re.compile(fr'[{SPLIT_BOUNDARY}]') # Regexes which check capitalization in sentences. DISALLOWED_REGEXES = [re.compile(regex) for regex in [ diff --git a/tools/lib/gitlint-rules.py b/tools/lib/gitlint-rules.py index 3934cd2e3a..b909de126a 100644 --- a/tools/lib/gitlint-rules.py +++ b/tools/lib/gitlint-rules.py @@ -98,7 +98,7 @@ def head_binary_search(key: Text, words: List[str]) -> str: while True: if lower > upper: # Should not happen - raise Exception("Cannot find imperative mood of {}".format(key)) + raise Exception(f"Cannot find imperative mood of {key}") mid = (lower + upper) // 2 imperative_form = words[mid] @@ -156,7 +156,7 @@ class TitleMatchRegexAllowException(LineRule): regex = self.options['regex'].value pattern = re.compile(regex, re.UNICODE) if not pattern.search(title) and not title.startswith("Revert \""): - violation_msg = "Title does not match regex ({})".format(regex) + violation_msg = f"Title does not match regex ({regex})" return [RuleViolation(self.id, violation_msg, title)] return [] diff --git a/tools/linter_lib/custom_check.py b/tools/linter_lib/custom_check.py index 69ee1d73e7..52c42467f2 100644 --- a/tools/linter_lib/custom_check.py +++ b/tools/linter_lib/custom_check.py @@ -11,15 +11,15 @@ from zulint.custom_rules import Rule, RuleList # 'include_only': 'set([, ...])' - includes only those files where is a substring of the filepath. PYDELIMS = r'''"'()\[\]{}#\\''' -PYREG = r"[^{}]".format(PYDELIMS) +PYREG = fr"[^{PYDELIMS}]" PYSQ = r'"(?:[^"\\]|\\.)*"' PYDQ = r"'(?:[^'\\]|\\.)*'" PYLEFT = r"[(\[{]" PYRIGHT = r"[)\]}]" PYCODE = PYREG for depth in range(5): - PYGROUP = r"""(?:{}|{}|{}{}*{})""".format(PYSQ, PYDQ, PYLEFT, PYCODE, PYRIGHT) - PYCODE = r"""(?:{}|{})""".format(PYREG, PYGROUP) + PYGROUP = fr"""(?:{PYSQ}|{PYDQ}|{PYLEFT}{PYCODE}*{PYRIGHT})""" + PYCODE = fr"""(?:{PYREG}|{PYGROUP})""" FILES_WITH_LEGACY_SUBJECT = { # This basically requires a big DB migration: @@ -305,7 +305,7 @@ python_rules = RuleList( {'pattern': r'''\WJsonableError\(["'].+\)''', 'exclude': {'zerver/tests', 'zerver/views/development/'}, 'description': 'Argument to JsonableError should be a literal string enclosed by _()'}, - {'pattern': r"""\b_\((?:\s|{}|{})*[^\s'")]""".format(PYSQ, PYDQ), + {'pattern': fr"""\b_\((?:\s|{PYSQ}|{PYDQ})*[^\s'")]""", 'description': 'Called _() on a computed string', 'exclude_line': {('zerver/lib/i18n.py', 'result = _(string)')}, 'good_lines': ["return json_error(_('No presence data for %s') % (target.email,))"], diff --git a/tools/setup/emoji/build_emoji b/tools/setup/emoji/build_emoji index 9bcc10f831..4e78c55b69 100755 --- a/tools/setup/emoji/build_emoji +++ b/tools/setup/emoji/build_emoji @@ -91,7 +91,7 @@ def main() -> None: with open(success_stamp, 'w') as f: f.close() - print("build_emoji: Using cached emojis from {}".format(source_emoji_dump)) + print(f"build_emoji: Using cached emojis from {source_emoji_dump}") if os.path.lexists(TARGET_EMOJI_DUMP): os.remove(TARGET_EMOJI_DUMP) os.symlink(source_emoji_dump, TARGET_EMOJI_DUMP) @@ -300,13 +300,13 @@ def setup_old_emoji_farm(cache_path: str, for name, codepoint in emoji_map.items(): mapped_codepoint = REMAPPED_EMOJIS.get(codepoint, codepoint) - image_file_path = os.path.join(google_emoji_cache_path, '{}.png'.format(mapped_codepoint)) - symlink_path = os.path.join(emoji_cache_path, '{}.png'.format(name)) + image_file_path = os.path.join(google_emoji_cache_path, f'{mapped_codepoint}.png') + symlink_path = os.path.join(emoji_cache_path, f'{name}.png') os.symlink(image_file_path, symlink_path) try: # `emoji_map` contains duplicate entries for the same codepoint with different # names. So creation of symlink for .png may throw `FileExistsError`. - unicode_symlink_path = os.path.join(unicode_emoji_cache_path, '{}.png'.format(codepoint)) + unicode_symlink_path = os.path.join(unicode_emoji_cache_path, f'{codepoint}.png') os.symlink(image_file_path, unicode_symlink_path) except FileExistsError: pass diff --git a/tools/test-backend b/tools/test-backend index 7bb90471dd..9e8bce0574 100755 --- a/tools/test-backend +++ b/tools/test-backend @@ -169,7 +169,7 @@ class ZulipInternetBlockedError(Exception): "More details and advice are available here:" "https://zulip.readthedocs.io/en/latest/testing/testing.html#internet-access-inside-test-suites" ) - msg = "{}\nResponses library error message: {}".format(zulip_msg, original_msg) + msg = f"{zulip_msg}\nResponses library error message: {original_msg}" super().__init__(msg) def main() -> None: @@ -405,7 +405,7 @@ def main() -> None: missed_count = len(templates_not_rendered) print("\nError: %s templates have no tests!" % (missed_count,)) for template in templates_not_rendered: - print(' {}'.format(template)) + print(f' {template}') print("See zerver/tests/test_templates.py for the exclude list.") failures = True @@ -452,11 +452,11 @@ def main() -> None: prof.disable() with tempfile.NamedTemporaryFile(prefix='profile.data.', delete=False) as stats_file: prof.dump_stats(stats_file.name) - print("Profile data saved to {}".format(stats_file.name)) - print("You can visualize it using e.g. `snakeviz {}`".format(shlex.quote(stats_file.name))) + print(f"Profile data saved to {stats_file.name}") + print(f"You can visualize it using e.g. `snakeviz {shlex.quote(stats_file.name)}`") print("Note: If you are using vagrant for development environment you will need to do:") print("1.) `vagrant ssh -- -L 8080:127.0.0.1:8080`") - print("2.) `snakeviz -s {}`".format(shlex.quote(stats_file.name))) + print(f"2.) `snakeviz -s {shlex.quote(stats_file.name)}`") if options.report_slow_tests: from zerver.lib.test_runner import report_slow_tests diff --git a/tools/test-js-with-node b/tools/test-js-with-node index 3f698e23ab..2320665135 100755 --- a/tools/test-js-with-node +++ b/tools/test-js-with-node @@ -310,7 +310,7 @@ def enforce_proper_coverage(coverage_json: Any) -> bool: line_mapping = coverage_json[path]['statementMap'] if check_line_coverage(relative_path, line_coverage, line_mapping, log=False): coverage_not_enforced = True - print_error("{} unexpectedly has 100% line coverage.".format(relative_path)) + print_error(f"{relative_path} unexpectedly has 100% line coverage.") if coverage_not_enforced: print() @@ -332,7 +332,7 @@ if options.coverage and ret == 0: print() if ret == 0: if options.coverage: - reports_location = 'http://{}/node-coverage/index.html'.format(get_dev_host()) + reports_location = f'http://{get_dev_host()}/node-coverage/index.html' print('View coverage reports at ' + CYAN + reports_location + ENDC) print(GREEN + "Test(s) passed. SUCCESS!" + ENDC) diff --git a/tools/test-queue-worker-reload b/tools/test-queue-worker-reload index 590c935f8c..152edf202e 100755 --- a/tools/test-queue-worker-reload +++ b/tools/test-queue-worker-reload @@ -56,7 +56,7 @@ def check_worker_launch(run_dev: "subprocess.Popen[str]") -> bool: if __name__ == '__main__': print('\nStarting Development Server') - args = ["{}/run-dev.py".format(TOOLS_DIR)] + args = [f"{TOOLS_DIR}/run-dev.py"] run_dev = subprocess.Popen( args, bufsize=1, # line buffered diff --git a/tools/test-run-dev b/tools/test-run-dev index a8759badb3..9835c27021 100755 --- a/tools/test-run-dev +++ b/tools/test-run-dev @@ -19,7 +19,7 @@ def start_server(logfile_name: str) -> Tuple[bool, str]: with open(logfile_name, 'rb', buffering=0) as logfile: for i in range(200): time.sleep(0.5) - print("{}. Polling run-dev...".format(i)) + print(f"{i}. Polling run-dev...") new_data = logfile.read().decode() if new_data: datalog.append(new_data) diff --git a/tools/tests/test_zulint_custom_rules.py b/tools/tests/test_zulint_custom_rules.py index 86d26eb3ad..ce11d9ea7d 100644 --- a/tools/tests/test_zulint_custom_rules.py +++ b/tools/tests/test_zulint_custom_rules.py @@ -23,18 +23,18 @@ class TestRuleList(TestCase): for path in rule.get('exclude', {}): abs_path = os.path.abspath(os.path.join(ROOT_DIR, path)) self.assertTrue(os.path.exists(abs_path), - "'{}' is neither an existing file, nor a directory. {}".format(path, CHECK_MESSAGE)) + f"'{path}' is neither an existing file, nor a directory. {CHECK_MESSAGE}") for line_tuple in rule.get('exclude_line', {}): path = line_tuple[0] abs_path = os.path.abspath(os.path.join(ROOT_DIR, path)) self.assertTrue(os.path.isfile(abs_path), - "The file '{}' doesn't exist. {}".format(path, CHECK_MESSAGE)) + f"The file '{path}' doesn't exist. {CHECK_MESSAGE}") for path in rule.get('include_only', {}): if not os.path.splitext(path)[1]: self.assertTrue(path.endswith('/'), - "The path '{}' should end with '/'. {}".format(path, CHECK_MESSAGE)) + f"The path '{path}' should end with '/'. {CHECK_MESSAGE}") def test_rule_patterns(self) -> None: """Verifies that the search regex specified in a custom rule actually matches @@ -45,7 +45,7 @@ class TestRuleList(TestCase): # create=True is superfluous when mocking built-ins in Python >= 3.5 with patch('builtins.open', return_value=StringIO(line + '\n\n'), create=True, autospec=True): self.assertFalse(RuleList([], [rule]).custom_check_file('foo.bar', 'baz', ''), - "The pattern '{}' matched the line '{}' while it shouldn't.".format(pattern, line)) + f"The pattern '{pattern}' matched the line '{line}' while it shouldn't.") for line in rule.get('bad_lines', []): # create=True is superfluous when mocking built-ins in Python >= 3.5 @@ -53,4 +53,4 @@ class TestRuleList(TestCase): return_value=StringIO(line + '\n\n'), create=True, autospec=True), patch('builtins.print'): filename = list(rule.get('include_only', {'foo.bar'}))[0] self.assertTrue(RuleList([], [rule]).custom_check_file(filename, 'baz', ''), - "The pattern '{}' didn't match the line '{}' while it should.".format(pattern, line)) + f"The pattern '{pattern}' didn't match the line '{line}' while it should.") diff --git a/tools/update-zuliprc-api-field b/tools/update-zuliprc-api-field index b75630bc5a..dfde686911 100755 --- a/tools/update-zuliprc-api-field +++ b/tools/update-zuliprc-api-field @@ -72,4 +72,4 @@ for zuliprc_path in zuliprc_paths_list: else: result = 'SUCCESS' reason = 'API key for user %s is already consistent' % (email,) - print('{}: {}: {}'.format(zuliprc_path, result, reason)) + print(f'{zuliprc_path}: {result}: {reason}') diff --git a/zerver/data_import/hipchat.py b/zerver/data_import/hipchat.py index 2c90d7301e..61965a12f3 100755 --- a/zerver/data_import/hipchat.py +++ b/zerver/data_import/hipchat.py @@ -119,12 +119,12 @@ def convert_user_data(user_handler: UserHandler, if role == UserProfile.ROLE_GUEST: # Hipchat guest users don't have emails, so # we just fake them. - email = 'guest-{id}@example.com'.format(id=id) + email = f'guest-{id}@example.com' delivery_email = email else: # Hipchat sometimes doesn't export an email for deactivated users. assert not is_active - email = delivery_email = "deactivated-{id}@example.com".format(id=id) + email = delivery_email = f"deactivated-{id}@example.com" # unmapped fields: # title - Developer, Project Manager, etc. diff --git a/zerver/data_import/hipchat_user.py b/zerver/data_import/hipchat_user.py index 92196a0f88..10b3950dee 100644 --- a/zerver/data_import/hipchat_user.py +++ b/zerver/data_import/hipchat_user.py @@ -45,7 +45,7 @@ class UserHandler: user_id = self._new_mirror_user_id() short_name = name full_name = name - email = 'mirror-{user_id}@example.com'.format(user_id=user_id) + email = f'mirror-{user_id}@example.com' delivery_email = email avatar_source = 'G' date_joined = int(timezone_now().timestamp()) diff --git a/zerver/data_import/slack.py b/zerver/data_import/slack.py index 749c47b3ad..ee3b9ab3a7 100755 --- a/zerver/data_import/slack.py +++ b/zerver/data_import/slack.py @@ -1112,7 +1112,7 @@ def log_token_warning(token: str) -> None: def get_slack_api_data(slack_api_url: str, get_param: str, **kwargs: Any) -> Any: if not kwargs.get("token"): raise AssertionError("Slack token missing in kwargs") - data = requests.get("{}?{}".format(slack_api_url, urlencode(kwargs))) + data = requests.get(f"{slack_api_url}?{urlencode(kwargs)}") if data.status_code == requests.codes.ok: result = data.json() diff --git a/zerver/decorator.py b/zerver/decorator.py index 8a7d01e563..436a398f88 100644 --- a/zerver/decorator.py +++ b/zerver/decorator.py @@ -305,7 +305,7 @@ body: def full_webhook_client_name(raw_client_name: Optional[str]=None) -> Optional[str]: if raw_client_name is None: return None - return "Zulip{}Webhook".format(raw_client_name) + return f"Zulip{raw_client_name}Webhook" # Use this for webhook views that don't get an email passed in. def api_key_only_webhook_view( diff --git a/zerver/forms.py b/zerver/forms.py index 5d264536b3..617dcea6ca 100644 --- a/zerver/forms.py +++ b/zerver/forms.py @@ -228,7 +228,7 @@ def generate_password_reset_url(user_profile: UserProfile, uid = urlsafe_base64_encode(force_bytes(user_profile.id)) endpoint = reverse('django.contrib.auth.views.password_reset_confirm', kwargs=dict(uidb64=uid, token=token)) - return "{}{}".format(user_profile.realm.uri, endpoint) + return f"{user_profile.realm.uri}{endpoint}" class ZulipPasswordResetForm(PasswordResetForm): def save(self, @@ -319,7 +319,7 @@ class RateLimitedPasswordResetByEmail(RateLimitedObject): super().__init__() def key(self) -> str: - return "{}:{}".format(type(self).__name__, self.email) + return f"{type(self).__name__}:{self.email}" def rules(self) -> List[Tuple[int, int]]: return settings.RATE_LIMITING_RULES['password_reset_form_by_email'] diff --git a/zerver/lib/actions.py b/zerver/lib/actions.py index 682ad84385..dd097e65c0 100644 --- a/zerver/lib/actions.py +++ b/zerver/lib/actions.py @@ -754,8 +754,8 @@ def do_scrub_realm(realm: Realm) -> None: for user in users: do_delete_messages_by_sender(user) do_delete_avatar_image(user) - user.full_name = "Scrubbed {}".format(generate_key()[:15]) - scrubbed_email = "scrubbed-{}@{}".format(generate_key()[:15], realm.host) + user.full_name = f"Scrubbed {generate_key()[:15]}" + scrubbed_email = f"scrubbed-{generate_key()[:15]}@{realm.host}" user.email = scrubbed_email user.delivery_email = scrubbed_email user.save(update_fields=["full_name", "email", "delivery_email"]) diff --git a/zerver/lib/bot_config.py b/zerver/lib/bot_config.py index 756ea28f1b..caf6cd2059 100644 --- a/zerver/lib/bot_config.py +++ b/zerver/lib/bot_config.py @@ -59,10 +59,10 @@ def set_bot_config(bot_profile: UserProfile, key: str, value: str) -> None: obj.save() def load_bot_config_template(bot: str) -> Dict[str, str]: - bot_module_name = 'zulip_bots.bots.{}'.format(bot) + bot_module_name = f'zulip_bots.bots.{bot}' bot_module = importlib.import_module(bot_module_name) bot_module_path = os.path.dirname(bot_module.__file__) - config_path = os.path.join(bot_module_path, '{}.conf'.format(bot)) + config_path = os.path.join(bot_module_path, f'{bot}.conf') if os.path.isfile(config_path): config = configparser.ConfigParser() with open(config_path) as conf: diff --git a/zerver/lib/bot_storage.py b/zerver/lib/bot_storage.py index 93f2543865..ba3a9b1af3 100644 --- a/zerver/lib/bot_storage.py +++ b/zerver/lib/bot_storage.py @@ -31,9 +31,9 @@ def set_bot_storage(bot_profile: UserProfile, entries: List[Tuple[str, str]]) -> storage_size_difference = 0 for key, value in entries: if not isinstance(key, str): - raise StateError("Key type is {}, but should be str.".format(type(key))) + raise StateError(f"Key type is {type(key)}, but should be str.") if not isinstance(value, str): - raise StateError("Value type is {}, but should be str.".format(type(value))) + raise StateError(f"Value type is {type(value)}, but should be str.") storage_size_difference += (len(key) + len(value)) - get_bot_storage_size(bot_profile, key) new_storage_size = get_bot_storage_size(bot_profile) + storage_size_difference if new_storage_size > storage_size_limit: diff --git a/zerver/lib/bugdown/__init__.py b/zerver/lib/bugdown/__init__.py index 4682f69266..bac604ae30 100644 --- a/zerver/lib/bugdown/__init__.py +++ b/zerver/lib/bugdown/__init__.py @@ -769,7 +769,7 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor): def youtube_title(self, extracted_data: Dict[str, Any]) -> Optional[str]: title = extracted_data.get("title") if title is not None: - return "YouTube - {}".format(title) + return f"YouTube - {title}" return None def youtube_image(self, url: str) -> Optional[str]: @@ -796,7 +796,7 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor): def vimeo_title(self, extracted_data: Dict[str, Any]) -> Optional[str]: title = extracted_data.get("title") if title is not None: - return "Vimeo - {}".format(title) + return f"Vimeo - {title}" return None def twitter_text(self, text: str, @@ -1201,7 +1201,7 @@ class Avatar(markdown.inlinepatterns.Pattern): profile_id = user_dict['id'] img.set('class', 'message_body_gravatar') - img.set('src', '/avatar/{}?s=30'.format(profile_id or email)) + img.set('src', f'/avatar/{profile_id or email}?s=30') img.set('title', email) img.set('alt', email) return img @@ -1637,7 +1637,7 @@ class UserMentionPattern(markdown.inlinepatterns.Pattern): el.set('class', 'user-mention silent') else: el.set('class', 'user-mention') - text = "@{}".format(text) + text = f"@{text}" el.text = markdown.util.AtomicString(text) return el return None @@ -1691,8 +1691,8 @@ class StreamPattern(CompiledPattern): # provide more clarity to API clients. # Also do the same for StreamTopicPattern. stream_url = encode_stream(stream['id'], name) - el.set('href', '/#narrow/stream/{stream_url}'.format(stream_url=stream_url)) - text = '#{stream_name}'.format(stream_name=name) + el.set('href', f'/#narrow/stream/{stream_url}') + text = f'#{name}' el.text = markdown.util.AtomicString(text) return el return None @@ -1721,7 +1721,7 @@ class StreamTopicPattern(CompiledPattern): link = '/#narrow/stream/{stream_url}/topic/{topic_url}'.format(stream_url=stream_url, topic_url=topic_url) el.set('href', link) - text = '#{stream_name} > {topic_name}'.format(stream_name=stream_name, topic_name=topic_name) + text = f'#{stream_name} > {topic_name}' el.text = markdown.util.AtomicString(text) return el return None diff --git a/zerver/lib/bugdown/api_arguments_table_generator.py b/zerver/lib/bugdown/api_arguments_table_generator.py index d08cb5ab68..6810901116 100644 --- a/zerver/lib/bugdown/api_arguments_table_generator.py +++ b/zerver/lib/bugdown/api_arguments_table_generator.py @@ -113,7 +113,7 @@ class APIArgumentsTablePreprocessor(Preprocessor): default = argument.get('schema', {}).get('default') if default is not None: - description += '\nDefaults to `{}`.'.format(json.dumps(default)) + description += f'\nDefaults to `{json.dumps(default)}`.' # TODO: OpenAPI allows indicating where the argument goes # (path, querystring, form data...). We should document this detail. diff --git a/zerver/lib/bugdown/include.py b/zerver/lib/bugdown/include.py index 7dd79a1e73..1743428e85 100644 --- a/zerver/lib/bugdown/include.py +++ b/zerver/lib/bugdown/include.py @@ -45,7 +45,7 @@ class IncludeCustomPreprocessor(IncludePreprocessor): with open(filename, encoding=self.encoding) as r: text = r.readlines() except Exception as e: - print('Warning: could not find file {}. Error: {}'.format(filename, e)) + print(f'Warning: could not find file {filename}. Error: {e}') lines[loc] = INC_SYNTAX.sub('', line) raise InvalidMarkdownIncludeStatement(m.group(0).strip()) diff --git a/zerver/lib/bugdown/tabbed_sections.py b/zerver/lib/bugdown/tabbed_sections.py index 1b331f3587..bd38d4e9ed 100644 --- a/zerver/lib/bugdown/tabbed_sections.py +++ b/zerver/lib/bugdown/tabbed_sections.py @@ -124,7 +124,7 @@ class TabbedSectionsPreprocessor(Preprocessor): # Wrapping the content in two newlines is necessary here. # If we don't do this, the inner Markdown does not get # rendered properly. - content='\n{}\n'.format(content)) + content=f'\n{content}\n') tab_content_blocks.append(tab_content_block) return '\n'.join(tab_content_blocks) diff --git a/zerver/lib/cache.py b/zerver/lib/cache.py index d634363454..866ab5b617 100644 --- a/zerver/lib/cache.py +++ b/zerver/lib/cache.py @@ -216,7 +216,7 @@ def validate_cache_key(key: str) -> None: if not bool(re.fullmatch(r"([!-~])+", key)): raise InvalidCacheKeyException("Invalid characters in the cache key: " + key) if len(key) > MEMCACHED_MAX_KEY_LENGTH: - raise InvalidCacheKeyException("Cache key too long: {} Length: {}".format(key, len(key))) + raise InvalidCacheKeyException(f"Cache key too long: {key} Length: {len(key)}") def cache_set(key: str, val: Any, cache_name: Optional[str]=None, timeout: Optional[int]=None) -> None: final_key = KEY_PREFIX + key diff --git a/zerver/lib/debug.py b/zerver/lib/debug.py index d3790a2992..d248816db1 100644 --- a/zerver/lib/debug.py +++ b/zerver/lib/debug.py @@ -52,7 +52,7 @@ def tracemalloc_dump() -> None: gc.collect() tracemalloc.take_snapshot().dump(path) - with open('/proc/{}/stat'.format(os.getpid()), 'rb') as f: + with open(f'/proc/{os.getpid()}/stat', 'rb') as f: procstat = f.read().split() rss_pages = int(procstat[23]) logger.info("tracemalloc dump: tracing %s MiB (%s MiB peak), using %s MiB; rss %s MiB; dumped %s", @@ -79,7 +79,7 @@ def tracemalloc_listen() -> None: listener_pid = os.getpid() sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) - path = "/tmp/tracemalloc.{}".format(os.getpid()) + path = f"/tmp/tracemalloc.{os.getpid()}" sock.bind(path) thread = threading.Thread(target=lambda: tracemalloc_listen_sock(sock), daemon=True) diff --git a/zerver/lib/email_mirror.py b/zerver/lib/email_mirror.py index 02efb26c4d..d91ed3b310 100644 --- a/zerver/lib/email_mirror.py +++ b/zerver/lib/email_mirror.py @@ -43,15 +43,15 @@ def redact_email_address(error_message: str) -> str: # Annotate basic info about the address before scrubbing: if is_missed_message_address(email_address): redacted_message = error_message.replace(email_address, - "{} ".format(email_address)) + f"{email_address} ") else: try: target_stream_id = decode_stream_email_address(email_address)[0].id - annotated_address = "{}
".format(email_address, target_stream_id) + annotated_address = f"{email_address}
" redacted_message = error_message.replace(email_address, annotated_address) except ZulipEmailForwardError: redacted_message = error_message.replace(email_address, - "{} ".format(email_address)) + f"{email_address} ") # Scrub the address from the message, to the form XXXXX@example.com: string_to_scrub = address_match.groups()[0] @@ -429,7 +429,7 @@ def mirror_email_message(data: Dict[str, str]) -> Dict[str, str]: except ZulipEmailForwardError as e: return { "status": "error", - "msg": "5.1.1 Bad destination mailbox address: {}".format(e) + "msg": f"5.1.1 Bad destination mailbox address: {e}" } queue_json_publish( @@ -449,7 +449,7 @@ class RateLimitedRealmMirror(RateLimitedObject): super().__init__() def key(self) -> str: - return "{}:{}".format(type(self).__name__, self.realm.string_id) + return f"{type(self).__name__}:{self.realm.string_id}" def rules(self) -> List[Tuple[int, int]]: return settings.RATE_LIMITING_MIRROR_REALM_RULES diff --git a/zerver/lib/email_notifications.py b/zerver/lib/email_notifications.py index 9848f2df76..a83297191b 100644 --- a/zerver/lib/email_notifications.py +++ b/zerver/lib/email_notifications.py @@ -141,9 +141,9 @@ def build_message_list(user_profile: UserProfile, messages: List[Message]) -> Li return re.sub(r"\[(\S*)\]\((\S*)\)", r"\2", content) def append_sender_to_message(message_plain: str, message_html: str, sender: str) -> Tuple[str, str]: - message_plain = "{}: {}".format(sender, message_plain) + message_plain = f"{sender}: {message_plain}" message_soup = BeautifulSoup(message_html, "html.parser") - sender_name_soup = BeautifulSoup("{}: ".format(sender), "html.parser") + sender_name_soup = BeautifulSoup(f"{sender}: ", "html.parser") first_tag = message_soup.find() if first_tag.name == "p": first_tag.insert(0, sender_name_soup) diff --git a/zerver/lib/emoji.py b/zerver/lib/emoji.py index bd52810ff2..68e40604b0 100644 --- a/zerver/lib/emoji.py +++ b/zerver/lib/emoji.py @@ -30,9 +30,9 @@ EMOTICON_CONVERSIONS = emoji_codes["emoticon_conversions"] possible_emoticons = EMOTICON_CONVERSIONS.keys() possible_emoticon_regexes = (re.escape(emoticon) for emoticon in possible_emoticons) terminal_symbols = ',.;?!()\\[\\] "\'\\n\\t' # from composebox_typeahead.js -emoticon_regex = ('(?('.format(terminal_symbols) +emoticon_regex = (f'(?(' + ')|('.join(possible_emoticon_regexes) - + '))(?![^{}])'.format(terminal_symbols)) + + f'))(?![^{terminal_symbols}])') # Translates emoticons to their colon syntax, e.g. `:smiley:`. def translate_emoticons(text: str) -> str: diff --git a/zerver/lib/i18n.py b/zerver/lib/i18n.py index a1300ab6a9..70936593a0 100644 --- a/zerver/lib/i18n.py +++ b/zerver/lib/i18n.py @@ -92,5 +92,5 @@ def get_language_translation_data(language: str) -> Dict[str, str]: with open(path) as reader: return ujson.load(reader) except FileNotFoundError: - print('Translation for {} not found at {}'.format(language, path)) + print(f'Translation for {language} not found at {path}') return {} diff --git a/zerver/lib/import_realm.py b/zerver/lib/import_realm.py index 1d7a2066e1..72a1471f3b 100644 --- a/zerver/lib/import_realm.py +++ b/zerver/lib/import_realm.py @@ -333,7 +333,7 @@ def idseq(model_class: Any) -> str: return 'zerver_botuserstatedata_id_seq' elif model_class == BotConfigData: return 'zerver_botuserconfigdata_id_seq' - return '{}_id_seq'.format(model_class._meta.db_table) + return f'{model_class._meta.db_table}_id_seq' def allocate_ids(model_class: Any, count: int) -> List[int]: """ diff --git a/zerver/lib/integrations.py b/zerver/lib/integrations.py index 78f82f2d0b..90b9d98ebd 100644 --- a/zerver/lib/integrations.py +++ b/zerver/lib/integrations.py @@ -139,9 +139,9 @@ class BotIntegration(Integration): self.logo_url = staticfiles_storage.url(logo) if display_name is None: - display_name = "{} Bot".format(name.title()) # nocoverage + display_name = f"{name.title()} Bot" # nocoverage else: - display_name = "{} Bot".format(display_name) + display_name = f"{display_name} Bot" self.display_name = display_name if doc is None: @@ -235,7 +235,7 @@ class HubotIntegration(Integration): logo_alt: Optional[str]=None, git_url: Optional[str]=None, legacy: bool=False) -> None: if logo_alt is None: - logo_alt = "{} logo".format(name.title()) + logo_alt = f"{name.title()} logo" self.logo_alt = logo_alt if git_url is None: diff --git a/zerver/lib/logging_util.py b/zerver/lib/logging_util.py index 0018de4788..40d621857c 100644 --- a/zerver/lib/logging_util.py +++ b/zerver/lib/logging_util.py @@ -170,7 +170,7 @@ def find_log_origin(record: logging.LogRecord) -> str: # responsible for the request in the logs. from zerver.tornado.ioloop_logging import logging_data shard = logging_data.get('port', 'unknown') - logger_name = "{}:{}".format(logger_name, shard) + logger_name = f"{logger_name}:{shard}" return logger_name diff --git a/zerver/lib/rate_limiter.py b/zerver/lib/rate_limiter.py index 867bb4fd22..e980e46958 100644 --- a/zerver/lib/rate_limiter.py +++ b/zerver/lib/rate_limiter.py @@ -116,7 +116,7 @@ class RateLimitedUser(RateLimitedObject): super().__init__(backend=backend) def key(self) -> str: - return "{}:{}:{}".format(type(self).__name__, self.user.id, self.domain) + return f"{type(self).__name__}:{self.user.id}:{self.domain}" def rules(self) -> List[Tuple[int, int]]: # user.rate_limits are general limits, applicable to the domain 'api_by_user' @@ -294,7 +294,7 @@ class TornadoInMemoryRateLimiterBackend(RateLimiterBackend): class RedisRateLimiterBackend(RateLimiterBackend): @classmethod def get_keys(cls, entity_key: str) -> List[str]: - return ["{}ratelimit:{}:{}".format(KEY_PREFIX, entity_key, keytype) + return [f"{KEY_PREFIX}ratelimit:{entity_key}:{keytype}" for keytype in ['list', 'zset', 'block']] @classmethod diff --git a/zerver/lib/remote_server.py b/zerver/lib/remote_server.py index b69a1f885b..8ab76f29c9 100644 --- a/zerver/lib/remote_server.py +++ b/zerver/lib/remote_server.py @@ -60,7 +60,7 @@ def send_to_push_bouncer(method: str, except (requests.exceptions.Timeout, requests.exceptions.SSLError, requests.exceptions.ConnectionError) as e: raise PushNotificationBouncerRetryLaterError( - "{} while trying to connect to push notification bouncer".format(e.__class__.__name__)) + f"{e.__class__.__name__} while trying to connect to push notification bouncer") if res.status_code >= 500: # 500s should be resolved by the people who run the push diff --git a/zerver/lib/test_classes.py b/zerver/lib/test_classes.py index fae16ad36a..f8e4d28bda 100644 --- a/zerver/lib/test_classes.py +++ b/zerver/lib/test_classes.py @@ -329,7 +329,7 @@ class ZulipTestCase(TestCase): return None else: self.assert_json_success(result) - bot_email = '{}-bot@zulip.testserver'.format(short_name) + bot_email = f'{short_name}-bot@zulip.testserver' bot_profile = get_user(bot_email, user_profile.realm) return bot_profile @@ -865,7 +865,7 @@ class ZulipTestCase(TestCase): the attribute only for the specific test function that calls this method, and is isolated from other tests. """ - dn = "uid={username},ou=users,dc=zulip,dc=com".format(username=username) + dn = f"uid={username},ou=users,dc=zulip,dc=com" if binary: with open(attr_value, "rb") as f: # attr_value should be a path to the file with the binary data @@ -884,7 +884,7 @@ class ZulipTestCase(TestCase): return self.example_user_ldap_username_map[username] def ldap_password(self, uid: str) -> str: - return "{}_ldap_password".format(uid) + return f"{uid}_ldap_password" class WebhookTestCase(ZulipTestCase): """ @@ -955,15 +955,15 @@ class WebhookTestCase(ZulipTestCase): has_arguments = kwargs or args if has_arguments and url.find('?') == -1: - url = "{}?".format(url) # nocoverage + url = f"{url}?" # nocoverage else: - url = "{}&".format(url) + url = f"{url}&" for key, value in kwargs.items(): - url = "{}{}={}&".format(url, key, value) + url = f"{url}{key}={value}&" for arg in args: - url = "{}{}&".format(url, arg) + url = f"{url}{arg}&" return url[:-1] if has_arguments else url @@ -995,7 +995,7 @@ class MigrationsTestCase(ZulipTestCase): # nocoverage def setUp(self) -> None: assert self.migrate_from and self.migrate_to, \ - "TestCase '{}' must define migrate_from and migrate_to properties".format(type(self).__name__) + f"TestCase '{type(self).__name__}' must define migrate_from and migrate_to properties" migrate_from: List[Tuple[str, str]] = [(self.app, self.migrate_from)] migrate_to: List[Tuple[str, str]] = [(self.app, self.migrate_to)] executor = MigrationExecutor(connection) diff --git a/zerver/lib/test_fixtures.py b/zerver/lib/test_fixtures.py index 890022300f..192ed5aad2 100644 --- a/zerver/lib/test_fixtures.py +++ b/zerver/lib/test_fixtures.py @@ -345,7 +345,7 @@ def destroy_leaked_test_databases(expiry_time: int = 60 * 60) -> int: if round(time.time()) - os.path.getmtime(file) < expiry_time: with open(file) as f: for line in f: - databases_in_use.add('zulip_test_template_{}'.format(line).rstrip()) + databases_in_use.add(f'zulip_test_template_{line}'.rstrip()) else: # Any test-backend run older than expiry_time can be # cleaned up, both the database and the file listing its diff --git a/zerver/lib/test_runner.py b/zerver/lib/test_runner.py index edac98fc30..2c10c05113 100644 --- a/zerver/lib/test_runner.py +++ b/zerver/lib/test_runner.py @@ -43,12 +43,12 @@ random_id_range_start = str(random.randint(1, 10000000)) def get_database_id(worker_id: Optional[int]=None) -> str: if worker_id: - return "{}_{}".format(random_id_range_start, worker_id) + return f"{random_id_range_start}_{worker_id}" return random_id_range_start # The root directory for this run of the test suite. TEST_RUN_DIR = get_or_create_dev_uuid_var_path( - os.path.join('test-backend', 'run_{}'.format(get_database_id()))) + os.path.join('test-backend', f'run_{get_database_id()}')) _worker_id = 0 # Used to identify the worker process. @@ -165,7 +165,7 @@ class TextTestResult(runner.TextTestResult): def startTest(self, test: TestCase) -> None: TestResult.startTest(self, test) - self.stream.writeln("Running {}".format(full_test_name(test))) # type: ignore[attr-defined] # https://github.com/python/typeshed/issues/3139 + self.stream.writeln(f"Running {full_test_name(test)}") # type: ignore[attr-defined] # https://github.com/python/typeshed/issues/3139 self.stream.flush() # type: ignore[attr-defined] # https://github.com/python/typeshed/issues/3139 def addSuccess(self, *args: Any, **kwargs: Any) -> None: @@ -382,7 +382,7 @@ def check_import_error(test_name: str) -> None: def initialize_worker_path(worker_id: int) -> None: # Allow each test worker process to write to a unique directory # within `TEST_RUN_DIR`. - worker_path = os.path.join(TEST_RUN_DIR, 'worker_{}'.format(_worker_id)) + worker_path = os.path.join(TEST_RUN_DIR, f'worker_{_worker_id}') os.makedirs(worker_path, exist_ok=True) settings.TEST_WORKER_DIR = worker_path diff --git a/zerver/lib/users.py b/zerver/lib/users.py index c024093a4d..aba28539af 100644 --- a/zerver/lib/users.py +++ b/zerver/lib/users.py @@ -247,7 +247,7 @@ def validate_user_custom_profile_field(realm_id: int, field: CustomProfileField, value: Union[int, str, List[int]]) -> Optional[str]: validators = CustomProfileField.FIELD_VALIDATORS field_type = field.field_type - var_name = '{}'.format(field.name) + var_name = f'{field.name}' if field_type in validators: validator = validators[field_type] result = validator(var_name, value) diff --git a/zerver/lib/webhooks/git.py b/zerver/lib/webhooks/git.py index 6104b87532..28c85baf41 100644 --- a/zerver/lib/webhooks/git.py +++ b/zerver/lib/webhooks/git.py @@ -91,7 +91,7 @@ def get_push_commits_event_message(user_name: str, compare_url: Optional[str], committers_details = "{} ({})".format(*committers_items[0]) for name, number_of_commits in committers_items[1:-1]: - committers_details = "{}, {} ({})".format(committers_details, name, number_of_commits) + committers_details = f"{committers_details}, {name} ({number_of_commits})" if len(committers_items) > 1: committers_details = "{} and {} ({})".format(committers_details, *committers_items[-1]) @@ -140,7 +140,7 @@ def get_pull_request_event_message(user_name: str, action: str, url: str, number 'action': action, 'type': type, 'url': url, - 'id': ' #{}'.format(number) if number is not None else '', + 'id': f' #{number}' if number is not None else '', 'title': title, } @@ -162,19 +162,19 @@ def get_pull_request_event_message(user_name: str, action: str, url: str, number assignee_info = PULL_REQUEST_OR_ISSUE_ASSIGNEE_INFO_TEMPLATE.format( assignee=assignees_string) - main_message = "{} {}".format(main_message, assignee_info) + main_message = f"{main_message} {assignee_info}" elif assignee: assignee_info = PULL_REQUEST_OR_ISSUE_ASSIGNEE_INFO_TEMPLATE.format( assignee=assignee) - main_message = "{} {}".format(main_message, assignee_info) + main_message = f"{main_message} {assignee_info}" if target_branch and base_branch: branch_info = PULL_REQUEST_BRANCH_INFO_TEMPLATE.format( target=target_branch, base=base_branch ) - main_message = "{} {}".format(main_message, branch_info) + main_message = f"{main_message} {branch_info}" punctuation = ':' if message else '.' if (assignees or assignee or (target_branch and base_branch) or (title is None)): @@ -195,7 +195,7 @@ def get_setup_webhook_message(integration: str, user_name: Optional[str]=None) - content = SETUP_MESSAGE_TEMPLATE.format(integration=integration) if user_name: content += SETUP_MESSAGE_USER_PART.format(user_name=user_name) - content = "{}.".format(content) + content = f"{content}." return content def get_issue_event_message(user_name: str, @@ -234,7 +234,7 @@ def get_push_tag_event_message(user_name: str, ) if tag_name[-1] not in string.punctuation: - message = '{}.'.format(message) + message = f'{message}.' return message @@ -250,7 +250,7 @@ def get_commits_comment_action_message(user_name: str, url=commit_url ) punctuation = ':' if message else '.' - content = '{}{}'.format(content, punctuation) + content = f'{content}{punctuation}' if message: content += CONTENT_MESSAGE_TEMPLATE.format( message=message diff --git a/zerver/management/commands/compilemessages.py b/zerver/management/commands/compilemessages.py index 178491b297..e64dfb2e08 100644 --- a/zerver/management/commands/compilemessages.py +++ b/zerver/management/commands/compilemessages.py @@ -57,7 +57,7 @@ class Command(compilemessages.Command): return po_template.format(locale_path, locale) def get_json_filename(self, locale_path: str, locale: str) -> str: - return "{}/{}/translations.json".format(locale_path, locale) + return f"{locale_path}/{locale}/translations.json" def get_name_from_po_file(self, po_filename: str, locale: str) -> str: lang_name_re = re.compile(r'"Language-Team: (.*?) \(') @@ -67,7 +67,7 @@ class Command(compilemessages.Command): try: return result.group(1) except Exception: - print("Problem in parsing {}".format(po_filename)) + print(f"Problem in parsing {po_filename}") raise else: raise Exception("Unknown language %s" % (locale,)) @@ -85,8 +85,8 @@ class Command(compilemessages.Command): return locales def extract_language_options(self) -> None: - locale_path = "{}/locale".format(settings.DEPLOY_ROOT) - output_path = "{}/language_options.json".format(locale_path) + locale_path = f"{settings.DEPLOY_ROOT}/locale" + output_path = f"{locale_path}/language_options.json" data: Dict[str, List[Dict[str, Any]]] = {'languages': []} diff --git a/zerver/management/commands/export.py b/zerver/management/commands/export.py index 4f3ed462ba..7a0a4c0c95 100644 --- a/zerver/management/commands/export.py +++ b/zerver/management/commands/export.py @@ -164,9 +164,9 @@ class Command(ZulipBaseCommand): if reaction.user_profile.realm != realm: raise CommandError("Users from a different realm reacted to message. Aborting...") - print("\n\033[94mMessage content:\033[0m\n{}\n".format(message.content)) + print(f"\n\033[94mMessage content:\033[0m\n{message.content}\n") - print("\033[94mNumber of users that reacted outbox:\033[0m {}\n".format(len(reactions))) + print(f"\033[94mNumber of users that reacted outbox:\033[0m {len(reactions)}\n") # Allows us to trigger exports separately from command line argument parsing export_realm_wrapper(realm=realm, output_dir=output_dir, diff --git a/zerver/management/commands/makemessages.py b/zerver/management/commands/makemessages.py index d2f5d17337..3fa4040ba5 100644 --- a/zerver/management/commands/makemessages.py +++ b/zerver/management/commands/makemessages.py @@ -71,7 +71,7 @@ class Command(makemessages.Command): xgettext_options = makemessages.Command.xgettext_options for func, tag in tags: - xgettext_options += ['--keyword={}:1,"{}"'.format(func, tag)] + xgettext_options += [f'--keyword={func}:1,"{tag}"'] def add_arguments(self, parser: ArgumentParser) -> None: super().add_arguments(parser) @@ -241,7 +241,7 @@ class Command(makemessages.Command): def write_translation_strings(self, translation_strings: List[str]) -> None: for locale, output_path in zip(self.get_locales(), self.get_output_paths()): - self.stdout.write("[frontend] processing locale {}".format(locale)) + self.stdout.write(f"[frontend] processing locale {locale}") try: with open(output_path) as reader: old_strings = json.load(reader) diff --git a/zerver/management/commands/send_to_email_mirror.py b/zerver/management/commands/send_to_email_mirror.py index b2af8b2e90..414ebd88e0 100644 --- a/zerver/management/commands/send_to_email_mirror.py +++ b/zerver/management/commands/send_to_email_mirror.py @@ -89,7 +89,7 @@ Example: def _parse_email_fixture(self, fixture_path: str) -> Message: if not self._does_fixture_path_exist(fixture_path): - raise CommandError('Fixture {} does not exist'.format(fixture_path)) + raise CommandError(f'Fixture {fixture_path} does not exist') if fixture_path.endswith('.json'): message = self._parse_email_json_fixture(fixture_path) diff --git a/zerver/openapi/markdown_extension.py b/zerver/openapi/markdown_extension.py index 4da4ed33b3..646fe1b35d 100644 --- a/zerver/openapi/markdown_extension.py +++ b/zerver/openapi/markdown_extension.py @@ -153,7 +153,7 @@ def render_javascript_code_example(function: str, admin_config: Optional[bool]=F for line in snippet: result = re.search('const result.*=(.*);', line) if result: - line = " return{};".format(result.group(1)) + line = f" return{result.group(1)};" # Strip newlines code_example.append(line.rstrip()) code_example.append("}).then(console.log).catch(console.err);") @@ -167,7 +167,7 @@ def curl_method_arguments(endpoint: str, method: str, api_url: str) -> List[str]: # We also include the -sS verbosity arguments here. method = method.upper() - url = "{}/v1{}".format(api_url, endpoint) + url = f"{api_url}/v1{endpoint}" valid_methods = ["GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS"] if method == "GET": # Then we need to make sure that each -d option translates to becoming @@ -206,7 +206,7 @@ cURL example.""".format(endpoint, method, param_name) raise ValueError(msg) ordered_ex_val_str = json.dumps(example_value, sort_keys=True) if curl_argument: - return " --data-urlencode {}='{}'".format(param_name, ordered_ex_val_str) + return f" --data-urlencode {param_name}='{ordered_ex_val_str}'" return ordered_ex_val_str # nocoverage else: example_value = param.get("example", DEFAULT_EXAMPLE[param_type]) @@ -215,7 +215,7 @@ cURL example.""".format(endpoint, method, param_name) if jsonify: example_value = json.dumps(example_value) if curl_argument: - return " -d '{}={}'".format(param_name, example_value) + return f" -d '{param_name}={example_value}'" return example_value def generate_curl_example(endpoint: str, method: str, diff --git a/zerver/openapi/openapi.py b/zerver/openapi/openapi.py index 3e119bdf12..555835b321 100644 --- a/zerver/openapi/openapi.py +++ b/zerver/openapi/openapi.py @@ -185,7 +185,7 @@ def validate_object(content: Dict[str, Any], schema: Dict[str, Any]) -> None: # If the object is not opaque then continue statements # will be executed above and this will be skipped if expected_type is dict: - raise SchemaError('Opaque object "{}"'.format(key)) + raise SchemaError(f'Opaque object "{key}"') # Check that at least all the required keys are present if 'required' in schema: for req_key in schema['required']: diff --git a/zerver/openapi/python_examples.py b/zerver/openapi/python_examples.py index baf78f5cc8..b32bfa58c2 100644 --- a/zerver/openapi/python_examples.py +++ b/zerver/openapi/python_examples.py @@ -97,7 +97,7 @@ def test_authorization_errors_fatal(client: Client, nonadmin_client: Client) -> stream_id = client.get_stream_id('private_stream')['stream_id'] client.call_endpoint( - 'streams/{}'.format(stream_id), + f'streams/{stream_id}', method='PATCH', request={'is_private': True} ) @@ -945,7 +945,7 @@ def upload_custom_emoji(client: Client) -> None: with open(emoji_path, 'rb') as fp: emoji_name = 'my_custom_emoji' result = client.call_endpoint( - 'realm/emoji/{}'.format(emoji_name), + f'realm/emoji/{emoji_name}', method='POST', files=[fp] ) @@ -1064,8 +1064,8 @@ def test_against_fixture(result: Dict[str, Any], fixture: Dict[str, Any], check_ def assertEqual(key: str, result: Dict[str, Any], fixture: Dict[str, Any]) -> None: if result[key] != fixture[key]: - first = "{key} = {value}".format(key=key, value=result[key]) - second = "{key} = {value}".format(key=key, value=fixture[key]) + first = f"{key} = {result[key]}" + second = f"{key} = {fixture[key]}" raise AssertionError("Actual and expected outputs do not match; showing diff:\n" + mdiff.diff_strings(first, second)) else: @@ -1083,7 +1083,7 @@ def assertLength(result: Dict[str, Any], fixture: Dict[str, Any]) -> None: def assertIn(key: str, result: Dict[str, Any]) -> None: if key not in result.keys(): raise AssertionError( - "The actual output does not contain the the key `{key}`.".format(key=key) + f"The actual output does not contain the the key `{key}`." ) else: assert key in result diff --git a/zerver/openapi/test_curl_examples.py b/zerver/openapi/test_curl_examples.py index ccc02aa679..2fea31bbfb 100644 --- a/zerver/openapi/test_curl_examples.py +++ b/zerver/openapi/test_curl_examples.py @@ -11,7 +11,7 @@ from zerver.models import get_realm from zerver.openapi.curl_param_value_generators import REGISTERED_GENERATOR_FUNCTIONS, CALLED_GENERATOR_FUNCTIONS def test_generated_curl_examples_for_success(client: Client) -> None: - authentication_line = "{}:{}".format(client.email, client.api_key) + authentication_line = f"{client.email}:{client.api_key}" # A limited markdown engine that just processes the code example syntax. realm = get_realm("zulip") md_engine = markdown.Markdown(extensions=[markdown_extension.makeExtension( diff --git a/zerver/signals.py b/zerver/signals.py index f54c2d70e0..ddcf2c080b 100644 --- a/zerver/signals.py +++ b/zerver/signals.py @@ -87,7 +87,7 @@ def email_on_new_login(sender: Any, user: UserProfile, request: Any, **kwargs: A hhmm_string = local_time.strftime('%H:%M') else: hhmm_string = local_time.strftime('%I:%M%p') - context['login_time'] = local_time.strftime('%A, %B %d, %Y at {} %Z'.format(hhmm_string)) + context['login_time'] = local_time.strftime(f'%A, %B %d, %Y at {hhmm_string} %Z') context['device_ip'] = request.META.get('REMOTE_ADDR') or _("Unknown IP address") context['device_os'] = get_device_os(user_agent) or _("an unknown operating system") context['device_browser'] = get_device_browser(user_agent) or _("An unknown browser") diff --git a/zerver/tests/test_attachments.py b/zerver/tests/test_attachments.py index 0f89221c95..5fefdb9471 100644 --- a/zerver/tests/test_attachments.py +++ b/zerver/tests/test_attachments.py @@ -26,14 +26,14 @@ class AttachmentsTests(ZulipTestCase): user_profile = self.example_user('cordelia') self.login_user(user_profile) with mock.patch('zerver.lib.attachments.delete_message_image', side_effect=Exception()): - result = self.client_delete('/json/attachments/{id}'.format(id=self.attachment.id)) + result = self.client_delete(f'/json/attachments/{self.attachment.id}') self.assert_json_error(result, "An error occurred while deleting the attachment. Please try again later.") @mock.patch('zerver.lib.attachments.delete_message_image') def test_remove_attachment(self, ignored: Any) -> None: user_profile = self.example_user('cordelia') self.login_user(user_profile) - result = self.client_delete('/json/attachments/{id}'.format(id=self.attachment.id)) + result = self.client_delete(f'/json/attachments/{self.attachment.id}') self.assert_json_success(result) attachments = user_attachments(user_profile) self.assertEqual(attachments, []) @@ -48,7 +48,7 @@ class AttachmentsTests(ZulipTestCase): def test_remove_another_user(self) -> None: user_profile = self.example_user('iago') self.login_user(user_profile) - result = self.client_delete('/json/attachments/{id}'.format(id=self.attachment.id)) + result = self.client_delete(f'/json/attachments/{self.attachment.id}') self.assert_json_error(result, 'Invalid attachment') user_profile_to_remove = self.example_user('cordelia') attachments = user_attachments(user_profile_to_remove) @@ -59,5 +59,5 @@ class AttachmentsTests(ZulipTestCase): self.assert_json_error(result, 'Not logged in: API authentication or user session required', status_code=401) def test_delete_unauthenticated(self) -> None: - result = self.client_delete('/json/attachments/{id}'.format(id=self.attachment.id)) + result = self.client_delete(f'/json/attachments/{self.attachment.id}') self.assert_json_error(result, 'Not logged in: API authentication or user session required', status_code=401) diff --git a/zerver/tests/test_auth_backends.py b/zerver/tests/test_auth_backends.py index e738bdd68c..eef6f803e9 100644 --- a/zerver/tests/test_auth_backends.py +++ b/zerver/tests/test_auth_backends.py @@ -491,7 +491,7 @@ class RateLimitAuthenticationTests(ZulipTestCase): salt = generate_random_token(32) def _mock_key(self: RateLimitedAuthenticationByUsername) -> str: - return "{}:{}".format(salt, original_key_method(self)) + return f"{salt}:{original_key_method(self)}" def attempt_authentication(username: str, password: str) -> Optional[UserProfile]: request = HttpRequest() @@ -1291,7 +1291,7 @@ class SocialAuthBase(DesktopFlowTestingLib, ZulipTestCase): ldap_user_attr_map = {'full_name': 'cn'} account_data_dict = self.get_account_data_dict(email=email, name=name) - backend_path = 'zproject.backends.{}'.format(self.BACKEND_CLASS.__name__) + backend_path = f'zproject.backends.{self.BACKEND_CLASS.__name__}' with self.settings( POPULATE_PROFILE_VIA_LDAP=True, LDAP_APPEND_DOMAIN='zulip.com', @@ -1333,7 +1333,7 @@ class SocialAuthBase(DesktopFlowTestingLib, ZulipTestCase): ldap_user_attr_map = {'full_name': 'cn'} account_data_dict = self.get_account_data_dict(email=email, name=name) - backend_path = 'zproject.backends.{}'.format(self.BACKEND_CLASS.__name__) + backend_path = f'zproject.backends.{self.BACKEND_CLASS.__name__}' with self.settings( POPULATE_PROFILE_VIA_LDAP=True, LDAP_EMAIL_ATTR='mail', @@ -1503,7 +1503,7 @@ class SAMLAuthBackendTest(SocialAuthBase): self.assertTrue(saml_auth_enabled()) result = self.client_get("/saml/metadata.xml") self.assert_in_success_response( - ['entityID="{}"'.format(settings.SOCIAL_AUTH_SAML_SP_ENTITY_ID)], result + [f'entityID="{settings.SOCIAL_AUTH_SAML_SP_ENTITY_ID}"'], result ) def test_social_auth_complete(self) -> None: @@ -1737,17 +1737,17 @@ class SAMLAuthBackendTest(SocialAuthBase): def test_social_auth_saml_login_bad_idp_arg(self) -> None: for action in ['login', 'register']: - result = self.client_get('/accounts/{}/social/saml'.format(action)) + result = self.client_get(f'/accounts/{action}/social/saml') # Missing idp argument. self.assertEqual(result.status_code, 302) self.assertEqual(result.url, '/config-error/saml') - result = self.client_get('/accounts/{}/social/saml/nonexistent_idp'.format(action)) + result = self.client_get(f'/accounts/{action}/social/saml/nonexistent_idp') # No such IdP is configured. self.assertEqual(result.status_code, 302) self.assertEqual(result.url, '/config-error/saml') - result = self.client_get('/accounts/{}/social/saml/'.format(action)) + result = self.client_get(f'/accounts/{action}/social/saml/') # No matching url pattern. self.assertEqual(result.status_code, 404) @@ -4327,7 +4327,7 @@ class TestMaybeSendToRegistration(ZulipTestCase): result = self.client_get(result.url) self.assert_in_response('action="/accounts/register/"', result) - self.assert_in_response('value="{}" name="key"'.format(confirmation_key), result) + self.assert_in_response(f'value="{confirmation_key}" name="key"', result) def test_sso_only_when_preregistration_user_exists(self) -> None: rf = RequestFactory() diff --git a/zerver/tests/test_bots.py b/zerver/tests/test_bots.py index b66b8853c5..b8edc1327d 100644 --- a/zerver/tests/test_bots.py +++ b/zerver/tests/test_bots.py @@ -70,7 +70,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): def deactivate_bot(self) -> None: email = 'hambot-bot@zulip.testserver' - result = self.client_delete("/json/bots/{}".format(self.get_bot_user(email).id)) + result = self.client_delete(f"/json/bots/{self.get_bot_user(email).id}") self.assert_json_success(result) def test_add_bot_with_bad_username(self) -> None: @@ -541,7 +541,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): self.create_bot() self.assert_num_bots_equal(1) invalid_user_id = 1000 - result = self.client_delete("/json/bots/{}".format(invalid_user_id)) + result = self.client_delete(f"/json/bots/{invalid_user_id}") self.assert_json_error(result, 'No such bot') self.assert_num_bots_equal(1) @@ -591,7 +591,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): bot_email = result.json()['bots'][0]['username'] bot = get_user(bot_email, user.realm) self.login('iago') - result = self.client_delete("/json/bots/{}".format(bot.id)) + result = self.client_delete(f"/json/bots/{bot.id}") self.assert_json_error(result, 'No such bot') def test_bot_deactivation_attacks(self) -> None: @@ -610,7 +610,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): self.assert_json_error(result, 'No such bot') email = 'hambot-bot@zulip.testserver' - result = self.client_delete("/json/bots/{}".format(self.get_bot_user(email).id)) + result = self.client_delete(f"/json/bots/{self.get_bot_user(email).id}") self.assert_json_error(result, 'Insufficient permission') # But we don't actually deactivate the other person's bot. @@ -618,7 +618,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): self.assert_num_bots_equal(1) # Cannot deactivate a bot as a user - result = self.client_delete("/json/users/{}".format(self.get_bot_user(email).id)) + result = self.client_delete(f"/json/users/{self.get_bot_user(email).id}") self.assert_json_error(result, 'No such user') self.assert_num_bots_equal(1) @@ -632,13 +632,13 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): self.login('othello') email = 'hambot-bot@zulip.testserver' - result = self.client_post("/json/bots/{}/api_key/regenerate".format(self.get_bot_user(email).id)) + result = self.client_post(f"/json/bots/{self.get_bot_user(email).id}/api_key/regenerate") self.assert_json_error(result, 'Insufficient permission') bot_info = { 'full_name': 'Fred', } - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_error(result, 'Insufficient permission') def get_bot(self) -> Dict[str, Any]: @@ -652,7 +652,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): bot = self.get_bot() old_api_key = bot['api_key'] email = 'hambot-bot@zulip.testserver' - result = self.client_post('/json/bots/{}/api_key/regenerate'.format(self.get_bot_user(email).id)) + result = self.client_post(f'/json/bots/{self.get_bot_user(email).id}/api_key/regenerate') self.assert_json_success(result) new_api_key = result.json()['api_key'] self.assertNotEqual(old_api_key, new_api_key) @@ -662,7 +662,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): def test_update_api_key_for_invalid_user(self) -> None: self.login('hamlet') invalid_user_id = 1000 - result = self.client_post('/json/bots/{}/api_key/regenerate'.format(invalid_user_id)) + result = self.client_post(f'/json/bots/{invalid_user_id}/api_key/regenerate') self.assert_json_error(result, 'No such bot') def test_add_bot_with_bot_type_default(self) -> None: @@ -810,7 +810,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): 'full_name': 'Fred', } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_success(result) self.assertEqual('Fred', result.json()['full_name']) @@ -832,7 +832,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): bot_email = 'hambot-bot@zulip.testserver' bot = self.get_bot_user(bot_email) - url = "/json/bots/{}".format(bot.id) + url = f"/json/bots/{bot.id}" # It doesn't matter whether a name is taken by a human # or a bot, we can't use it. @@ -890,7 +890,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): 'bot_owner_id': othello.id, } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_success(result) # Test bot's owner has been changed successfully. @@ -912,7 +912,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): bot_info = { 'bot_owner_id': bad_bot_owner_id, } - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_error(result, "Failed to change owner, no such user") profile = get_user('hambot-bot@zulip.testserver', get_realm('zulip')) self.assertEqual(profile.bot_owner, self.example_user("hamlet")) @@ -931,7 +931,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_error(result, "Failed to change owner, user is deactivated") profile = self.get_bot_user(email) self.assertEqual(profile.bot_owner, self.example_user("hamlet")) @@ -946,7 +946,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_error(result, "Failed to change owner, no such user") profile = self.get_bot_user(email) self.assertEqual(profile.bot_owner, self.example_user("hamlet")) @@ -961,7 +961,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) # Check that we're still the owner self.assert_json_success(result) @@ -984,7 +984,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): 'bot_owner_id': self.get_bot_user('hamelbot-bot@zulip.testserver').id, } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_error(result, "Failed to change owner, bots can't own other bots") profile = get_user(email, get_realm('zulip')) self.assertEqual(profile.bot_owner, self.example_user("hamlet")) @@ -1008,7 +1008,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): with get_test_image_file('img.png') as fp1, \ get_test_image_file('img.gif') as fp2: result = self.client_patch_multipart( - '/json/bots/{}'.format(self.get_bot_user(email).id), + f'/json/bots/{self.get_bot_user(email).id}', dict(file1=fp1, file2=fp2)) self.assert_json_error(result, 'You may only upload one file at a time') @@ -1018,7 +1018,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): # HAPPY PATH with get_test_image_file('img.png') as fp: result = self.client_patch_multipart( - '/json/bots/{}'.format(self.get_bot_user(email).id), + f'/json/bots/{self.get_bot_user(email).id}', dict(file=fp)) profile = get_user(bot_email, bot_realm) self.assertEqual(profile.avatar_version, 2) @@ -1043,7 +1043,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): 'default_sending_stream': 'Denmark', } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_success(result) self.assertEqual('Denmark', result.json()['default_sending_stream']) @@ -1063,7 +1063,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): 'default_sending_stream': 'Rome', } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_success(result) self.assertEqual('Rome', result.json()['default_sending_stream']) @@ -1083,7 +1083,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): 'default_sending_stream': '', } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_success(result) bot_email = "hambot-bot@zulip.testserver" @@ -1111,7 +1111,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): 'default_sending_stream': 'Denmark', } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_success(result) self.assertEqual('Denmark', result.json()['default_sending_stream']) @@ -1137,7 +1137,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): 'default_sending_stream': 'Denmark', } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_error(result, "Invalid stream name 'Denmark'") def test_patch_bot_to_stream_not_found(self) -> None: @@ -1152,7 +1152,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): 'default_sending_stream': 'missing', } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_error(result, "Invalid stream name 'missing'") def test_patch_bot_events_register_stream(self) -> None: @@ -1167,7 +1167,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): email = 'hambot-bot@zulip.testserver' bot_user = self.get_bot_user(email) - url = "/json/bots/{}".format(bot_user.id) + url = f"/json/bots/{bot_user.id}" # Successfully give the bot a default stream. stream_name = 'Denmark' @@ -1197,7 +1197,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): self.assert_json_success(result) # Make sure the bot cannot create their own default stream. - url = "/api/v1/bots/{}".format(bot_user.id) + url = f"/api/v1/bots/{bot_user.id}" result = self.api_patch(bot_user, url, bot_info) self.assert_json_error_contains(result, 'endpoint does not accept') @@ -1217,7 +1217,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): 'default_events_register_stream': 'Denmark', } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_success(result) self.assertEqual('Denmark', result.json()['default_events_register_stream']) @@ -1242,7 +1242,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): 'default_events_register_stream': 'Denmark', } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_error(result, "Invalid stream name 'Denmark'") def test_patch_bot_events_register_stream_none(self) -> None: @@ -1257,7 +1257,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): 'default_events_register_stream': '', } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_success(result) bot_email = "hambot-bot@zulip.testserver" @@ -1280,7 +1280,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): 'default_events_register_stream': 'missing', } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_error(result, "Invalid stream name 'missing'") def test_patch_bot_default_all_public_streams_true(self) -> None: @@ -1295,7 +1295,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): 'default_all_public_streams': ujson.dumps(True), } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_success(result) self.assertEqual(result.json()['default_all_public_streams'], True) @@ -1315,7 +1315,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): 'default_all_public_streams': ujson.dumps(False), } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_success(result) self.assertEqual(result.json()['default_all_public_streams'], False) @@ -1337,7 +1337,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): } email = 'hambot-bot@zulip.testserver' # Important: We intentionally use the wrong method, post, here. - result = self.client_post("/json/bots/{}".format(self.get_bot_user(email).id), + result = self.client_post(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_success(result) @@ -1354,7 +1354,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): 'full_name': 'Fred', } invalid_user_id = 1000 - result = self.client_patch("/json/bots/{}".format(invalid_user_id), bot_info) + result = self.client_patch(f"/json/bots/{invalid_user_id}", bot_info) self.assert_json_error(result, 'No such bot') self.assert_num_bots_equal(1) @@ -1374,7 +1374,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): 'service_interface': Service.SLACK, } email = 'hambot-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_success(result) service_interface = ujson.loads(result.content)['service_interface'] @@ -1392,7 +1392,7 @@ class BotTest(ZulipTestCase, UploadSerializeMixin): config_data=ujson.dumps({'key': '12345678'})) bot_info = {'config_data': ujson.dumps({'key': '87654321'})} email = 'test-bot@zulip.testserver' - result = self.client_patch("/json/bots/{}".format(self.get_bot_user(email).id), bot_info) + result = self.client_patch(f"/json/bots/{self.get_bot_user(email).id}", bot_info) self.assert_json_success(result) config_data = ujson.loads(result.content)['config_data'] self.assertEqual(config_data, ujson.loads(bot_info['config_data'])) diff --git a/zerver/tests/test_bugdown.py b/zerver/tests/test_bugdown.py index b18dd7dbac..f578b44b57 100644 --- a/zerver/tests/test_bugdown.py +++ b/zerver/tests/test_bugdown.py @@ -1580,7 +1580,7 @@ class BugdownTest(ZulipTestCase): cordelia = self.example_user('cordelia') msg = Message(sender=sender_user_profile, sending_client=get_client("test")) - content = "@**Mark Twin|{}**, @**Mark Twin|{}** and @**Cordelia Lear**, hi.".format(twin1.id, twin2.id) + content = f"@**Mark Twin|{twin1.id}**, @**Mark Twin|{twin2.id}** and @**Cordelia Lear**, hi." self.assertEqual(render_markdown(msg, content), '

' @@ -1918,7 +1918,7 @@ class BugdownTest(ZulipTestCase): stream = Stream.objects.create(name='Stream #1234', realm=realm) msg = Message(sender=sender_user_profile, sending_client=get_client("test")) content = "#**Stream #1234**" - href = '/#narrow/stream/{stream_id}-Stream-.231234'.format(stream_id=stream.id) + href = f'/#narrow/stream/{stream.id}-Stream-.231234' self.assertEqual( render_markdown(msg, content), '

#{s.name}

'.format( @@ -2159,7 +2159,7 @@ class BugdownAvatarTestCase(ZulipTestCase): message = Message(sender=sender_user_profile, sending_client=get_client("test")) user_profile = self.example_user('hamlet') - msg = '!avatar({})'.format(user_profile.email) + msg = f'!avatar({user_profile.email})' converted = bugdown.convert(msg, message=message) values = {'email': user_profile.email, 'id': user_profile.id} self.assertEqual( @@ -2171,7 +2171,7 @@ class BugdownAvatarTestCase(ZulipTestCase): message = Message(sender=sender_user_profile, sending_client=get_client("test")) email = 'fakeuser@example.com' - msg = '!avatar({})'.format(email) + msg = f'!avatar({email})' converted = bugdown.convert(msg, message=message) self.assertEqual( converted, diff --git a/zerver/tests/test_cache.py b/zerver/tests/test_cache.py index 94f8ecfe26..50a58fb843 100644 --- a/zerver/tests/test_cache.py +++ b/zerver/tests/test_cache.py @@ -62,7 +62,7 @@ class CacheKeyValidationTest(ZulipTestCase): class CacheWithKeyDecoratorTest(ZulipTestCase): def test_cache_with_key_invalid_character(self) -> None: def invalid_characters_cache_key_function(user_id: int) -> str: - return 'CacheWithKeyDecoratorTest:invalid_character:Ä…:{}'.format(user_id) + return f'CacheWithKeyDecoratorTest:invalid_character:Ä…:{user_id}' @cache_with_key(invalid_characters_cache_key_function, timeout=1000) def get_user_function_with_bad_cache_keys(user_id: int) -> UserProfile: @@ -101,7 +101,7 @@ class CacheWithKeyDecoratorTest(ZulipTestCase): def test_cache_with_key_good_key(self) -> None: def good_cache_key_function(user_id: int) -> str: - return 'CacheWithKeyDecoratorTest:good_cache_key:{}'.format(user_id) + return f'CacheWithKeyDecoratorTest:good_cache_key:{user_id}' @cache_with_key(good_cache_key_function, timeout=1000) def get_user_function_with_good_cache_keys(user_id: int) -> UserProfile: @@ -125,7 +125,7 @@ class CacheWithKeyDecoratorTest(ZulipTestCase): def test_cache_with_key_none_values(self) -> None: def cache_key_function(user_id: int) -> str: - return 'CacheWithKeyDecoratorTest:test_cache_with_key_none_values:{}'.format(user_id) + return f'CacheWithKeyDecoratorTest:test_cache_with_key_none_values:{user_id}' @cache_with_key(cache_key_function, timeout=1000) def get_user_function_can_return_none(user_id: int) -> Optional[UserProfile]: @@ -155,7 +155,7 @@ class GetCacheWithKeyDecoratorTest(ZulipTestCase): # we got the result from calling the function (None) def good_cache_key_function(user_id: int) -> str: - return 'CacheWithKeyDecoratorTest:good_cache_key:{}'.format(user_id) + return f'CacheWithKeyDecoratorTest:good_cache_key:{user_id}' @get_cache_with_key(good_cache_key_function) def get_user_function_with_good_cache_keys(user_id: int) -> Any: # nocoverage @@ -173,7 +173,7 @@ class GetCacheWithKeyDecoratorTest(ZulipTestCase): def test_get_cache_with_bad_key(self) -> None: def bad_cache_key_function(user_id: int) -> str: - return 'CacheWithKeyDecoratorTest:invalid_character:Ä…:{}'.format(user_id) + return f'CacheWithKeyDecoratorTest:invalid_character:Ä…:{user_id}' @get_cache_with_key(bad_cache_key_function) def get_user_function_with_bad_cache_keys(user_id: int) -> Any: # nocoverage diff --git a/zerver/tests/test_compatibility.py b/zerver/tests/test_compatibility.py index b93fc979b8..6f21f510d2 100644 --- a/zerver/tests/test_compatibility.py +++ b/zerver/tests/test_compatibility.py @@ -29,7 +29,7 @@ class VersionTest(ZulipTestCase): def test_version_lt(self) -> None: for ver1, cmp, ver2 in self.data: - msg = 'expected {} {} {}'.format(ver1, cmp, ver2) + msg = f'expected {ver1} {cmp} {ver2}' if cmp == '<': self.assertTrue(version_lt(ver1, ver2), msg=msg) self.assertFalse(version_lt(ver2, ver1), msg=msg) diff --git a/zerver/tests/test_custom_profile_data.py b/zerver/tests/test_custom_profile_data.py index 5fd9d3fd06..31ce952621 100644 --- a/zerver/tests/test_custom_profile_data.py +++ b/zerver/tests/test_custom_profile_data.py @@ -150,7 +150,7 @@ class CreateCustomProfileFieldTest(CustomProfileFieldTestCase): self.assertEqual(field.name, DEFAULT_EXTERNAL_ACCOUNTS['twitter']['name']) self.assertEqual(field.hint, DEFAULT_EXTERNAL_ACCOUNTS['twitter']['hint']) - result = self.client_delete("/json/realm/profile_fields/{}".format(field.id)) + result = self.client_delete(f"/json/realm/profile_fields/{field.id}") self.assert_json_success(result) # Should also work without name or hint and only external field type and subtype data @@ -161,13 +161,13 @@ class CreateCustomProfileFieldTest(CustomProfileFieldTestCase): # Default external account field data cannot be updated field = CustomProfileField.objects.get(name="Twitter", realm=realm) result = self.client_patch( - "/json/realm/profile_fields/{}".format(field.id), + f"/json/realm/profile_fields/{field.id}", info={'name': 'Twitter username', 'field_type': CustomProfileField.EXTERNAL_ACCOUNT} ) self.assert_json_error(result, 'Default custom field cannot be updated.') - result = self.client_delete("/json/realm/profile_fields/{}".format(field.id)) + result = self.client_delete(f"/json/realm/profile_fields/{field.id}") self.assert_json_success(result) def test_create_external_account_field(self) -> None: @@ -292,7 +292,7 @@ class DeleteCustomProfileFieldTest(CustomProfileFieldTestCase): self.assertTrue(self.custom_field_exists_in_realm(field.id)) result = self.client_delete( - "/json/realm/profile_fields/{}".format(field.id)) + f"/json/realm/profile_fields/{field.id}") self.assert_json_success(result) self.assertFalse(self.custom_field_exists_in_realm(field.id)) @@ -359,7 +359,7 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase): field = CustomProfileField.objects.get(name="Phone number", realm=realm) result = self.client_patch( - "/json/realm/profile_fields/{}".format(field.id), + f"/json/realm/profile_fields/{field.id}", info={'name': '', 'field_type': CustomProfileField.SHORT_TEXT} ) @@ -367,7 +367,7 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase): self.assertEqual(CustomProfileField.objects.count(), self.original_count) result = self.client_patch( - "/json/realm/profile_fields/{}".format(field.id), + f"/json/realm/profile_fields/{field.id}", info={'name': 'New phone number', 'field_type': CustomProfileField.SHORT_TEXT}) self.assert_json_success(result) @@ -378,14 +378,14 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase): self.assertEqual(field.field_type, CustomProfileField.SHORT_TEXT) result = self.client_patch( - "/json/realm/profile_fields/{}".format(field.id), + f"/json/realm/profile_fields/{field.id}", info={'name': '*' * 41, 'field_type': CustomProfileField.SHORT_TEXT}) msg = "name is too long (limit: 40 characters)" self.assert_json_error(result, msg) result = self.client_patch( - "/json/realm/profile_fields/{}".format(field.id), + f"/json/realm/profile_fields/{field.id}", info={'name': 'New phone number', 'hint': '*' * 81, 'field_type': CustomProfileField.SHORT_TEXT}) @@ -393,7 +393,7 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase): self.assert_json_error(result, msg) result = self.client_patch( - "/json/realm/profile_fields/{}".format(field.id), + f"/json/realm/profile_fields/{field.id}", info={'name': 'New phone number', 'hint': 'New contact number', 'field_type': CustomProfileField.SHORT_TEXT}) @@ -407,7 +407,7 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase): field = CustomProfileField.objects.get(name="Favorite editor", realm=realm) result = self.client_patch( - "/json/realm/profile_fields/{}".format(field.id), + f"/json/realm/profile_fields/{field.id}", info={'name': 'Favorite editor', 'field_data': 'invalid'}) self.assert_json_error(result, "Bad value for 'field_data': invalid") @@ -417,7 +417,7 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase): 'emacs': {'order': '2', 'text': 'Emacs'}, }) result = self.client_patch( - "/json/realm/profile_fields/{}".format(field.id), + f"/json/realm/profile_fields/{field.id}", info={'name': 'Favorite editor', 'field_data': field_data}) self.assert_json_error(result, "field_data is not a dict") @@ -428,7 +428,7 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase): 'notepad': {'order': '3', 'text': 'Notepad'}, }) result = self.client_patch( - "/json/realm/profile_fields/{}".format(field.id), + f"/json/realm/profile_fields/{field.id}", info={'name': 'Favorite editor', 'field_data': field_data}) self.assert_json_success(result) @@ -445,7 +445,7 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase): self.assertTrue(self.custom_field_exists_in_realm(field_1.id)) self.assertTrue(self.custom_field_exists_in_realm(field_2.id)) result = self.client_patch( - "/json/realm/profile_fields/{}".format(field_2.id), + f"/json/realm/profile_fields/{field_2.id}", info={'name': 'Phone', 'field_type': CustomProfileField.SHORT_TEXT}) self.assert_json_error( result, 'A field with that label already exists.') @@ -472,19 +472,19 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase): def test_update_invalid_short_text(self) -> None: field_name = "Phone number" self.assert_error_update_invalid_value(field_name, 't' * 201, - "{} is too long (limit: 50 characters)".format(field_name)) + f"{field_name} is too long (limit: 50 characters)") def test_update_invalid_date(self) -> None: field_name = "Birthday" self.assert_error_update_invalid_value(field_name, "a-b-c", - "{} is not a date".format(field_name)) + f"{field_name} is not a date") self.assert_error_update_invalid_value(field_name, 123, - "{} is not a string".format(field_name)) + f"{field_name} is not a string") def test_update_invalid_url(self) -> None: field_name = "Favorite website" self.assert_error_update_invalid_value(field_name, "not URL", - "{} is not a URL".format(field_name)) + f"{field_name} is not a URL") def test_update_invalid_user_field(self) -> None: field_name = "Mentor" @@ -554,7 +554,7 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase): def test_update_invalid_choice_field(self) -> None: field_name = "Favorite editor" self.assert_error_update_invalid_value(field_name, "foobar", - "'foobar' is not a valid choice for '{}'.".format(field_name)) + f"'foobar' is not a valid choice for '{field_name}'.") def test_update_choice_field_successfully(self) -> None: self.login('iago') diff --git a/zerver/tests/test_digest.py b/zerver/tests/test_digest.py index 716201d047..6f634d6765 100644 --- a/zerver/tests/test_digest.py +++ b/zerver/tests/test_digest.py @@ -262,7 +262,7 @@ class TestDigestEmailMessages(ZulipTestCase): cordelia = self.example_user('cordelia') stream_id = create_stream_if_needed(cordelia.realm, 'New stream')[0].id new_stream = gather_new_streams(cordelia, cutoff)[1] - expected_html = "New stream".format(stream_id=stream_id) + expected_html = f"New stream" self.assertIn(expected_html, new_stream['html']) def simulate_stream_conversation(self, stream: str, senders: List[str]) -> List[int]: @@ -271,7 +271,7 @@ class TestDigestEmailMessages(ZulipTestCase): message_ids = [] # List[int] for sender_name in senders: sender = self.example_user(sender_name) - content = 'some content for {} from {}'.format(stream, sender_name) + content = f'some content for {stream} from {sender_name}' message_id = self.send_stream_message(sender, stream, content) message_ids.append(message_id) Message.objects.filter(id__in=message_ids).update(sending_client=sending_client) diff --git a/zerver/tests/test_docs.py b/zerver/tests/test_docs.py index f66381a6e2..48846eae7b 100644 --- a/zerver/tests/test_docs.py +++ b/zerver/tests/test_docs.py @@ -103,7 +103,7 @@ class DocPageTest(ZulipTestCase): files = list(filter(_filter_func, files)) for f in files: - endpoint = '/api/{}'.format(os.path.splitext(f)[0]) + endpoint = f'/api/{os.path.splitext(f)[0]}' self._test(endpoint, '', doc_html_str=True) @slow("Tests dozens of endpoints, including generating lots of emails") @@ -181,7 +181,7 @@ class DocPageTest(ZulipTestCase): ]) for integration in INTEGRATIONS.keys(): - url = '/integrations/doc-html/{}'.format(integration) + url = f'/integrations/doc-html/{integration}' self._test(url, '', doc_html_str=True) def test_integration_pages_open_graph_metadata(self) -> None: @@ -209,13 +209,13 @@ class DocPageTest(ZulipTestCase): # We don't need to test all the pages for 404 for integration in list(INTEGRATIONS.keys())[5]: with self.settings(ROOT_DOMAIN_LANDING_PAGE=True): - url = '/en/integrations/doc-html/{}'.format(integration) + url = f'/en/integrations/doc-html/{integration}' result = self.client_get(url, subdomain="", follow=True) self.assertEqual(result.status_code, 404) result = self.client_get(url, subdomain="zephyr", follow=True) self.assertEqual(result.status_code, 404) - url = '/en/integrations/doc-html/{}'.format(integration) + url = f'/en/integrations/doc-html/{integration}' result = self.client_get(url, subdomain="", follow=True) self.assertEqual(result.status_code, 404) result = self.client_get(url, subdomain="zephyr", follow=True) diff --git a/zerver/tests/test_email_change.py b/zerver/tests/test_email_change.py index cf0374881d..1e64c43742 100644 --- a/zerver/tests/test_email_change.py +++ b/zerver/tests/test_email_change.py @@ -211,7 +211,7 @@ class EmailChangeTestCase(ZulipTestCase): response) user_profile = get_user_profile_by_id(user_profile.id) self.assertEqual(user_profile.delivery_email, new_email) - self.assertEqual(user_profile.email, "user{}@zulip.testserver".format(user_profile.id)) + self.assertEqual(user_profile.email, f"user{user_profile.id}@zulip.testserver") obj.refresh_from_db() self.assertEqual(obj.status, 1) with self.assertRaises(UserProfile.DoesNotExist): diff --git a/zerver/tests/test_email_mirror.py b/zerver/tests/test_email_mirror.py index 8f5905a798..3621a8dd5a 100644 --- a/zerver/tests/test_email_mirror.py +++ b/zerver/tests/test_email_mirror.py @@ -73,11 +73,11 @@ class TestEncodeDecode(ZulipTestCase): stream_name = 'dev. help' stream = ensure_stream(realm, stream_name) email_address = encode_email_address(stream) - self.assertEqual(email_address, "dev-help.{}@testserver".format(stream.email_token)) + self.assertEqual(email_address, f"dev-help.{stream.email_token}@testserver") # The default form of the email address (with an option - "include-footer"): token, options = decode_email_address( - "dev-help.{}.include-footer@testserver".format(stream.email_token) + f"dev-help.{stream.email_token}.include-footer@testserver" ) self._assert_options(options, include_footer=True) self.assertEqual(token, stream.email_token) @@ -85,7 +85,7 @@ class TestEncodeDecode(ZulipTestCase): # Using + instead of . as the separator is also supported for backwards compatibility, # since that was the original form of addresses that we used: token, options = decode_email_address( - "dev-help+{}+include-footer@testserver".format(stream.email_token) + f"dev-help+{stream.email_token}+include-footer@testserver" ) self._assert_options(options, include_footer=True) self.assertEqual(token, stream.email_token) @@ -164,8 +164,8 @@ class TestEncodeDecode(ZulipTestCase): def test_decode_prefer_text_options(self) -> None: stream = get_stream("Denmark", get_realm("zulip")) - address_prefer_text = "Denmark.{}.prefer-text@testserver".format(stream.email_token) - address_prefer_html = "Denmark.{}.prefer-html@testserver".format(stream.email_token) + address_prefer_text = f"Denmark.{stream.email_token}.prefer-text@testserver" + address_prefer_html = f"Denmark.{stream.email_token}.prefer-html@testserver" token, options = decode_email_address(address_prefer_text) self._assert_options(options, prefer_text=True) @@ -301,7 +301,7 @@ class TestStreamEmailMessagesSuccess(ZulipTestCase): # stream address is angle-addr within multiple addresses stream_to_addresses = ["A.N. Other ", - "Denmark <{}>".format(encode_email_address(stream))] + f"Denmark <{encode_email_address(stream)}>"] incoming_valid_message = MIMEText('TestStreamEmailMessages Body') @@ -566,8 +566,8 @@ class TestEmailMirrorMessagesWithAttachments(ZulipTestCase): self.login_user(user_profile) self.subscribe(user_profile, "Denmark") stream = get_stream("Denmark", user_profile.realm) - stream_address = "Denmark.{}@testserver".format(stream.email_token) - stream_address_prefer_html = "Denmark.{}.prefer-html@testserver".format(stream.email_token) + stream_address = f"Denmark.{stream.email_token}@testserver" + stream_address_prefer_html = f"Denmark.{stream.email_token}.prefer-html@testserver" text = "Test message" html = "Test html message" @@ -601,7 +601,7 @@ class TestEmailMirrorMessagesWithAttachments(ZulipTestCase): self.login_user(user_profile) self.subscribe(user_profile, "Denmark") stream = get_stream("Denmark", user_profile.realm) - stream_address_prefer_html = "Denmark.{}.prefer-html@testserver".format(stream.email_token) + stream_address_prefer_html = f"Denmark.{stream.email_token}.prefer-html@testserver" text = "Test message" # This should be correctly identified as empty html body: diff --git a/zerver/tests/test_email_notifications.py b/zerver/tests/test_email_notifications.py index e4384e317e..ec9c83a58f 100644 --- a/zerver/tests/test_email_notifications.py +++ b/zerver/tests/test_email_notifications.py @@ -700,8 +700,8 @@ class TestMissedMessages(ZulipTestCase): self.example_user('othello'), self.example_user('hamlet'), 'Come and join us in #**Verona**.') stream_id = get_stream('Verona', get_realm('zulip')).id - href = "http://zulip.testserver/#narrow/stream/{stream_id}-Verona".format(stream_id=stream_id) - verify_body_include = ['#Verona#Verona None: assert self.bot_profile is not None self.send_stream_message(self.user_profile, "Denmark", - content="@**{}** foo".format(self.bot_profile.full_name), + content=f"@**{self.bot_profile.full_name}** foo", topic_name="bar") last_message = self.get_last_message() self.assertEqual(last_message.content, "beep boop") @@ -56,7 +56,7 @@ class TestEmbeddedBotMessaging(ZulipTestCase): with patch('zulip_bots.bots.helloworld.helloworld.HelloWorldHandler.initialize', create=True) as mock_initialize: self.send_stream_message(self.user_profile, "Denmark", - content="@**{}** foo".format(self.bot_profile.full_name), + content=f"@**{self.bot_profile.full_name}** foo", topic_name="bar") mock_initialize.assert_called_once() @@ -66,7 +66,7 @@ class TestEmbeddedBotMessaging(ZulipTestCase): side_effect=EmbeddedBotQuitException("I'm quitting!")): with patch('logging.warning') as mock_logging: self.send_stream_message(self.user_profile, "Denmark", - content="@**{}** foo".format(self.bot_profile.full_name), + content=f"@**{self.bot_profile.full_name}** foo", topic_name="bar") mock_logging.assert_called_once_with("I'm quitting!") @@ -83,7 +83,7 @@ class TestEmbeddedBotFailures(ZulipTestCase): service_profile.save() with patch('logging.error') as logging_error_mock: self.send_stream_message(user_profile, "Denmark", - content="@**{}** foo".format(bot_profile.full_name), + content=f"@**{bot_profile.full_name}** foo", topic_name="bar") logging_error_mock.assert_called_once_with( "Error: User %s has bot with invalid embedded bot service %s", diff --git a/zerver/tests/test_events.py b/zerver/tests/test_events.py index 757b51cce0..ac147890cb 100644 --- a/zerver/tests/test_events.py +++ b/zerver/tests/test_events.py @@ -2803,7 +2803,7 @@ class EventsRegisterTest(ZulipTestCase): hamlet = self.example_user("hamlet") self.subscribe(hamlet, "Denmark") - body = "First message ...[zulip.txt](http://{}".format(hamlet.realm.host) + data['uri'] + ")" + body = f"First message ...[zulip.txt](http://{hamlet.realm.host}" + data['uri'] + ")" events = self.do_test( lambda: self.send_stream_message(self.example_user("hamlet"), "Denmark", body, "test"), num_events=2) @@ -2888,7 +2888,7 @@ class EventsRegisterTest(ZulipTestCase): audit_log_entry = RealmAuditLog.objects.filter( event_type=RealmAuditLog.REALM_EXPORTED).first() events = self.do_test( - lambda: self.client_delete('/json/export/realm/{id}'.format(id=audit_log_entry.id)), + lambda: self.client_delete(f'/json/export/realm/{audit_log_entry.id}'), state_change_expected=False, num_events=1) error = deletion_schema_checker('events[0]', events[0]) self.assert_on_error(error) diff --git a/zerver/tests/test_i18n.py b/zerver/tests/test_i18n.py index 75b1579cc1..6c550da043 100644 --- a/zerver/tests/test_i18n.py +++ b/zerver/tests/test_i18n.py @@ -105,7 +105,7 @@ class TranslationTestCase(ZulipTestCase): ] for lang, word in languages: - response = self.fetch('get', '/{}/integrations/'.format(lang), 200) + response = self.fetch('get', f'/{lang}/integrations/', 200) self.assert_in_response(word, response) diff --git a/zerver/tests/test_import_export.py b/zerver/tests/test_import_export.py index 28cabc4e66..71bfdcf23e 100644 --- a/zerver/tests/test_import_export.py +++ b/zerver/tests/test_import_export.py @@ -946,7 +946,7 @@ class ImportExportTest(ZulipTestCase): def get_user_mention(r: Realm) -> Set[Any]: mentioned_user = UserProfile.objects.get(delivery_email=self.example_email("hamlet"), realm=r) - data_user_id = 'data-user-id="{}"'.format(mentioned_user.id) + data_user_id = f'data-user-id="{mentioned_user.id}"' mention_message = get_stream_messages(r).get(rendered_content__contains=data_user_id) return mention_message.content @@ -954,7 +954,7 @@ class ImportExportTest(ZulipTestCase): def get_stream_mention(r: Realm) -> Set[Any]: mentioned_stream = get_stream('Denmark', r) - data_stream_id = 'data-stream-id="{}"'.format(mentioned_stream.id) + data_stream_id = f'data-stream-id="{mentioned_stream.id}"' mention_message = get_stream_messages(r).get(rendered_content__contains=data_stream_id) return mention_message.content @@ -962,7 +962,7 @@ class ImportExportTest(ZulipTestCase): def get_user_group_mention(r: Realm) -> Set[Any]: user_group = UserGroup.objects.get(realm=r, name='hamletcharacters') - data_usergroup_id = 'data-user-group-id="{}"'.format(user_group.id) + data_usergroup_id = f'data-user-group-id="{user_group.id}"' mention_message = get_stream_messages(r).get(rendered_content__contains=data_usergroup_id) return mention_message.content diff --git a/zerver/tests/test_integrations_dev_panel.py b/zerver/tests/test_integrations_dev_panel.py index 266a28cbe3..13058684a8 100644 --- a/zerver/tests/test_integrations_dev_panel.py +++ b/zerver/tests/test_integrations_dev_panel.py @@ -9,7 +9,7 @@ class TestIntegrationsDevPanel(ZulipTestCase): def test_check_send_webhook_fixture_message_for_error(self) -> None: bot = get_user('webhook-bot@zulip.com', self.zulip_realm) - url = "/api/v1/external/airbrake?api_key={key}".format(key=bot.api_key) + url = f"/api/v1/external/airbrake?api_key={bot.api_key}" target_url = "/devtools/integrations/check_send_webhook_fixture_message" body = "{}" # This empty body should generate a KeyError on the webhook code side. @@ -28,7 +28,7 @@ class TestIntegrationsDevPanel(ZulipTestCase): def test_check_send_webhook_fixture_message_for_success_without_headers(self) -> None: bot = get_user('webhook-bot@zulip.com', self.zulip_realm) - url = "/api/v1/external/airbrake?api_key={key}&stream=Denmark&topic=Airbrake Notifications".format(key=bot.api_key) + url = f"/api/v1/external/airbrake?api_key={bot.api_key}&stream=Denmark&topic=Airbrake Notifications" target_url = "/devtools/integrations/check_send_webhook_fixture_message" with open("zerver/webhooks/airbrake/fixtures/error_message.json") as f: body = f.read() @@ -55,7 +55,7 @@ class TestIntegrationsDevPanel(ZulipTestCase): def test_check_send_webhook_fixture_message_for_success_with_headers(self) -> None: bot = get_user('webhook-bot@zulip.com', self.zulip_realm) - url = "/api/v1/external/github?api_key={key}&stream=Denmark&topic=GitHub Notifications".format(key=bot.api_key) + url = f"/api/v1/external/github?api_key={bot.api_key}&stream=Denmark&topic=GitHub Notifications" target_url = "/devtools/integrations/check_send_webhook_fixture_message" with open("zerver/webhooks/github/fixtures/ping__organization.json") as f: body = f.read() @@ -78,7 +78,7 @@ class TestIntegrationsDevPanel(ZulipTestCase): def test_check_send_webhook_fixture_message_for_success_with_headers_and_non_json_fixtures(self) -> None: bot = get_user('webhook-bot@zulip.com', self.zulip_realm) - url = "/api/v1/external/wordpress?api_key={key}&stream=Denmark&topic=Wordpress Notifications".format(key=bot.api_key) + url = f"/api/v1/external/wordpress?api_key={bot.api_key}&stream=Denmark&topic=Wordpress Notifications" target_url = "/devtools/integrations/check_send_webhook_fixture_message" with open("zerver/webhooks/wordpress/fixtures/publish_post_no_data_provided.txt") as f: body = f.read() @@ -129,7 +129,7 @@ class TestIntegrationsDevPanel(ZulipTestCase): def test_send_all_webhook_fixture_messages_for_success(self) -> None: bot = get_user('webhook-bot@zulip.com', self.zulip_realm) - url = "/api/v1/external/appfollow?api_key={key}&stream=Denmark&topic=Appfollow Bulk Notifications".format(key=bot.api_key) + url = f"/api/v1/external/appfollow?api_key={bot.api_key}&stream=Denmark&topic=Appfollow Bulk Notifications" target_url = "/devtools/integrations/send_all_webhook_fixture_messages" data = { @@ -173,7 +173,7 @@ class TestIntegrationsDevPanel(ZulipTestCase): def test_send_all_webhook_fixture_messages_for_success_with_non_json_fixtures(self) -> None: bot = get_user('webhook-bot@zulip.com', self.zulip_realm) - url = "/api/v1/external/wordpress?api_key={key}&stream=Denmark&topic=Wordpress Bulk Notifications".format(key=bot.api_key) + url = f"/api/v1/external/wordpress?api_key={bot.api_key}&stream=Denmark&topic=Wordpress Bulk Notifications" target_url = "/devtools/integrations/send_all_webhook_fixture_messages" data = { @@ -243,7 +243,7 @@ class TestIntegrationsDevPanel(ZulipTestCase): def test_send_all_webhook_fixture_messages_for_missing_fixtures(self, os_path_exists_mock: MagicMock) -> None: os_path_exists_mock.return_value = False bot = get_user('webhook-bot@zulip.com', self.zulip_realm) - url = "/api/v1/external/appfollow?api_key={key}&stream=Denmark&topic=Appfollow Bulk Notifications".format(key=bot.api_key) + url = f"/api/v1/external/appfollow?api_key={bot.api_key}&stream=Denmark&topic=Appfollow Bulk Notifications" data = { "url": url, "custom_headers": "{}", diff --git a/zerver/tests/test_link_embed.py b/zerver/tests/test_link_embed.py index 528f0d50eb..14a1204bc5 100644 --- a/zerver/tests/test_link_embed.py +++ b/zerver/tests/test_link_embed.py @@ -131,7 +131,7 @@ class OembedTestCase(ZulipTestCase): def test_autodiscovered_oembed_xml_format_html(self) -> None: iframe_content = '' - html = ''.format(iframe_content) + html = f'' stripped_html = strip_cdata(html) self.assertEqual(iframe_content, stripped_html) @@ -299,7 +299,7 @@ class PreviewTestCase(ZulipTestCase): with mock.patch('requests.get', mocked_response): FetchLinksEmbedData().consume(event) - embedded_link = 'The Rock'.format(url) + embedded_link = f'The Rock' msg = Message.objects.select_related("sender").get(id=msg_id) self.assertIn(embedded_link, msg.rendered_content) @@ -327,7 +327,7 @@ class PreviewTestCase(ZulipTestCase): # Verify the initial message doesn't have the embedded links rendered msg = Message.objects.select_related("sender").get(id=msg_id) self.assertNotIn( - 'The Rock'.format(url), + f'The Rock', msg.rendered_content) # Mock the network request result so the test can be fast without Internet @@ -367,7 +367,7 @@ class PreviewTestCase(ZulipTestCase): msg = Message.objects.select_related("sender").get(id=msg_id) # The content of the message has changed since the event for original_url has been created, # it should not be rendered. Another, up-to-date event will have been sent (edited_url). - self.assertNotIn('The Rock'.format(original_url), + self.assertNotIn(f'The Rock', msg.rendered_content) mocked_response_edited.assert_not_called() @@ -377,7 +377,7 @@ class PreviewTestCase(ZulipTestCase): # up-to-date event for edited_url. queue_json_publish(*args, **kwargs) msg = Message.objects.select_related("sender").get(id=msg_id) - self.assertIn('The Rock'.format(edited_url), + self.assertIn(f'The Rock', msg.rendered_content) with mock.patch('zerver.views.messages.queue_json_publish', wraps=wrapped_queue_json_publish) as patched: @@ -388,7 +388,7 @@ class PreviewTestCase(ZulipTestCase): def test_get_link_embed_data(self) -> None: url = 'http://test.org/' - embedded_link = 'The Rock'.format(url) + embedded_link = f'The Rock' # When humans send, we should get embedded content. msg = self._send_message_with_test_org_url(sender=self.example_user('hamlet')) @@ -659,8 +659,8 @@ class PreviewTestCase(ZulipTestCase): 'message_realm_id': msg.sender.realm_id, 'message_content': url} - mocked_data = {'html': ''.format(url), - 'oembed': True, 'type': 'video', 'image': '{}/image.png'.format(url)} + mocked_data = {'html': f'', + 'oembed': True, 'type': 'video', 'image': f'{url}/image.png'} mocked_response = mock.Mock(side_effect=self.create_mock_response(url)) with self.settings(TEST_SUITE=False, CACHES=TEST_CACHES): with mock.patch('requests.get', mocked_response): diff --git a/zerver/tests/test_management_commands.py b/zerver/tests/test_management_commands.py index 6e33a249ca..d9a274a144 100644 --- a/zerver/tests/test_management_commands.py +++ b/zerver/tests/test_management_commands.py @@ -283,7 +283,7 @@ class TestGenerateRealmCreationLink(ZulipTestCase): result = self.client_post(generated_link, {'email': email}) self.assertEqual(result.status_code, 302) - self.assertTrue(re.search('/accounts/new/send_confirm/{}$'.format(email), + self.assertTrue(re.search(f'/accounts/new/send_confirm/{email}$', result["Location"])) result = self.client_get(result["Location"]) self.assert_in_response("Check your email so we can get started", result) @@ -354,7 +354,7 @@ class TestSendToEmailMirror(ZulipTestCase): self.login_user(user_profile) self.subscribe(user_profile, "Denmark") - call_command(self.COMMAND_NAME, "--fixture={}".format(fixture_path)) + call_command(self.COMMAND_NAME, f"--fixture={fixture_path}") message = most_recent_message(user_profile) # last message should be equal to the body of the email in 1.txt @@ -366,7 +366,7 @@ class TestSendToEmailMirror(ZulipTestCase): self.login_user(user_profile) self.subscribe(user_profile, "Denmark") - call_command(self.COMMAND_NAME, "--fixture={}".format(fixture_path)) + call_command(self.COMMAND_NAME, f"--fixture={fixture_path}") message = most_recent_message(user_profile) # last message should be equal to the body of the email in 1.json @@ -378,7 +378,7 @@ class TestSendToEmailMirror(ZulipTestCase): self.login_user(user_profile) self.subscribe(user_profile, "Denmark2") - call_command(self.COMMAND_NAME, "--fixture={}".format(fixture_path), "--stream=Denmark2") + call_command(self.COMMAND_NAME, f"--fixture={fixture_path}", "--stream=Denmark2") message = most_recent_message(user_profile) # last message should be equal to the body of the email in 1.txt @@ -395,7 +395,7 @@ class TestConvertMattermostData(ZulipTestCase): with patch('zerver.management.commands.convert_mattermost_data.do_convert_data') as m: mm_fixtures = self.fixture_file_name("", "mattermost_fixtures") output_dir = self.make_import_output_dir("mattermost") - call_command(self.COMMAND_NAME, mm_fixtures, "--output={}".format(output_dir)) + call_command(self.COMMAND_NAME, mm_fixtures, f"--output={output_dir}") m.assert_called_with( masking_content=False, @@ -425,7 +425,7 @@ class TestExport(ZulipTestCase): do_add_reaction(self.example_user("hamlet"), message, "outbox", "1f4e4", Reaction.UNICODE_EMOJI) with patch("zerver.management.commands.export.export_realm_wrapper") as m: - call_command(self.COMMAND_NAME, "-r=zulip", "--consent-message-id={}".format(message.id)) + call_command(self.COMMAND_NAME, "-r=zulip", f"--consent-message-id={message.id}") m.assert_called_once_with(realm=realm, public_only=False, consent_message_id=message.id, delete_after_upload=False, threads=mock.ANY, output_dir=mock.ANY, upload=False) @@ -436,10 +436,10 @@ class TestExport(ZulipTestCase): message.last_edit_time = timezone_now() message.save() with self.assertRaisesRegex(CommandError, "Message was edited. Aborting..."): - call_command(self.COMMAND_NAME, "-r=zulip", "--consent-message-id={}".format(message.id)) + call_command(self.COMMAND_NAME, "-r=zulip", f"--consent-message-id={message.id}") message.last_edit_time = None message.save() do_add_reaction(self.mit_user("sipbtest"), message, "outbox", "1f4e4", Reaction.UNICODE_EMOJI) with self.assertRaisesRegex(CommandError, "Users from a different realm reacted to message. Aborting..."): - call_command(self.COMMAND_NAME, "-r=zulip", "--consent-message-id={}".format(message.id)) + call_command(self.COMMAND_NAME, "-r=zulip", f"--consent-message-id={message.id}") diff --git a/zerver/tests/test_messages.py b/zerver/tests/test_messages.py index 0a480a7d8d..5000542b93 100644 --- a/zerver/tests/test_messages.py +++ b/zerver/tests/test_messages.py @@ -796,7 +796,7 @@ class PersonalMessagesTest(ZulipTestCase): user_message = most_recent_usermessage(user_profile) self.assertEqual( str(user_message), - ''.format(user_profile.email) + f'' ) @slow("checks several profiles") @@ -1409,7 +1409,7 @@ class MessageDictTest(ZulipTestCase): # extract messages. Note that we increased this from 1ms to # 1.5ms to handle tests running in parallel being a bit # slower. - error_msg = "Number of ids: {}. Time delay: {}".format(num_ids, delay) + error_msg = f"Number of ids: {num_ids}. Time delay: {delay}" self.assertTrue(delay < 0.0015 * num_ids, error_msg) self.assert_length(queries, 7) self.assertEqual(len(rows), num_ids) @@ -1959,14 +1959,14 @@ class MessagePOSTTest(ZulipTestCase): "content": "Test message", "client": "test suite", "to": ujson.dumps([othello.id])}) - self.assert_json_error(result, "'{}' is no longer using Zulip.".format(othello.email)) + self.assert_json_error(result, f"'{othello.email}' is no longer using Zulip.") result = self.client_post("/json/messages", { "type": "private", "content": "Test message", "client": "test suite", "to": ujson.dumps([othello.id, cordelia.id])}) - self.assert_json_error(result, "'{}' is no longer using Zulip.".format(othello.email)) + self.assert_json_error(result, f"'{othello.email}' is no longer using Zulip.") def test_invalid_type(self) -> None: """ @@ -2960,7 +2960,7 @@ class EditMessageTest(ZulipTestCase): topic_name='editing', content='This message has not been edited.') - result = self.client_get('/json/messages/{}/history'.format(msg_id)) + result = self.client_get(f'/json/messages/{msg_id}/history') self.assert_json_success(result) @@ -4158,7 +4158,7 @@ class MessageHasKeywordsTest(ZulipTestCase): def test_claim_attachment(self) -> None: user_profile = self.example_user('hamlet') dummy_path_ids = self.setup_dummy_attachments(user_profile) - dummy_urls = ["http://zulip.testserver/user_uploads/{}".format(x) for x in dummy_path_ids] + dummy_urls = [f"http://zulip.testserver/user_uploads/{x}" for x in dummy_path_ids] # Send message referring the attachment self.subscribe(user_profile, "Denmark") @@ -4178,17 +4178,17 @@ class MessageHasKeywordsTest(ZulipTestCase): # This message tries to claim the third attachment but fails because # Bugdown would not set has_attachments = True here. - body = "Link in code: `{}`".format(dummy_urls[2]) + body = f"Link in code: `{dummy_urls[2]}`" self.send_stream_message(user_profile, "Denmark", body, "test") assert_attachment_claimed(dummy_path_ids[2], False) # Another scenario where we wouldn't parse the link. - body = "Link to not parse: .{}.`".format(dummy_urls[2]) + body = f"Link to not parse: .{dummy_urls[2]}.`" self.send_stream_message(user_profile, "Denmark", body, "test") assert_attachment_claimed(dummy_path_ids[2], False) # Finally, claim attachment 3. - body = "Link: {}".format(dummy_urls[2]) + body = f"Link: {dummy_urls[2]}" self.send_stream_message(user_profile, "Denmark", body, "test") assert_attachment_claimed(dummy_path_ids[2], True) assert_attachment_claimed(dummy_path_ids[1], False) @@ -4255,7 +4255,7 @@ class MessageHasKeywordsTest(ZulipTestCase): def test_has_attachment(self) -> None: hamlet = self.example_user('hamlet') dummy_path_ids = self.setup_dummy_attachments(hamlet) - dummy_urls = ["http://zulip.testserver/user_uploads/{}".format(x) for x in dummy_path_ids] + dummy_urls = [f"http://zulip.testserver/user_uploads/{x}" for x in dummy_path_ids] self.subscribe(hamlet, "Denmark") body = ("Files ...[zulip.txt]({}) {} {}").format(dummy_urls[0], dummy_urls[1], dummy_urls[2]) @@ -4267,24 +4267,24 @@ class MessageHasKeywordsTest(ZulipTestCase): self.assertFalse(msg.has_attachment) self.update_message(msg, body) self.assertTrue(msg.has_attachment) - self.update_message(msg, 'Link in code: `{}`'.format(dummy_urls[1])) + self.update_message(msg, f'Link in code: `{dummy_urls[1]}`') self.assertFalse(msg.has_attachment) # Test blockquotes - self.update_message(msg, '> {}'.format(dummy_urls[1])) + self.update_message(msg, f'> {dummy_urls[1]}') self.assertTrue(msg.has_attachment) # Additional test to check has_attachment is being set is due to the correct attachment. - self.update_message(msg, 'Outside: {}. In code: `{}`.'.format(dummy_urls[0], dummy_urls[1])) + self.update_message(msg, f'Outside: {dummy_urls[0]}. In code: `{dummy_urls[1]}`.') self.assertTrue(msg.has_attachment) self.assertTrue(msg.attachment_set.filter(path_id=dummy_path_ids[0])) self.assertEqual(msg.attachment_set.count(), 1) - self.update_message(msg, 'Outside: {}. In code: `{}`.'.format(dummy_urls[1], dummy_urls[0])) + self.update_message(msg, f'Outside: {dummy_urls[1]}. In code: `{dummy_urls[0]}`.') self.assertTrue(msg.has_attachment) self.assertTrue(msg.attachment_set.filter(path_id=dummy_path_ids[1])) self.assertEqual(msg.attachment_set.count(), 1) - self.update_message(msg, 'Both in code: `{} {}`.'.format(dummy_urls[1], dummy_urls[0])) + self.update_message(msg, f'Both in code: `{dummy_urls[1]} {dummy_urls[0]}`.') self.assertFalse(msg.has_attachment) self.assertEqual(msg.attachment_set.count(), 0) @@ -4304,16 +4304,16 @@ class MessageHasKeywordsTest(ZulipTestCase): self.assertTrue(m.called) m.reset_mock() - self.update_message(msg, '[link](/user_uploads/{})'.format(dummy_path_ids[1])) + self.update_message(msg, f'[link](/user_uploads/{dummy_path_ids[1]})') self.assertTrue(m.called) m.reset_mock() - self.update_message(msg, '[new text link](/user_uploads/{})'.format(dummy_path_ids[1])) + self.update_message(msg, f'[new text link](/user_uploads/{dummy_path_ids[1]})') self.assertFalse(m.called) m.reset_mock() # It's not clear this is correct behavior - self.update_message(msg, '[link](user_uploads/{})'.format(dummy_path_ids[2])) + self.update_message(msg, f'[link](user_uploads/{dummy_path_ids[2]})') self.assertFalse(m.called) m.reset_mock() @@ -4486,10 +4486,10 @@ class DeleteMessageTest(ZulipTestCase): self.login('iago') hamlet = self.example_user('hamlet') msg_id = self.send_stream_message(hamlet, "Scotland") - result = self.client_delete('/json/messages/{msg_id}'.format(msg_id=msg_id + 1), + result = self.client_delete(f'/json/messages/{msg_id + 1}', {'message_id': msg_id}) self.assert_json_error(result, "Invalid message(s)") - result = self.client_delete('/json/messages/{msg_id}'.format(msg_id=msg_id)) + result = self.client_delete(f'/json/messages/{msg_id}') self.assert_json_success(result) def test_delete_message_by_user(self) -> None: @@ -4504,17 +4504,17 @@ class DeleteMessageTest(ZulipTestCase): def test_delete_message_by_admin(msg_id: int) -> HttpResponse: self.login('iago') - result = self.client_delete('/json/messages/{msg_id}'.format(msg_id=msg_id)) + result = self.client_delete(f'/json/messages/{msg_id}') return result def test_delete_message_by_owner(msg_id: int) -> HttpResponse: self.login('hamlet') - result = self.client_delete('/json/messages/{msg_id}'.format(msg_id=msg_id)) + result = self.client_delete(f'/json/messages/{msg_id}') return result def test_delete_message_by_other_user(msg_id: int) -> HttpResponse: self.login('cordelia') - result = self.client_delete('/json/messages/{msg_id}'.format(msg_id=msg_id)) + result = self.client_delete(f'/json/messages/{msg_id}') return result # Test if message deleting is not allowed(default). diff --git a/zerver/tests/test_narrow.py b/zerver/tests/test_narrow.py index 5e8bda3411..9d59452b14 100644 --- a/zerver/tests/test_narrow.py +++ b/zerver/tests/test_narrow.py @@ -1143,7 +1143,7 @@ class GetOldMessagesTest(ZulipTestCase): 'emoji_name': reaction_name } - url = '/json/messages/{}/reactions'.format(message_id) + url = f'/json/messages/{message_id}/reactions' payload = self.client_post(url, reaction_info) self.assert_json_success(payload) @@ -2667,7 +2667,7 @@ class GetOldMessagesTest(ZulipTestCase): stream = get_stream('Scotland', realm) recipient_id = stream.recipient.id - cond = "AND NOT (recipient_id = {scotland} AND upper(subject) = upper('golf'))".format(scotland=recipient_id) + cond = f"AND NOT (recipient_id = {recipient_id} AND upper(subject) = upper('golf'))" self.assertIn(cond, queries[0]['sql']) # Next, verify the use_first_unread_anchor setting invokes diff --git a/zerver/tests/test_openapi.py b/zerver/tests/test_openapi.py index 8d5fb0ef04..3a3b11f013 100644 --- a/zerver/tests/test_openapi.py +++ b/zerver/tests/test_openapi.py @@ -332,7 +332,7 @@ so maybe we shouldn't mark it as intentionally undocumented in the urls. except AssertionError: # nocoverage msg = "The following endpoints have been documented but can't be found in urls.py:" for undocumented_path in undocumented_paths: - msg += "\n + {}".format(undocumented_path) + msg += f"\n + {undocumented_path}" raise AssertionError(msg) def get_type_by_priority(self, types: Sequence[Union[type, Tuple[type, object]]]) -> Union[type, Tuple[type, object]]: @@ -417,7 +417,7 @@ do not match the types declared in the implementation of {}.\n""".format(functio if element[0] == vname: fdvtype = element[1] break - msg += "{:<10s}{:^30s}{:>10s}\n".format(vname, str(opvtype), str(fdvtype)) + msg += f"{vname:<10s}{str(opvtype):^30s}{str(fdvtype):>10s}\n" raise AssertionError(msg) def check_argument_types(self, function: Callable[..., HttpResponse], diff --git a/zerver/tests/test_outgoing_webhook_system.py b/zerver/tests/test_outgoing_webhook_system.py index ddfe0bd03e..fa7df64c6c 100644 --- a/zerver/tests/test_outgoing_webhook_system.py +++ b/zerver/tests/test_outgoing_webhook_system.py @@ -241,7 +241,7 @@ class TestOutgoingWebhookMessaging(ZulipTestCase): bot = self.create_outgoing_bot(bot_owner) self.send_stream_message(bot_owner, "Denmark", - content="@**{}** foo".format(bot.full_name), + content=f"@**{bot.full_name}** foo", topic_name="bar") last_message = self.get_last_message() self.assertEqual(last_message.content, "Hidley ho, I'm a webhook responding!") diff --git a/zerver/tests/test_presence.py b/zerver/tests/test_presence.py index 6a4386282b..4504ed2559 100644 --- a/zerver/tests/test_presence.py +++ b/zerver/tests/test_presence.py @@ -498,7 +498,7 @@ class UserPresenceAggregationTests(ZulipTestCase): } ) - result = self.client_get("/json/users/{}/presence".format(user.email)) + result = self.client_get(f"/json/users/{user.email}/presence") return result.json() def test_aggregated_info(self) -> None: diff --git a/zerver/tests/test_push_notifications.py b/zerver/tests/test_push_notifications.py index f694526227..457c3aec29 100644 --- a/zerver/tests/test_push_notifications.py +++ b/zerver/tests/test_push_notifications.py @@ -559,8 +559,8 @@ class AnalyticsBouncerTest(BouncerTestCase): check_for_unwanted_data.first_call = False # type: ignore[attr-defined] else: # Test that we're respecting SYNCED_BILLING_EVENTS - self.assertIn('"event_type":{}'.format(RealmAuditLog.USER_REACTIVATED), str(args)) - self.assertNotIn('"event_type":{}'.format(RealmAuditLog.REALM_LOGO_CHANGED), str(args)) + self.assertIn(f'"event_type":{RealmAuditLog.USER_REACTIVATED}', str(args)) + self.assertNotIn(f'"event_type":{RealmAuditLog.REALM_LOGO_CHANGED}', str(args)) # Test that we're respecting REALMAUDITLOG_PUSHED_FIELDS self.assertIn('backfilled', str(args)) self.assertNotIn('modified_user', str(args)) @@ -1774,7 +1774,7 @@ class TestClearOnRead(ZulipTestCase): message_ids = [self.send_stream_message(self.example_user("iago"), stream.name, - "yo {}".format(i)) + f"yo {i}") for i in range(n_msgs)] UserMessage.objects.filter( user_profile_id=hamlet.id, diff --git a/zerver/tests/test_realm_export.py b/zerver/tests/test_realm_export.py index 4c2c7822bf..0c0a040699 100644 --- a/zerver/tests/test_realm_export.py +++ b/zerver/tests/test_realm_export.py @@ -78,7 +78,7 @@ class RealmExportTest(ZulipTestCase): event_type=RealmAuditLog.REALM_EXPORTED).count()) # Finally, delete the file. - result = self.client_delete('/json/export/realm/{id}'.format(id=audit_log_entry.id)) + result = self.client_delete(f'/json/export/realm/{audit_log_entry.id}') self.assert_json_success(result) with self.assertRaises(botocore.exceptions.ClientError): bucket.Object(path_id).load() @@ -87,7 +87,7 @@ class RealmExportTest(ZulipTestCase): audit_log_entry.refresh_from_db() export_data = ujson.loads(audit_log_entry.extra_data) self.assertIn('deleted_timestamp', export_data) - result = self.client_delete('/json/export/realm/{id}'.format(id=audit_log_entry.id)) + result = self.client_delete(f'/json/export/realm/{audit_log_entry.id}') self.assert_json_error(result, "Export already deleted") # Now try to delete a non-existent export. @@ -137,7 +137,7 @@ class RealmExportTest(ZulipTestCase): event_type=RealmAuditLog.REALM_EXPORTED).count()) # Finally, delete the file. - result = self.client_delete('/json/export/realm/{id}'.format(id=audit_log_entry.id)) + result = self.client_delete(f'/json/export/realm/{audit_log_entry.id}') self.assert_json_success(result) response = self.client_get(path_id) self.assertEqual(response.status_code, 404) @@ -146,7 +146,7 @@ class RealmExportTest(ZulipTestCase): audit_log_entry.refresh_from_db() export_data = ujson.loads(audit_log_entry.extra_data) self.assertIn('deleted_timestamp', export_data) - result = self.client_delete('/json/export/realm/{id}'.format(id=audit_log_entry.id)) + result = self.client_delete(f'/json/export/realm/{audit_log_entry.id}') self.assert_json_error(result, "Export already deleted") # Now try to delete a non-existent export. diff --git a/zerver/tests/test_realm_filters.py b/zerver/tests/test_realm_filters.py index 90f3b8d167..f94c2b1881 100644 --- a/zerver/tests/test_realm_filters.py +++ b/zerver/tests/test_realm_filters.py @@ -107,9 +107,9 @@ class RealmFilterTest(ZulipTestCase): "#(?P[123])", "https://realm.com/my_realm_filter/%(id)s") filters_count = RealmFilter.objects.count() - result = self.client_delete("/json/realm/filters/{}".format(filter_id + 1)) + result = self.client_delete(f"/json/realm/filters/{filter_id + 1}") self.assert_json_error(result, 'Filter not found') - result = self.client_delete("/json/realm/filters/{}".format(filter_id)) + result = self.client_delete(f"/json/realm/filters/{filter_id}") self.assert_json_success(result) self.assertEqual(RealmFilter.objects.count(), filters_count - 1) diff --git a/zerver/tests/test_signup.py b/zerver/tests/test_signup.py index a67d978300..ecaf78ab62 100644 --- a/zerver/tests/test_signup.py +++ b/zerver/tests/test_signup.py @@ -257,7 +257,7 @@ class PasswordResetTest(ZulipTestCase): email, url_pattern=settings.EXTERNAL_HOST + r"(\S\S+)") result = self.client_get(password_reset_url) self.assertEqual(result.status_code, 302) - self.assertTrue(result.url.endswith('/{}/'.format(INTERNAL_RESET_URL_TOKEN))) + self.assertTrue(result.url.endswith(f'/{INTERNAL_RESET_URL_TOKEN}/')) final_reset_url = result.url result = self.client_get(final_reset_url) @@ -593,7 +593,7 @@ class LoginTest(ZulipTestCase): reset_emails_in_zulip_realm() realm = get_realm("zulip") - stream_names = ["stream_{}".format(i) for i in range(40)] + stream_names = [f"stream_{i}" for i in range(40)] for stream_name in stream_names: stream = self.make_stream(stream_name, realm=realm) DefaultStream.objects.create(stream=stream, realm=realm) @@ -1007,7 +1007,7 @@ class InviteUserTest(InviteUserBase): """ self.login('hamlet') email = "alice-test@zulip.com" - invitee = "Alice Test <{}>".format(email) + invitee = f"Alice Test <{email}>" self.assert_json_success(self.invite(invitee, ["Denmark"])) self.assertTrue(find_key_by_email(email)) self.check_sent_emails([email], custom_from_name="Hamlet") @@ -1020,7 +1020,7 @@ class InviteUserTest(InviteUserBase): self.login('hamlet') email = "alice-test@zulip.com" email2 = "bob-test@zulip.com" - invitee = "Alice Test <{}>, {}".format(email, email2) + invitee = f"Alice Test <{email}>, {email2}" self.assert_json_success(self.invite(invitee, ["Denmark"])) self.assertTrue(find_key_by_email(email)) self.assertTrue(find_key_by_email(email2)) @@ -1037,7 +1037,7 @@ class InviteUserTest(InviteUserBase): self.login('hamlet') email = "alice-test@zulip.com" email2 = "bob-test@zulip.com" - invitee = "Alice Test <{}>, {}".format(email, email2) + invitee = f"Alice Test <{email}>, {email2}" self.assert_json_error(self.invite(invitee, ["Denmark"]), "Must be an organization administrator") @@ -1090,7 +1090,7 @@ class InviteUserTest(InviteUserBase): second_msg = last_3_messages[1] self.assertEqual(second_msg.sender.email, "notification-bot@zulip.com") self.assertTrue(second_msg.content.startswith( - "alice_zulip.com <`{}`> accepted your".format(invitee_profile.email) + f"alice_zulip.com <`{invitee_profile.email}`> accepted your" )) # The second, from welcome-bot to the user who was invited. @@ -1175,7 +1175,7 @@ earl-test@zulip.com""", ["Denmark"])) """ self.login('hamlet') self.assert_json_error(self.invite("iago-test@zulip.com", ["NotARealStream"]), - "Stream does not exist with id: {}. No invites were sent.".format(self.INVALID_STREAM_ID)) + f"Stream does not exist with id: {self.INVALID_STREAM_ID}. No invites were sent.") self.check_sent_emails([]) def test_invite_existing_user(self) -> None: @@ -1878,22 +1878,22 @@ class InviteeEmailsParserTests(TestCase): self.email3 = "email3@zulip.com" def test_if_emails_separated_by_commas_are_parsed_and_striped_correctly(self) -> None: - emails_raw = "{} ,{}, {}".format(self.email1, self.email2, self.email3) + emails_raw = f"{self.email1} ,{self.email2}, {self.email3}" expected_set = {self.email1, self.email2, self.email3} self.assertEqual(get_invitee_emails_set(emails_raw), expected_set) def test_if_emails_separated_by_newlines_are_parsed_and_striped_correctly(self) -> None: - emails_raw = "{}\n {}\n {} ".format(self.email1, self.email2, self.email3) + emails_raw = f"{self.email1}\n {self.email2}\n {self.email3} " expected_set = {self.email1, self.email2, self.email3} self.assertEqual(get_invitee_emails_set(emails_raw), expected_set) def test_if_emails_from_email_client_separated_by_newlines_are_parsed_correctly(self) -> None: - emails_raw = "Email One <{}>\nEmailTwo<{}>\nEmail Three<{}>".format(self.email1, self.email2, self.email3) + emails_raw = f"Email One <{self.email1}>\nEmailTwo<{self.email2}>\nEmail Three<{self.email3}>" expected_set = {self.email1, self.email2, self.email3} self.assertEqual(get_invitee_emails_set(emails_raw), expected_set) def test_if_emails_in_mixed_style_are_parsed_correctly(self) -> None: - emails_raw = "Email One <{}>,EmailTwo<{}>\n{}".format(self.email1, self.email2, self.email3) + emails_raw = f"Email One <{self.email1}>,EmailTwo<{self.email2}>\n{self.email3}" expected_set = {self.email1, self.email2, self.email3} self.assertEqual(get_invitee_emails_set(emails_raw), expected_set) @@ -3018,7 +3018,7 @@ class UserSignUpTest(InviteUserBase): request.session = {} # type: ignore[attr-defined] email = 'user@acme.com' form = HomepageForm({'email': email}, realm=realm) - self.assertIn("Your email address, {}, is not in one of the domains".format(email), + self.assertIn(f"Your email address, {email}, is not in one of the domains", form.errors['email'][0]) def test_failed_signup_due_to_disposable_email(self) -> None: @@ -3052,7 +3052,7 @@ class UserSignUpTest(InviteUserBase): request.session = {} # type: ignore[attr-defined] email = 'user@zulip.com' form = HomepageForm({'email': email}, realm=realm) - self.assertIn("Please request an invite for {} from".format(email), + self.assertIn(f"Please request an invite for {email} from", form.errors['email'][0]) def test_failed_signup_due_to_nonexistent_realm(self) -> None: @@ -3856,10 +3856,10 @@ class UserSignUpTest(InviteUserBase): result = self.client_post('/devtools/register_realm/') self.assertEqual(result.status_code, 302) self.assertTrue(result["Location"].startswith( - 'http://{}.testserver/accounts/login/subdomain'.format(string_id))) + f'http://{string_id}.testserver/accounts/login/subdomain')) result = self.client_get(result["Location"], subdomain=string_id) self.assertEqual(result.status_code, 302) - self.assertEqual(result["Location"], 'http://{}.testserver'.format(string_id)) + self.assertEqual(result["Location"], f'http://{string_id}.testserver') user_profile = UserProfile.objects.all().order_by("id").last() self.assert_logged_in_user_id(user_profile.id) @@ -4041,7 +4041,7 @@ class TestFindMyTeam(ZulipTestCase): self.assertEqual(len(outbox), 0) def test_find_team_more_than_ten_emails(self) -> None: - data = {'emails': ','.join(['hamlet-{}@zulip.com'.format(i) for i in range(11)])} + data = {'emails': ','.join([f'hamlet-{i}@zulip.com' for i in range(11)])} result = self.client_post('/accounts/find/', data) self.assertEqual(result.status_code, 200) self.assertIn("Please enter at most 10", result.content.decode('utf8')) diff --git a/zerver/tests/test_slack_importer.py b/zerver/tests/test_slack_importer.py index fa85c051f1..cff36c07b2 100644 --- a/zerver/tests/test_slack_importer.py +++ b/zerver/tests/test_slack_importer.py @@ -831,7 +831,7 @@ class SlackImporter(ZulipTestCase): image_path = zerver_attachment[0]['path_id'] self.assertIn('/SlackImportAttachment/', image_path) - expected_content = '[Apple](/user_uploads/{image_path})\n[banana](example.com/banana.zip)'.format(image_path=image_path) + expected_content = f'[Apple](/user_uploads/{image_path})\n[banana](example.com/banana.zip)' self.assertEqual(info['content'], expected_content) self.assertTrue(info['has_link']) diff --git a/zerver/tests/test_subs.py b/zerver/tests/test_subs.py index f62e86e45f..7518f82ced 100644 --- a/zerver/tests/test_subs.py +++ b/zerver/tests/test_subs.py @@ -702,7 +702,7 @@ class StreamAdminTest(ZulipTestCase): # Inspect the notification message sent message = self.get_last_message() actual_stream = Stream.objects.get(id=message.recipient.type_id) - message_content = '@_**King Hamlet|{}** renamed stream **stream_name1** to **stream_name2**.'.format(user_profile.id) + message_content = f'@_**King Hamlet|{user_profile.id}** renamed stream **stream_name1** to **stream_name2**.' self.assertEqual(actual_stream.name, 'stream_name2') self.assertEqual(actual_stream.realm_id, user_profile.realm_id) self.assertEqual(message.recipient.type, Recipient.STREAM) @@ -1458,11 +1458,11 @@ class DefaultStreamGroupTest(ZulipTestCase): new_streams.append(new_stream) streams.append(new_stream) - result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id), + result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams", {"stream_names": ujson.dumps(new_stream_names)}) self.assert_json_error(result, "Missing 'op' argument") - result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id), + result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams", {"op": "invalid", "stream_names": ujson.dumps(new_stream_names)}) self.assert_json_error(result, 'Invalid value for "op". Specify one of "add" or "remove".') @@ -1470,16 +1470,16 @@ class DefaultStreamGroupTest(ZulipTestCase): {"op": "add", "stream_names": ujson.dumps(new_stream_names)}) self.assert_json_error(result, "Default stream group with id '12345' does not exist.") - result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id), {"op": "add"}) + result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams", {"op": "add"}) self.assert_json_error(result, "Missing 'stream_names' argument") do_add_default_stream(new_streams[0]) - result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id), + result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams", {"op": "add", "stream_names": ujson.dumps(new_stream_names)}) self.assert_json_error(result, "'stream4' is a default stream and cannot be added to 'group1'") do_remove_default_stream(new_streams[0]) - result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id), + result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams", {"op": "add", "stream_names": ujson.dumps(new_stream_names)}) self.assert_json_success(result) default_stream_groups = get_default_stream_groups(realm) @@ -1487,7 +1487,7 @@ class DefaultStreamGroupTest(ZulipTestCase): self.assertEqual(default_stream_groups[0].name, group_name) self.assertEqual(list(default_stream_groups[0].streams.all().order_by('name')), streams) - result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id), + result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams", {"op": "add", "stream_names": ujson.dumps(new_stream_names)}) self.assert_json_error(result, "Stream 'stream4' is already present in default stream group 'group1'") @@ -1497,12 +1497,12 @@ class DefaultStreamGroupTest(ZulipTestCase): {"op": "remove", "stream_names": ujson.dumps(new_stream_names)}) self.assert_json_error(result, "Default stream group with id '12345' does not exist.") - result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id), + result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams", {"op": "remove", "stream_names": ujson.dumps(["random stream name"])}) self.assert_json_error(result, "Invalid stream name 'random stream name'") streams.remove(new_streams[0]) - result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id), + result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams", {"op": "remove", "stream_names": ujson.dumps([new_stream_names[0]])}) self.assert_json_success(result) default_stream_groups = get_default_stream_groups(realm) @@ -1510,14 +1510,14 @@ class DefaultStreamGroupTest(ZulipTestCase): self.assertEqual(default_stream_groups[0].name, group_name) self.assertEqual(list(default_stream_groups[0].streams.all().order_by('name')), streams) - result = self.client_patch("/json/default_stream_groups/{}/streams".format(group_id), + result = self.client_patch(f"/json/default_stream_groups/{group_id}/streams", {"op": "remove", "stream_names": ujson.dumps(new_stream_names)}) self.assert_json_error(result, "Stream 'stream4' is not present in default stream group 'group1'") # Test changing description of default stream group new_description = "new group1 description" - result = self.client_patch("/json/default_stream_groups/{}".format(group_id), + result = self.client_patch(f"/json/default_stream_groups/{group_id}", {"group_name": group_name, "op": "change"}) self.assert_json_error(result, 'You must pass "new_description" or "new_group_name".') @@ -1525,7 +1525,7 @@ class DefaultStreamGroupTest(ZulipTestCase): {"op": "change", "new_description": ujson.dumps(new_description)}) self.assert_json_error(result, "Default stream group with id '12345' does not exist.") - result = self.client_patch("/json/default_stream_groups/{}".format(group_id), + result = self.client_patch(f"/json/default_stream_groups/{group_id}", {"group_name": group_name, "op": "change", "new_description": ujson.dumps(new_description)}) @@ -1538,17 +1538,17 @@ class DefaultStreamGroupTest(ZulipTestCase): # Test changing name of default stream group new_group_name = "new group1" do_create_default_stream_group(realm, "group2", "", []) - result = self.client_patch("/json/default_stream_groups/{}".format(group_id), + result = self.client_patch(f"/json/default_stream_groups/{group_id}", {"op": "change", "new_group_name": ujson.dumps("group2")}) self.assert_json_error(result, "Default stream group 'group2' already exists") new_group = lookup_default_stream_groups(["group2"], realm)[0] do_remove_default_stream_group(realm, new_group) - result = self.client_patch("/json/default_stream_groups/{}".format(group_id), + result = self.client_patch(f"/json/default_stream_groups/{group_id}", {"op": "change", "new_group_name": ujson.dumps(group_name)}) self.assert_json_error(result, "This default stream group is already named 'group1'") - result = self.client_patch("/json/default_stream_groups/{}".format(group_id), + result = self.client_patch(f"/json/default_stream_groups/{group_id}", {"op": "change", "new_group_name": ujson.dumps(new_group_name)}) self.assert_json_success(result) default_stream_groups = get_default_stream_groups(realm) @@ -1557,13 +1557,13 @@ class DefaultStreamGroupTest(ZulipTestCase): self.assertEqual(default_stream_groups[0].description, new_description) # Test deleting a default stream group - result = self.client_delete('/json/default_stream_groups/{}'.format(group_id)) + result = self.client_delete(f'/json/default_stream_groups/{group_id}') self.assert_json_success(result) default_stream_groups = get_default_stream_groups(realm) self.assert_length(default_stream_groups, 0) - result = self.client_delete('/json/default_stream_groups/{}'.format(group_id)) - self.assert_json_error(result, "Default stream group with id '{}' does not exist.".format(group_id)) + result = self.client_delete(f'/json/default_stream_groups/{group_id}') + self.assert_json_error(result, f"Default stream group with id '{group_id}' does not exist.") def test_invalid_default_stream_group_name(self) -> None: self.login('iago') @@ -2900,7 +2900,7 @@ class SubscriptionAPITest(ZulipTestCase): result = self.common_subscribe_to_streams(self.test_user, "Denmark", post_data) self.assert_json_error( result, - "User not authorized to execute queries on behalf of '{}'".format(target_profile.id), + f"User not authorized to execute queries on behalf of '{target_profile.id}'", status_code=403) def test_subscriptions_add_for_principal_invite_only(self) -> None: diff --git a/zerver/tests/test_tornado.py b/zerver/tests/test_tornado.py index 2a758c7d76..18d2dc3ff0 100644 --- a/zerver/tests/test_tornado.py +++ b/zerver/tests/test_tornado.py @@ -66,7 +66,7 @@ class TornadoWebTestCase(AsyncHTTPTestCase, ZulipTestCase): session_cookie = settings.SESSION_COOKIE_NAME session_key = self.client.session.session_key self.session_cookie = { - "Cookie": "{}={}".format(session_cookie, session_key) + "Cookie": f"{session_cookie}={session_key}" } def get_session_cookie(self) -> Dict[str, str]: @@ -102,7 +102,7 @@ class EventsTestCase(TornadoWebTestCase): 'last_event_id': -1, } - path = '/json/events?{}'.format(urllib.parse.urlencode(data)) + path = f'/json/events?{urllib.parse.urlencode(data)}' self.client_get_async(path) def process_events() -> None: diff --git a/zerver/tests/test_upload.py b/zerver/tests/test_upload.py index a2918d82aa..e7bbe18227 100644 --- a/zerver/tests/test_upload.py +++ b/zerver/tests/test_upload.py @@ -353,9 +353,9 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase): self.subscribe(self.example_user("hamlet"), "Denmark") host = self.example_user('hamlet').realm.host - body = "First message ...[zulip.txt](http://{}/user_uploads/".format(host) + d1_path_id + ")" + body = f"First message ...[zulip.txt](http://{host}/user_uploads/" + d1_path_id + ")" self.send_stream_message(self.example_user("hamlet"), "Denmark", body, "test") - body = "Second message ...[zulip.txt](http://{}/user_uploads/".format(host) + d1_path_id + ")" + body = f"Second message ...[zulip.txt](http://{host}/user_uploads/" + d1_path_id + ")" self.send_stream_message(self.example_user("hamlet"), "Denmark", body, "test") self.assertEqual(Attachment.objects.get(path_id=d1_path_id).messages.count(), 2) @@ -374,25 +374,25 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase): self.subscribe(self.example_user("hamlet"), "private_stream") # First, send the message to the new private stream. - body = "First message ...[zulip.txt](http://{}/user_uploads/".format(host) + d1_path_id + ")" + body = f"First message ...[zulip.txt](http://{host}/user_uploads/" + d1_path_id + ")" self.send_stream_message(self.example_user("hamlet"), "private_stream", body, "test") self.assertFalse(Attachment.objects.get(path_id=d1_path_id).is_realm_public) self.assertEqual(Attachment.objects.get(path_id=d1_path_id).messages.count(), 1) # Then, try having a user who didn't receive the message try to publish it, and fail - body = "Illegal message ...[zulip.txt](http://{}/user_uploads/".format(host) + d1_path_id + ")" + body = f"Illegal message ...[zulip.txt](http://{host}/user_uploads/" + d1_path_id + ")" self.send_stream_message(self.example_user("cordelia"), "Denmark", body, "test") self.assertEqual(Attachment.objects.get(path_id=d1_path_id).messages.count(), 1) self.assertFalse(Attachment.objects.get(path_id=d1_path_id).is_realm_public) # Then, have the owner PM it to another user, giving that other user access. - body = "Second message ...[zulip.txt](http://{}/user_uploads/".format(host) + d1_path_id + ")" + body = f"Second message ...[zulip.txt](http://{host}/user_uploads/" + d1_path_id + ")" self.send_personal_message(self.example_user("hamlet"), self.example_user("othello"), body) self.assertEqual(Attachment.objects.get(path_id=d1_path_id).messages.count(), 2) self.assertFalse(Attachment.objects.get(path_id=d1_path_id).is_realm_public) # Then, have that new recipient user publish it. - body = "Third message ...[zulip.txt](http://{}/user_uploads/".format(host) + d1_path_id + ")" + body = f"Third message ...[zulip.txt](http://{host}/user_uploads/" + d1_path_id + ")" self.send_stream_message(self.example_user("othello"), "Denmark", body, "test") self.assertEqual(Attachment.objects.get(path_id=d1_path_id).messages.count(), 3) self.assertTrue(Attachment.objects.get(path_id=d1_path_id).is_realm_public) @@ -415,14 +415,14 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase): f2_path_id = re.sub('/user_uploads/', '', result.json()['uri']) self.subscribe(hamlet, "test") - body = ("[f1.txt](http://{}/user_uploads/".format(host) + f1_path_id + ") " + body = (f"[f1.txt](http://{host}/user_uploads/" + f1_path_id + ") " "[f2.txt](http://{}/user_uploads/".format(host) + f2_path_id + ")") msg_id = self.send_stream_message(hamlet, "test", body, "test") result = self.client_post("/json/user_uploads", {'file': f3}) f3_path_id = re.sub('/user_uploads/', '', result.json()['uri']) - new_body = ("[f3.txt](http://{}/user_uploads/".format(host) + f3_path_id + ") " + new_body = (f"[f3.txt](http://{host}/user_uploads/" + f3_path_id + ") " "[f2.txt](http://{}/user_uploads/".format(host) + f2_path_id + ")") result = self.client_patch("/json/messages/" + str(msg_id), { 'message_id': msg_id, @@ -535,7 +535,7 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase): result = self.client_post("/json/user_uploads", {'file': fp}) uri = result.json()['uri'] fp_path_id = re.sub('/user_uploads/', '', uri) - body = "First message ...[zulip.txt](http://{}/user_uploads/".format(host) + fp_path_id + ")" + body = f"First message ...[zulip.txt](http://{host}/user_uploads/" + fp_path_id + ")" with self.settings(CROSS_REALM_BOT_EMAILS = {user_2.email, user_3.email}): internal_send_private_message( realm=r1, @@ -575,7 +575,7 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase): result = self.client_post("/json/user_uploads", {'file': fp}) uri = result.json()['uri'] fp_path_id = re.sub('/user_uploads/', '', uri) - body = "First message ...[zulip.txt](http://{}/user_uploads/".format(realm.host) + fp_path_id + ")" + body = f"First message ...[zulip.txt](http://{realm.host}/user_uploads/" + fp_path_id + ")" self.send_stream_message(hamlet, stream_name, body, "test") self.logout() @@ -629,7 +629,7 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase): result = self.client_post("/json/user_uploads", {'file': fp}) uri = result.json()['uri'] fp_path_id = re.sub('/user_uploads/', '', uri) - body = "First message ...[zulip.txt](http://{}/user_uploads/".format(user.realm.host) + fp_path_id + ")" + body = f"First message ...[zulip.txt](http://{user.realm.host}/user_uploads/" + fp_path_id + ")" self.send_stream_message(user, stream_name, body, "test") self.logout() @@ -697,7 +697,7 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase): uri = result.json()['uri'] fp_path_id = re.sub('/user_uploads/', '', uri) for i in range(20): - body = "First message ...[zulip.txt](http://{}/user_uploads/".format(hamlet.realm.host) + fp_path_id + ")" + body = f"First message ...[zulip.txt](http://{hamlet.realm.host}/user_uploads/" + fp_path_id + ")" self.send_stream_message(self.example_user("hamlet"), "test-subscribe %s" % (i % 5,), body, "test") self.logout() @@ -739,7 +739,7 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase): result = self.client_post("/json/user_uploads", {'file': fp}) uri = result.json()['uri'] fp_path_id = re.sub('/user_uploads/', '', uri) - body = "First message ...[zulip.txt](http://{}/user_uploads/".format(realm.host) + fp_path_id + ")" + body = f"First message ...[zulip.txt](http://{realm.host}/user_uploads/" + fp_path_id + ")" self.send_stream_message(self.example_user("hamlet"), "test-subscribe", body, "test") self.logout() @@ -1530,7 +1530,7 @@ class LocalStorageTest(UploadSerializeMixin, ZulipTestCase): realm_id=user_profile.realm_id, emoji_file_name=file_name, ) - expected_url = "/user_avatars/{emoji_path}".format(emoji_path=emoji_path) + expected_url = f"/user_avatars/{emoji_path}" self.assertEqual(expected_url, url) def test_tarball_upload_and_deletion_local(self) -> None: @@ -1843,7 +1843,7 @@ class S3Test(ZulipTestCase): url = zerver.lib.upload.upload_backend.get_emoji_url('emoji.png', realm_id) - expected_url = "https://{bucket}.s3.amazonaws.com/{path}".format(bucket=bucket, path=path) + expected_url = f"https://{bucket}.s3.amazonaws.com/{path}" self.assertEqual(expected_url, url) @use_s3_backend diff --git a/zerver/tests/test_user_groups.py b/zerver/tests/test_user_groups.py index eac9e9fa18..423a533dcb 100644 --- a/zerver/tests/test_user_groups.py +++ b/zerver/tests/test_user_groups.py @@ -150,11 +150,11 @@ class UserGroupAPITestCase(ZulipTestCase): 'name': 'help', 'description': 'Troubleshooting team', } - result = self.client_patch('/json/user_groups/{}'.format(user_group.id), info=params) + result = self.client_patch(f'/json/user_groups/{user_group.id}', info=params) self.assert_json_success(result) # Test when new data is not supplied. - result = self.client_patch('/json/user_groups/{}'.format(user_group.id), info={}) + result = self.client_patch(f'/json/user_groups/{user_group.id}', info={}) self.assert_json_error(result, "No new data supplied") # Test when invalid user group is supplied @@ -170,7 +170,7 @@ class UserGroupAPITestCase(ZulipTestCase): 'name': 'help', 'description': 'Troubleshooting', } - result = self.client_patch('/json/user_groups/{}'.format(user_group.id), info=params) + result = self.client_patch(f'/json/user_groups/{user_group.id}', info=params) self.assert_json_error(result, "Only group members and organization administrators can administer this group.") self.logout() @@ -181,7 +181,7 @@ class UserGroupAPITestCase(ZulipTestCase): 'name': 'help', 'description': 'Troubleshooting', } - result = self.client_patch('/json/user_groups/{}'.format(user_group.id), info=params) + result = self.client_patch(f'/json/user_groups/{user_group.id}', info=params) self.assert_json_success(result) def test_user_group_update_by_guest_user(self) -> None: @@ -203,7 +203,7 @@ class UserGroupAPITestCase(ZulipTestCase): 'name': 'help', 'description': 'Troubleshooting team', } - result = self.client_patch('/json/user_groups/{}'.format(user_group.id), info=params) + result = self.client_patch(f'/json/user_groups/{user_group.id}', info=params) self.assert_json_error(result, "Not allowed for guest users") def test_user_group_update_to_already_existing_name(self) -> None: @@ -216,9 +216,9 @@ class UserGroupAPITestCase(ZulipTestCase): params = { 'name': marketing_user_group.name, } - result = self.client_patch('/json/user_groups/{}'.format(support_user_group.id), info=params) + result = self.client_patch(f'/json/user_groups/{support_user_group.id}', info=params) self.assert_json_error( - result, "User group '{}' already exists.".format(marketing_user_group.name)) + result, f"User group '{marketing_user_group.name}' already exists.") def test_user_group_delete(self) -> None: hamlet = self.example_user('hamlet') @@ -233,7 +233,7 @@ class UserGroupAPITestCase(ZulipTestCase): # Test success self.assertEqual(UserGroup.objects.count(), 2) self.assertEqual(UserGroupMembership.objects.count(), 3) - result = self.client_delete('/json/user_groups/{}'.format(user_group.id)) + result = self.client_delete(f'/json/user_groups/{user_group.id}') self.assert_json_success(result) self.assertEqual(UserGroup.objects.count(), 1) self.assertEqual(UserGroupMembership.objects.count(), 2) @@ -255,7 +255,7 @@ class UserGroupAPITestCase(ZulipTestCase): cordelia = self.example_user('cordelia') self.login_user(cordelia) - result = self.client_delete('/json/user_groups/{}'.format(user_group.id)) + result = self.client_delete(f'/json/user_groups/{user_group.id}') self.assert_json_error(result, "Only group members and organization administrators can administer this group.") self.assertEqual(UserGroup.objects.count(), 2) @@ -264,7 +264,7 @@ class UserGroupAPITestCase(ZulipTestCase): iago = self.example_user('iago') self.login_user(iago) - result = self.client_delete('/json/user_groups/{}'.format(user_group.id)) + result = self.client_delete(f'/json/user_groups/{user_group.id}') self.assert_json_success(result) self.assertEqual(UserGroup.objects.count(), 1) self.assertEqual(UserGroupMembership.objects.count(), 2) @@ -284,7 +284,7 @@ class UserGroupAPITestCase(ZulipTestCase): # Guest users can't delete any user group(not even those of which they are a member) self.login_user(guest_user) - result = self.client_delete('/json/user_groups/{}'.format(user_group.id)) + result = self.client_delete(f'/json/user_groups/{user_group.id}') self.assert_json_error(result, "Not allowed for guest users") def test_update_members_of_user_group(self) -> None: @@ -303,7 +303,7 @@ class UserGroupAPITestCase(ZulipTestCase): othello = self.example_user('othello') add = [othello.id] params = {'add': ujson.dumps(add)} - result = self.client_post('/json/user_groups/{}/members'.format(user_group.id), + result = self.client_post(f'/json/user_groups/{user_group.id}/members', info=params) self.assert_json_success(result) self.assertEqual(UserGroupMembership.objects.count(), 4) @@ -311,9 +311,9 @@ class UserGroupAPITestCase(ZulipTestCase): self.assertEqual(len(members), 2) # Test adding a member already there. - result = self.client_post('/json/user_groups/{}/members'.format(user_group.id), + result = self.client_post(f'/json/user_groups/{user_group.id}/members', info=params) - self.assert_json_error(result, "User {} is already a member of this group".format(othello.id)) + self.assert_json_error(result, f"User {othello.id} is already a member of this group") self.assertEqual(UserGroupMembership.objects.count(), 4) members = get_memberships_of_users(user_group, [hamlet, othello]) self.assertEqual(len(members), 2) @@ -324,7 +324,7 @@ class UserGroupAPITestCase(ZulipTestCase): self.login_user(cordelia) add = [cordelia.id] params = {'add': ujson.dumps(add)} - result = self.client_post('/json/user_groups/{}/members'.format(user_group.id), + result = self.client_post(f'/json/user_groups/{user_group.id}/members', info=params) self.assert_json_error(result, "Only group members and organization administrators can administer this group.") self.assertEqual(UserGroupMembership.objects.count(), 4) @@ -336,7 +336,7 @@ class UserGroupAPITestCase(ZulipTestCase): aaron = self.example_user('aaron') add = [aaron.id] params = {'add': ujson.dumps(add)} - result = self.client_post('/json/user_groups/{}/members'.format(user_group.id), + result = self.client_post(f'/json/user_groups/{user_group.id}/members', info=params) self.assert_json_success(result) self.assertEqual(UserGroupMembership.objects.count(), 5) @@ -348,7 +348,7 @@ class UserGroupAPITestCase(ZulipTestCase): self.login_user(hamlet) # Test remove members params = {'delete': ujson.dumps([othello.id])} - result = self.client_post('/json/user_groups/{}/members'.format(user_group.id), + result = self.client_post(f'/json/user_groups/{user_group.id}/members', info=params) self.assert_json_success(result) self.assertEqual(UserGroupMembership.objects.count(), 4) @@ -357,15 +357,15 @@ class UserGroupAPITestCase(ZulipTestCase): # Test remove a member that's already removed params = {'delete': ujson.dumps([othello.id])} - result = self.client_post('/json/user_groups/{}/members'.format(user_group.id), + result = self.client_post(f'/json/user_groups/{user_group.id}/members', info=params) - self.assert_json_error(result, "There is no member '{}' in this user group".format(othello.id)) + self.assert_json_error(result, f"There is no member '{othello.id}' in this user group") self.assertEqual(UserGroupMembership.objects.count(), 4) members = get_memberships_of_users(user_group, [hamlet, othello, aaron]) self.assertEqual(len(members), 2) # Test when nothing is provided - result = self.client_post('/json/user_groups/{}/members'.format(user_group.id), + result = self.client_post(f'/json/user_groups/{user_group.id}/members', info={}) msg = 'Nothing to do. Specify at least one of "add" or "delete".' self.assert_json_error(result, msg) @@ -374,7 +374,7 @@ class UserGroupAPITestCase(ZulipTestCase): self.logout() self.login_user(cordelia) params = {'delete': ujson.dumps([hamlet.id])} - result = self.client_post('/json/user_groups/{}/members'.format(user_group.id), + result = self.client_post(f'/json/user_groups/{user_group.id}/members', info=params) self.assert_json_error(result, "Only group members and organization administrators can administer this group.") self.assertEqual(UserGroupMembership.objects.count(), 4) @@ -383,7 +383,7 @@ class UserGroupAPITestCase(ZulipTestCase): # Test when organization admin tries to remove members from group iago = self.example_user('iago') self.login_user(iago) - result = self.client_post('/json/user_groups/{}/members'.format(user_group.id), + result = self.client_post(f'/json/user_groups/{user_group.id}/members', info=params) self.assert_json_success(result) self.assertEqual(UserGroupMembership.objects.count(), 3) @@ -460,13 +460,13 @@ class UserGroupAPITestCase(ZulipTestCase): # Test add member params = {'add': ujson.dumps([cordelia.id])} - result = self.client_post('/json/user_groups/{}/members'.format(user_group.id), + result = self.client_post(f'/json/user_groups/{user_group.id}/members', info=params) self.assert_json_success(result) # Test remove member params = {'delete': ujson.dumps([cordelia.id])} - result = self.client_post('/json/user_groups/{}/members'.format(user_group.id), + result = self.client_post(f'/json/user_groups/{user_group.id}/members', info=params) self.assert_json_success(result) @@ -475,11 +475,11 @@ class UserGroupAPITestCase(ZulipTestCase): 'name': 'help', 'description': 'Troubleshooting', } - result = self.client_patch('/json/user_groups/{}'.format(user_group.id), info=params) + result = self.client_patch(f'/json/user_groups/{user_group.id}', info=params) self.assert_json_success(result) # Test delete a group - result = self.client_delete('/json/user_groups/{}'.format(user_group.id)) + result = self.client_delete(f'/json/user_groups/{user_group.id}') self.assert_json_success(result) user_group = create_user_group(name='support', @@ -502,12 +502,12 @@ class UserGroupAPITestCase(ZulipTestCase): # Test add member params = {'add': ujson.dumps([cordelia.id])} - result = self.client_post('/json/user_groups/{}/members'.format(user_group.id), + result = self.client_post(f'/json/user_groups/{user_group.id}/members', info=params) self.assert_json_error(result, "Must be an organization administrator") # Test delete a group - result = self.client_delete('/json/user_groups/{}'.format(user_group.id)) + result = self.client_delete(f'/json/user_groups/{user_group.id}') self.assert_json_error(result, "Must be an organization administrator") # Test changing groups name @@ -515,5 +515,5 @@ class UserGroupAPITestCase(ZulipTestCase): 'name': 'help', 'description': 'Troubleshooting', } - result = self.client_patch('/json/user_groups/{}'.format(user_group.id), info=params) + result = self.client_patch(f'/json/user_groups/{user_group.id}', info=params) self.assert_json_error(result, "Must be an organization administrator") diff --git a/zerver/tests/test_users.py b/zerver/tests/test_users.py index 8515e91c90..b1c052dcd2 100644 --- a/zerver/tests/test_users.py +++ b/zerver/tests/test_users.py @@ -116,7 +116,7 @@ class PermissionTest(ZulipTestCase): do_change_user_role(admin, UserProfile.ROLE_REALM_ADMINISTRATOR) invalid_user_id = 1000 - result = self.client_patch('/json/users/{}'.format(invalid_user_id), {}) + result = self.client_patch(f'/json/users/{invalid_user_id}', {}) self.assert_json_error(result, 'No such user') def test_admin_api(self) -> None: @@ -142,7 +142,7 @@ class PermissionTest(ZulipTestCase): events: List[Mapping[str, Any]] = [] with tornado_redirected_to_list(events): - result = self.client_patch('/json/users/{}'.format(othello.id), req) + result = self.client_patch(f'/json/users/{othello.id}', req) self.assert_json_success(result) admin_users = realm.get_human_admin_users() self.assertTrue(othello in admin_users) @@ -154,7 +154,7 @@ class PermissionTest(ZulipTestCase): req = dict(role=ujson.dumps(UserProfile.ROLE_MEMBER)) events = [] with tornado_redirected_to_list(events): - result = self.client_patch('/json/users/{}'.format(othello.id), req) + result = self.client_patch(f'/json/users/{othello.id}', req) self.assert_json_success(result) admin_users = realm.get_human_admin_users() self.assertFalse(othello in admin_users) @@ -167,7 +167,7 @@ class PermissionTest(ZulipTestCase): req = dict(role=ujson.dumps(UserProfile.ROLE_MEMBER)) events = [] with tornado_redirected_to_list(events): - result = self.client_patch('/json/users/{}'.format(desdemona.id), req) + result = self.client_patch(f'/json/users/{desdemona.id}', req) self.assert_json_success(result) admin_users = realm.get_human_admin_users() self.assertFalse(desdemona in admin_users) @@ -175,12 +175,12 @@ class PermissionTest(ZulipTestCase): self.assertEqual(person['user_id'], desdemona.id) self.assertEqual(person['role'], UserProfile.ROLE_MEMBER) with tornado_redirected_to_list([]): - result = self.client_patch('/json/users/{}'.format(iago.id), req) + result = self.client_patch(f'/json/users/{iago.id}', req) self.assert_json_error(result, 'Cannot remove the only organization administrator') # Make sure only admins can patch other user's info. self.login('othello') - result = self.client_patch('/json/users/{}'.format(hamlet.id), req) + result = self.client_patch(f'/json/users/{hamlet.id}', req) self.assert_json_error(result, 'Insufficient permission') def test_admin_api_hide_emails(self) -> None: @@ -261,7 +261,7 @@ class PermissionTest(ZulipTestCase): self.login('iago') hamlet = self.example_user('hamlet') req = dict(full_name=ujson.dumps(new_name)) - result = self.client_patch('/json/users/{}'.format(hamlet.id), req) + result = self.client_patch(f'/json/users/{hamlet.id}', req) self.assert_json_success(result) hamlet = self.example_user('hamlet') self.assertEqual(hamlet.full_name, new_name) @@ -355,7 +355,7 @@ class PermissionTest(ZulipTestCase): req = dict(role=ujson.dumps(UserProfile.ROLE_GUEST)) events: List[Mapping[str, Any]] = [] with tornado_redirected_to_list(events): - result = self.client_patch('/json/users/{}'.format(hamlet.id), req) + result = self.client_patch(f'/json/users/{hamlet.id}', req) self.assert_json_success(result) hamlet = self.example_user("hamlet") @@ -374,7 +374,7 @@ class PermissionTest(ZulipTestCase): req = dict(role=ujson.dumps(UserProfile.ROLE_MEMBER)) events: List[Mapping[str, Any]] = [] with tornado_redirected_to_list(events): - result = self.client_patch('/json/users/{}'.format(polonius.id), req) + result = self.client_patch(f'/json/users/{polonius.id}', req) self.assert_json_success(result) polonius = self.example_user("polonius") @@ -397,7 +397,7 @@ class PermissionTest(ZulipTestCase): req = dict(role=ujson.dumps(UserProfile.ROLE_GUEST)) events: List[Mapping[str, Any]] = [] with tornado_redirected_to_list(events): - result = self.client_patch('/json/users/{}'.format(hamlet.id), req) + result = self.client_patch(f'/json/users/{hamlet.id}', req) self.assert_json_success(result) hamlet = self.example_user("hamlet") @@ -421,7 +421,7 @@ class PermissionTest(ZulipTestCase): req = dict(role=ujson.dumps(UserProfile.ROLE_REALM_ADMINISTRATOR)) events: List[Mapping[str, Any]] = [] with tornado_redirected_to_list(events): - result = self.client_patch('/json/users/{}'.format(polonius.id), req) + result = self.client_patch(f'/json/users/{polonius.id}', req) self.assert_json_success(result) polonius = self.example_user("polonius") @@ -457,7 +457,7 @@ class PermissionTest(ZulipTestCase): 'value': fields[field_name], }) - result = self.client_patch('/json/users/{}'.format(cordelia.id), + result = self.client_patch(f'/json/users/{cordelia.id}', {'profile_data': ujson.dumps(new_profile_data)}) self.assert_json_success(result) @@ -482,7 +482,7 @@ class PermissionTest(ZulipTestCase): 'value': field_value, }) - result = self.client_patch('/json/users/{}'.format(cordelia.id), + result = self.client_patch(f'/json/users/{cordelia.id}', {'profile_data': ujson.dumps(new_profile_data)}) self.assert_json_error(result, error_msg) @@ -491,7 +491,7 @@ class PermissionTest(ZulipTestCase): 'id': 9001, 'value': '' }] - result = self.client_patch('/json/users/{}'.format(cordelia.id), + result = self.client_patch(f'/json/users/{cordelia.id}', {'profile_data': ujson.dumps(invalid_profile_data)}) self.assert_json_error(result, 'Field id 9001 not found.') @@ -500,7 +500,7 @@ class PermissionTest(ZulipTestCase): 'id': 9001, 'value': 'some data' }] - result = self.client_patch('/json/users/{}'.format(cordelia.id), + result = self.client_patch(f'/json/users/{cordelia.id}', {'profile_data': ujson.dumps(invalid_profile_data)}) self.assert_json_error(result, 'Field id 9001 not found.') @@ -515,7 +515,7 @@ class PermissionTest(ZulipTestCase): 'id': field.id, 'value': value, }) - result = self.client_patch('/json/users/{}'.format(cordelia.id), + result = self.client_patch(f'/json/users/{cordelia.id}', {'profile_data': ujson.dumps(empty_profile_data)}) self.assert_json_success(result) for field_dict in cordelia.profile_data: @@ -544,7 +544,7 @@ class PermissionTest(ZulipTestCase): 'id': field.id, 'value': value, }) - result = self.client_patch('/json/users/{}'.format(cordelia.id), + result = self.client_patch(f'/json/users/{cordelia.id}', {'profile_data': ujson.dumps(new_profile_data)}) self.assert_json_success(result) for field_dict in cordelia.profile_data: @@ -562,7 +562,7 @@ class PermissionTest(ZulipTestCase): 'id': field.id, 'value': "New hamlet Biography", }) - result = self.client_patch('/json/users/{}'.format(hamlet.id), + result = self.client_patch(f'/json/users/{hamlet.id}', {'profile_data': ujson.dumps(new_profile_data)}) self.assert_json_error(result, 'Insufficient permission') @@ -586,7 +586,7 @@ class BulkCreateUserTest(ZulipTestCase): fred = get_user_by_delivery_email('fred@zulip.com', realm) self.assertEqual( fred.email, - 'user{}@zulip.testserver'.format(fred.id) + f'user{fred.id}@zulip.testserver' ) lisa = get_user_by_delivery_email('lisa@zulip.com', realm) @@ -970,12 +970,12 @@ class ActivateTest(ZulipTestCase): user = self.example_user('hamlet') self.assertTrue(user.is_active) - result = self.client_delete('/json/users/{}'.format(user.id)) + result = self.client_delete(f'/json/users/{user.id}') self.assert_json_success(result) user = self.example_user('hamlet') self.assertFalse(user.is_active) - result = self.client_post('/json/users/{}/reactivate'.format(user.id)) + result = self.client_post(f'/json/users/{user.id}/reactivate') self.assert_json_success(result) user = self.example_user('hamlet') self.assertTrue(user.is_active) @@ -990,7 +990,7 @@ class ActivateTest(ZulipTestCase): # Cannot deactivate a nonexistent user. invalid_user_id = 1000 - result = self.client_delete('/json/users/{}'.format(invalid_user_id)) + result = self.client_delete(f'/json/users/{invalid_user_id}') self.assert_json_error(result, 'No such user') result = self.client_delete('/json/users/{}'.format(self.example_user("webhook_bot").id)) @@ -999,12 +999,12 @@ class ActivateTest(ZulipTestCase): result = self.client_delete('/json/users/{}'.format(self.example_user("iago").id)) self.assert_json_success(result) - result = self.client_delete('/json/users/{}'.format(admin.id)) + result = self.client_delete(f'/json/users/{admin.id}') self.assert_json_error(result, 'Cannot deactivate the only organization administrator') # Cannot reactivate a nonexistent user. invalid_user_id = 1000 - result = self.client_post('/json/users/{}/reactivate'.format(invalid_user_id)) + result = self.client_post(f'/json/users/{invalid_user_id}/reactivate') self.assert_json_error(result, 'No such user') def test_api_with_insufficient_permissions(self) -> None: @@ -1398,7 +1398,7 @@ class GetProfileTest(ZulipTestCase): # Tests the GET ../users/{id} api endpoint. user = self.example_user('hamlet') - result = ujson.loads(self.client_get('/json/users/{}'.format(user.id)).content) + result = ujson.loads(self.client_get(f'/json/users/{user.id}').content) self.assertEqual(result['user']['email'], user.email) self.assertEqual(result['user']['full_name'], user.full_name) self.assertIn("user_id", result['user']) @@ -1407,14 +1407,14 @@ class GetProfileTest(ZulipTestCase): self.assertFalse(result['user']['is_admin']) self.assertFalse(result['user']['is_owner']) - result = ujson.loads(self.client_get('/json/users/{}?include_custom_profile_fields=true'.format(user.id)).content) + result = ujson.loads(self.client_get(f'/json/users/{user.id}?include_custom_profile_fields=true').content) self.assertIn('profile_data', result['user']) - result = self.client_get('/json/users/{}?'.format(30)) + result = self.client_get(f'/json/users/{30}?') self.assert_json_error(result, "No such user") bot = self.example_user("default_bot") - result = ujson.loads(self.client_get('/json/users/{}'.format(bot.id)).content) + result = ujson.loads(self.client_get(f'/json/users/{bot.id}').content) self.assertEqual(result['user']['email'], bot.email) self.assertTrue(result['user']['is_bot']) diff --git a/zerver/views/development/integrations.py b/zerver/views/development/integrations.py index 4ad97f2cd9..fbb0a4f02a 100644 --- a/zerver/views/development/integrations.py +++ b/zerver/views/development/integrations.py @@ -96,7 +96,7 @@ def check_send_webhook_fixture_message(request: HttpRequest, try: custom_headers_dict = ujson.loads(custom_headers) except ValueError as ve: - return json_error("Custom HTTP headers are not in a valid JSON format. {}".format(ve)) # nolint + return json_error(f"Custom HTTP headers are not in a valid JSON format. {ve}") # nolint response = send_webhook_fixture_message(url, body, is_json, custom_headers_dict) diff --git a/zerver/views/documentation.py b/zerver/views/documentation.py index 958515b525..452b84784b 100644 --- a/zerver/views/documentation.py +++ b/zerver/views/documentation.py @@ -153,12 +153,12 @@ def add_integrations_open_graph_context(context: Dict[str, Any], request: HttpRe if path_name in INTEGRATIONS: integration = INTEGRATIONS[path_name] - context['OPEN_GRAPH_TITLE'] = 'Connect {name} to Zulip'.format(name=integration.display_name) + context['OPEN_GRAPH_TITLE'] = f'Connect {integration.display_name} to Zulip' context['OPEN_GRAPH_DESCRIPTION'] = description elif path_name in CATEGORIES: category = CATEGORIES[path_name] - context['OPEN_GRAPH_TITLE'] = 'Connect your {category} tools to Zulip'.format(category=category) + context['OPEN_GRAPH_TITLE'] = f'Connect your {category} tools to Zulip' context['OPEN_GRAPH_DESCRIPTION'] = description elif path_name == 'integrations': diff --git a/zerver/views/messages.py b/zerver/views/messages.py index 58620413b9..3295c2c541 100644 --- a/zerver/views/messages.py +++ b/zerver/views/messages.py @@ -223,7 +223,7 @@ class NarrowBuilder: if ord(c) >= 128: # convert the character to hex postgres regex will take # \uXXXX - s[i] = '\\u{:0>4x}'.format(ord(c)) + s[i] = f'\\u{ord(c):0>4x}' else: s[i] = '\\' + c return ''.join(s) diff --git a/zerver/webhooks/alertmanager/view.py b/zerver/webhooks/alertmanager/view.py index 960c0ec390..1329bf3216 100644 --- a/zerver/webhooks/alertmanager/view.py +++ b/zerver/webhooks/alertmanager/view.py @@ -24,11 +24,11 @@ def api_alertmanager_webhook(request: HttpRequest, user_profile: UserProfile, name = labels.get( name_field, annotations.get(name_field, "(unknown)")) desc = labels.get( - desc_field, annotations.get(desc_field, "".format(desc_field))) + desc_field, annotations.get(desc_field, f"")) url = alert.get("generatorURL").replace("tab=1", "tab=0") - body = "{description} ([graph]({url}))".format(description=desc, url=url) + body = f"{desc} ([graph]({url}))" if name not in topics: topics[name] = {"firing": [], "resolved": []} topics[name][alert["status"]].append(body) @@ -51,7 +51,7 @@ def api_alertmanager_webhook(request: HttpRequest, user_profile: UserProfile, title=title, message=messages[0]) else: - message_list = "\n".join(["* {}".format(m) for m in messages]) + message_list = "\n".join([f"* {m}" for m in messages]) body = "{icon} **{title}**\n{messages}".format( icon=icon, title=title, diff --git a/zerver/webhooks/basecamp/view.py b/zerver/webhooks/basecamp/view.py index f76a2d976c..4efd4f8906 100644 --- a/zerver/webhooks/basecamp/view.py +++ b/zerver/webhooks/basecamp/view.py @@ -80,7 +80,7 @@ def get_verb(event: str, prefix: str) -> str: def add_punctuation_if_necessary(body: str, title: str) -> str: if title[-1] not in string.punctuation: - body = '{}.'.format(body) + body = f'{body}.' return body def get_document_body(event: str, payload: Dict[str, Any]) -> str: diff --git a/zerver/webhooks/bitbucket/tests.py b/zerver/webhooks/bitbucket/tests.py index b7f9da77f2..b1979283ad 100644 --- a/zerver/webhooks/bitbucket/tests.py +++ b/zerver/webhooks/bitbucket/tests.py @@ -16,7 +16,7 @@ class BitbucketHookTests(WebhookTestCase): fixture_name = 'push' self.url = self.build_webhook_url(payload=self.get_body(fixture_name)) commit_info = '* c ([25f93d2](https://bitbucket.org/kolaszek/repository-name/commits/25f93d22b719e2d678a7ad5ee0ef0d1fcdf39c12))' - expected_message = "kolaszek pushed 1 commit to branch master.\n\n{}".format(commit_info) + expected_message = f"kolaszek pushed 1 commit to branch master.\n\n{commit_info}" self.api_stream_message(self.test_user, fixture_name, self.EXPECTED_TOPIC_BRANCH_EVENTS, expected_message) @@ -24,7 +24,7 @@ class BitbucketHookTests(WebhookTestCase): fixture_name = 'push_without_user_info' self.url = self.build_webhook_url(payload=self.get_body(fixture_name)) commit_info = '* c ([25f93d2](https://bitbucket.org/kolaszek/repository-name/commits/25f93d22b719e2d678a7ad5ee0ef0d1fcdf39c12))' - expected_message = "Someone pushed 1 commit to branch master. Commits by eeshangarg (1).\n\n{}".format(commit_info) + expected_message = f"Someone pushed 1 commit to branch master. Commits by eeshangarg (1).\n\n{commit_info}" self.api_stream_message(self.test_user, fixture_name, self.EXPECTED_TOPIC_BRANCH_EVENTS, expected_message) @@ -33,7 +33,7 @@ class BitbucketHookTests(WebhookTestCase): self.url = self.build_webhook_url(payload=self.get_body(fixture_name), branches='master,development') commit_info = '* c ([25f93d2](https://bitbucket.org/kolaszek/repository-name/commits/25f93d22b719e2d678a7ad5ee0ef0d1fcdf39c12))' - expected_message = "kolaszek pushed 1 commit to branch master.\n\n{}".format(commit_info) + expected_message = f"kolaszek pushed 1 commit to branch master.\n\n{commit_info}" self.api_stream_message(self.test_user, fixture_name, self.EXPECTED_TOPIC_BRANCH_EVENTS, expected_message) @@ -41,7 +41,7 @@ class BitbucketHookTests(WebhookTestCase): fixture_name = 'push_commits_above_limit' self.url = self.build_webhook_url(payload=self.get_body(fixture_name)) commit_info = '* c ([25f93d2](https://bitbucket.org/kolaszek/repository-name/commits/25f93d22b719e2d678a7ad5ee0ef0d1fcdf39c12))\n' - expected_message = "kolaszek pushed 50 commits to branch master.\n\n{}[and 30 more commit(s)]".format(commit_info * 20) + expected_message = f"kolaszek pushed 50 commits to branch master.\n\n{commit_info * 20}[and 30 more commit(s)]" self.api_stream_message(self.test_user, fixture_name, self.EXPECTED_TOPIC_BRANCH_EVENTS, expected_message) @@ -50,7 +50,7 @@ class BitbucketHookTests(WebhookTestCase): self.url = self.build_webhook_url(payload=self.get_body(fixture_name), branches='master,development') commit_info = '* c ([25f93d2](https://bitbucket.org/kolaszek/repository-name/commits/25f93d22b719e2d678a7ad5ee0ef0d1fcdf39c12))\n' - expected_message = "kolaszek pushed 50 commits to branch master.\n\n{}[and 30 more commit(s)]".format(commit_info * 20) + expected_message = f"kolaszek pushed 50 commits to branch master.\n\n{commit_info * 20}[and 30 more commit(s)]" self.api_stream_message(self.test_user, fixture_name, self.EXPECTED_TOPIC_BRANCH_EVENTS, expected_message) diff --git a/zerver/webhooks/bitbucket2/tests.py b/zerver/webhooks/bitbucket2/tests.py index b984411db6..28265076bc 100644 --- a/zerver/webhooks/bitbucket2/tests.py +++ b/zerver/webhooks/bitbucket2/tests.py @@ -14,35 +14,35 @@ class Bitbucket2HookTests(WebhookTestCase): def test_bitbucket2_on_push_event(self) -> None: commit_info = '* first commit ([84b96ad](https://bitbucket.org/kolaszek/repository-name/commits/84b96adc644a30fd6465b3d196369d880762afed))' - expected_message = "kolaszek [pushed](https://bitbucket.org/kolaszek/repository-name/branch/master) 1 commit to branch master.\n\n{}".format(commit_info) + expected_message = f"kolaszek [pushed](https://bitbucket.org/kolaszek/repository-name/branch/master) 1 commit to branch master.\n\n{commit_info}" self.send_and_test_stream_message('push', self.EXPECTED_TOPIC_BRANCH_EVENTS, expected_message) def test_bitbucket2_on_push_commits_multiple_committers(self) -> None: commit_info = '* first commit ([84b96ad](https://bitbucket.org/kolaszek/repository-name/commits/84b96adc644a30fd6465b3d196369d880762afed))\n' - expected_message = """kolaszek [pushed](https://bitbucket.org/kolaszek/repository-name/branch/master) 3 commits to branch master. Commits by zbenjamin (2) and kolaszek (1).\n\n{}* first commit ([84b96ad](https://bitbucket.org/kolaszek/repository-name/commits/84b96adc644a30fd6465b3d196369d880762afed))""".format(commit_info*2) + expected_message = f"""kolaszek [pushed](https://bitbucket.org/kolaszek/repository-name/branch/master) 3 commits to branch master. Commits by zbenjamin (2) and kolaszek (1).\n\n{commit_info*2}* first commit ([84b96ad](https://bitbucket.org/kolaszek/repository-name/commits/84b96adc644a30fd6465b3d196369d880762afed))""" self.send_and_test_stream_message('push_multiple_committers', self.EXPECTED_TOPIC_BRANCH_EVENTS, expected_message) def test_bitbucket2_on_push_commits_multiple_committers_with_others(self) -> None: commit_info = '* first commit ([84b96ad](https://bitbucket.org/kolaszek/repository-name/commits/84b96adc644a30fd6465b3d196369d880762afed))\n' - expected_message = """kolaszek [pushed](https://bitbucket.org/kolaszek/repository-name/branch/master) 10 commits to branch master. Commits by james (3), Brendon (2), Tomasz (2) and others (3).\n\n{}* first commit ([84b96ad](https://bitbucket.org/kolaszek/repository-name/commits/84b96adc644a30fd6465b3d196369d880762afed))""".format(commit_info*9) + expected_message = f"""kolaszek [pushed](https://bitbucket.org/kolaszek/repository-name/branch/master) 10 commits to branch master. Commits by james (3), Brendon (2), Tomasz (2) and others (3).\n\n{commit_info*9}* first commit ([84b96ad](https://bitbucket.org/kolaszek/repository-name/commits/84b96adc644a30fd6465b3d196369d880762afed))""" self.send_and_test_stream_message('push_multiple_committers_with_others', self.EXPECTED_TOPIC_BRANCH_EVENTS, expected_message) def test_bitbucket2_on_push_commits_multiple_committers_filtered_by_branches(self) -> None: self.url = self.build_webhook_url(branches='master,development') commit_info = '* first commit ([84b96ad](https://bitbucket.org/kolaszek/repository-name/commits/84b96adc644a30fd6465b3d196369d880762afed))\n' - expected_message = """kolaszek [pushed](https://bitbucket.org/kolaszek/repository-name/branch/master) 3 commits to branch master. Commits by zbenjamin (2) and kolaszek (1).\n\n{}* first commit ([84b96ad](https://bitbucket.org/kolaszek/repository-name/commits/84b96adc644a30fd6465b3d196369d880762afed))""".format(commit_info*2) + expected_message = f"""kolaszek [pushed](https://bitbucket.org/kolaszek/repository-name/branch/master) 3 commits to branch master. Commits by zbenjamin (2) and kolaszek (1).\n\n{commit_info*2}* first commit ([84b96ad](https://bitbucket.org/kolaszek/repository-name/commits/84b96adc644a30fd6465b3d196369d880762afed))""" self.send_and_test_stream_message('push_multiple_committers', self.EXPECTED_TOPIC_BRANCH_EVENTS, expected_message) def test_bitbucket2_on_push_commits_multiple_committers_with_others_filtered_by_branches(self) -> None: self.url = self.build_webhook_url(branches='master,development') commit_info = '* first commit ([84b96ad](https://bitbucket.org/kolaszek/repository-name/commits/84b96adc644a30fd6465b3d196369d880762afed))\n' - expected_message = """kolaszek [pushed](https://bitbucket.org/kolaszek/repository-name/branch/master) 10 commits to branch master. Commits by james (3), Brendon (2), Tomasz (2) and others (3).\n\n{}* first commit ([84b96ad](https://bitbucket.org/kolaszek/repository-name/commits/84b96adc644a30fd6465b3d196369d880762afed))""".format(commit_info*9) + expected_message = f"""kolaszek [pushed](https://bitbucket.org/kolaszek/repository-name/branch/master) 10 commits to branch master. Commits by james (3), Brendon (2), Tomasz (2) and others (3).\n\n{commit_info*9}* first commit ([84b96ad](https://bitbucket.org/kolaszek/repository-name/commits/84b96adc644a30fd6465b3d196369d880762afed))""" self.send_and_test_stream_message('push_multiple_committers_with_others', self.EXPECTED_TOPIC_BRANCH_EVENTS, expected_message) def test_bitbucket2_on_push_event_filtered_by_branches(self) -> None: self.url = self.build_webhook_url(branches='master,development') commit_info = '* first commit ([84b96ad](https://bitbucket.org/kolaszek/repository-name/commits/84b96adc644a30fd6465b3d196369d880762afed))' - expected_message = "kolaszek [pushed](https://bitbucket.org/kolaszek/repository-name/branch/master) 1 commit to branch master.\n\n{}".format(commit_info) + expected_message = f"kolaszek [pushed](https://bitbucket.org/kolaszek/repository-name/branch/master) 1 commit to branch master.\n\n{commit_info}" self.send_and_test_stream_message('push', self.EXPECTED_TOPIC_BRANCH_EVENTS, expected_message) def test_bitbucket2_on_push_commits_above_limit_event(self) -> None: diff --git a/zerver/webhooks/bitbucket2/view.py b/zerver/webhooks/bitbucket2/view.py index d227ae2b65..9e889af38c 100644 --- a/zerver/webhooks/bitbucket2/view.py +++ b/zerver/webhooks/bitbucket2/view.py @@ -348,7 +348,7 @@ def get_push_tag_body(payload: Dict[str, Any], change: Dict[str, Any]) -> str: def append_punctuation(title: str, message: str) -> str: if title[-1] not in string.punctuation: - message = "{}.".format(message) + message = f"{message}." return message diff --git a/zerver/webhooks/bitbucket3/view.py b/zerver/webhooks/bitbucket3/view.py index 2b13a492fc..a6a6fab9ca 100644 --- a/zerver/webhooks/bitbucket3/view.py +++ b/zerver/webhooks/bitbucket3/view.py @@ -68,7 +68,7 @@ def repo_comment_handler(payload: Dict[str, Any], action: str) -> List[Dict[str, commit_url += "commits/%s" % (sha,) message = payload["comment"]["text"] if action == "deleted their comment": - message = "~~{message}~~".format(message=message) + message = f"~~{message}~~" body = get_commits_comment_action_message( user_name=get_user_name(payload), action=action, @@ -100,7 +100,7 @@ def repo_modified_handler(payload: Dict[str, Any]) -> List[Dict[str, str]]: new=new_name ) # As of writing this, the only change we'd be notified about is a name change. punctuation = '.' if new_name[-1] not in string.punctuation else '' - body = "{}{}".format(body, punctuation) + body = f"{body}{punctuation}" return [{"subject": subject_new, "body": body}] def repo_push_branch_data(payload: Dict[str, Any], change: Dict[str, Any]) -> Dict[str, str]: @@ -217,7 +217,7 @@ def get_pr_opened_or_modified_body(payload: Dict[str, Any], action: str, else: body = PULL_REQUEST_OPENED_OR_MODIFIED_TEMPLATE_WITH_REVIEWERS.format(**parameters) punctuation = ':' if description else '.' - body = "{}{}".format(body, punctuation) + body = f"{body}{punctuation}" if description: body += '\n' + CONTENT_MESSAGE_TEMPLATE.format(message=description) return body @@ -265,7 +265,7 @@ def get_pr_reassigned_body(payload: Dict[str, Any], include_title: Optional[bool url=pr["links"]["self"][0]["href"], title=pr["title"] ) - message = "{}{}".format(message, punctuation) + message = f"{message}{punctuation}" return message if not include_title: return PULL_REQUEST_REASSIGNED_TEMPLATE.format( @@ -305,7 +305,7 @@ def pr_comment_handler(payload: Dict[str, Any], action: str, title=pr["title"]) message = payload["comment"]["text"] if action == "deleted their comment on": - message = "~~{message}~~".format(message=message) + message = f"~~{message}~~" body = get_pull_request_event_message( user_name=get_user_name(payload), action=action, diff --git a/zerver/webhooks/clubhouse/view.py b/zerver/webhooks/clubhouse/view.py index 1d2138e70e..04c118b12e 100644 --- a/zerver/webhooks/clubhouse/view.py +++ b/zerver/webhooks/clubhouse/view.py @@ -310,7 +310,7 @@ def get_story_update_estimate_body(payload: Dict[str, Any]) -> str: new = action["changes"]["estimate"].get("new") if new: - kwargs["estimate"] = "{} points".format(new) + kwargs["estimate"] = f"{new} points" else: kwargs["estimate"] = "*Unestimated*" diff --git a/zerver/webhooks/dialogflow/view.py b/zerver/webhooks/dialogflow/view.py index d87ba13745..3d2295d7ad 100644 --- a/zerver/webhooks/dialogflow/view.py +++ b/zerver/webhooks/dialogflow/view.py @@ -29,7 +29,7 @@ def api_dialogflow_webhook(request: HttpRequest, user_profile: UserProfile, body = result else: error_status = payload["status"]["errorDetails"] - body = "{} - {}".format(status, error_status) + body = f"{status} - {error_status}" profile = get_user_profile_by_email(email) check_send_private_message(user_profile, request.client, profile, body) diff --git a/zerver/webhooks/flock/view.py b/zerver/webhooks/flock/view.py index c85f39c3b2..99f2232303 100644 --- a/zerver/webhooks/flock/view.py +++ b/zerver/webhooks/flock/view.py @@ -22,7 +22,7 @@ def api_flock_webhook(request: HttpRequest, user_profile: UserProfile, message_body = payload["notification"] topic = 'Flock notifications' - body = "{}".format(message_body) + body = f"{message_body}" check_send_webhook_message(request, user_profile, topic, body) diff --git a/zerver/webhooks/front/view.py b/zerver/webhooks/front/view.py index 3506d90ee7..40659f4505 100644 --- a/zerver/webhooks/front/view.py +++ b/zerver/webhooks/front/view.py @@ -63,33 +63,33 @@ def get_conversation_assigned_body(payload: Dict[str, Any]) -> str: def get_conversation_unassigned_body(payload: Dict[str, Any]) -> str: name = get_source_name(payload) - return "Unassigned by **{name}**.".format(name=name) + return f"Unassigned by **{name}**." def get_conversation_archived_body(payload: Dict[str, Any]) -> str: name = get_source_name(payload) - return "Archived by **{name}**.".format(name=name) + return f"Archived by **{name}**." def get_conversation_reopened_body(payload: Dict[str, Any]) -> str: name = get_source_name(payload) - return "Reopened by **{name}**.".format(name=name) + return f"Reopened by **{name}**." def get_conversation_deleted_body(payload: Dict[str, Any]) -> str: name = get_source_name(payload) - return "Deleted by **{name}**.".format(name=name) + return f"Deleted by **{name}**." def get_conversation_restored_body(payload: Dict[str, Any]) -> str: name = get_source_name(payload) - return "Restored by **{name}**.".format(name=name) + return f"Restored by **{name}**." def get_conversation_tagged_body(payload: Dict[str, Any]) -> str: name = get_source_name(payload) tag = payload['target']['data']['name'] - return "**{name}** added tag **{tag}**.".format(name=name, tag=tag) + return f"**{name}** added tag **{tag}**." def get_conversation_untagged_body(payload: Dict[str, Any]) -> str: name = get_source_name(payload) tag = payload['target']['data']['name'] - return "**{name}** removed tag **{tag}**.".format(name=name, tag=tag) + return f"**{name}** removed tag **{tag}**." EVENT_FUNCTION_MAPPER = { 'inbound': get_inbound_message_body, diff --git a/zerver/webhooks/gci/view.py b/zerver/webhooks/gci/view.py index a493e51369..801235e95e 100644 --- a/zerver/webhooks/gci/view.py +++ b/zerver/webhooks/gci/view.py @@ -13,7 +13,7 @@ GCI_TOPIC_TEMPLATE = '{student_name}' def build_instance_url(instance_id: str) -> str: - return "https://codein.withgoogle.com/dashboard/task-instances/{}/".format(instance_id) + return f"https://codein.withgoogle.com/dashboard/task-instances/{instance_id}/" class UnknownEventType(Exception): pass @@ -132,7 +132,7 @@ def get_event(payload: Dict[str, Any]) -> Optional[str]: if event in EVENTS_FUNCTION_MAPPER: return event - raise UnknownEventType("Event '{}' is unknown and cannot be handled".format(event)) # nocoverage + raise UnknownEventType(f"Event '{event}' is unknown and cannot be handled") # nocoverage def get_body_based_on_event(event: str) -> Any: return EVENTS_FUNCTION_MAPPER[event] diff --git a/zerver/webhooks/github/tests.py b/zerver/webhooks/github/tests.py index 951e0479dc..f5edd754d3 100644 --- a/zerver/webhooks/github/tests.py +++ b/zerver/webhooks/github/tests.py @@ -52,27 +52,27 @@ class GithubWebhookTest(WebhookTestCase): def test_push_multiple_comitters(self) -> None: commits_info = '* Update README.md ([0d1a26e](https://github.com/baxterthehacker/public-repo/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c))\n' - expected_message = """baxterthehacker [pushed](https://github.com/baxterthehacker/public-repo/compare/9049f1265b7d...0d1a26e67d8f) 6 commits to branch changes. Commits by Tomasz (3), Ben (2) and baxterthehacker (1).\n\n{}* Update README.md ([0d1a26e](https://github.com/baxterthehacker/public-repo/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c))""".format(commits_info * 5) + expected_message = f"""baxterthehacker [pushed](https://github.com/baxterthehacker/public-repo/compare/9049f1265b7d...0d1a26e67d8f) 6 commits to branch changes. Commits by Tomasz (3), Ben (2) and baxterthehacker (1).\n\n{commits_info * 5}* Update README.md ([0d1a26e](https://github.com/baxterthehacker/public-repo/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c))""" self.send_and_test_stream_message('push__multiple_committers', self.EXPECTED_TOPIC_BRANCH_EVENTS, expected_message) def test_push_multiple_comitters_with_others(self) -> None: commits_info = '* Update README.md ([0d1a26e](https://github.com/baxterthehacker/public-repo/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c))\n' - expected_message = """baxterthehacker [pushed](https://github.com/baxterthehacker/public-repo/compare/9049f1265b7d...0d1a26e67d8f) 10 commits to branch changes. Commits by Tomasz (4), Ben (3), James (2) and others (1).\n\n{}* Update README.md ([0d1a26e](https://github.com/baxterthehacker/public-repo/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c))""".format(commits_info * 9) + expected_message = f"""baxterthehacker [pushed](https://github.com/baxterthehacker/public-repo/compare/9049f1265b7d...0d1a26e67d8f) 10 commits to branch changes. Commits by Tomasz (4), Ben (3), James (2) and others (1).\n\n{commits_info * 9}* Update README.md ([0d1a26e](https://github.com/baxterthehacker/public-repo/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c))""" self.send_and_test_stream_message('push__multiple_committers_with_others', self.EXPECTED_TOPIC_BRANCH_EVENTS, expected_message) def test_push_multiple_comitters_filtered_by_branches(self) -> None: self.url = self.build_webhook_url('master,changes') commits_info = '* Update README.md ([0d1a26e](https://github.com/baxterthehacker/public-repo/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c))\n' - expected_message = """baxterthehacker [pushed](https://github.com/baxterthehacker/public-repo/compare/9049f1265b7d...0d1a26e67d8f) 6 commits to branch changes. Commits by Tomasz (3), Ben (2) and baxterthehacker (1).\n\n{}* Update README.md ([0d1a26e](https://github.com/baxterthehacker/public-repo/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c))""".format(commits_info * 5) + expected_message = f"""baxterthehacker [pushed](https://github.com/baxterthehacker/public-repo/compare/9049f1265b7d...0d1a26e67d8f) 6 commits to branch changes. Commits by Tomasz (3), Ben (2) and baxterthehacker (1).\n\n{commits_info * 5}* Update README.md ([0d1a26e](https://github.com/baxterthehacker/public-repo/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c))""" self.send_and_test_stream_message('push__multiple_committers', self.EXPECTED_TOPIC_BRANCH_EVENTS, expected_message) def test_push_multiple_comitters_with_others_filtered_by_branches(self) -> None: self.url = self.build_webhook_url('master,changes') commits_info = '* Update README.md ([0d1a26e](https://github.com/baxterthehacker/public-repo/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c))\n' - expected_message = """baxterthehacker [pushed](https://github.com/baxterthehacker/public-repo/compare/9049f1265b7d...0d1a26e67d8f) 10 commits to branch changes. Commits by Tomasz (4), Ben (3), James (2) and others (1).\n\n{}* Update README.md ([0d1a26e](https://github.com/baxterthehacker/public-repo/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c))""".format(commits_info * 9) + expected_message = f"""baxterthehacker [pushed](https://github.com/baxterthehacker/public-repo/compare/9049f1265b7d...0d1a26e67d8f) 10 commits to branch changes. Commits by Tomasz (4), Ben (3), James (2) and others (1).\n\n{commits_info * 9}* Update README.md ([0d1a26e](https://github.com/baxterthehacker/public-repo/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c))""" self.send_and_test_stream_message('push__multiple_committers_with_others', self.EXPECTED_TOPIC_BRANCH_EVENTS, expected_message) diff --git a/zerver/webhooks/github/view.py b/zerver/webhooks/github/view.py index c7ce800a94..aafc93b69f 100644 --- a/zerver/webhooks/github/view.py +++ b/zerver/webhooks/github/view.py @@ -61,7 +61,7 @@ def get_assigned_or_unassigned_pull_request_body(payload: Dict[str, Any], title=pull_request['title'] if include_title else None ) if assignee is not None: - return "{} to {}.".format(base_message[:-1], assignee) + return f"{base_message[:-1]} to {assignee}." return base_message def get_closed_pull_request_body(payload: Dict[str, Any], @@ -124,7 +124,7 @@ def get_issue_comment_body(payload: Dict[str, Any], if action == 'created': action = '[commented]' else: - action = '{} a [comment]'.format(action) + action = f'{action} a [comment]' action += '({}) on'.format(comment['html_url']) return get_issue_event_message( @@ -167,7 +167,7 @@ def get_commit_comment_body(payload: Dict[str, Any]) -> str: comment = payload['comment'] comment_url = comment['html_url'] commit_url = comment_url.split('#', 1)[0] - action = '[commented]({})'.format(comment_url) + action = f'[commented]({comment_url})' return get_commits_comment_action_message( get_sender_name(payload), action, @@ -214,7 +214,7 @@ def get_wiki_pages_body(payload: Dict[str, Any]) -> str: title=page['title'], url=page['html_url'], ) - return "{}:\n{}".format(get_sender_name(payload), wiki_info.rstrip()) + return f"{get_sender_name(payload)}:\n{wiki_info.rstrip()}" def get_watch_body(payload: Dict[str, Any]) -> str: return "{} starred [the repository]({}).".format( @@ -240,16 +240,16 @@ def get_team_body(payload: Dict[str, Any]) -> str: if "description" in changes: actor = payload["sender"]["login"] new_description = payload["team"]["description"] - return "**{}** changed the team description to:\n```quote\n{}\n```".format(actor, new_description) + return f"**{actor}** changed the team description to:\n```quote\n{new_description}\n```" if "name" in changes: original_name = changes["name"]["from"] new_name = payload["team"]["name"] - return "Team `{}` was renamed to `{}`.".format(original_name, new_name) + return f"Team `{original_name}` was renamed to `{new_name}`." if "privacy" in changes: new_visibility = payload["team"]["privacy"] - return "Team visibility changed to `{}`".format(new_visibility) + return f"Team visibility changed to `{new_visibility}`" else: # nocoverage - raise UnexpectedWebhookEventType("GitHub", "Team Edited: {}".format(changes.keys())) + raise UnexpectedWebhookEventType("GitHub", f"Team Edited: {changes.keys()}") def get_release_body(payload: Dict[str, Any]) -> str: data = { @@ -273,7 +273,7 @@ def get_page_build_body(payload: Dict[str, Any]) -> str: 'built': 'has finished building', } - action = actions.get(status, 'is {}'.format(status)) + action = actions.get(status, f'is {status}') action.format( CONTENT_MESSAGE_TEMPLATE.format(message=build['error']['message']) ) @@ -465,7 +465,7 @@ def get_subject_based_on_type(payload: Dict[str, Any], event: str) -> str: if payload.get('repository') is None: return get_organization_name(payload) elif event == 'check_run': - return "{} / checks".format(get_repository_name(payload)) + return f"{get_repository_name(payload)} / checks" return get_repository_name(payload) @@ -545,7 +545,7 @@ def get_event(request: HttpRequest, payload: Dict[str, Any], branches: Optional[ if action == 'closed': return 'closed_pull_request' if action == 'review_requested': - return '{}_{}'.format(event, action) + return f'{event}_{action}' if action == 'ready_for_review': return 'pull_request_ready_for_review' # Unsupported pull_request events diff --git a/zerver/webhooks/gitlab/tests.py b/zerver/webhooks/gitlab/tests.py index 4edeb95cd0..d8b6fc5cae 100644 --- a/zerver/webhooks/gitlab/tests.py +++ b/zerver/webhooks/gitlab/tests.py @@ -39,7 +39,7 @@ class GitlabHookTests(WebhookTestCase): def test_push_multiple_committers_with_others(self) -> None: expected_topic = "my-awesome-project / tomek" commit_info = "* b ([eb6ae1e](https://gitlab.com/tomaszkolek0/my-awesome-project/commit/eb6ae1e591e0819dc5bf187c6bfe18ec065a80e9))\n" - expected_message = "Tomasz Kolek [pushed](https://gitlab.com/tomaszkolek0/my-awesome-project/compare/5fcdd5551fc3085df79bece2c32b1400802ac407...eb6ae1e591e0819dc5bf187c6bfe18ec065a80e9) 7 commits to branch tomek. Commits by Ben (3), baxterthehacker (2), James (1) and others (1).\n\n{}* b ([eb6ae1e](https://gitlab.com/tomaszkolek0/my-awesome-project/commit/eb6ae1e591e0819dc5bf187c6bfe18ec065a80e9))".format(commit_info * 6) + expected_message = f"Tomasz Kolek [pushed](https://gitlab.com/tomaszkolek0/my-awesome-project/compare/5fcdd5551fc3085df79bece2c32b1400802ac407...eb6ae1e591e0819dc5bf187c6bfe18ec065a80e9) 7 commits to branch tomek. Commits by Ben (3), baxterthehacker (2), James (1) and others (1).\n\n{commit_info * 6}* b ([eb6ae1e](https://gitlab.com/tomaszkolek0/my-awesome-project/commit/eb6ae1e591e0819dc5bf187c6bfe18ec065a80e9))" self.send_and_test_stream_message('push_hook__push_multiple_committers_with_others', expected_topic, expected_message) def test_push_commits_more_than_limit_event_message(self) -> None: diff --git a/zerver/webhooks/gitlab/view.py b/zerver/webhooks/gitlab/view.py index 8cbf76200d..51c04e6713 100644 --- a/zerver/webhooks/gitlab/view.py +++ b/zerver/webhooks/gitlab/view.py @@ -233,7 +233,7 @@ def get_build_hook_event_body(payload: Dict[str, Any]) -> str: elif build_status == 'running': action = 'started' else: - action = 'changed status to {}'.format(build_status) + action = f'changed status to {build_status}' return "Build {} from {} stage {}.".format( payload.get('build_name'), payload.get('build_stage'), @@ -251,7 +251,7 @@ def get_pipeline_event_body(payload: Dict[str, Any]) -> str: elif pipeline_status == 'running': action = 'started' else: - action = 'changed status to {}'.format(pipeline_status) + action = f'changed status to {pipeline_status}' project_homepage = get_project_homepage(payload) pipeline_url = '{}/pipelines/{}'.format( @@ -267,8 +267,8 @@ def get_pipeline_event_body(payload: Dict[str, Any]) -> str: ) artifact_filename = build.get('artifacts_file', {}).get('filename', None) if artifact_filename: - artifact_download_url = '{}/artifacts/download'.format(build_url) - artifact_browse_url = '{}/artifacts/browse'.format(build_url) + artifact_download_url = f'{build_url}/artifacts/download' + artifact_browse_url = f'{build_url}/artifacts/browse' artifact_string = ' * built artifact: *{}* [[Browse]({})|[Download]({})]\n'.format( artifact_filename, artifact_browse_url, @@ -380,7 +380,7 @@ def get_body_based_on_event(event: str) -> Any: def get_subject_based_on_event(event: str, payload: Dict[str, Any]) -> str: if event == 'Push Hook': - return "{} / {}".format(get_repo_name(payload), get_branch_name(payload)) + return f"{get_repo_name(payload)} / {get_branch_name(payload)}" elif event == 'Job Hook' or event == 'Build Hook': return "{} / {}".format(payload['repository'].get('name'), get_branch_name(payload)) elif event == 'Pipeline Hook': diff --git a/zerver/webhooks/gogs/tests.py b/zerver/webhooks/gogs/tests.py index b8110148a2..b731e9b910 100644 --- a/zerver/webhooks/gogs/tests.py +++ b/zerver/webhooks/gogs/tests.py @@ -19,14 +19,14 @@ class GogsHookTests(WebhookTestCase): def test_push_multiple_committers(self) -> None: commit_info = '* Webhook Test ([d8fce16](http://localhost:3000/john/try-git/commit/d8fce16c72a2ff56a5afc8a08645a6ce45491794))\n' expected_topic = "try-git / master" - expected_message = """john [pushed](http://localhost:3000/john/try-git/compare/479e6b772b7fba19412457483f50b201286d0103...d8fce16c72a2ff56a5afc8a08645a6ce45491794) 2 commits to branch master. Commits by Benjamin (1) and John (1).\n\n{}* Webhook Test ([d8fce16](http://localhost:3000/john/try-git/commit/d8fce16c72a2ff56a5afc8a08645a6ce45491794))""".format(commit_info) + expected_message = f"""john [pushed](http://localhost:3000/john/try-git/compare/479e6b772b7fba19412457483f50b201286d0103...d8fce16c72a2ff56a5afc8a08645a6ce45491794) 2 commits to branch master. Commits by Benjamin (1) and John (1).\n\n{commit_info}* Webhook Test ([d8fce16](http://localhost:3000/john/try-git/commit/d8fce16c72a2ff56a5afc8a08645a6ce45491794))""" self.send_and_test_stream_message('push__commits_multiple_committers', expected_topic, expected_message) def test_push_multiple_committers_filtered_by_branches(self) -> None: self.url = self.build_webhook_url(branches='master,development') commit_info = '* Webhook Test ([d8fce16](http://localhost:3000/john/try-git/commit/d8fce16c72a2ff56a5afc8a08645a6ce45491794))\n' expected_topic = "try-git / master" - expected_message = """john [pushed](http://localhost:3000/john/try-git/compare/479e6b772b7fba19412457483f50b201286d0103...d8fce16c72a2ff56a5afc8a08645a6ce45491794) 2 commits to branch master. Commits by Benjamin (1) and John (1).\n\n{}* Webhook Test ([d8fce16](http://localhost:3000/john/try-git/commit/d8fce16c72a2ff56a5afc8a08645a6ce45491794))""".format(commit_info) + expected_message = f"""john [pushed](http://localhost:3000/john/try-git/compare/479e6b772b7fba19412457483f50b201286d0103...d8fce16c72a2ff56a5afc8a08645a6ce45491794) 2 commits to branch master. Commits by Benjamin (1) and John (1).\n\n{commit_info}* Webhook Test ([d8fce16](http://localhost:3000/john/try-git/commit/d8fce16c72a2ff56a5afc8a08645a6ce45491794))""" self.send_and_test_stream_message('push__commits_multiple_committers', expected_topic, expected_message) def test_push_filtered_by_branches(self) -> None: diff --git a/zerver/webhooks/gogs/view.py b/zerver/webhooks/gogs/view.py index 0dcc5c96e1..16f9973589 100644 --- a/zerver/webhooks/gogs/view.py +++ b/zerver/webhooks/gogs/view.py @@ -19,7 +19,7 @@ from zerver.models import UserProfile fixture_to_headers = get_http_headers_from_filename("HTTP_X_GOGS_EVENT") def get_issue_url(repo_url: str, issue_nr: int) -> str: - return "{}/issues/{}".format(repo_url, issue_nr) + return f"{repo_url}/issues/{issue_nr}" def format_push_event(payload: Dict[str, Any]) -> str: @@ -89,7 +89,7 @@ def format_issue_comment_event(payload: Dict[str, Any], include_title: Optional[ if action == 'created': action = '[commented]' else: - action = '{} a [comment]'.format(action) + action = f'{action} a [comment]' action += '({}) on'.format(comment['html_url']) return get_issue_event_message( diff --git a/zerver/webhooks/gosquared/view.py b/zerver/webhooks/gosquared/view.py index 44909dc6f8..91ff5ffbb0 100644 --- a/zerver/webhooks/gosquared/view.py +++ b/zerver/webhooks/gosquared/view.py @@ -38,7 +38,7 @@ def api_gosquared_webhook(request: HttpRequest, user_profile: UserProfile, body = TRAFFIC_SPIKE_TEMPLATE.format(website_name=domain_name, website_url=acc_url, user_num=user_num) - topic = 'GoSquared - {website_name}'.format(website_name=domain_name) + topic = f'GoSquared - {domain_name}' check_send_webhook_message(request, user_profile, topic, body) # Live chat message event @@ -47,7 +47,7 @@ def api_gosquared_webhook(request: HttpRequest, user_profile: UserProfile, # Only support non-private messages if not payload['message']['private']: session_title = payload['message']['session']['title'] - topic = 'Live Chat Session - {}'.format(session_title) + topic = f'Live Chat Session - {session_title}' body = CHAT_MESSAGE_TEMPLATE.format( status=payload['person']['status'], name=payload['person']['_anon']['name'], diff --git a/zerver/webhooks/greenhouse/view.py b/zerver/webhooks/greenhouse/view.py index a8565977d4..3f8dcb5d62 100644 --- a/zerver/webhooks/greenhouse/view.py +++ b/zerver/webhooks/greenhouse/view.py @@ -22,9 +22,9 @@ def dict_list_to_string(some_list: List[Any]) -> str: item_value = item.get('value') item_url = item.get('url') if item_type and item_value: - internal_template += "{} ({}), ".format(item_value, item_type) + internal_template += f"{item_value} ({item_type}), " elif item_type and item_url: - internal_template += "[{}]({}), ".format(item_type, item_url) + internal_template += f"[{item_type}]({item_url}), " internal_template = internal_template[:-2] return internal_template diff --git a/zerver/webhooks/harbor/view.py b/zerver/webhooks/harbor/view.py index aabd7e67c2..c16a1a54d2 100644 --- a/zerver/webhooks/harbor/view.py +++ b/zerver/webhooks/harbor/view.py @@ -101,7 +101,7 @@ def api_harbor_webhook(request: HttpRequest, user_profile: UserProfile, operator_username, user_profile.realm) if operator_profile: - operator_username = "@**{}**".format(operator_profile.full_name) # nocoverage + operator_username = f"@**{operator_profile.full_name}**" # nocoverage event = payload["type"] topic = payload["event_data"]["repository"]["repo_full_name"] diff --git a/zerver/webhooks/hellosign/view.py b/zerver/webhooks/hellosign/view.py index 644aab4595..3a0c82852f 100644 --- a/zerver/webhooks/hellosign/view.py +++ b/zerver/webhooks/hellosign/view.py @@ -34,7 +34,7 @@ def get_message_body(payload: Dict[str, Dict[str, Any]]) -> str: ) if recipients_text: - recipients_text = "{}, and {}".format(recipients_text, text) + recipients_text = f"{recipients_text}, and {text}" else: recipients_text = text @@ -47,8 +47,8 @@ def get_recipients_text(recipients: List[str]) -> str: recipients_text = "{}".format(*recipients) else: for recipient in recipients[:-1]: - recipients_text += "{}, ".format(recipient) - recipients_text += "and {}".format(recipients[-1]) + recipients_text += f"{recipient}, " + recipients_text += f"and {recipients[-1]}" return recipients_text diff --git a/zerver/webhooks/jira/view.py b/zerver/webhooks/jira/view.py index 5812b80f97..73ede8e2f3 100644 --- a/zerver/webhooks/jira/view.py +++ b/zerver/webhooks/jira/view.py @@ -81,11 +81,11 @@ def convert_jira_markup(content: str, realm: Realm) -> str: # Try to look up username user_profile = guess_zulip_user_from_jira(username, realm) if user_profile: - replacement = "**{}**".format(user_profile.full_name) + replacement = f"**{user_profile.full_name}**" else: - replacement = "**{}**".format(username) + replacement = f"**{username}**" - content = content.replace("[~{}]".format(username,), replacement) + content = content.replace(f"[~{username}]", replacement) return content @@ -105,13 +105,13 @@ def get_issue_string(payload: Dict[str, Any], issue_id: Optional[str]=None, with issue_id = get_issue_id(payload) if with_title: - text = "{}: {}".format(issue_id, get_issue_title(payload)) + text = f"{issue_id}: {get_issue_title(payload)}" else: text = issue_id base_url = re.match(r"(.*)\/rest\/api/.*", get_in(payload, ['issue', 'self'])) if base_url and len(base_url.groups()): - return "[{}]({}/browse/{})".format(text, base_url.group(1), issue_id) + return f"[{text}]({base_url.group(1)}/browse/{issue_id})" else: return text @@ -121,7 +121,7 @@ def get_assignee_mention(assignee_email: str, realm: Realm) -> str: assignee_name = get_user_by_delivery_email(assignee_email, realm).full_name except UserProfile.DoesNotExist: assignee_name = assignee_email - return "**{}**".format(assignee_name) + return f"**{assignee_name}**" return '' def get_issue_author(payload: Dict[str, Any]) -> str: @@ -152,7 +152,7 @@ def get_issue_title(payload: Dict[str, Any]) -> str: return get_in(payload, ['issue', 'fields', 'summary']) def get_issue_subject(payload: Dict[str, Any]) -> str: - return "{}: {}".format(get_issue_id(payload), get_issue_title(payload)) + return f"{get_issue_id(payload)}: {get_issue_title(payload)}" def get_sub_event_for_update_issue(payload: Dict[str, Any]) -> str: sub_event = payload.get('issue_event_type_name', '') @@ -170,11 +170,11 @@ def get_event_type(payload: Dict[str, Any]) -> Optional[str]: return event def add_change_info(content: str, field: str, from_field: str, to_field: str) -> str: - content += "* Changed {}".format(field) + content += f"* Changed {field}" if from_field: - content += " from **{}**".format(from_field) + content += f" from **{from_field}**" if to_field: - content += " to {}\n".format(to_field) + content += f" to {to_field}\n" return content def handle_updated_issue_event(payload: Dict[str, Any], user_profile: UserProfile) -> str: @@ -188,7 +188,7 @@ def handle_updated_issue_event(payload: Dict[str, Any], user_profile: UserProfil assignee_mention = get_assignee_mention(assignee_email, user_profile.realm) if assignee_mention != '': - assignee_blurb = " (assigned to {})".format(assignee_mention) + assignee_blurb = f" (assigned to {assignee_mention})" else: assignee_blurb = '' @@ -206,15 +206,15 @@ def handle_updated_issue_event(payload: Dict[str, Any], user_profile: UserProfil else: author = get_issue_author(payload) - content = "{} {} {}{}".format(author, verb, issue, assignee_blurb) + content = f"{author} {verb} {issue}{assignee_blurb}" comment = get_in(payload, ['comment', 'body']) if comment: comment = convert_jira_markup(comment, user_profile.realm) - content = "{}:\n\n``` quote\n{}\n```".format(content, comment) + content = f"{content}:\n\n``` quote\n{comment}\n```" else: - content = "{}.".format(content) + content = f"{content}." else: - content = "{} updated {}{}:\n\n".format(get_issue_author(payload), issue, assignee_blurb) + content = f"{get_issue_author(payload)} updated {issue}{assignee_blurb}:\n\n" changelog = get_in(payload, ['changelog']) if changelog != '': diff --git a/zerver/webhooks/librato/view.py b/zerver/webhooks/librato/view.py index 8a89f41be9..83788150af 100644 --- a/zerver/webhooks/librato/view.py +++ b/zerver/webhooks/librato/view.py @@ -136,8 +136,8 @@ class LibratoWebhookHandler(LibratoWebhookParser): metric_name=metric_name, summary_function=summary_function, condition_type=condition_type, threshold=threshold) if duration: - content += " by {duration}s".format(duration=duration) - content += ", recorded at {recorded_at} UTC.".format(recorded_at=recorded_at) + content += f" by {duration}s" + content += f", recorded at {recorded_at} UTC." return content @api_key_only_webhook_view('Librato') diff --git a/zerver/webhooks/opbeat/view.py b/zerver/webhooks/opbeat/view.py index a4145b8555..2a930bd4ca 100644 --- a/zerver/webhooks/opbeat/view.py +++ b/zerver/webhooks/opbeat/view.py @@ -68,26 +68,26 @@ def format_object( url: str = obj['html_url'] if 'opbeat.com' not in url: url = 'https://opbeat.com/' + url.lstrip('/') - message += '\n**[{}]({})**'.format(title_str, url) + message += f'\n**[{title_str}]({url})**' else: - message += '\n**{}**'.format(title_str) + message += f'\n**{title_str}**' for key_list in keys: if len(key_list) > 1: value = key_list[0].format(get_value(obj, key_list[1])) - message += '\n>{}'.format(value) + message += f'\n>{value}' else: key = key_list[0] key_raw = key.lstrip('!').lstrip('#').lstrip('"') if key_raw != 'html_url' and key_raw != 'subject' and ':' not in key_raw: value = get_value(obj, key_raw) if key.startswith('!'): - message += '\n>{}'.format(value) + message += f'\n>{value}' elif key.startswith('#'): - message += '\n{}'.format(value) + message += f'\n{value}' elif key.startswith('"'): - message += '\n{}'.format(key_raw) + message += f'\n{key_raw}' else: - message += '\n>{}: {}'.format(key, value) + message += f'\n>{key}: {value}' if key == 'subject': message = format_object( obj['subject'], obj['subject_type'], message + '\n') diff --git a/zerver/webhooks/pingdom/view.py b/zerver/webhooks/pingdom/view.py index 6d747a4817..d8b14527f6 100644 --- a/zerver/webhooks/pingdom/view.py +++ b/zerver/webhooks/pingdom/view.py @@ -72,7 +72,7 @@ def get_body_for_http_request(payload: Dict[str, Any]) -> str: description = DESC_TEMPLATE.format(description=payload['long_description']) body += description else: - body = '{}.'.format(body[:-1]) + body = f'{body[:-1]}.' return body diff --git a/zerver/webhooks/pivotal/tests.py b/zerver/webhooks/pivotal/tests.py index d0fc806978..b39447c27c 100644 --- a/zerver/webhooks/pivotal/tests.py +++ b/zerver/webhooks/pivotal/tests.py @@ -144,4 +144,4 @@ Try again next time self.send_and_test_stream_message('type_changed', expected_topic, expected_message, content_type="application/xml") def get_body(self, fixture_name: str) -> str: - return self.webhook_fixture_data('pivotal', "v5_{}".format(fixture_name), file_type='json') + return self.webhook_fixture_data('pivotal', f"v5_{fixture_name}", file_type='json') diff --git a/zerver/webhooks/raygun/view.py b/zerver/webhooks/raygun/view.py index 6aadff02e5..98f1751523 100644 --- a/zerver/webhooks/raygun/view.py +++ b/zerver/webhooks/raygun/view.py @@ -91,7 +91,7 @@ def make_message_chunk(message: str) -> str: returns an empty string. """ # "Message" shouldn't be included if there is none supplied. - return "* **Message**: {}\n".format(message) if message != "" else "" + return f"* **Message**: {message}\n" if message != "" else "" def make_app_info_chunk(app_dict: Dict[str, str]) -> str: @@ -103,7 +103,7 @@ def make_app_info_chunk(app_dict: Dict[str, str]) -> str: """ app_name = app_dict['name'] app_url = app_dict['url'] - return "* **Application details**: [{}]({})\n".format(app_name, app_url) + return f"* **Application details**: [{app_name}]({app_url})\n" def notification_message_follow_up(payload: Dict[str, Any]) -> str: @@ -127,7 +127,7 @@ def notification_message_follow_up(payload: Dict[str, Any]) -> str: # minute", where "FiveMinuteFollowUp" is "Five minute". prefix = followup_type[:len(followup_type) - 14] + " minute" - message += "{} {}:\n".format(prefix, followup_link_md) + message += f"{prefix} {followup_link_md}:\n" # Get the message of the error. payload_msg = payload['error']['message'] @@ -153,9 +153,9 @@ def notification_message_error_occurred(payload: Dict[str, Any]) -> str: # Stylize the message based on the event type of the error. if payload['eventType'] == "NewErrorOccurred": - message += "{}:\n".format("New {} occurred".format(error_link_md)) + message += "{}:\n".format(f"New {error_link_md} occurred") elif payload['eventType'] == "ErrorReoccurred": - message += "{}:\n".format("{} reoccurred".format(error_link_md)) + message += "{}:\n".format(f"{error_link_md} reoccurred") # Get the message of the error. This value can be empty (as in ""). payload_msg = payload['error']['message'] @@ -192,7 +192,7 @@ def notification_message_error_occurred(payload: Dict[str, Any]) -> str: # We don't know what the keys and values beforehand, so we are forced # to iterate. for key in sorted(custom_data.keys()): - message += "* **{}**: {}\n".format(key, custom_data[key]) + message += f"* **{key}**: {custom_data[key]}\n" message += make_app_info_chunk(payload['application']) diff --git a/zerver/webhooks/sentry/view.py b/zerver/webhooks/sentry/view.py index 07b50bd725..706fc91dca 100644 --- a/zerver/webhooks/sentry/view.py +++ b/zerver/webhooks/sentry/view.py @@ -78,7 +78,7 @@ def convert_lines_to_traceback_string(lines: Optional[List[str]]) -> str: if (line == ""): traceback += "\n" else: - traceback += " {}\n".format(line) + traceback += f" {line}\n" return traceback diff --git a/zerver/webhooks/slack/view.py b/zerver/webhooks/slack/view.py index 63fd857a8b..a917749324 100644 --- a/zerver/webhooks/slack/view.py +++ b/zerver/webhooks/slack/view.py @@ -23,7 +23,7 @@ def api_slack_webhook(request: HttpRequest, user_profile: UserProfile, return json_error(_('Error: channels_map_to_topics parameter other than 0 or 1')) if channels_map_to_topics == VALID_OPTIONS['SHOULD_BE_MAPPED']: - subject = "channel: {}".format(channel_name) + subject = f"channel: {channel_name}" else: stream = channel_name subject = _("Message from Slack") diff --git a/zerver/webhooks/slack_incoming/view.py b/zerver/webhooks/slack_incoming/view.py index a33131f2dc..418953c657 100644 --- a/zerver/webhooks/slack_incoming/view.py +++ b/zerver/webhooks/slack_incoming/view.py @@ -67,7 +67,7 @@ def add_block(block: Dict[str, Any], body: str) -> str: text = block["text"] while type(text) == dict: # handle stuff like block["text"]["text"] text = text["text"] - body += "\n\n{}".format(text) + body += f"\n\n{text}" if "accessory" in block: accessory = block["accessory"] diff --git a/zerver/webhooks/solano/view.py b/zerver/webhooks/solano/view.py index 6d039702aa..7fd9518a16 100644 --- a/zerver/webhooks/solano/view.py +++ b/zerver/webhooks/solano/view.py @@ -48,11 +48,11 @@ def api_solano_webhook(request: HttpRequest, user_profile: UserProfile, # commit itself. commit_url = repository.split('@')[1] if 'github' in repository: - commit_url += '/commit/{}'.format(commit_id) + commit_url += f'/commit/{commit_id}' elif 'bitbucket' in repository: - commit_url += '/commits/{}'.format(commit_id) + commit_url += f'/commits/{commit_id}' elif 'gitlab' in repository: - commit_url += '/pipelines/{}'.format(commit_id) + commit_url += f'/pipelines/{commit_id}' body = MESSAGE_TEMPLATE.format( author=author, build_log_url=build_log, diff --git a/zerver/webhooks/splunk/view.py b/zerver/webhooks/splunk/view.py index a785688d67..85960598f0 100644 --- a/zerver/webhooks/splunk/view.py +++ b/zerver/webhooks/splunk/view.py @@ -31,7 +31,7 @@ def api_splunk_webhook(request: HttpRequest, user_profile: UserProfile, # for the default topic, use search name but truncate if too long if len(search_name) >= MAX_TOPIC_NAME_LENGTH: - topic = "{}...".format(search_name[:(MAX_TOPIC_NAME_LENGTH - 3)]) + topic = f"{search_name[:(MAX_TOPIC_NAME_LENGTH - 3)]}..." else: topic = search_name diff --git a/zerver/webhooks/stripe/view.py b/zerver/webhooks/stripe/view.py index f27edb4353..489aafc7a6 100644 --- a/zerver/webhooks/stripe/view.py +++ b/zerver/webhooks/stripe/view.py @@ -122,7 +122,7 @@ def topic_and_body(payload: Dict[str, Any]) -> Tuple[str, str]: body += '\nEmail: {}'.format(object_['email']) if object_['metadata']: # nocoverage for key, value in object_['metadata'].items(): - body += '\n{}: {}'.format(key, value) + body += f'\n{key}: {value}' if resource == 'discount': body = 'Discount {verbed} ([{coupon_name}]({coupon_url})).'.format( verbed=event.replace('_', ' '), @@ -161,8 +161,8 @@ def topic_and_body(payload: Dict[str, Any]) -> Tuple[str, str]: # We are taking advantage of logical AND short circuiting here since we need the else # statement below. object_id = object_['id'] - invoice_link = 'https://dashboard.stripe.com/invoices/{}'.format(object_id) - body = '[Invoice]({invoice_link}) is now paid'.format(invoice_link=invoice_link) + invoice_link = f'https://dashboard.stripe.com/invoices/{object_id}' + body = f'[Invoice]({invoice_link}) is now paid' else: body = default_body(update_blacklist=['lines', 'description', 'number', 'finalized_at', 'status_transitions', 'payment_intent']) @@ -200,11 +200,11 @@ def amount_string(amount: int, currency: str) -> str: if currency in zero_decimal_currencies: decimal_amount = str(amount) # nocoverage else: - decimal_amount = '{:.02f}'.format(float(amount) * 0.01) + decimal_amount = f'{float(amount) * 0.01:.02f}' if currency == 'usd': # nocoverage return '$' + decimal_amount - return decimal_amount + ' {}'.format(currency.upper()) + return decimal_amount + f' {currency.upper()}' def linkified_id(object_id: str, lower: bool=False) -> str: names_and_urls: Dict[str, Tuple[str, Optional[str]]] = { @@ -250,7 +250,7 @@ def linkified_id(object_id: str, lower: bool=False) -> str: name = name.lower() if url_prefix is None: # nocoverage return name - return '[{}](https://dashboard.stripe.com/{}/{})'.format(name, url_prefix, object_id) + return f'[{name}](https://dashboard.stripe.com/{url_prefix}/{object_id})' def stringify(value: Any) -> str: if isinstance(value, int) and value > 1500000000 and value < 2000000000: diff --git a/zerver/webhooks/teamcity/view.py b/zerver/webhooks/teamcity/view.py index 3afc97e5cd..c4aa7d57cb 100644 --- a/zerver/webhooks/teamcity/view.py +++ b/zerver/webhooks/teamcity/view.py @@ -122,7 +122,7 @@ def api_teamcity_webhook(request: HttpRequest, user_profile: UserProfile, "Teamcity user '%s' or '%s'", teamcity_fullname, teamcity_shortname) return json_success() - body = "Your personal build for {}".format(body) + body = f"Your personal build for {body}" check_send_private_message(user_profile, request.client, teamcity_user, body) return json_success() diff --git a/zerver/webhooks/transifex/tests.py b/zerver/webhooks/transifex/tests.py index 67e73e96f8..115a1cd810 100644 --- a/zerver/webhooks/transifex/tests.py +++ b/zerver/webhooks/transifex/tests.py @@ -17,8 +17,8 @@ class TransifexHookTests(WebhookTestCase): def test_transifex_reviewed_message(self) -> None: self.REVIEWED = True - expected_topic = "{} in {}".format(self.PROJECT, self.LANGUAGE) - expected_message = "Resource {} fully reviewed.".format(self.RESOURCE) + expected_topic = f"{self.PROJECT} in {self.LANGUAGE}" + expected_message = f"Resource {self.RESOURCE} fully reviewed." self.url = self.build_webhook_url( self.URL_REVIEWED_METHOD_TEMPLATE, project=self.PROJECT, @@ -29,8 +29,8 @@ class TransifexHookTests(WebhookTestCase): def test_transifex_translated_message(self) -> None: self.REVIEWED = False - expected_topic = "{} in {}".format(self.PROJECT, self.LANGUAGE) - expected_message = "Resource {} fully translated.".format(self.RESOURCE) + expected_topic = f"{self.PROJECT} in {self.LANGUAGE}" + expected_message = f"Resource {self.RESOURCE} fully translated." self.url = self.build_webhook_url( self.URL_TRANSLATED_METHOD_TEMPLATE, project=self.PROJECT, diff --git a/zerver/webhooks/transifex/view.py b/zerver/webhooks/transifex/view.py index 8ade7cb88f..8614807fa0 100644 --- a/zerver/webhooks/transifex/view.py +++ b/zerver/webhooks/transifex/view.py @@ -23,11 +23,11 @@ def api_transifex_webhook( translated: Optional[int] = REQ(validator=check_int, default=None), reviewed: Optional[int] = REQ(validator=check_int, default=None), ) -> HttpResponse: - subject = "{} in {}".format(project, language) + subject = f"{project} in {language}" if translated: - body = "Resource {} fully translated.".format(resource) + body = f"Resource {resource} fully translated." elif reviewed: - body = "Resource {} fully reviewed.".format(resource) + body = f"Resource {resource} fully reviewed." else: raise UnexpectedWebhookEventType('Transifex', 'Unknown Event Type') check_send_webhook_message(request, user_profile, subject, body) diff --git a/zerver/webhooks/travis/tests.py b/zerver/webhooks/travis/tests.py index 7c2065efab..abb34fb670 100644 --- a/zerver/webhooks/travis/tests.py +++ b/zerver/webhooks/travis/tests.py @@ -40,7 +40,7 @@ class TravisHookTests(WebhookTestCase): self.assertNotEqual(msg.topic_name(), self.TOPIC) def test_travis_pull_requests_are_not_ignored_when_applicable(self) -> None: - self.url = "{}&ignore_pull_requests=false".format(self.build_webhook_url()) + self.url = f"{self.build_webhook_url()}&ignore_pull_requests=false" expected_message = ("Author: josh_mandel\nBuild status: Passed :thumbs_up:\n" "Details: [changes](https://github.com/hl7-fhir/fhir-sv" "n/compare/6dccb98bcfd9...6c457d366a31), [build log](ht" diff --git a/zerver/webhooks/travis/view.py b/zerver/webhooks/travis/view.py index 0966e2697d..54c856e501 100644 --- a/zerver/webhooks/travis/view.py +++ b/zerver/webhooks/travis/view.py @@ -41,7 +41,7 @@ def api_travis_webhook(request: HttpRequest, user_profile: UserProfile, elif message_status in PENDING_STATUSES: emoji = ':counterclockwise:' else: - emoji = "(No emoji specified for status '{}'.)".format(message_status) + emoji = f"(No emoji specified for status '{message_status}'.)" body = MESSAGE_TEMPLATE.format( message['author_name'], diff --git a/zerver/webhooks/trello/view/__init__.py b/zerver/webhooks/trello/view/__init__.py index 69d201e3ae..c455383037 100644 --- a/zerver/webhooks/trello/view/__init__.py +++ b/zerver/webhooks/trello/view/__init__.py @@ -46,4 +46,4 @@ def get_subject_and_body(payload: Mapping[str, Any], action_type: str) -> Option if action_type in SUPPORTED_BOARD_ACTIONS: return process_board_action(payload, action_type) - raise UnexpectedWebhookEventType("Trello", '{} is not supported'.format(action_type)) + raise UnexpectedWebhookEventType("Trello", f'{action_type} is not supported') diff --git a/zerver/webhooks/trello/view/board_actions.py b/zerver/webhooks/trello/view/board_actions.py index a35fc57656..7d3172f20a 100644 --- a/zerver/webhooks/trello/view/board_actions.py +++ b/zerver/webhooks/trello/view/board_actions.py @@ -48,7 +48,7 @@ def get_subject(payload: Mapping[str, Any]) -> str: def get_body(payload: Mapping[str, Any], action_type: str) -> str: message_body = ACTIONS_TO_FILL_BODY_MAPPER[action_type](payload, action_type) creator = payload['action']['memberCreator']['fullName'] - return '{full_name} {rest}'.format(full_name=creator, rest=message_body) + return f'{creator} {message_body}' def get_managed_member_body(payload: Mapping[str, Any], action_type: str) -> str: data = { diff --git a/zerver/webhooks/trello/view/card_actions.py b/zerver/webhooks/trello/view/card_actions.py index ad29dbf33b..4f779eb7d7 100644 --- a/zerver/webhooks/trello/view/card_actions.py +++ b/zerver/webhooks/trello/view/card_actions.py @@ -114,7 +114,7 @@ def get_subject(payload: Mapping[str, Any]) -> str: def get_body(payload: Mapping[str, Any], action_type: str) -> str: message_body = ACTIONS_TO_FILL_BODY_MAPPER[action_type](payload, action_type) creator = payload['action']['memberCreator'].get('fullName') - return '{full_name} {rest}'.format(full_name=creator, rest=message_body) + return f'{creator} {message_body}' def get_added_checklist_body(payload: Mapping[str, Any], action_type: str) -> str: data = { diff --git a/zerver/webhooks/updown/view.py b/zerver/webhooks/updown/view.py index 9081214a11..968e32d8c0 100644 --- a/zerver/webhooks/updown/view.py +++ b/zerver/webhooks/updown/view.py @@ -24,11 +24,11 @@ def get_body_for_up_event(event: Dict[str, Any]) -> str: body = "Service is `up`" event_downtime = event['downtime'] if event_downtime['started_at']: - body = "{} again".format(body) + body = f"{body} again" string_date = get_time_string_based_on_duration(event_downtime['duration']) if string_date: - body = "{} after {}".format(body, string_date) - return "{}.".format(body) + body = f"{body} after {string_date}" + return f"{body}." def get_time_string_based_on_duration(duration: int) -> str: days, reminder = divmod(duration, 86400) @@ -44,9 +44,9 @@ def get_time_string_based_on_duration(duration: int) -> str: def add_time_part_to_string_date_if_needed(value: int, text_name: str) -> str: if value == 1: - return "1 {} ".format(text_name) + return f"1 {text_name} " if value > 1: - return "{} {}s ".format(value, text_name) + return f"{value} {text_name}s " return '' def get_body_for_down_event(event: Dict[str, Any]) -> str: diff --git a/zerver/worker/queue_processors.py b/zerver/worker/queue_processors.py index 5f4fe21794..924f32e2b3 100644 --- a/zerver/worker/queue_processors.py +++ b/zerver/worker/queue_processors.py @@ -108,7 +108,7 @@ def retry_send_email_failures( func(worker, data) except (smtplib.SMTPServerDisconnected, socket.gaierror, EmailNotDeliveredException): def on_failure(event: Dict[str, Any]) -> None: - logging.exception("Event {} failed".format(event)) + logging.exception(f"Event {event} failed") retry_event(worker.queue_name, data, on_failure) diff --git a/zilencer/management/commands/compare_messages.py b/zilencer/management/commands/compare_messages.py index 2a9bcb285b..450d5d311d 100644 --- a/zilencer/management/commands/compare_messages.py +++ b/zilencer/management/commands/compare_messages.py @@ -26,5 +26,5 @@ class Command(BaseCommand): if m1['content'] != m2['content']: changed_count += 1 self.stdout.write('Changed message id: {id}'.format(id=m1['id'])) - self.stdout.write('Total messages: {count}'.format(count=total_count)) - self.stdout.write('Changed messages: {count}'.format(count=changed_count)) + self.stdout.write(f'Total messages: {total_count}') + self.stdout.write(f'Changed messages: {changed_count}') diff --git a/zilencer/management/commands/render_messages.py b/zilencer/management/commands/render_messages.py index fafaa89707..be193e1c95 100644 --- a/zilencer/management/commands/render_messages.py +++ b/zilencer/management/commands/render_messages.py @@ -33,7 +33,7 @@ class Command(BaseCommand): dest_dir = os.path.realpath(os.path.dirname(options['destination'])) amount = int(options['amount']) latest = int(options['latest_id']) or Message.objects.latest('id').id - self.stdout.write('Latest message id: {latest}'.format(latest=latest)) + self.stdout.write(f'Latest message id: {latest}') if not os.path.exists(dest_dir): os.makedirs(dest_dir) diff --git a/zproject/backends.py b/zproject/backends.py index d00bfd5e55..7029c7c111 100644 --- a/zproject/backends.py +++ b/zproject/backends.py @@ -192,7 +192,7 @@ class RateLimitedAuthenticationByUsername(RateLimitedObject): super().__init__() def key(self) -> str: - return "{}:{}".format(type(self).__name__, self.username) + return f"{type(self).__name__}:{self.username}" def rules(self) -> List[Tuple[int, int]]: return rate_limiting_rules @@ -832,7 +832,7 @@ def sync_user_from_ldap(user_profile: UserProfile, logger: logging.Logger) -> bo logger.info("Updated %s.", user_profile.delivery_email) return True - raise PopulateUserLDAPError("populate_user unexpectedly returned {}".format(updated_user)) + raise PopulateUserLDAPError(f"populate_user unexpectedly returned {updated_user}") # Quick tool to test whether you're correctly authenticating to LDAP def query_ldap(email: str) -> List[str]: @@ -842,7 +842,7 @@ def query_ldap(email: str) -> List[str]: try: ldap_username = backend.django_to_ldap_username(email) except ZulipLDAPExceptionNoMatchingLDAPUser as e: - values.append("No such user found: {}".format(e)) + values.append(f"No such user found: {e}") return values ldap_attrs = _LDAPUser(backend, ldap_username).attrs @@ -1738,7 +1738,7 @@ class SAMLAuthBackend(SocialAuthMixin, SAMLAuth): continue saml_dict: ExternalAuthMethodDictT = dict( - name='saml:{}'.format(idp_name), + name=f'saml:{idp_name}', display_name=idp_dict.get('display_name', cls.auth_backend_name), display_icon=idp_dict.get('display_icon', cls.display_icon), login_url=reverse('login-social-extra-arg', args=('saml', idp_name)), diff --git a/zproject/settings.py b/zproject/settings.py index 88fa7fabec..0a4d33e830 100644 --- a/zproject/settings.py +++ b/zproject/settings.py @@ -1050,7 +1050,7 @@ for idp_name, idp_dict in SOCIAL_AUTH_SAML_ENABLED_IDPS.items(): if 'x509cert_path' in idp_dict: path = idp_dict['x509cert_path'] else: - path = "/etc/zulip/saml/idps/{}.crt".format(idp_name) + path = f"/etc/zulip/saml/idps/{idp_name}.crt" idp_dict['x509cert'] = get_from_file_if_exists(path) SOCIAL_AUTH_PIPELINE = [ diff --git a/zproject/urls.py b/zproject/urls.py index 5d245661bc..b0a9aff3c4 100644 --- a/zproject/urls.py +++ b/zproject/urls.py @@ -699,7 +699,7 @@ for app_name in settings.EXTRA_INSTALLED_APPS: app_dir = os.path.join(settings.DEPLOY_ROOT, app_name) if os.path.exists(os.path.join(app_dir, 'urls.py')): urls += [url(r'^', include('%s.urls' % (app_name,)))] - i18n_urls += import_string("{}.urls.i18n_urlpatterns".format(app_name)) + i18n_urls += import_string(f"{app_name}.urls.i18n_urlpatterns") # Tornado views urls += [