ruff: Fix UP032 Use f-string instead of format call.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2023-10-27 22:00:51 -07:00
parent a49add3d02
commit ddccf0eda3
24 changed files with 88 additions and 187 deletions

View file

@ -55,11 +55,11 @@ def pack(options: argparse.Namespace) -> None:
zip_file.write(options.config, "zuliprc")
# Pack the config file for the botfarm.
bot_config = textwrap.dedent(
"""\
f"""\
[deploy]
bot={}
bot={options.main}
zuliprc=zuliprc
""".format(options.main)
"""
)
zip_file.writestr("config.ini", bot_config)
zip_file.close()

View file

@ -58,12 +58,10 @@ the Python version this command is executed with."""
return_code = subprocess.call([options.python_interpreter, "-m", "venv", venv_dir])
except OSError:
print(
"{red}Installation with venv failed. Probable errors are: "
f"{red}Installation with venv failed. Probable errors are: "
"You are on Ubuntu and you haven't installed python3-venv,"
"or you are running an unsupported python version"
"or python is not installed properly{end_format}".format(
red=red, end_format=end_format
)
f"or python is not installed properly{end_format}"
)
sys.exit(1)
raise

View file

@ -47,7 +47,7 @@ if __name__ == "__main__":
traceback.print_exc()
print(
"You have unsatisfied dependencies. Install all missing dependencies with "
"{} --provision".format(sys.argv[0])
f"{sys.argv[0]} --provision"
)
sys.exit(1)

View file

@ -118,11 +118,7 @@ class MatrixBridgeScriptTests(TestCase):
)
self.assertEqual(
output_lines,
[
"Wrote sample configuration to '{}' using zuliprc file '{}'".format(
path, zuliprc_path
)
],
[f"Wrote sample configuration to '{path}' using zuliprc file '{zuliprc_path}'"],
)
with open(path) as sample_file:
@ -143,11 +139,7 @@ class MatrixBridgeScriptTests(TestCase):
)
self.assertEqual(
output_lines,
[
"Could not write sample config: Zuliprc file '{}' does not exist.".format(
zuliprc_path
)
],
[f"Could not write sample config: Zuliprc file '{zuliprc_path}' does not exist."],
)
def test_parse_multiple_bridges(self) -> None:

View file

@ -173,10 +173,7 @@ def handle_event(event: Dict[str, Any]) -> None:
if "status_id" in changes:
status_change = changes.get("status_id")
content += "Status changed from **{}** to **{}**\n\n".format(
status_change[0],
status_change[1],
)
content += f"Status changed from **{status_change[0]}** to **{status_change[1]}**\n\n"
elif event_type == "ticketing_milestone":
stream = config.ZULIP_TICKETS_STREAM_NAME
@ -199,12 +196,7 @@ def handle_event(event: Dict[str, Any]) -> None:
url = make_url(f"projects/{project_link}/repositories/{repo_link}/commit/{commit}")
subject = f"{actor_name} commented on {commit}"
content = "{} commented on [{}]({}):\n\n~~~ quote\n{}".format(
actor_name,
commit,
url,
comment,
)
content = f"{actor_name} commented on [{commit}]({url}):\n\n~~~ quote\n{comment}"
else:
# Otherwise, this is a Discussion item, and handle it
subj = raw_props.get("subject")

View file

@ -30,18 +30,12 @@ def format_summary_line(
if web_url:
shortlog_base_url = web_url.rstrip("/") + "/shortlog/"
summary_url = "{shortlog}{tip}?revcount={revcount}".format(
shortlog=shortlog_base_url, tip=tip - 1, revcount=revcount
)
formatted_commit_count = "[{revcount} commit{s}]({url})".format(
revcount=revcount, s=plural, url=summary_url
)
summary_url = f"{shortlog_base_url}{tip - 1}?revcount={revcount}"
formatted_commit_count = f"[{revcount} commit{plural}]({summary_url})"
else:
formatted_commit_count = f"{revcount} commit{plural}"
return "**{user}** pushed {commits} to **{branch}** (`{tip}:{node}`):\n\n".format(
user=user, commits=formatted_commit_count, branch=branch, tip=tip, node=node[:12]
)
return f"**{user}** pushed {formatted_commit_count} to **{branch}** (`{tip}:{node[:12]}`):\n\n"
def format_commit_lines(web_url: str, repo: repo, base: int, tip: int) -> str:

View file

@ -77,7 +77,7 @@ if hasattr(config, "P4_WEB"):
if p4web is not None:
# linkify the change number
change = "[{change}]({p4web}/{change}?ac=10)".format(p4web=p4web, change=change)
change = f"[{change}]({p4web}/{change}?ac=10)"
message = """**{user}** committed revision @{change} to `{path}`.

View file

@ -177,12 +177,7 @@ def send_zulip(entry: Any, feed_name: str) -> Dict[str, Any]:
if opts.unwrap:
body = unwrap_text(body)
content = "**[{}]({})**\n{}\n{}".format(
entry.title,
entry.link,
strip_tags(body),
entry.link,
)
content = f"**[{entry.title}]({entry.link})**\n{strip_tags(body)}\n{entry.link}"
if opts.math:
content = content.replace("$", "$$")

View file

@ -793,9 +793,7 @@ Feedback button or at support@zulip.com."""
# Forward messages sent to '(instance "WHITESPACE")' back to the
# appropriate WHITESPACE instance for bidirectional mirroring
instance = match_whitespace_instance.group(1)
elif instance == f"instance {zephyr_class}" or instance == "test instance {}".format(
zephyr_class,
):
elif instance == f"instance {zephyr_class}" or instance == f"test instance {zephyr_class}":
# Forward messages to e.g. -c -i white-magic back from the
# place we forward them to
if instance.startswith("test"):

View file

@ -41,9 +41,7 @@ Zulip API configuration:
expanded_test_path = os.path.abspath(os.path.expanduser(test_path))
self.assertEqual(
str(cm.exception),
"api_key or email not specified and " "file {} does not exist".format(
expanded_test_path
),
"api_key or email not specified and " f"file {expanded_test_path} does not exist",
)

View file

@ -417,8 +417,8 @@ class Client:
if insecure is None:
raise ZulipError(
"The ZULIP_ALLOW_INSECURE environment "
"variable is set to '{}', it must be "
"'true' or 'false'".format(insecure_setting)
f"variable is set to '{insecure_setting}', it must be "
"'true' or 'false'"
)
if config_file is None:
config_file = get_default_config_filename()
@ -448,10 +448,8 @@ class Client:
if insecure is None:
raise ZulipError(
"insecure is set to '{}', it must be "
"'true' or 'false' if it is used in {}".format(
insecure_setting, config_file
)
f"insecure is set to '{insecure_setting}', it must be "
f"'true' or 'false' if it is used in {config_file}"
)
elif None in (api_key, email):
@ -561,11 +559,7 @@ class Client:
elif vendor == "Darwin":
vendor_version = platform.mac_ver()[0]
return "{client_name} ({vendor}; {vendor_version})".format(
client_name=self.client_name,
vendor=vendor,
vendor_version=vendor_version,
)
return f"{self.client_name} ({vendor}; {vendor_version})"
def do_api_query(
self,

View file

@ -26,9 +26,7 @@ def get_beeminder_response(message_content: str, config_info: Dict[str, str]) ->
if message_content == "" or message_content == "help":
return help_message
url = "https://www.beeminder.com/api/v1/users/{}/goals/{}/datapoints.json".format(
username, goalname
)
url = f"https://www.beeminder.com/api/v1/users/{username}/goals/{goalname}/datapoints.json"
message_pieces = message_content.split(",")
for i in range(len(message_pieces)):
message_pieces[i] = message_pieces[i].strip()
@ -66,13 +64,11 @@ at syntax by: @mention-botname help"
if r.status_code == 401: # Handles case of invalid key and missing key
return "Error. Check your key!"
else:
return "Error occured : {}".format(
r.status_code
) # Occures in case of unprocessable entity
return f"Error occured : {r.status_code}" # Occures in case of unprocessable entity
else:
datapoint_link = f"https://www.beeminder.com/{username}/{goalname}"
return "[Datapoint]({}) created.".format(
datapoint_link
return (
f"[Datapoint]({datapoint_link}) created."
) # Handles the case of successful datapoint creation
except ConnectionError as e:
logging.exception(str(e))

View file

@ -124,9 +124,7 @@ def get_bot_converter_response(message: Dict[str, str], bot_handler: BotHandler)
number_res = round_to(number_res, 7)
results.append(
"{} {} = {} {}".format(
number, words[convert_index + 2], number_res, words[convert_index + 3]
)
f"{number} {words[convert_index + 2]} = {number_res} {words[convert_index + 3]}"
)
else:

View file

@ -27,7 +27,7 @@ class GithubHandler:
"To reference an issue or pull request usename mention the bot then "
"anytime in the message type its id, for example:\n"
"@**Github detail** #3212 zulip#3212 zulip/zulip#3212\n"
"The default owner is {} and the default repo is {}.".format(self.owner, self.repo)
f"The default owner is {self.owner} and the default repo is {self.repo}."
)
def format_message(self, details: Dict[str, Any]) -> str:
@ -44,10 +44,8 @@ class GithubHandler:
message_string = (
f"**[{owner}/{repo}#{number}]",
f"({link}) - {title}**\n",
"Created by **[{author}](https://github.com/{author})**\n".format(author=author),
"Status - **{status}**\n```quote\n{description}\n```".format(
status=status, description=description
),
f"Created by **[{author}](https://github.com/{author})**\n",
f"Status - **{status}**\n```quote\n{description}\n```",
)
return "".join(message_string)
@ -100,9 +98,7 @@ class GithubHandler:
bot_messages.append(self.format_message(details))
else:
bot_messages.append(
"Failed to find issue/pr: {owner}/{repo}#{id}".format(
owner=owner, repo=repo, id=issue_pr.group(3)
)
f"Failed to find issue/pr: {owner}/{repo}#{issue_pr.group(3)}"
)
else:
bot_messages.append("Failed to detect owner and repository name.")

View file

@ -124,26 +124,15 @@ def format_incident_for_widget(ticket_id: str, incident: Dict[str, Any]) -> str:
def format_incident_for_markdown(ticket_id: str, incident: Dict[str, Any]) -> str:
answer_list = "\n".join(
"* **{code}** {answer}".format(
code=code,
answer=ANSWERS[code],
)
for code in "1234"
)
answer_list = "\n".join(f"* **{code}** {ANSWERS[code]}" for code in "1234")
how_to_respond = f"""**reply**: answer {ticket_id} <code>"""
content = """
content = f"""
Incident: {incident}
Q: {question}
Q: {QUESTION}
{answer_list}
{how_to_respond}""".format(
question=QUESTION,
answer_list=answer_list,
how_to_respond=how_to_respond,
incident=incident,
)
{how_to_respond}"""
return content

View file

@ -242,24 +242,14 @@ class JiraHandler:
response = "Oh no! Jira raised an error:\n > " + ", ".join(errors)
else:
response = (
"**Issue *[{}]({})*: {}**\n\n"
" - Type: *{}*\n"
f"**Issue *[{key}]({url})*: {summary}**\n\n"
f" - Type: *{type_name}*\n"
" - Description:\n"
" > {}\n"
" - Creator: *{}*\n"
" - Project: *{}*\n"
" - Priority: *{}*\n"
" - Status: *{}*\n"
).format(
key,
url,
summary,
type_name,
description,
creator_name,
project_name,
priority_name,
status_name,
f" > {description}\n"
f" - Creator: *{creator_name}*\n"
f" - Project: *{project_name}*\n"
f" - Priority: *{priority_name}*\n"
f" - Status: *{status_name}*\n"
)
elif create_match:
jira_response = requests.post(

View file

@ -284,8 +284,8 @@ def create_room(topic_name, merels_storage):
return response
else:
return (
"Failed: Cannot create an already existing game in {}. "
"Please finish the game first.".format(topic_name)
f"Failed: Cannot create an already existing game in {topic_name}. "
"Please finish the game first."
)
@ -309,9 +309,9 @@ def display_game(topic_name, merels_storage):
take = "No"
response += interface.graph_grid(data.grid()) + "\n"
response += """Phase {}. Take mode: {}.
X taken: {}, O taken: {}.
""".format(data.get_phase(), take, data.x_taken, data.o_taken)
response += f"""Phase {data.get_phase()}. Take mode: {take}.
X taken: {data.x_taken}, O taken: {data.o_taken}.
"""
return response
@ -362,9 +362,7 @@ def move_man(topic_name, p1, p2, merels_storage):
data.hill_uid,
data.take_mode,
)
return "Moved a man from ({}, {}) -> ({}, {}) for {}.".format(
p1[0], p1[1], p2[0], p2[1], data.turn
)
return f"Moved a man from ({p1[0]}, {p1[1]}) -> ({p2[0]}, {p2[1]}) for {data.turn}."
else:
raise BadMoveException("Failed: That's not a legal move. Please try again.")

View file

@ -189,24 +189,14 @@ def format_quiz_for_widget(quiz_id: str, quiz: Dict[str, Any]) -> str:
def format_quiz_for_markdown(quiz_id: str, quiz: Dict[str, Any]) -> str:
question = quiz["question"]
answers = quiz["answers"]
answer_list = "\n".join(
"* **{letter}** {answer}".format(
letter=letter,
answer=answers[letter],
)
for letter in "ABCD"
)
answer_list = "\n".join(f"* **{letter}** {answers[letter]}" for letter in "ABCD")
how_to_respond = f"""**reply**: answer {quiz_id} <letter>"""
content = """
content = f"""
Q: {question}
{answer_list}
{how_to_respond}""".format(
question=question,
answer_list=answer_list,
how_to_respond=how_to_respond,
)
{how_to_respond}"""
return content

View file

@ -62,11 +62,11 @@ def get_xkcd_bot_response(message: Dict[str, str], quoted_name: str) -> str:
commands_help = (
"%s"
"\n* `{0} help` to show this help message."
"\n* `{0} latest` to fetch the latest comic strip from xkcd."
"\n* `{0} random` to fetch a random comic strip from xkcd."
"\n* `{0} <comic id>` to fetch a comic strip based on `<comic id>` "
"e.g `{0} 1234`.".format(quoted_name)
f"\n* `{quoted_name} help` to show this help message."
f"\n* `{quoted_name} latest` to fetch the latest comic strip from xkcd."
f"\n* `{quoted_name} random` to fetch a random comic strip from xkcd."
f"\n* `{quoted_name} <comic id>` to fetch a comic strip based on `<comic id>` "
f"e.g `{quoted_name} 1234`."
)
try:

View file

@ -80,12 +80,12 @@ class GameAdapter:
self.put_user_cache()
def help_message(self) -> str:
return """** {} Bot Help:**
*Preface all commands with @**{}***
return f"""** {self.game_name} Bot Help:**
*Preface all commands with @**{self.get_bot_username()}***
* To start a game in a stream (*recommended*), type
`start game`
* To start a game against another player, type
`start game with @<player-name>`{}
`start game with @<player-name>`{self.play_with_computer_help()}
* To play game with the current number of players, type
`play game`
* To quit a game at any time, type
@ -100,23 +100,18 @@ class GameAdapter:
`cancel game`
* To see rules of this game, type
`rules`
{}""".format(
self.game_name,
self.get_bot_username(),
self.play_with_computer_help(),
self.move_help_message,
)
{self.move_help_message}"""
def help_message_single_player(self) -> str:
return """** {} Bot Help:**
*Preface all commands with @**{}***
return f"""** {self.game_name} Bot Help:**
*Preface all commands with @**{self.get_bot_username()}***
* To start a game in a stream, type
`start game`
* To quit a game at any time, type
`quit`
* To see rules of this game, type
`rules`
{}""".format(self.game_name, self.get_bot_username(), self.move_help_message)
{self.move_help_message}"""
def get_commands(self) -> Dict[str, str]:
action = self.help_message_single_player()
@ -359,9 +354,7 @@ class GameAdapter:
if len(users) + 1 < self.min_players:
self.send_reply(
message,
"You must have at least {} players to play.\nGame cancelled.".format(
self.min_players
),
f"You must have at least {self.min_players} players to play.\nGame cancelled.",
)
return
if len(users) + 1 > self.max_players:
@ -546,11 +539,9 @@ class GameAdapter:
self.instances[game_id].start()
def get_formatted_game_object(self, game_id: str) -> str:
object = """> **Game `{}`**
> {}
> {}/{} players""".format(
game_id, self.game_name, self.get_number_of_players(game_id), self.max_players
)
object = f"""> **Game `{game_id}`**
> {self.game_name}
> {self.get_number_of_players(game_id)}/{self.max_players} players"""
if game_id in self.instances.keys():
instance = self.instances[game_id]
if not self.is_single_player:
@ -631,18 +622,16 @@ class GameAdapter:
return
self.send_reply(
message,
"Join your game using the link below!\n\n{}".format(
self.get_formatted_game_object(game_id)
),
f"Join your game using the link below!\n\n{self.get_formatted_game_object(game_id)}",
)
return
if game["subject"] != message["subject"] or game["stream"] != message["display_recipient"]:
if game_id not in self.pending_subject_changes:
self.send_reply(
message,
"Your current game is not in this subject. \n\
f"Your current game is not in this subject. \n\
To move subjects, send your message again, otherwise join the game using the link below.\n\n\
{}".format(self.get_formatted_game_object(game_id)),
{self.get_formatted_game_object(game_id)}",
)
self.pending_subject_changes.append(game_id)
return
@ -950,9 +939,7 @@ class GameInstance:
if not is_computer:
self.current_messages.append(
self.gameAdapter.gameMessageHandler.alert_move_message(
"**{}**".format(
self.gameAdapter.get_username_by_email(self.players[self.turn])
),
f"**{self.gameAdapter.get_username_by_email(self.players[self.turn])}**",
content,
)
)
@ -973,9 +960,7 @@ class GameInstance:
if not is_computer:
self.current_messages.append(
self.gameAdapter.gameMessageHandler.alert_move_message(
"**{}**".format(
self.gameAdapter.get_username_by_email(self.players[self.turn])
),
f"**{self.gameAdapter.get_username_by_email(self.players[self.turn])}**",
content,
)
)

View file

@ -222,21 +222,21 @@ class ExternalBotHandler:
user_profile = client.get_profile()
except ZulipError as e:
print(
"""
ERROR: {}
f"""
ERROR: {e}
Have you not started the server?
Or did you mis-specify the URL?
""".format(e)
"""
)
sys.exit(1)
if user_profile.get("result") == "error":
msg = user_profile.get("msg", "unknown")
print(
f"""
ERROR: {msg}
"""
ERROR: {}
""".format(msg)
)
sys.exit(1)
@ -323,18 +323,18 @@ class ExternalBotHandler:
if bot_name not in self.bot_config_file:
print(
"""
f"""
WARNING!
{} does not adhere to the
{self.bot_config_file} does not adhere to the
file naming convention, and it could be a
sign that you passed in the
wrong third-party configuration file.
The suggested name is {}.conf
The suggested name is {bot_name}.conf
We will proceed anyway.
""".format(self.bot_config_file, bot_name)
"""
)
# We expect the caller to pass in None if the user does
@ -368,8 +368,8 @@ class ExternalBotHandler:
return open(abs_filepath)
else:
raise PermissionError(
'Cannot open file "{}". Bots may only access '
"files in their local directory.".format(abs_filepath)
f'Cannot open file "{abs_filepath}". Bots may only access '
"files in their local directory."
)
def quit(self, message: str = "") -> None:

View file

@ -19,7 +19,7 @@ def get_bot_message_handler(bot_name: str) -> Any:
# handler class. Eventually, we want bot's handler classes to
# inherit from a common prototype specifying the handle_message
# function.
lib_module: Any = import_module("zulip_bots.bots.{bot}.{bot}".format(bot=bot_name))
lib_module: Any = import_module(f"zulip_bots.bots.{bot_name}.{bot_name}")
return lib_module.handler_class()

View file

@ -273,8 +273,8 @@ class BotServerTests(BotServerTestCase):
# load invalid file path
with self.assertRaisesRegex(
SystemExit,
'Error: Bot "{}/zulip_bots/zulip_bots/bots/helloworld.py" doesn\'t exist. '
"Please make sure you have set up the botserverrc file correctly.".format(root_dir),
f'Error: Bot "{root_dir}/zulip_bots/zulip_bots/bots/helloworld.py" doesn\'t exist. '
"Please make sure you have set up the botserverrc file correctly.",
):
path = Path(
root_dir, "zulip_bots/zulip_bots/bots/{bot}.py".format(bot="helloworld")

View file

@ -90,9 +90,7 @@ def read_config_file(
bot_section = parser.sections()[0]
bots_config[bot_name] = read_config_section(parser, bot_section)
logging.warning(
"First bot name in the config list was changed from '{}' to '{}'".format(
bot_section, bot_name
)
f"First bot name in the config list was changed from '{bot_section}' to '{bot_name}'"
)
ignored_sections = parser.sections()[1:]
@ -118,7 +116,7 @@ def load_lib_modules(available_bots: List[str]) -> Dict[str, ModuleType]:
if bot.endswith(".py") and os.path.isfile(bot):
lib_module = import_module_from_source(bot, "custom_bot_module")
else:
module_name = "zulip_bots.bots.{bot}.{bot}".format(bot=bot)
module_name = f"zulip_bots.bots.{bot}.{bot}"
lib_module = import_module(module_name)
bots_lib_module[bot] = lib_module
except ImportError: