diff --git a/analytics/lib/fixtures.py b/analytics/lib/fixtures.py index c707220a19..be7de5f5fa 100644 --- a/analytics/lib/fixtures.py +++ b/analytics/lib/fixtures.py @@ -47,7 +47,7 @@ def generate_time_series_data(days: int=100, business_hours_base: float=10, raise AssertionError(f"Unknown frequency: {frequency}") if length < 2: raise AssertionError("Must be generating at least 2 data points. " - "Currently generating %s" % (length,)) + f"Currently generating {length}") growth_base = growth ** (1. / (length-1)) values_no_noise = [seasonality[i % len(seasonality)] * (growth_base**i) for i in range(length)] diff --git a/analytics/management/commands/analyze_user_activity.py b/analytics/management/commands/analyze_user_activity.py index 07d52136d2..9c122e4f14 100644 --- a/analytics/management/commands/analyze_user_activity.py +++ b/analytics/management/commands/analyze_user_activity.py @@ -24,7 +24,7 @@ def analyze_activity(options: Dict[str, Any]) -> None: continue total_duration += duration - print("%-*s%s" % (37, user_profile.email, duration)) + print(f"{user_profile.email:<37}{duration}") print(f"\nTotal Duration: {total_duration}") print(f"\nTotal Duration in minutes: {total_duration.total_seconds() / 60.}") diff --git a/analytics/management/commands/check_analytics_state.py b/analytics/management/commands/check_analytics_state.py index 698317b6f5..5d66e05f99 100644 --- a/analytics/management/commands/check_analytics_state.py +++ b/analytics/management/commands/check_analytics_state.py @@ -60,8 +60,7 @@ class Command(BaseCommand): critical_threshold = timedelta(minutes=150) if floor_function(last_fill) != last_fill: - return {'status': 2, 'message': 'FillState not on %s boundary for %s' % - (stat.frequency, property)} + return {'status': 2, 'message': f'FillState not on {stat.frequency} boundary for {property}'} time_to_last_fill = timezone_now() - last_fill if time_to_last_fill > critical_threshold: @@ -72,7 +71,16 @@ class Command(BaseCommand): if len(critical_unfilled_properties) == 0 and len(warning_unfilled_properties) == 0: return {'status': 0, 'message': 'FillState looks fine.'} if len(critical_unfilled_properties) == 0: - return {'status': 1, 'message': 'Missed filling %s once.' % - (', '.join(warning_unfilled_properties),)} - return {'status': 2, 'message': 'Missed filling %s once. Missed filling %s at least twice.' % - (', '.join(warning_unfilled_properties), ', '.join(critical_unfilled_properties))} + return { + 'status': 1, + 'message': 'Missed filling {} once.'.format( + ', '.join(warning_unfilled_properties), + ), + } + return { + 'status': 2, + 'message': 'Missed filling {} once. Missed filling {} at least twice.'.format( + ', '.join(warning_unfilled_properties), + ', '.join(critical_unfilled_properties), + ), + } diff --git a/analytics/management/commands/update_analytics_counts.py b/analytics/management/commands/update_analytics_counts.py index d414a04747..eed57976ab 100644 --- a/analytics/management/commands/update_analytics_counts.py +++ b/analytics/management/commands/update_analytics_counts.py @@ -83,8 +83,7 @@ class Command(BaseCommand): last = time.time() if options['verbose']: - print("Finished updating analytics counts through %s in %.3fs" % - (fill_to_time, time.time() - start)) + print(f"Finished updating analytics counts through {fill_to_time} in {time.time() - start:.3f}s") logger.info("Finished updating analytics counts through %s", fill_to_time) if settings.PUSH_NOTIFICATION_BOUNCER_URL and settings.SUBMIT_USAGE_STATISTICS: diff --git a/analytics/views.py b/analytics/views.py index a73df62abd..d9147ae3b2 100644 --- a/analytics/views.py +++ b/analytics/views.py @@ -746,7 +746,7 @@ def user_activity_intervals() -> Tuple[mark_safe, Dict[str, float]]: total_duration += duration realm_duration += duration - output += " %-*s%s\n" % (37, email, duration) + output += f" {email:<37}{duration}\n" realm_minutes[string_id] = realm_duration.total_seconds() / 60 diff --git a/corporate/lib/stripe.py b/corporate/lib/stripe.py index 20f3f5f01d..3113e4a4ae 100644 --- a/corporate/lib/stripe.py +++ b/corporate/lib/stripe.py @@ -87,7 +87,7 @@ def next_month(billing_cycle_anchor: datetime, dt: datetime) -> datetime: if 20 < (proposed_next_month - dt).days < 40: return proposed_next_month raise AssertionError('Something wrong in next_month calculation with ' - 'billing_cycle_anchor: %s, dt: %s' % (billing_cycle_anchor, dt)) + f'billing_cycle_anchor: {billing_cycle_anchor}, dt: {dt}') def start_of_next_billing_cycle(plan: CustomerPlan, event_time: datetime) -> datetime: if plan.status == CustomerPlan.FREE_TRIAL: diff --git a/puppet/zulip/files/nagios_plugins/zulip_nagios_server/check_postgres_replication_lag b/puppet/zulip/files/nagios_plugins/zulip_nagios_server/check_postgres_replication_lag index bb37975cbe..053a863115 100755 --- a/puppet/zulip/files/nagios_plugins/zulip_nagios_server/check_postgres_replication_lag +++ b/puppet/zulip/files/nagios_plugins/zulip_nagios_server/check_postgres_replication_lag @@ -87,5 +87,4 @@ if recv_diff > 16 * 1024**2: if replay_diff > 16 * 1024**2: report('WARNING', f'secondary is {replay_diff} bytes behind on applying received xlog') -report('OK', ('secondary is %d bytes behind on receiving and %d bytes behind on applying xlog' - % (recv_diff, replay_diff))) +report('OK', f'secondary is {recv_diff} bytes behind on receiving and {replay_diff} bytes behind on applying xlog') diff --git a/scripts/lib/zulip_tools.py b/scripts/lib/zulip_tools.py index f460830809..3e6127a9ba 100755 --- a/scripts/lib/zulip_tools.py +++ b/scripts/lib/zulip_tools.py @@ -173,7 +173,7 @@ def get_deployment_lock(error_rerun_script: str) -> None: print(FAIL + "Deployment already in progress. Please run\n" + " {}\n".format(error_rerun_script) + "manually when the previous deployment finishes, or run\n" + - " rmdir %s\n" % (LOCK_DIR,) + + " rmdir {}\n".format(LOCK_DIR) + "if the previous deployment crashed." + ENDC) sys.exit(1) @@ -189,9 +189,9 @@ def run(args: Sequence[str], **kwargs: Any) -> None: subprocess.check_call(args, **kwargs) except subprocess.CalledProcessError: print() - print(WHITEONRED + "Error running a subcommand of %s: %s" % - (sys.argv[0], " ".join(map(shlex.quote, args))) + - ENDC) + print(WHITEONRED + "Error running a subcommand of {}: {}".format( + sys.argv[0], " ".join(map(shlex.quote, args)), + ) + ENDC) print(WHITEONRED + "Actual error output for the subcommand is just above this." + ENDC) print() diff --git a/scripts/restart-server b/scripts/restart-server index 33b2f132c5..c4849110ae 100755 --- a/scripts/restart-server +++ b/scripts/restart-server @@ -98,12 +98,11 @@ if change_symlink and "PWD" in os.environ: if os.path.commonprefix([os.environ["PWD"], symlink]) == symlink: print( """ -%sYour shell entered its current directory through a symlink: - %s +{}Your shell entered its current directory through a symlink: + {} which has now changed. Your shell will not see this change until you run: - cd %s -to traverse the symlink again.%s -""" - % (WARNING, symlink, shlex.quote(os.environ["PWD"]), ENDC), + cd {} +to traverse the symlink again.{} +""".format(WARNING, symlink, shlex.quote(os.environ["PWD"]), ENDC), file=sys.stderr, ) diff --git a/scripts/setup/generate_secrets.py b/scripts/setup/generate_secrets.py index 1bb880e278..07ad5be456 100755 --- a/scripts/setup/generate_secrets.py +++ b/scripts/setup/generate_secrets.py @@ -148,7 +148,7 @@ def generate_secrets(development: bool = False) -> None: with open(filename, "a") as f: f.write( "# Set a Redis password based on zulip-secrets.conf\n" - "requirepass '%s'\n" % (redis_password,), + f"requirepass '{redis_password}'\n", ) break diff --git a/tools/lib/pretty_print.py b/tools/lib/pretty_print.py index 2abc94ac2b..c23c1cacfe 100644 --- a/tools/lib/pretty_print.py +++ b/tools/lib/pretty_print.py @@ -200,7 +200,7 @@ def validate_indent_html(fn: str, fix: bool) -> int: # Since we successfully fixed the issues, we exit with status 0 return 0 print('Invalid Indentation detected in file: ' - '%s\nDiff for the file against expected indented file:' % (fn,), flush=True) + f'{fn}\nDiff for the file against expected indented file:', flush=True) with subprocess.Popen( ['diff', fn, '-'], stdin=subprocess.PIPE, diff --git a/tools/lib/provision.py b/tools/lib/provision.py index a67034129b..1885eea2ea 100755 --- a/tools/lib/provision.py +++ b/tools/lib/provision.py @@ -311,10 +311,14 @@ def install_yum_deps(deps_to_install: List[str]) -> None: # Later steps will ensure postgres is started # Link in tsearch data files - overwrite_symlink("/usr/share/myspell/en_US.dic", "/usr/pgsql-%s/share/tsearch_data/en_us.dict" - % (POSTGRES_VERSION,)) - overwrite_symlink("/usr/share/myspell/en_US.aff", "/usr/pgsql-%s/share/tsearch_data/en_us.affix" - % (POSTGRES_VERSION,)) + overwrite_symlink( + "/usr/share/myspell/en_US.dic", + "/usr/pgsql-{}/share/tsearch_data/en_us.dict".format(POSTGRES_VERSION), + ) + overwrite_symlink( + "/usr/share/myspell/en_US.aff", + "/usr/pgsql-{}/share/tsearch_data/en_us.affix".format(POSTGRES_VERSION,), + ) def main(options: argparse.Namespace) -> "NoReturn": diff --git a/zerver/lib/bugdown/__init__.py b/zerver/lib/bugdown/__init__.py index 7cc0d7acc7..1a36f16a2b 100644 --- a/zerver/lib/bugdown/__init__.py +++ b/zerver/lib/bugdown/__init__.py @@ -2358,8 +2358,9 @@ def do_convert(content: str, # rest of the codebase from any bugs where we end up rendering # something huge. if len(rendered_content) > MAX_MESSAGE_LENGTH * 10: - raise BugdownRenderingException('Rendered content exceeds %s characters (message %s)' % - (MAX_MESSAGE_LENGTH * 10, logging_message_id)) + raise BugdownRenderingException( + f'Rendered content exceeds {MAX_MESSAGE_LENGTH * 10} characters (message {logging_message_id})' + ) return rendered_content except Exception: cleaned = privacy_clean_markdown(content) diff --git a/zerver/lib/email_notifications.py b/zerver/lib/email_notifications.py index c618dda143..2508ecbb38 100644 --- a/zerver/lib/email_notifications.py +++ b/zerver/lib/email_notifications.py @@ -309,8 +309,7 @@ def do_send_missedmessage_events_reply_in_zulip(user_profile: UserProfile, recipients = {(msg['message'].recipient_id, msg['message'].topic_name()) for msg in missed_messages} if len(recipients) != 1: raise ValueError( - 'All missed_messages must have the same recipient and topic %r' % - (recipients,), + f'All missed_messages must have the same recipient and topic {recipients!r}', ) # This link is no longer a part of the email, but keeping the code in case diff --git a/zerver/lib/error_notify.py b/zerver/lib/error_notify.py index 60512a4e34..e5c0c50334 100644 --- a/zerver/lib/error_notify.py +++ b/zerver/lib/error_notify.py @@ -20,16 +20,15 @@ def format_email_subject(email_subject: str) -> str: return email_subject.replace('\n', '\\n').replace('\r', '\\r') def logger_repr(report: Dict[str, Any]) -> str: - return ("Logger %(logger_name)s, from module %(log_module)s line %(log_lineno)d:" - % dict(report)) + return "Logger {logger_name}, from module {log_module} line {log_lineno}:".format(**report) def user_info_str(report: Dict[str, Any]) -> str: if report['user_full_name'] and report['user_email']: - user_info = "%(user_full_name)s (%(user_email)s)" % dict(report) + user_info = "{user_full_name} ({user_email})".format(**report) else: user_info = "Anonymous user (not logged in)" - user_info += " on %s deployment" % (report['deployment'],) + user_info += " on {deployment} deployment".format(**report) return user_info def deployment_repr(report: Dict[str, Any]) -> str: @@ -47,14 +46,21 @@ def notify_browser_error(report: Dict[str, Any]) -> None: def email_browser_error(report: Dict[str, Any]) -> None: email_subject = f"Browser error for {user_info_str(report)}" - body = ("User: %(user_full_name)s <%(user_email)s> on %(deployment)s\n\n" - "Message:\n%(message)s\n\nStacktrace:\n%(stacktrace)s\n\n" - "IP address: %(ip_address)s\n" - "User agent: %(user_agent)s\n" - "href: %(href)s\n" - "Server path: %(server_path)s\n" - "Deployed version: %(version)s\n" - % dict(report)) + body = """\ +User: {user_full_name} <{user_email}> on {deployment} + +Message: +{message} + +Stacktrace: +{stacktrace} + +IP address: {ip_address} +User agent: {user_agent} +href: {href} +Server path: {server_path} +Deployed version: {version} +""".format(**report) more_info = report['more_info'] if more_info is not None: @@ -62,18 +68,17 @@ def email_browser_error(report: Dict[str, Any]) -> None: for (key, value) in more_info.items(): body += f"\n {key}: {value}" - body += "\n\nLog:\n{}".format(report['log']) + body += "\n\nLog:\n{log}".format(**report) mail_admins(email_subject, body) def zulip_browser_error(report: Dict[str, Any]) -> None: - email_subject = "JS error: {}".format(report['user_email']) + email_subject = "JS error: {user_email}".format(**report) user_info = user_info_str(report) body = f"User: {user_info}\n" - body += ("Message: %(message)s\n" - % dict(report)) + body += "Message: {message}\n".format(**report) error_bot = get_system_bot(settings.ERROR_BOT) realm = error_bot.realm @@ -94,17 +99,19 @@ def notify_server_error(report: Dict[str, Any], skip_error_zulip: bool=False) -> zulip_server_error(report) def zulip_server_error(report: Dict[str, Any]) -> None: - email_subject = '%(node)s: %(message)s' % dict(report) + email_subject = '{node}: {message}'.format(**report) logger_str = logger_repr(report) user_info = user_info_str(report) deployment = deployment_repr(report) if report['has_request']: - request_repr = ( - "Request info:\n~~~~\n" - "- path: %(path)s\n" - "- %(method)s: %(data)s\n") % dict(report) + request_repr = """\ +Request info: +~~~~ +- path: {path} +- {method}: {data} +""".format(**report) for field in ["REMOTE_ADDR", "QUERY_STRING", "SERVER_NAME"]: val = report.get(field.lower()) if field == "QUERY_STRING": @@ -114,8 +121,15 @@ def zulip_server_error(report: Dict[str, Any]) -> None: else: request_repr = "Request info: none" - message = ("%s\nError generated by %s\n\n~~~~ pytb\n%s\n\n~~~~\n%s\n%s" - % (logger_str, user_info, report['stack_trace'], deployment, request_repr)) + message = f"""{logger_str} +Error generated by {user_info} + +~~~~ pytb +{report['stack_trace']} + +~~~~ +{deployment} +{request_repr}""" error_bot = get_system_bot(settings.ERROR_BOT) realm = error_bot.realm @@ -130,17 +144,18 @@ def zulip_server_error(report: Dict[str, Any]) -> None: ) def email_server_error(report: Dict[str, Any]) -> None: - email_subject = '%(node)s: %(message)s' % dict(report) + email_subject = '{node}: {message}'.format(**report) logger_str = logger_repr(report) user_info = user_info_str(report) deployment = deployment_repr(report) if report['has_request']: - request_repr = ( - "Request info:\n" - "- path: %(path)s\n" - "- %(method)s: %(data)s\n") % dict(report) + request_repr = """\ +Request info: +- path: {path} +- {method}: {data} +""".format(**report) for field in ["REMOTE_ADDR", "QUERY_STRING", "SERVER_NAME"]: val = report.get(field.lower()) if field == "QUERY_STRING": @@ -149,8 +164,15 @@ def email_server_error(report: Dict[str, Any]) -> None: else: request_repr = "Request info: none\n" - message = ("%s\nError generated by %s\n\n%s\n\n%s\n\n%s" - % (logger_str, user_info, report['stack_trace'], deployment, request_repr)) + message = f"""\ +{logger_str} +Error generated by {user_info} + +{report['stack_trace']} + +{deployment} + +{request_repr}""" mail_admins(format_email_subject(email_subject), message, fail_silently=True) diff --git a/zerver/lib/management.py b/zerver/lib/management.py index 3da9b47a6e..0f157c45aa 100644 --- a/zerver/lib/management.py +++ b/zerver/lib/management.py @@ -83,8 +83,7 @@ You can use the command list_realms to find ID of the realms in this server.""" return Realm.objects.get(id=val) return Realm.objects.get(string_id=val) except Realm.DoesNotExist: - raise CommandError("There is no realm with id '%s'. Aborting." % - (options["realm_id"],)) + raise CommandError("There is no realm with id '{}'. Aborting.".format(options["realm_id"])) def get_users(self, options: Dict[str, Any], realm: Optional[Realm], is_bot: Optional[bool]=None, diff --git a/zerver/lib/outgoing_webhook.py b/zerver/lib/outgoing_webhook.py index 88105c379d..638636e130 100644 --- a/zerver/lib/outgoing_webhook.py +++ b/zerver/lib/outgoing_webhook.py @@ -236,11 +236,10 @@ def notify_bot_owner(event: Dict[str, Any], notification_message += f"\nThe webhook got a response with status code *{status_code}*." if response_content: notification_message += "\nThe response contains the following payload:\n" \ - "```\n%s\n```" % (str(response_content),) + f"```\n{response_content!r}\n```" if exception: notification_message += "\nWhen trying to send a request to the webhook service, an exception " \ - "of type %s occurred:\n```\n%s\n```" % ( - type(exception).__name__, str(exception)) + f"of type {type(exception).__name__} occurred:\n```\n{exception}\n```" message_info = dict( type='private', @@ -329,9 +328,10 @@ def do_rest_call(base_url: str, request_retry(event, failure_message=failure_message) except requests.exceptions.RequestException as e: - response_message = ("An exception of type *%s* occurred for message `%s`! " - "See the Zulip server logs for more information." % ( - type(e).__name__, event["command"])) + response_message = ( + f"An exception of type *{type(e).__name__}* occurred for message `{event['command']}`! " + "See the Zulip server logs for more information." + ) logging.exception("Outhook trigger failed:") fail_with_message(event, response_message) notify_bot_owner(event, exception=e) diff --git a/zerver/lib/send_email.py b/zerver/lib/send_email.py index fc26078f6f..6534a6dbe7 100644 --- a/zerver/lib/send_email.py +++ b/zerver/lib/send_email.py @@ -128,14 +128,12 @@ class EmailNotDeliveredException(Exception): class DoubledEmailArgumentException(CommandError): def __init__(self, argument_name: str) -> None: - msg = "Argument '%s' is ambiguously present in both options and email template." % ( - argument_name) + msg = f"Argument '{argument_name}' is ambiguously present in both options and email template." super().__init__(msg) class NoEmailArgumentException(CommandError): def __init__(self, argument_name: str) -> None: - msg = "Argument '%s' is required in either options or email template." % ( - argument_name) + msg = f"Argument '{argument_name}' is required in either options or email template." super().__init__(msg) # When changing the arguments to this function, you may need to write a diff --git a/zerver/lib/unminify.py b/zerver/lib/unminify.py index 3c19ea7a8d..ec789746de 100644 --- a/zerver/lib/unminify.py +++ b/zerver/lib/unminify.py @@ -60,8 +60,7 @@ class SourceMap: webpack_prefix = "webpack:///" if display_src.startswith(webpack_prefix): display_src = display_src[len(webpack_prefix):] - out += (' = %s line %d column %d\n' % - (display_src, result.src_line+1, result.src_col+1)) + out += f' = {display_src} line {result.src_line+1} column {result.src_col+1}\n' except IndexError: out += ' [Unable to look up in source map]\n' diff --git a/zerver/management/commands/add_users_to_mailing_list.py b/zerver/management/commands/add_users_to_mailing_list.py index 8ea4b84ca6..d053176e7b 100644 --- a/zerver/management/commands/add_users_to_mailing_list.py +++ b/zerver/management/commands/add_users_to_mailing_list.py @@ -49,8 +49,9 @@ class Command(BaseCommand): raise CommandError('Please supply a MailChimp List ID to --list-id, or add a ' 'ZULIP_FRIENDS_LIST_ID to your server settings file.') - endpoint = "https://%s.api.mailchimp.com/3.0/lists/%s/members" % \ - (api_key.split('-')[1], options['list_id']) + endpoint = "https://{}.api.mailchimp.com/3.0/lists/{}/members".format( + api_key.split('-')[1], options['list_id'], + ) for user in UserProfile.objects.filter(is_bot=False, is_active=True) \ .values('email', 'full_name', 'realm_id'): diff --git a/zerver/management/commands/export.py b/zerver/management/commands/export.py index 2b9eaf1cc7..a3a0b5cca9 100644 --- a/zerver/management/commands/export.py +++ b/zerver/management/commands/export.py @@ -121,8 +121,7 @@ class Command(ZulipBaseCommand): if os.path.exists(output_dir): if os.listdir(output_dir): raise CommandError( - "Refusing to overwrite nonempty directory: %s. Aborting..." - % (output_dir,), + f"Refusing to overwrite nonempty directory: {output_dir}. Aborting...", ) else: os.makedirs(output_dir) diff --git a/zerver/management/commands/realm_domain.py b/zerver/management/commands/realm_domain.py index 35b4c41e17..e395e2c385 100644 --- a/zerver/management/commands/realm_domain.py +++ b/zerver/management/commands/realm_domain.py @@ -51,8 +51,8 @@ class Command(ZulipBaseCommand): allow_subdomains=options["allow_subdomains"]) sys.exit(0) except IntegrityError: - raise CommandError("The domain %(domain)s is already a part " - "of your organization." % {'domain': domain}) + raise CommandError(f"The domain {domain} is already a part " + "of your organization.") elif options["op"] == "remove": try: RealmDomain.objects.get(realm=realm, domain=domain).delete() diff --git a/zerver/management/commands/register_server.py b/zerver/management/commands/register_server.py index 31c39427a6..13856faed5 100644 --- a/zerver/management/commands/register_server.py +++ b/zerver/management/commands/register_server.py @@ -73,8 +73,10 @@ class Command(ZulipBaseCommand): try: response = requests.post(registration_url, params=request) except Exception: - raise CommandError("Network error connecting to push notifications service (%s)" - % (settings.PUSH_NOTIFICATION_BOUNCER_URL,)) + raise CommandError( + "Network error connecting to push notifications service " + f"({settings.PUSH_NOTIFICATION_BOUNCER_URL})", + ) try: response.raise_for_status() except Exception: diff --git a/zerver/management/commands/soft_deactivate_users.py b/zerver/management/commands/soft_deactivate_users.py index cf44d80a75..0d92daad0b 100644 --- a/zerver/management/commands/soft_deactivate_users.py +++ b/zerver/management/commands/soft_deactivate_users.py @@ -25,8 +25,11 @@ def get_users_from_emails(emails: List[str], if len(users) != len(emails): user_emails_found = {user.delivery_email for user in users} user_emails_not_found = '\n'.join(set(emails) - user_emails_found) - raise CommandError('Users with the following emails were not found:\n\n%s\n\n' - 'Check if they are correct.' % (user_emails_not_found,)) + raise CommandError( + 'Users with the following emails were not found:\n\n' + f'{user_emails_not_found}\n\n' + 'Check if they are correct.', + ) return users class Command(ZulipBaseCommand): diff --git a/zerver/middleware.py b/zerver/middleware.py index 95795b64b3..2dd90c1fbc 100644 --- a/zerver/middleware.py +++ b/zerver/middleware.py @@ -193,13 +193,8 @@ def write_log_line(log_data: MutableMapping[str, Any], path: str, method: str, r else: extra_request_data = "" logger_client = f"({requestor_for_logs} via {client_name})" - logger_timing = ('%5s%s%s%s%s%s %s' % - (format_timedelta(time_delta), optional_orig_delta, - remote_cache_output, bugdown_output, - db_time_output, startup_output, path)) - logger_line = ('%-15s %-7s %3d %s%s %s' % - (remote_ip, method, status_code, - logger_timing, extra_request_data, logger_client)) + logger_timing = f'{format_timedelta(time_delta):>5}{optional_orig_delta}{remote_cache_output}{bugdown_output}{db_time_output}{startup_output} {path}' + logger_line = f'{remote_ip:<15} {method:<7} {status_code:3} {logger_timing}{extra_request_data} {logger_client}' if (status_code in [200, 304] and method == "GET" and path.startswith("/static")): logger.debug(logger_line) else: diff --git a/zerver/migrations/0145_reactions_realm_emoji_name_to_id.py b/zerver/migrations/0145_reactions_realm_emoji_name_to_id.py index 5a7be517f8..d7bffafcc7 100644 --- a/zerver/migrations/0145_reactions_realm_emoji_name_to_id.py +++ b/zerver/migrations/0145_reactions_realm_emoji_name_to_id.py @@ -24,8 +24,7 @@ def realm_emoji_name_to_id(apps: StateApps, schema_editor: DatabaseSchemaEditor) # Realm emoji used in this reaction has been deleted so this # reaction should also be deleted. We don't need to reverse # this step in migration reversal code. - print("Reaction for (%s, %s) refers to deleted custom emoji %s; deleting" % - (emoji_name, reaction.message_id, reaction.user_profile_id)) + print(f"Reaction for ({emoji_name}, {reaction.message_id}) refers to deleted custom emoji {reaction.user_profile_id}; deleting") reaction.delete() else: reaction.emoji_code = realm_emoji["id"] diff --git a/zerver/tests/test_auth_backends.py b/zerver/tests/test_auth_backends.py index 90c1228717..88cf0862c7 100644 --- a/zerver/tests/test_auth_backends.py +++ b/zerver/tests/test_auth_backends.py @@ -819,8 +819,7 @@ class SocialAuthBase(DesktopFlowTestingLib, ZulipTestCase): expected_result_url_prefix = f'http://testserver/login/{self.backend.name}/' if settings.SOCIAL_AUTH_SUBDOMAIN is not None: - expected_result_url_prefix = ('http://%s.testserver/login/%s/' % - (settings.SOCIAL_AUTH_SUBDOMAIN, self.backend.name)) + expected_result_url_prefix = f'http://{settings.SOCIAL_AUTH_SUBDOMAIN}.testserver/login/{self.backend.name}/' if result.status_code != 302 or not result.url.startswith(expected_result_url_prefix): return result @@ -1773,8 +1772,8 @@ class SAMLAuthBackendTest(SocialAuthBase): self.assertEqual(result.status_code, 302) self.assertEqual('/login/', result.url) self.assertEqual(m.output, [self.logger_output( - '/complete/saml/: Authentication request with IdP %s but this provider is not enabled ' - 'for this subdomain %s.' % ("test_idp", "zephyr"), 'info', + '/complete/saml/: Authentication request with IdP test_idp but this provider is not enabled ' + 'for this subdomain zephyr.', 'info', )]) def test_social_auth_saml_login_bad_idp_arg(self) -> None: @@ -1908,7 +1907,7 @@ class SAMLAuthBackendTest(SocialAuthBase): self.assertEqual(result.status_code, 302) self.assertEqual('/login/', result.url) self.assertEqual(m.output, [self.logger_output( - "/complete/saml/: Can't figure out subdomain for this authentication request. relayed_params: %s" % {}, + "/complete/saml/: Can't figure out subdomain for this authentication request. relayed_params: {}", "info", )]) @@ -2598,8 +2597,8 @@ class GitHubAuthBackendTest(SocialAuthBase): self.assertEqual(result.status_code, 302) self.assertEqual(result.url, "/login/") self.assertEqual(m.output, [self.logger_output( - "Social auth (%s) failed because user has no verified" - " emails associated with the account" % ("GitHub",), + "Social auth (GitHub) failed because user has no verified" + " emails associated with the account", "warning", )]) @@ -2622,8 +2621,8 @@ class GitHubAuthBackendTest(SocialAuthBase): self.assertEqual(result.status_code, 302) self.assertEqual(result.url, "/login/") self.assertEqual(m.output, [self.logger_output( - "Social auth (%s) failed because user has no verified" - " emails associated with the account" % ("GitHub",), + "Social auth (GitHub) failed because user has no verified" + " emails associated with the account", "warning", )]) diff --git a/zerver/tests/test_bots.py b/zerver/tests/test_bots.py index ab8733720c..61b0613e81 100644 --- a/zerver/tests/test_bots.py +++ b/zerver/tests/test_bots.py @@ -38,7 +38,7 @@ from zerver.models import ( # A test validator def _check_string(var_name: str, val: object) -> Optional[str]: if str(val).startswith("_"): - return ('%s starts with a "_" and is hence invalid.') % (var_name,) + return f'{var_name} starts with a "_" and is hence invalid.' return None stripe_sample_config_options = [ diff --git a/zerver/tests/test_bugdown.py b/zerver/tests/test_bugdown.py index c5ae876a2f..c1176681a7 100644 --- a/zerver/tests/test_bugdown.py +++ b/zerver/tests/test_bugdown.py @@ -745,17 +745,17 @@ class BugdownTest(ZulipTestCase): ## As of right now, all previews are mocked to be the exact same tweet return ('
' - '@King Hamlet
' % (user_id,)) + f'data-user-id="{user_id}">' + '@King Hamlet') self.assertEqual(msg.mentions_user_ids, {user_profile.id}) def test_mention_silent(self) -> None: @@ -1464,8 +1464,8 @@ class BugdownTest(ZulipTestCase): content = "@_**King Hamlet**" self.assertEqual(render_markdown(msg, content), '' - 'King Hamlet
' % (user_id,)) + f'data-user-id="{user_id}">' + 'King Hamlet') self.assertEqual(msg.mentions_user_ids, set()) def test_possible_mentions(self) -> None: @@ -1493,10 +1493,10 @@ class BugdownTest(ZulipTestCase): self.assertEqual(render_markdown(msg, content), '' '@King Hamlet and ' + f'data-user-id="{hamlet.id}">@King Hamlet and ' '@Cordelia Lear, ' - 'check this out
' % (hamlet.id, cordelia.id)) + f'data-user-id="{cordelia.id}">@Cordelia Lear, ' + 'check this out') self.assertEqual(msg.mentions_user_ids, {hamlet.id, cordelia.id}) def test_mention_in_quotes(self) -> None: @@ -1508,21 +1508,21 @@ class BugdownTest(ZulipTestCase): content = "> @**King Hamlet** and @**Othello, the Moor of Venice**\n\n @**King Hamlet** and @**Cordelia Lear**" self.assertEqual(render_markdown(msg, content), '\n\n' '' - 'King Hamlet' + f'King Hamlet' ' and ' - 'Othello, the Moor of Venice' + f'Othello, the Moor of Venice' '
\n
' - '@King Hamlet' + f'@King Hamlet' ' and ' - '@Cordelia Lear' - '
' % (hamlet.id, othello.id, hamlet.id, cordelia.id)) + f'@Cordelia Lear' + '') self.assertEqual(msg.mentions_user_ids, {hamlet.id, cordelia.id}) # Both fenced quote and > quote should be identical for both silent and regular syntax. expected = ('\n' % (hamlet.id,)) + f'King Hamlet' + '\n') content = "```quote\n@**King Hamlet**\n```" self.assertEqual(render_markdown(msg, content), expected) self.assertEqual(msg.mentions_user_ids, set()) @@ -1559,12 +1559,12 @@ class BugdownTest(ZulipTestCase): self.assertEqual(render_markdown(msg, content), '' - 'King Hamlet' - '
\n
' '@Mark Twin, ' + f'data-user-id="{twin1.id}">@Mark Twin, ' '@Mark Twin and ' + f'data-user-id="{twin2.id}">@Mark Twin and ' '@Cordelia Lear, ' - 'hi.
' % (twin1.id, twin2.id, cordelia.id)) + f'data-user-id="{cordelia.id}">@Cordelia Lear, ' + 'hi.') self.assertEqual(msg.mentions_user_ids, {twin1.id, twin2.id, cordelia.id}) def test_mention_invalid(self) -> None: @@ -1599,14 +1599,14 @@ class BugdownTest(ZulipTestCase): content = "@**Atomic #123**" self.assertEqual(render_markdown(msg, content), '' - '@Atomic #123
' % (test_user.id,)) + f'data-user-id="{test_user.id}">' + '@Atomic #123') self.assertEqual(msg.mentions_user_ids, {test_user.id}) content = "@_**Atomic #123**" self.assertEqual(render_markdown(msg, content), '' - 'Atomic #123
' % (test_user.id,)) + f'data-user-id="{test_user.id}">' + 'Atomic #123') self.assertEqual(msg.mentions_user_ids, set()) def create_user_group_for_test(self, user_group_name: str) -> UserGroup: @@ -1623,12 +1623,11 @@ class BugdownTest(ZulipTestCase): content = "@**King Hamlet** @*support*" self.assertEqual(render_markdown(msg, content), '' + f'data-user-id="{user_id}">' '@King Hamlet ' '' - '@support
' % (user_id, - user_group.id)) + f'data-user-group-id="{user_group.id}">' + '@support') self.assertEqual(msg.mentions_user_ids, {user_profile.id}) self.assertEqual(msg.mentions_user_group_ids, {user_group.id}) @@ -1654,12 +1653,11 @@ class BugdownTest(ZulipTestCase): content = "@**King Hamlet** @*support #123*" self.assertEqual(render_markdown(msg, content), '' + f'data-user-id="{user_id}">' '@King Hamlet ' '' - '@support #123
' % (user_id, - user_group.id)) + f'data-user-group-id="{user_group.id}">' + '@support #123') self.assertEqual(msg.mentions_user_ids, {user_profile.id}) self.assertEqual(msg.mentions_user_group_ids, {user_group.id}) @@ -1692,14 +1690,14 @@ class BugdownTest(ZulipTestCase): self.assertEqual(render_markdown(msg, content), '' '' + f'data-user-group-id="{support.id}">' '@support ' 'and ' '' + f'data-user-group-id="{backend.id}">' '@backend, ' 'check this out' - '
' % (support.id, backend.id)) + '') self.assertEqual(msg.mentions_user_group_ids, {support.id, backend.id}) diff --git a/zerver/tests/test_custom_profile_data.py b/zerver/tests/test_custom_profile_data.py index eccd737c63..80c87cc893 100644 --- a/zerver/tests/test_custom_profile_data.py +++ b/zerver/tests/test_custom_profile_data.py @@ -498,8 +498,7 @@ class UpdateCustomProfileFieldTest(CustomProfileFieldTestCase): field_name = "Mentor" invalid_user_id = 1000 self.assert_error_update_invalid_value(field_name, [invalid_user_id], - "Invalid user ID: %d" - % (invalid_user_id,)) + f"Invalid user ID: {invalid_user_id}") def test_update_profile_data_successfully(self) -> None: self.login('iago') diff --git a/zerver/tests/test_import_export.py b/zerver/tests/test_import_export.py index 0fdacd442a..b2da7b8ed2 100644 --- a/zerver/tests/test_import_export.py +++ b/zerver/tests/test_import_export.py @@ -958,18 +958,16 @@ class ImportExportTest(ZulipTestCase): original_msg = Message.objects.get(content=special_characters_message, sender__realm=original_realm) self.assertEqual( original_msg.rendered_content, - (''\n
@Polonius
' % - (orig_polonius_user.id,)), + ''\n
@Polonius
', ) imported_polonius_user = UserProfile.objects.get(delivery_email=self.example_email("polonius"), realm=imported_realm) imported_msg = Message.objects.get(content=special_characters_message, sender__realm=imported_realm) self.assertEqual( imported_msg.rendered_content, - ('\'\n
@Polonius
' % - (imported_polonius_user.id,)), + '\'\n
@Polonius
', ) # Check recipient_id was generated correctly for the imported users and streams. diff --git a/zerver/tests/test_narrow.py b/zerver/tests/test_narrow.py index d6012dde84..9ff4eedb61 100644 --- a/zerver/tests/test_narrow.py +++ b/zerver/tests/test_narrow.py @@ -2954,6 +2954,6 @@ WHERE user_profile_id = {hamlet_id} AND (content ILIKE '%jumping%' OR subject IL 'say hello') self.assertEqual( hello_message['match_content'], - ('How are you doing, ' + - '@Othello, the Moor of Venice?
') % ( - othello.id)) + f'How are you doing, ' + '@Othello, the Moor of Venice?
', + ) diff --git a/zerver/tests/test_openapi.py b/zerver/tests/test_openapi.py index b57c145865..7f81de2fd1 100644 --- a/zerver/tests/test_openapi.py +++ b/zerver/tests/test_openapi.py @@ -601,8 +601,7 @@ so maybe we shouldn't include it in pending_endpoints. openapi_parameters = get_openapi_parameters(url_pattern, method, include_url_parameters=False) except Exception: # nocoverage - raise AssertionError("Could not find OpenAPI docs for %s %s" % - (method, url_pattern)) + raise AssertionError(f"Could not find OpenAPI docs for {method} {url_pattern}") # We now have everything we need to understand the # function as defined in our urls.py: diff --git a/zerver/tests/test_push_notifications.py b/zerver/tests/test_push_notifications.py index 0cc191112e..ce901da49b 100644 --- a/zerver/tests/test_push_notifications.py +++ b/zerver/tests/test_push_notifications.py @@ -2015,5 +2015,4 @@ class PushBouncerSignupTest(ZulipTestCase): contact_email="server-admin@example.com", ) result = self.client_post("/api/v1/remotes/server/register", request) - self.assert_json_error(result, "Zulip server auth failure: key does not match role %s" % - (zulip_org_id,)) + self.assert_json_error(result, f"Zulip server auth failure: key does not match role {zulip_org_id}") diff --git a/zerver/tests/test_realm.py b/zerver/tests/test_realm.py index a4184a6e1d..251b6f24ed 100644 --- a/zerver/tests/test_realm.py +++ b/zerver/tests/test_realm.py @@ -524,10 +524,10 @@ class RealmTest(ZulipTestCase): def do_test_invalid_integer_attribute_value(self, val_name: str, invalid_val: int) -> None: possible_messages = { - "Invalid %(field_name)s" % dict(field_name=val_name), - "Bad value for '%(field_name)s'" % dict(field_name=val_name), - "Bad value for '%(field_name)s': %(value)s" % dict(field_name=val_name, value=invalid_val), - "Invalid %(field_name)s %(value)s" % dict(field_name=val_name, value=invalid_val), + f"Invalid {val_name}", + f"Bad value for '{val_name}'", + f"Bad value for '{val_name}': {invalid_val}", + f"Invalid {val_name} {invalid_val}", } req = {val_name: invalid_val} diff --git a/zerver/tests/test_realm_export.py b/zerver/tests/test_realm_export.py index e9af3781dd..4f5401e6c8 100644 --- a/zerver/tests/test_realm_export.py +++ b/zerver/tests/test_realm_export.py @@ -186,12 +186,16 @@ class RealmExportTest(ZulipTestCase): with patch('zerver.models.Realm.currently_used_upload_space_bytes', return_value=11 * 1024 * 1024 * 1024): result = self.client_post('/json/export/realm') - self.assert_json_error(result, 'Please request a manual export from %s.' % - settings.ZULIP_ADMINISTRATOR) + self.assert_json_error( + result, + f'Please request a manual export from {settings.ZULIP_ADMINISTRATOR}.', + ) # Message limit is set as 250000 realm_count.value = 250001 realm_count.save(update_fields=['value']) result = self.client_post('/json/export/realm') - self.assert_json_error(result, 'Please request a manual export from %s.' % - settings.ZULIP_ADMINISTRATOR) + self.assert_json_error( + result, + f'Please request a manual export from {settings.ZULIP_ADMINISTRATOR}.', + ) diff --git a/zerver/tests/test_slack_message_conversion.py b/zerver/tests/test_slack_message_conversion.py index 2fc2063e0a..fe358aeef8 100644 --- a/zerver/tests/test_slack_message_conversion.py +++ b/zerver/tests/test_slack_message_conversion.py @@ -80,8 +80,7 @@ class SlackMessageConversion(ZulipTestCase): # multiple mentioning message = 'Hi <@U08RGD1RD|john>: How are you?<@U0CBK5KAT> asked.' text, mentioned_users, has_link = convert_to_zulip_markdown(message, users, channel_map, slack_user_map) - self.assertEqual(text, 'Hi @**%s**: How are you?@**%s** asked.' % - ('John Doe', 'aaron.anzalone')) + self.assertEqual(text, 'Hi @**John Doe**: How are you?@**aaron.anzalone** asked.') self.assertEqual(mentioned_users, [540, 554]) # Check wrong mentioning diff --git a/zerver/tests/test_subs.py b/zerver/tests/test_subs.py index aa950cb3eb..1a740e6ec8 100644 --- a/zerver/tests/test_subs.py +++ b/zerver/tests/test_subs.py @@ -774,8 +774,10 @@ class StreamAdminTest(ZulipTestCase): result = self.client_patch(f'/json/streams/{stream_id}', {'description': ujson.dumps('a' * 1025)}) - self.assert_json_error(result, "description is too long (limit: %s characters)" - % (Stream.MAX_DESCRIPTION_LENGTH,)) + self.assert_json_error( + result, + f"description is too long (limit: {Stream.MAX_DESCRIPTION_LENGTH} characters)", + ) result = self.client_patch(f'/json/streams/{stream_id}', {'description': ujson.dumps('a\nmulti\nline\ndescription')}) @@ -2931,8 +2933,11 @@ class SubscriptionAPITest(ZulipTestCase): get_user(invalid_principal, invalid_principal_realm) result = self.common_subscribe_to_streams(self.test_user, self.streams, {"principals": ujson.dumps([invalid_principal])}) - self.assert_json_error(result, "User not authorized to execute queries on behalf of '%s'" - % (invalid_principal,), status_code=403) + self.assert_json_error( + result, + f"User not authorized to execute queries on behalf of '{invalid_principal}'", + status_code=403, + ) def test_subscription_add_invalid_principal(self) -> None: invalid_principal = 999 @@ -2941,8 +2946,11 @@ class SubscriptionAPITest(ZulipTestCase): get_user_profile_by_id_in_realm(invalid_principal, invalid_principal_realm) result = self.common_subscribe_to_streams(self.test_user, self.streams, {"principals": ujson.dumps([invalid_principal])}) - self.assert_json_error(result, "User not authorized to execute queries on behalf of '%s'" - % (invalid_principal,), status_code=403) + self.assert_json_error( + result, + f"User not authorized to execute queries on behalf of '{invalid_principal}'", + status_code=403, + ) def test_subscription_add_principal_other_realm(self) -> None: """ @@ -2955,8 +2963,11 @@ class SubscriptionAPITest(ZulipTestCase): self.assertIsInstance(profile, UserProfile) result = self.common_subscribe_to_streams(self.test_user, self.streams, {"principals": ujson.dumps([principal])}) - self.assert_json_error(result, "User not authorized to execute queries on behalf of '%s'" - % (principal,), status_code=403) + self.assert_json_error( + result, + f"User not authorized to execute queries on behalf of '{principal}'", + status_code=403, + ) def helper_check_subs_before_and_after_remove(self, subscriptions: List[str], json_dict: Dict[str, Any], @@ -3144,7 +3155,7 @@ class SubscriptionAPITest(ZulipTestCase): with mock.patch('zerver.models.Recipient.__str__', return_value='recip'): self.assertEqual(str(subscription), '