pyupgrade: Reformat with --py36-plus.

This includes mainly fixes of string literals using f-strings or
.format(...), as well as unpacking of list comprehensions.
This commit is contained in:
PIG208 2021-05-28 19:19:40 +08:00 committed by Tim Abbott
parent e27ac0ddbe
commit 9ce7c52a10
78 changed files with 356 additions and 389 deletions

View file

@ -46,7 +46,7 @@ class IRCBot(irc.bot.SingleServerIRCBot):
def check_subscription_or_die(self) -> None:
resp = self.zulip_client.get_subscriptions()
if resp["result"] != "success":
print("ERROR: %s" % (resp["msg"],))
print("ERROR: {}".format(resp["msg"]))
exit(1)
subs = [s["name"] for s in resp["subscriptions"]]
if self.stream not in subs:
@ -61,7 +61,7 @@ class IRCBot(irc.bot.SingleServerIRCBot):
def on_welcome(self, c: ServerConnection, e: Event) -> None:
if len(self.nickserv_password) > 0:
msg = "identify %s" % (self.nickserv_password,)
msg = f"identify {self.nickserv_password}"
c.privmsg("NickServ", msg)
c.join(self.channel)
@ -75,7 +75,7 @@ class IRCBot(irc.bot.SingleServerIRCBot):
in_the_specified_stream = msg["display_recipient"] == self.stream
at_the_specified_subject = msg["subject"].casefold() == self.topic.casefold()
if in_the_specified_stream and at_the_specified_subject:
msg["content"] = ("@**%s**: " % (msg["sender_full_name"],)) + msg["content"]
msg["content"] = ("@**{}**: ".format(msg["sender_full_name"])) + msg["content"]
send = lambda x: self.c.privmsg(self.channel, x)
else:
return
@ -126,7 +126,7 @@ class IRCBot(irc.bot.SingleServerIRCBot):
"type": "stream",
"to": self.stream,
"subject": self.topic,
"content": "**{}**: {}".format(sender, content),
"content": f"**{sender}**: {content}",
}
)
)

View file

@ -77,7 +77,7 @@ def matrix_to_zulip(
"""
content = get_message_content_from_event(event, no_noise)
zulip_bot_user = "@%s:matrix.org" % (matrix_config["username"],)
zulip_bot_user = "@{}:matrix.org".format(matrix_config["username"])
# We do this to identify the messages generated from Zulip -> Matrix
# and we make sure we don't forward it again to the Zulip stream.
not_from_zulip_bot = event["sender"] != zulip_bot_user
@ -228,9 +228,7 @@ def read_configuration(config_file: str) -> Dict[str, Dict[str, str]]:
def write_sample_config(target_path: str, zuliprc: Optional[str]) -> None:
if os.path.exists(target_path):
raise Bridge_ConfigException(
"Path '{}' exists; not overwriting existing file.".format(target_path)
)
raise Bridge_ConfigException(f"Path '{target_path}' exists; not overwriting existing file.")
sample_dict = OrderedDict(
(
@ -262,7 +260,7 @@ def write_sample_config(target_path: str, zuliprc: Optional[str]) -> None:
if zuliprc is not None:
if not os.path.exists(zuliprc):
raise Bridge_ConfigException("Zuliprc file '{}' does not exist.".format(zuliprc))
raise Bridge_ConfigException(f"Zuliprc file '{zuliprc}' does not exist.")
zuliprc_config = configparser.ConfigParser()
try:
@ -293,10 +291,10 @@ def main() -> None:
try:
write_sample_config(options.sample_config, options.zuliprc)
except Bridge_ConfigException as exception:
print("Could not write sample config: {}".format(exception))
print(f"Could not write sample config: {exception}")
sys.exit(1)
if options.zuliprc is None:
print("Wrote sample configuration to '{}'".format(options.sample_config))
print(f"Wrote sample configuration to '{options.sample_config}'")
else:
print(
"Wrote sample configuration to '{}' using zuliprc file '{}'".format(
@ -312,7 +310,7 @@ def main() -> None:
try:
config = read_configuration(options.config)
except Bridge_ConfigException as exception:
print("Could not parse config file: {}".format(exception))
print(f"Could not parse config file: {exception}")
sys.exit(1)
# Get config for each client
@ -347,11 +345,11 @@ def main() -> None:
zulip_client.call_on_each_message(zulip_to_matrix(zulip_config, room))
except Bridge_FatalMatrixException as exception:
sys.exit("Matrix bridge error: {}".format(exception))
sys.exit(f"Matrix bridge error: {exception}")
except Bridge_ZulipFatalException as exception:
sys.exit("Zulip bridge error: {}".format(exception))
sys.exit(f"Zulip bridge error: {exception}")
except zulip.ZulipError as exception:
sys.exit("Zulip error: {}".format(exception))
sys.exit(f"Zulip error: {exception}")
except Exception:
traceback.print_exc()
backoff.fail()

View file

@ -49,14 +49,14 @@ class MatrixBridgeScriptTests(TestCase):
output_lines = self.output_from_script([])
expected_lines = [
"Options required: -c or --config to run, OR --write-sample-config.",
"usage: {} [-h]".format(script_file),
f"usage: {script_file} [-h]",
]
for expected, output in zip(expected_lines, output_lines):
self.assertIn(expected, output)
def test_help_usage_and_description(self) -> None:
output_lines = self.output_from_script(["-h"])
usage = "usage: {} [-h]".format(script_file)
usage = f"usage: {script_file} [-h]"
description = "Script to bridge"
self.assertIn(usage, output_lines[0])
blank_lines = [num for num, line in enumerate(output_lines) if line == ""]
@ -71,7 +71,7 @@ class MatrixBridgeScriptTests(TestCase):
with new_temp_dir() as tempdir:
path = os.path.join(tempdir, sample_config_path)
output_lines = self.output_from_script(["--write-sample-config", path])
self.assertEqual(output_lines, ["Wrote sample configuration to '{}'".format(path)])
self.assertEqual(output_lines, [f"Wrote sample configuration to '{path}'"])
with open(path) as sample_file:
self.assertEqual(sample_file.read(), sample_config_text)

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse
import os

View file

@ -56,7 +56,7 @@ while len(json_implementations):
def make_api_call(path: str) -> Optional[List[Dict[str, Any]]]:
response = requests.get(
"https://api3.codebasehq.com/%s" % (path,),
f"https://api3.codebasehq.com/{path}",
auth=(config.CODEBASE_API_USERNAME, config.CODEBASE_API_KEY),
params={"raw": "True"},
headers={
@ -76,13 +76,13 @@ def make_api_call(path: str) -> Optional[List[Dict[str, Any]]]:
sys.exit(-1)
else:
logging.warn(
"Found non-success response status code: %s %s" % (response.status_code, response.text)
f"Found non-success response status code: {response.status_code} {response.text}"
)
return None
def make_url(path: str) -> str:
return "%s/%s" % (config.CODEBASE_ROOT_URL, path)
return f"{config.CODEBASE_ROOT_URL}/{path}"
def handle_event(event: Dict[str, Any]) -> None:
@ -102,11 +102,11 @@ def handle_event(event: Dict[str, Any]) -> None:
project_name = raw_props.get("name")
project_repo_type = raw_props.get("scm_type")
url = make_url("projects/%s" % (project_link,))
scm = "of type %s" % (project_repo_type,) if project_repo_type else ""
url = make_url(f"projects/{project_link}")
scm = f"of type {project_repo_type}" if project_repo_type else ""
subject = "Repository %s Created" % (project_name,)
content = "%s created a new repository %s [%s](%s)" % (actor_name, scm, project_name, url)
subject = f"Repository {project_name} Created"
content = f"{actor_name} created a new repository {scm} [{project_name}]({url})"
elif event_type == "push":
stream = config.ZULIP_COMMITS_STREAM_NAME
@ -117,14 +117,14 @@ def handle_event(event: Dict[str, Any]) -> None:
deleted_ref = raw_props.get("deleted_ref")
new_ref = raw_props.get("new_ref")
subject = "Push to %s on %s" % (branch, project)
subject = f"Push to {branch} on {project}"
if deleted_ref:
content = "%s deleted branch %s from %s" % (actor_name, branch, project)
content = f"{actor_name} deleted branch {branch} from {project}"
else:
if new_ref:
branch = "new branch %s" % (branch,)
content = "%s pushed %s commit(s) to %s in project %s:\n\n" % (
branch = f"new branch {branch}"
content = "{} pushed {} commit(s) to {} in project {}:\n\n".format(
actor_name,
num_commits,
branch,
@ -132,11 +132,9 @@ def handle_event(event: Dict[str, Any]) -> None:
)
for commit in raw_props.get("commits"):
ref = commit.get("ref")
url = make_url(
"projects/%s/repositories/%s/commit/%s" % (project_link, repo_link, ref)
)
url = make_url(f"projects/{project_link}/repositories/{repo_link}/commit/{ref}")
message = commit.get("message")
content += "* [%s](%s): %s\n" % (ref, url, message)
content += f"* [{ref}]({url}): {message}\n"
elif event_type == "ticketing_ticket":
stream = config.ZULIP_TICKETS_STREAM_NAME
@ -144,11 +142,11 @@ def handle_event(event: Dict[str, Any]) -> None:
name = raw_props.get("subject")
assignee = raw_props.get("assignee")
priority = raw_props.get("priority")
url = make_url("projects/%s/tickets/%s" % (project_link, num))
url = make_url(f"projects/{project_link}/tickets/{num}")
if assignee is None:
assignee = "no one"
subject = "#%s: %s" % (num, name)
subject = f"#{num}: {name}"
content = (
"""%s created a new ticket [#%s](%s) priority **%s** assigned to %s:\n\n~~~ quote\n %s"""
% (actor_name, num, url, priority, assignee, name)
@ -161,12 +159,12 @@ def handle_event(event: Dict[str, Any]) -> None:
body = raw_props.get("content")
changes = raw_props.get("changes")
url = make_url("projects/%s/tickets/%s" % (project_link, num))
subject = "#%s: %s" % (num, name)
url = make_url(f"projects/{project_link}/tickets/{num}")
subject = f"#{num}: {name}"
content = ""
if body is not None and len(body) > 0:
content = "%s added a comment to ticket [#%s](%s):\n\n~~~ quote\n%s\n\n" % (
content = "{} added a comment to ticket [#{}]({}):\n\n~~~ quote\n{}\n\n".format(
actor_name,
num,
url,
@ -175,7 +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 **%s** to **%s**\n\n" % (
content += "Status changed from **{}** to **{}**\n\n".format(
status_change[0],
status_change[1],
)
@ -184,10 +182,10 @@ def handle_event(event: Dict[str, Any]) -> None:
name = raw_props.get("name")
identifier = raw_props.get("identifier")
url = make_url("projects/%s/milestone/%s" % (project_link, identifier))
url = make_url(f"projects/{project_link}/milestone/{identifier}")
subject = name
content = "%s created a new milestone [%s](%s)" % (actor_name, name, url)
content = f"{actor_name} created a new milestone [{name}]({url})"
elif event_type == "comment":
stream = config.ZULIP_COMMITS_STREAM_NAME
@ -198,12 +196,10 @@ def handle_event(event: Dict[str, Any]) -> None:
if commit:
repo_link = raw_props.get("repository_permalink")
url = make_url(
"projects/%s/repositories/%s/commit/%s" % (project_link, repo_link, commit)
)
url = make_url(f"projects/{project_link}/repositories/{repo_link}/commit/{commit}")
subject = "%s commented on %s" % (actor_name, commit)
content = "%s commented on [%s](%s):\n\n~~~ quote\n%s" % (
subject = f"{actor_name} commented on {commit}"
content = "{} commented on [{}]({}):\n\n~~~ quote\n{}".format(
actor_name,
commit,
url,
@ -215,13 +211,13 @@ def handle_event(event: Dict[str, Any]) -> None:
category = raw_props.get("category")
comment_content = raw_props.get("content")
subject = "Discussion: %s" % (subj,)
subject = f"Discussion: {subj}"
if category:
format_str = "%s started a new discussion in %s:\n\n~~~ quote\n%s\n~~~"
content = format_str % (actor_name, category, comment_content)
else:
content = "%s posted:\n\n~~~ quote\n%s\n~~~" % (actor_name, comment_content)
content = f"{actor_name} posted:\n\n~~~ quote\n{comment_content}\n~~~"
elif event_type == "deployment":
stream = config.ZULIP_COMMITS_STREAM_NAME
@ -233,19 +229,17 @@ def handle_event(event: Dict[str, Any]) -> None:
repo_link = raw_props.get("repository_permalink")
start_ref_url = make_url(
"projects/%s/repositories/%s/commit/%s" % (project_link, repo_link, start_ref)
)
end_ref_url = make_url(
"projects/%s/repositories/%s/commit/%s" % (project_link, repo_link, end_ref)
f"projects/{project_link}/repositories/{repo_link}/commit/{start_ref}"
)
end_ref_url = make_url(f"projects/{project_link}/repositories/{repo_link}/commit/{end_ref}")
between_url = make_url(
"projects/%s/repositories/%s/compare/%s...%s"
% (project_link, repo_link, start_ref, end_ref)
)
subject = "Deployment to %s" % (environment,)
subject = f"Deployment to {environment}"
content = "%s deployed [%s](%s) [through](%s) [%s](%s) to the **%s** environment." % (
content = "{} deployed [{}]({}) [through]({}) [{}]({}) to the **{}** environment.".format(
actor_name,
start_ref,
start_ref_url,
@ -256,7 +250,7 @@ def handle_event(event: Dict[str, Any]) -> None:
)
if servers is not None:
content += "\n\nServers deployed to: %s" % (
", ".join(["`%s`" % (server,) for server in servers])
", ".join(f"`{server}`" for server in servers)
)
elif event_type == "named_tree":
@ -270,7 +264,7 @@ def handle_event(event: Dict[str, Any]) -> None:
elif event_type == "sprint_ended":
logging.warn("Sprint notifications not yet implemented")
else:
logging.info("Unknown event type %s, ignoring!" % (event_type,))
logging.info(f"Unknown event type {event_type}, ignoring!")
if subject and content:
if len(subject) > 60:
@ -280,9 +274,9 @@ def handle_event(event: Dict[str, Any]) -> None:
{"type": "stream", "to": stream, "subject": subject, "content": content}
)
if res["result"] == "success":
logging.info("Successfully sent Zulip with id: %s" % (res["id"],))
logging.info("Successfully sent Zulip with id: {}".format(res["id"]))
else:
logging.warn("Failed to send Zulip: %s %s" % (res["result"], res["msg"]))
logging.warn("Failed to send Zulip: {} {}".format(res["result"], res["msg"]))
# the main run loop for this mirror script
@ -300,7 +294,7 @@ def run_mirror() -> None:
else:
since = datetime.fromtimestamp(float(timestamp), tz=pytz.utc)
except (ValueError, OSError) as e:
logging.warn("Could not open resume file: %s" % (str(e),))
logging.warn(f"Could not open resume file: {str(e)}")
since = default_since()
try:
@ -339,9 +333,7 @@ def check_permissions() -> None:
try:
open(config.RESUME_FILE, "a+")
except OSError as e:
sys.stderr.write(
"Could not open up the file %s for reading and writing" % (config.RESUME_FILE,)
)
sys.stderr.write(f"Could not open up the file {config.RESUME_FILE} for reading and writing")
sys.stderr.write(str(e))

View file

@ -41,14 +41,14 @@ def git_repository_name() -> str:
def git_commit_range(oldrev: str, newrev: str) -> str:
log_cmd = ["git", "log", "--reverse", "--pretty=%aE %H %s", "%s..%s" % (oldrev, newrev)]
log_cmd = ["git", "log", "--reverse", "--pretty=%aE %H %s", f"{oldrev}..{newrev}"]
commits = ""
for ln in subprocess.check_output(log_cmd, universal_newlines=True).splitlines():
author_email, commit_id, subject = ln.split(None, 2)
if hasattr(config, "format_commit_message"):
commits += config.format_commit_message(author_email, subject, commit_id)
else:
commits += "!avatar(%s) %s\n" % (author_email, subject)
commits += f"!avatar({author_email}) {subject}\n"
return commits
@ -75,19 +75,19 @@ def send_bot_message(oldrev: str, newrev: str, refname: str) -> None:
removed = git_commit_range(newrev, oldrev)
if oldrev == "0000000000000000000000000000000000000000":
message = "`%s` was pushed to new branch `%s`" % (new_head, branch)
message = f"`{new_head}` was pushed to new branch `{branch}`"
elif newrev == "0000000000000000000000000000000000000000":
message = "branch `%s` was removed (was `%s`)" % (branch, old_head)
message = f"branch `{branch}` was removed (was `{old_head}`)"
elif removed:
message = "`%s` was pushed to `%s`, **REMOVING**:\n\n%s" % (new_head, branch, removed)
message = f"`{new_head}` was pushed to `{branch}`, **REMOVING**:\n\n{removed}"
if added:
message += "\n**and adding**:\n\n" + added
message += "\n**A HISTORY REWRITE HAS OCCURRED!**"
message += "\n@everyone: Please check your local branches to deal with this."
elif added:
message = "`%s` was deployed to `%s` with:\n\n%s" % (new_head, branch, added)
message = f"`{new_head}` was deployed to `{branch}` with:\n\n{added}"
else:
message = "`%s` was pushed to `%s`... but nothing changed?" % (new_head, branch)
message = f"`{new_head}` was pushed to `{branch}`... but nothing changed?"
message_data = {
"type": "stream",

View file

@ -25,7 +25,7 @@ ZULIP_API_KEY = "0123456789abcdef0123456789abcdef"
# And similarly for branch "test-post-receive" (for use when testing).
def commit_notice_destination(repo: str, branch: str, commit: str) -> Optional[Dict[str, str]]:
if branch in ["master", "test-post-receive"]:
return dict(stream=STREAM_NAME, subject="%s" % (branch,))
return dict(stream=STREAM_NAME, subject=f"{branch}")
# Return None for cases where you don't want a notice sent
return None
@ -37,7 +37,7 @@ def commit_notice_destination(repo: str, branch: str, commit: str) -> Optional[D
#
# return '!avatar(%s) [%s](https://example.com/commits/%s)\n' % (author, subject, commit_id)
def format_commit_message(author: str, subject: str, commit_id: str) -> str:
return "!avatar(%s) %s\n" % (author, subject)
return f"!avatar({author}) {subject}\n"
## If properly installed, the Zulip API should be in your import

View file

@ -174,9 +174,9 @@ def send_reminders() -> Optional[None]:
key = (id, start)
if key not in sent:
if start.hour == 0 and start.minute == 0:
line = "%s is today." % (summary,)
line = f"{summary} is today."
else:
line = "%s starts at %s" % (summary, start.strftime("%H:%M"))
line = "{} starts at {}".format(summary, start.strftime("%H:%M"))
print("Sending reminder:", line)
messages.append(line)
keys.add(key)

View file

@ -37,7 +37,7 @@ def format_summary_line(
revcount=revcount, s=plural, url=summary_url
)
else:
formatted_commit_count = "{revcount} commit{s}".format(revcount=revcount, s=plural)
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]
@ -60,9 +60,9 @@ def format_commit_lines(web_url: str, repo: repo, base: int, tip: int) -> str:
if web_url:
summary_url = rev_base_url + str(rev_ctx)
summary = "* [{summary}]({url})".format(summary=one_liner, url=summary_url)
summary = f"* [{one_liner}]({summary_url})"
else:
summary = "* {summary}".format(summary=one_liner)
summary = f"* {one_liner}"
commit_summaries.append(summary)
@ -95,7 +95,7 @@ def get_config(ui: ui, item: str) -> str:
# config returns configuration value.
return ui.config("zulip", item)
except IndexError:
ui.warn("Zulip: Could not find required item {} in hg config.".format(item))
ui.warn(f"Zulip: Could not find required item {item} in hg config.")
sys.exit(1)
@ -106,10 +106,10 @@ def hook(ui: ui, repo: repo, **kwargs: str) -> None:
hooktype = kwargs["hooktype"]
node = kwargs["node"]
ui.debug("Zulip: received {hooktype} event\n".format(hooktype=hooktype))
ui.debug(f"Zulip: received {hooktype} event\n")
if hooktype != "changegroup":
ui.warn("Zulip: {hooktype} not supported\n".format(hooktype=hooktype))
ui.warn(f"Zulip: {hooktype} not supported\n")
sys.exit(1)
ctx = repo[node]
@ -123,14 +123,14 @@ def hook(ui: ui, repo: repo, **kwargs: str) -> None:
# Only send notifications on branches we are watching.
watched_branches = [b.lower().strip() for b in branch_whitelist.split(",")]
if branch.lower() not in watched_branches:
ui.debug("Zulip: ignoring event for {branch}\n".format(branch=branch))
ui.debug(f"Zulip: ignoring event for {branch}\n")
sys.exit(0)
if branch_blacklist:
# Don't send notifications for branches we've ignored.
ignored_branches = [b.lower().strip() for b in branch_blacklist.split(",")]
if branch.lower() in ignored_branches:
ui.debug("Zulip: ignoring event for {branch}\n".format(branch=branch))
ui.debug(f"Zulip: ignoring event for {branch}\n")
sys.exit(0)
# The first and final commits in the changeset.

View file

@ -65,7 +65,7 @@ def jid_to_zulip(jid: JID) -> str:
suffix = ""
if not jid.username.endswith("-bot"):
suffix = options.zulip_email_suffix
return "%s%s@%s" % (jid.username, suffix, options.zulip_domain)
return f"{jid.username}{suffix}@{options.zulip_domain}"
def zulip_to_jid(email: str, jabber_domain: str) -> JID:
@ -274,7 +274,7 @@ def get_rooms(zulipToJabber: ZulipToJabberBot) -> List[str]:
ret = method()
if ret.get("result") != "success":
logging.error(str(ret))
sys.exit("Could not get initial list of Zulip %s" % (key,))
sys.exit(f"Could not get initial list of Zulip {key}")
return ret[key]
if options.mode == "public":
@ -291,7 +291,7 @@ def get_rooms(zulipToJabber: ZulipToJabberBot) -> List[str]:
def config_error(msg: str) -> None:
sys.stderr.write("%s\n" % (msg,))
sys.stderr.write(f"{msg}\n")
sys.exit(2)
@ -442,10 +442,10 @@ option does not affect login credentials.""".replace(
try:
jid = JID(options.jid)
except InvalidJID as e:
config_error("Bad JID: %s: %s" % (options.jid, e.message))
config_error(f"Bad JID: {options.jid}: {e.message}")
if options.conference_domain is None:
options.conference_domain = "conference.%s" % (jid.domain,)
options.conference_domain = f"conference.{jid.domain}"
xmpp = JabberToZulipBot(jid, options.jabber_password, get_rooms(zulipToJabber))

View file

@ -46,12 +46,12 @@ def mkdir_p(path: str) -> None:
def send_log_zulip(file_name: str, count: int, lines: List[str], extra: str = "") -> None:
content = "%s new errors%s:\n```\n%s\n```" % (count, extra, "\n".join(lines))
content = "{} new errors{}:\n```\n{}\n```".format(count, extra, "\n".join(lines))
zulip_client.send_message(
{
"type": "stream",
"to": "logs",
"subject": "%s on %s" % (file_name, platform.node()),
"subject": f"{file_name} on {platform.node()}",
"content": content,
}
)
@ -84,7 +84,7 @@ def process_logs() -> None:
file_data = last_data.get(log_file, {})
if not os.path.exists(log_file):
# If the file doesn't exist, log an error and then move on to the next file
print("Log file does not exist or could not stat log file: %s" % (log_file,))
print(f"Log file does not exist or could not stat log file: {log_file}")
continue
length = int(subprocess.check_output(["wc", "-l", log_file]).split()[0])
if file_data.get("last") is None:
@ -95,7 +95,7 @@ def process_logs() -> None:
# a log file ends up at the same line length as before
# immediately after rotation, this tool won't notice.
file_data["last"] = 1
output = subprocess.check_output(["tail", "-n+%s" % (file_data["last"],), log_file])
output = subprocess.check_output(["tail", "-n+{}".format(file_data["last"]), log_file])
new_lines = output.decode("utf-8", errors="replace").split("\n")[:-1]
if len(new_lines) > 0:
process_lines(new_lines, log_file)
@ -124,7 +124,7 @@ if __name__ == "__main__":
try:
log_files = json.loads(open(args.control_path).read())
except (json.JSONDecodeError, OSError):
print("Could not load control data from %s" % (args.control_path,))
print(f"Could not load control data from {args.control_path}")
traceback.print_exc()
sys.exit(1)
process_logs()

View file

@ -31,16 +31,16 @@ msg = dict(type="stream", to=opts.stream) # type: Dict[str, Any]
if opts.service is None:
# Host notification
thing = "host" # type: Text
msg["subject"] = "host %s" % (opts.host,)
msg["subject"] = f"host {opts.host}"
else:
# Service notification
thing = "service"
msg["subject"] = "service %s on %s" % (opts.service, opts.host)
msg["subject"] = f"service {opts.service} on {opts.host}"
if len(msg["subject"]) > 60:
msg["subject"] = msg["subject"][0:57].rstrip() + "..."
# e.g. **PROBLEM**: service is CRITICAL
msg["content"] = "**%s**: %s is %s" % (opts.type, thing, opts.state)
msg["content"] = f"**{opts.type}**: {thing} is {opts.state}"
# The "long output" can contain newlines represented by "\n" escape sequences.
# The Nagios mail command uses /usr/bin/printf "%b" to expand these.

View file

@ -21,7 +21,7 @@ ZULIP_API_KEY = "0123456789abcdef0123456789abcdef"
# And similarly for branch "test-post-receive" (for use when testing).
def deployment_notice_destination(branch: str) -> Optional[Dict[str, str]]:
if branch in ["master", "test-post-receive"]:
return dict(stream="deployments", subject="%s" % (branch,))
return dict(stream="deployments", subject=f"{branch}")
# Return None for cases where you don't want a notice sent
return None
@ -46,7 +46,7 @@ def format_deployment_message(
dep_id: str = "",
dep_time: str = "",
) -> str:
return "Deployed commit `%s` (%s) in [%s](%s)" % (commit_id, branch, app_name, url)
return f"Deployed commit `{commit_id}` ({branch}) in [{app_name}]({url})"
## If properly installed, the Zulip API should be in your import

View file

@ -37,7 +37,7 @@ def commit_notice_destination(path: str, changelist: int) -> Optional[Dict[str,
directory = dirs[2]
if directory not in ["evil-master-plan", "my-super-secret-repository"]:
return dict(stream="%s-commits" % (directory,), subject=path)
return dict(stream=f"{directory}-commits", subject=path)
# Return None for cases where you don't want a notice sent
return None

View file

@ -105,7 +105,7 @@ try:
mkdir_p(opts.data_dir)
except OSError:
# We can't write to the logfile, so just print and give up.
print("Unable to store RSS data at %s." % (opts.data_dir,), file=sys.stderr)
print(f"Unable to store RSS data at {opts.data_dir}.", file=sys.stderr)
exit(1)
log_file = os.path.join(opts.data_dir, "rss-bot.log") # type: str
@ -170,7 +170,7 @@ def send_zulip(entry: Any, feed_name: str) -> Dict[str, Any]:
if opts.unwrap:
body = unwrap_text(body)
content = "**[%s](%s)**\n%s\n%s" % (
content = "**[{}]({})**\n{}\n{}".format(
entry.title,
entry.link,
strip_tags(body),
@ -194,7 +194,7 @@ try:
with open(opts.feed_file) as f:
feed_urls = [feed.strip() for feed in f.readlines()] # type: List[str]
except OSError:
log_error_and_exit("Unable to read feed file at %s." % (opts.feed_file,))
log_error_and_exit(f"Unable to read feed file at {opts.feed_file}.")
client = zulip.Client(
email=opts.zulip_email,
@ -245,7 +245,7 @@ for feed_url in feed_urls:
response = send_zulip(entry, feed_name) # type: Dict[str, Any]
if response["result"] != "success":
logger.error("Error processing %s" % (feed_url,))
logger.error(f"Error processing {feed_url}")
logger.error(str(response))
if first_message:
# This is probably some fundamental problem like the stream not

View file

@ -21,7 +21,7 @@ ZULIP_API_KEY = "0123456789abcdef0123456789abcdef"
def commit_notice_destination(path: str, commit: str) -> Optional[Dict[str, str]]:
repo = path.split("/")[-1]
if repo not in ["evil-master-plan", "my-super-secret-repository"]:
return dict(stream="commits", subject="%s" % (repo,))
return dict(stream="commits", subject=f"{repo}")
# Return None for cases where you don't want a notice sent
return None

View file

@ -38,7 +38,7 @@ client = zulip.Client(
def markdown_ticket_url(ticket: Any, heading: str = "ticket") -> str:
return "[%s #%s](%s/%s)" % (heading, ticket.id, config.TRAC_BASE_TICKET_URL, ticket.id)
return f"[{heading} #{ticket.id}]({config.TRAC_BASE_TICKET_URL}/{ticket.id})"
def markdown_block(desc: str) -> str:
@ -52,7 +52,7 @@ def truncate(string: str, length: int) -> str:
def trac_subject(ticket: Any) -> str:
return truncate("#%s: %s" % (ticket.id, ticket.values.get("summary")), 60)
return truncate("#{}: {}".format(ticket.id, ticket.values.get("summary")), 60)
def send_update(ticket: Any, content: str) -> None:
@ -71,7 +71,7 @@ class ZulipPlugin(Component):
def ticket_created(self, ticket: Any) -> None:
"""Called when a ticket is created."""
content = "%s created %s in component **%s**, priority **%s**:\n" % (
content = "{} created {} in component **{}**, priority **{}**:\n".format(
ticket.values.get("reporter"),
markdown_ticket_url(ticket),
ticket.values.get("component"),
@ -79,9 +79,9 @@ class ZulipPlugin(Component):
)
# Include the full subject if it will be truncated
if len(ticket.values.get("summary")) > 60:
content += "**%s**\n" % (ticket.values.get("summary"),)
content += "**{}**\n".format(ticket.values.get("summary"))
if ticket.values.get("description") != "":
content += "%s" % (markdown_block(ticket.values.get("description")),)
content += "{}".format(markdown_block(ticket.values.get("description")))
send_update(ticket, content)
def ticket_changed(
@ -98,26 +98,26 @@ class ZulipPlugin(Component):
):
return
content = "%s updated %s" % (author, markdown_ticket_url(ticket))
content = f"{author} updated {markdown_ticket_url(ticket)}"
if comment:
content += " with comment: %s\n\n" % (markdown_block(comment),)
content += f" with comment: {markdown_block(comment)}\n\n"
else:
content += ":\n\n"
field_changes = []
for key, value in old_values.items():
if key == "description":
content += "- Changed %s from %s\n\nto %s" % (
content += "- Changed {} from {}\n\nto {}".format(
key,
markdown_block(value),
markdown_block(ticket.values.get(key)),
)
elif old_values.get(key) == "":
field_changes.append("%s: => **%s**" % (key, ticket.values.get(key)))
field_changes.append(f"{key}: => **{ticket.values.get(key)}**")
elif ticket.values.get(key) == "":
field_changes.append('%s: **%s** => ""' % (key, old_values.get(key)))
field_changes.append(f'{key}: **{old_values.get(key)}** => ""')
else:
field_changes.append(
"%s: **%s** => **%s**" % (key, old_values.get(key), ticket.values.get(key))
f"{key}: **{old_values.get(key)}** => **{ticket.values.get(key)}**"
)
content += ", ".join(field_changes)
@ -125,5 +125,5 @@ class ZulipPlugin(Component):
def ticket_deleted(self, ticket: Any) -> None:
"""Called when a ticket is deleted."""
content = "%s was deleted." % (markdown_ticket_url(ticket, heading="Ticket"),)
content = "{} was deleted.".format(markdown_ticket_url(ticket, heading="Ticket"))
send_update(ticket, content)

View file

@ -25,7 +25,7 @@ def get_model_id(options):
"""
trello_api_url = "https://api.trello.com/1/board/{}".format(options.trello_board_id)
trello_api_url = f"https://api.trello.com/1/board/{options.trello_board_id}"
params = {
"key": options.trello_api_key,
@ -88,7 +88,7 @@ def create_webhook(options):
"""
# first, we need to get the idModel
print("Getting Trello idModel for the {} board...".format(options.trello_board_name))
print(f"Getting Trello idModel for the {options.trello_board_name} board...")
id_model = get_model_id(options)

View file

@ -202,8 +202,8 @@ for status in statuses[::-1][: opts.limit_tweets]:
continue # Continue with the loop for the next tweet
# https://twitter.com/eatevilpenguins/status/309995853408530432
composed = "%s (%s)" % (status.user.name, status.user.screen_name)
url = "https://twitter.com/%s/status/%s" % (status.user.screen_name, status.id)
composed = f"{status.user.name} ({status.user.screen_name})"
url = f"https://twitter.com/{status.user.screen_name}/status/{status.id}"
# This contains all strings that could have caused the tweet to match our query.
text_to_check = [status.text, status.user.screen_name]
text_to_check.extend(url.expanded_url for url in status.urls)

View file

@ -143,7 +143,7 @@ for tries in range(10):
missing = 0
for elt in zephyr_subs_to_add:
if elt not in zephyr_subs:
logging.error("Failed to subscribe to %s" % (elt,))
logging.error(f"Failed to subscribe to {elt}")
missing += 1
if missing == 0:
actually_subscribed = True
@ -220,9 +220,7 @@ for key, (stream, test) in zhkeys.items():
)
print_status_and_exit(1)
else:
logging.warning(
"Replaced key %s with %s due to Zephyr server failure." % (key, new_key)
)
logging.warning(f"Replaced key {key} with {new_key} due to Zephyr server failure.")
receive_zephyrs()
receive_zephyrs()

View file

@ -9,19 +9,19 @@ api_key = sys.argv[2]
ccache_data_encoded = sys.argv[3]
# Update the Kerberos ticket cache file
program_name = "zmirror-%s" % (short_user,)
with open("/home/zulip/ccache/%s" % (program_name,), "wb") as f:
program_name = f"zmirror-{short_user}"
with open(f"/home/zulip/ccache/{program_name}", "wb") as f:
f.write(base64.b64decode(ccache_data_encoded))
# Setup API key
api_key_path = "/home/zulip/api-keys/%s" % (program_name,)
api_key_path = f"/home/zulip/api-keys/{program_name}"
open(api_key_path, "w").write(api_key + "\n")
# Setup supervisord configuration
supervisor_path = "/etc/supervisor/conf.d/zulip/%s.conf" % (program_name,)
supervisor_path = f"/etc/supervisor/conf.d/zulip/{program_name}.conf"
template = os.path.join(os.path.dirname(__file__), "zmirror_private.conf.template")
template_data = open(template).read()
session_path = "/home/zulip/zephyr_sessions/%s" % (program_name,)
session_path = f"/home/zulip/zephyr_sessions/{program_name}"
# Preserve mail zephyrs forwarding setting across rewriting the config file

View file

@ -42,7 +42,7 @@ if options.forward_class_messages and not options.noshard:
jobs = list("0123456789abcdef")
def run_job(shard: str) -> int:
subprocess.call(args + ["--shard=%s" % (shard,)])
subprocess.call(args + [f"--shard={shard}"])
return 0
for (status, job) in run_parallel(run_job, jobs, threads=16):

View file

@ -54,7 +54,7 @@ def to_zephyr_username(zulip_username: str) -> str:
return user.lower() + "@ATHENA.MIT.EDU"
match_user = re.match(r"([a-zA-Z0-9_]+)\|(.+)", user)
if not match_user:
raise Exception("Could not parse Zephyr realm for cross-realm user %s" % (zulip_username,))
raise Exception(f"Could not parse Zephyr realm for cross-realm user {zulip_username}")
return match_user.group(1).lower() + "@" + match_user.group(2).upper()
@ -134,10 +134,10 @@ def send_zulip(zeph: ZephyrDict) -> Dict[str, Any]:
# Forward messages sent to -c foo -i bar to stream bar subject "instance"
if zeph["stream"] == "message":
message["to"] = zeph["subject"].lower()
message["subject"] = "instance %s" % (zeph["subject"],)
message["subject"] = "instance {}".format(zeph["subject"])
elif zeph["stream"] == "tabbott-test5":
message["to"] = zeph["subject"].lower()
message["subject"] = "test instance %s" % (zeph["subject"],)
message["subject"] = "test instance {}".format(zeph["subject"])
else:
message["to"] = zeph["stream"]
else:
@ -145,7 +145,7 @@ def send_zulip(zeph: ZephyrDict) -> Dict[str, Any]:
message["content"] = unwrap_lines(zeph["content"])
if options.test_mode and options.site == DEFAULT_SITE:
logger.debug("Message is: %s" % (str(message),))
logger.debug(f"Message is: {str(message)}")
return {"result": "success"}
return zulip_client.send_message(message)
@ -174,7 +174,7 @@ def zephyr_bulk_subscribe(subs: List[Tuple[str, str, str]]) -> None:
# retrying the next time the bot checks its subscriptions are
# up to date.
logger.exception("Error subscribing to streams (will retry automatically):")
logger.warning("Streams were: %s" % ([cls for cls, instance, recipient in subs],))
logger.warning(f"Streams were: {[cls for cls, instance, recipient in subs]}")
return
try:
actual_zephyr_subs = [cls for (cls, _, _) in zephyr._z.getSubscriptions()]
@ -186,7 +186,7 @@ def zephyr_bulk_subscribe(subs: List[Tuple[str, str, str]]) -> None:
return
for (cls, instance, recipient) in subs:
if cls not in actual_zephyr_subs:
logger.error("Zephyr failed to subscribe us to %s; will retry" % (cls,))
logger.error(f"Zephyr failed to subscribe us to {cls}; will retry")
try:
# We'll retry automatically when we next check for
# streams to subscribe to (within 15 seconds), but
@ -317,7 +317,7 @@ def parse_zephyr_body(zephyr_data: str, notice_format: str) -> Tuple[str, str]:
# Logic based off of owl_zephyr_get_message in barnowl
fields = body.split("\x00")
if len(fields) == 5:
body = "New transaction [%s] entered in %s\nFrom: %s (%s)\nSubject: %s" % (
body = "New transaction [{}] entered in {}\nFrom: {} ({})\nSubject: {}".format(
fields[0],
fields[1],
fields[2],
@ -419,7 +419,7 @@ def process_notice(notice: "zephyr.ZNotice", log: Optional[IO[str]]) -> None:
if is_personal and not options.forward_personals:
return
if (zephyr_class not in current_zephyr_subs) and not is_personal:
logger.debug("Skipping ... %s/%s/%s" % (zephyr_class, notice.instance, is_personal))
logger.debug(f"Skipping ... {zephyr_class}/{notice.instance}/{is_personal}")
return
if notice.format.startswith("Zephyr error: See") or notice.format.endswith("@(@color(blue))"):
logger.debug("Skipping message we got from Zulip!")
@ -471,23 +471,21 @@ def process_notice(notice: "zephyr.ZNotice", log: Optional[IO[str]]) -> None:
if notice.instance.strip() != "":
zeph["subject"] = notice.instance
else:
zeph["subject"] = '(instance "%s")' % (notice.instance,)
zeph["subject"] = f'(instance "{notice.instance}")'
# Add instances in for instanced personals
if is_personal:
if notice.cls.lower() != "message" and notice.instance.lower != "personal":
heading = "[-c %s -i %s]\n" % (notice.cls, notice.instance)
heading = f"[-c {notice.cls} -i {notice.instance}]\n"
elif notice.cls.lower() != "message":
heading = "[-c %s]\n" % (notice.cls,)
heading = f"[-c {notice.cls}]\n"
elif notice.instance.lower() != "personal":
heading = "[-i %s]\n" % (notice.instance,)
heading = f"[-i {notice.instance}]\n"
else:
heading = ""
zeph["content"] = heading + zeph["content"]
logger.info(
"Received a message on %s/%s from %s..." % (zephyr_class, notice.instance, notice.sender)
)
logger.info(f"Received a message on {zephyr_class}/{notice.instance} from {notice.sender}...")
if log is not None:
log.write(json.dumps(zeph) + "\n")
log.flush()
@ -499,7 +497,7 @@ def process_notice(notice: "zephyr.ZNotice", log: Optional[IO[str]]) -> None:
try:
res = send_zulip(zeph)
if res.get("result") != "success":
logger.error("Error relaying zephyr:\n%s\n%s" % (zeph, res))
logger.error(f"Error relaying zephyr:\n{zeph}\n{res}")
except Exception:
logger.exception("Error relaying zephyr:")
finally:
@ -630,7 +628,7 @@ def send_zephyr(zwrite_args: List[str], content: str) -> Tuple[int, str]:
logger.info("stdout: " + stdout)
elif stderr:
logger.warning(
"zwrite command '%s' printed the following warning:" % (" ".join(zwrite_args),)
"zwrite command '{}' printed the following warning:".format(" ".join(zwrite_args))
)
if stderr:
logger.warning("stderr: " + stderr)
@ -712,7 +710,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 == "instance %s" % (zephyr_class,) or instance == "test instance %s" % (
elif instance == f"instance {zephyr_class}" or instance == "test instance {}".format(
zephyr_class,
):
# Forward messages to e.g. -c -i white-magic back from the
@ -724,7 +722,7 @@ Feedback button or at support@zulip.com."""
instance = zephyr_class
zephyr_class = "message"
zwrite_args.extend(["-c", zephyr_class, "-i", instance])
logger.info("Forwarding message to class %s, instance %s" % (zephyr_class, instance))
logger.info(f"Forwarding message to class {zephyr_class}, instance {instance}")
elif message["type"] == "private":
if len(message["display_recipient"]) == 1:
recipient = to_zephyr_username(message["display_recipient"][0]["email"])
@ -744,7 +742,7 @@ Feedback button or at support@zulip.com."""
to_zephyr_username(user["email"]).replace("@ATHENA.MIT.EDU", "")
for user in message["display_recipient"]
]
logger.info("Forwarding message to %s" % (recipients,))
logger.info(f"Forwarding message to {recipients}")
zwrite_args.extend(recipients)
if message.get("invite_only_stream"):
@ -769,7 +767,7 @@ Zulip users (like you) received it, Zephyr users did not.
zwrite_args.extend(["-O", "crypt"])
if options.test_mode:
logger.debug("Would have forwarded: %s\n%s" % (zwrite_args, wrapped_content))
logger.debug(f"Would have forwarded: {zwrite_args}\n{wrapped_content}")
return
(code, stderr) = send_authed_zephyr(zwrite_args, wrapped_content)
@ -849,7 +847,7 @@ def maybe_forward_to_zephyr(message: Dict[str, Any]) -> None:
timestamp_now = int(time.time())
if float(message["timestamp"]) < timestamp_now - 15:
logger.warning(
"Skipping out of order message: %s < %s" % (message["timestamp"], timestamp_now)
"Skipping out of order message: {} < {}".format(message["timestamp"], timestamp_now)
)
return
try:
@ -932,7 +930,7 @@ def add_zulip_subscriptions(verbose: bool) -> None:
authorization_errors_fatal=False,
)
if res.get("result") != "success":
logger.error("Error subscribing to streams:\n%s" % (res["msg"],))
logger.error("Error subscribing to streams:\n{}".format(res["msg"]))
return
already = res.get("already_subscribed")
@ -940,10 +938,12 @@ def add_zulip_subscriptions(verbose: bool) -> None:
unauthorized = res.get("unauthorized")
if verbose:
if already is not None and len(already) > 0:
logger.info("\nAlready subscribed to: %s" % (", ".join(list(already.values())[0]),))
logger.info(
"\nAlready subscribed to: {}".format(", ".join(list(already.values())[0]))
)
if new is not None and len(new) > 0:
logger.info(
"\nSuccessfully subscribed to: %s" % (", ".join(list(new.values())[0]),)
"\nSuccessfully subscribed to: {}".format(", ".join(list(new.values())[0]))
)
if unauthorized is not None and len(unauthorized) > 0:
logger.info(
@ -962,7 +962,7 @@ on these streams and already use Zulip. They can subscribe you to them via the
"""
)
)
+ "\n\n %s" % (", ".join(unauthorized),)
+ "\n\n {}".format(", ".join(unauthorized))
)
if len(skipped) > 0:
@ -989,9 +989,9 @@ Zulip subscription to these lines in ~/.zephyr.subs:
for (cls, instance, recipient, reason) in skipped:
if verbose:
if reason != "":
logger.info(" [%s,%s,%s] (%s)" % (cls, instance, recipient, reason))
logger.info(f" [{cls},{instance},{recipient}] ({reason})")
else:
logger.info(" [%s,%s,%s]" % (cls, instance, recipient))
logger.info(f" [{cls},{instance},{recipient}]")
if len(skipped) > 0:
if verbose:
logger.info(
@ -1032,11 +1032,11 @@ def parse_zephyr_subs(verbose: bool = False) -> Set[Tuple[str, str, str]]:
recipient = recipient.replace("%me%", options.user)
if not valid_stream_name(cls):
if verbose:
logger.error("Skipping subscription to unsupported class name: [%s]" % (line,))
logger.error(f"Skipping subscription to unsupported class name: [{line}]")
continue
except Exception:
if verbose:
logger.error("Couldn't parse ~/.zephyr.subs line: [%s]" % (line,))
logger.error(f"Couldn't parse ~/.zephyr.subs line: [{line}]")
continue
zephyr_subscriptions.add((cls.strip(), instance.strip(), recipient.strip()))
return zephyr_subscriptions
@ -1051,7 +1051,7 @@ def open_logger() -> logging.Logger:
else:
log_file = "/var/log/zulip/mirror-log"
else:
f = tempfile.NamedTemporaryFile(prefix="zulip-log.%s." % (options.user,), delete=False)
f = tempfile.NamedTemporaryFile(prefix=f"zulip-log.{options.user}.", delete=False)
log_file = f.name
# Close the file descriptor, since the logging system will
# reopen it anyway.
@ -1230,10 +1230,10 @@ or specify the --api-key-file option."""
pgrep_query = "python.*zephyr_mirror"
if options.shard is not None:
# sharded class mirror
pgrep_query = "%s.*--shard=%s" % (pgrep_query, options.shard)
pgrep_query = f"{pgrep_query}.*--shard={options.shard}"
elif options.user is not None:
# Personals mirror on behalf of another user.
pgrep_query = "%s.*--user=%s" % (pgrep_query, options.user)
pgrep_query = f"{pgrep_query}.*--user={options.user}"
proc = subprocess.Popen(
["pgrep", "-U", os.environ["USER"], "-f", pgrep_query],
stdout=subprocess.PIPE,
@ -1245,7 +1245,7 @@ or specify the --api-key-file option."""
continue
# Another copy of zephyr_mirror.py! Kill it.
logger.info("Killing duplicate zephyr_mirror process %s" % (pid,))
logger.info(f"Killing duplicate zephyr_mirror process {pid}")
try:
os.kill(pid, signal.SIGINT)
except OSError:
@ -1261,7 +1261,7 @@ or specify the --api-key-file option."""
options.forward_mail_zephyrs = subscribed_to_mail_messages()
if options.session_path is None:
options.session_path = "/var/tmp/%s" % (options.user,)
options.session_path = f"/var/tmp/{options.user}"
if options.forward_from_zulip:
child_pid = os.fork() # type: Optional[int]
@ -1278,7 +1278,7 @@ or specify the --api-key-file option."""
logger_name = "zephyr=>zulip"
if options.shard is not None:
logger_name += "(%s)" % (options.shard,)
logger_name += f"({options.shard})"
configure_logger(logger, logger_name)
# Have the kernel reap children for when we fork off processes to send Zulips
signal.signal(signal.SIGCHLD, signal.SIG_IGN)

View file

@ -102,7 +102,7 @@ class RandomExponentialBackoff(CountingBackoff):
# between x and 2x where x is growing exponentially
delay_scale = int(2 ** (self.number_of_retries / 2.0 - 1)) + 1
delay = min(delay_scale + random.randint(1, delay_scale), self.delay_cap)
message = "Sleeping for %ss [max %s] before retrying." % (delay, delay_scale * 2)
message = f"Sleeping for {delay}s [max {delay_scale * 2}] before retrying."
try:
logger.warning(message)
except NameError:
@ -124,7 +124,7 @@ def add_default_arguments(
def custom_error_handling(self: argparse.ArgumentParser, message: str) -> None:
self.print_help(sys.stderr)
self.exit(2, "{}: error: {}\n".format(self.prog, message))
self.exit(2, f"{self.prog}: error: {message}\n")
parser.error = types.MethodType(custom_error_handling, parser) # type: ignore # patching function
@ -200,22 +200,22 @@ def generate_option_group(parser: optparse.OptionParser, prefix: str = "") -> op
)
group = optparse.OptionGroup(parser, "Zulip API configuration")
group.add_option(f"--{prefix}site", dest="zulip_site", help="Zulip server URI", default=None)
group.add_option(f"--{prefix}api-key", dest="zulip_api_key", action="store")
group.add_option(
"--%ssite" % (prefix,), dest="zulip_site", help="Zulip server URI", default=None
)
group.add_option("--%sapi-key" % (prefix,), dest="zulip_api_key", action="store")
group.add_option(
"--%suser" % (prefix,), dest="zulip_email", help="Email address of the calling bot or user."
f"--{prefix}user",
dest="zulip_email",
help="Email address of the calling bot or user.",
)
group.add_option(
"--%sconfig-file" % (prefix,),
f"--{prefix}config-file",
action="store",
dest="zulip_config_file",
help="Location of an ini file containing the\nabove information. (default ~/.zuliprc)",
)
group.add_option("-v", "--verbose", action="store_true", help="Provide detailed output.")
group.add_option(
"--%sclient" % (prefix,),
f"--{prefix}client",
action="store",
default=None,
dest="zulip_client",
@ -428,7 +428,7 @@ class Client:
elif None in (api_key, email):
raise ConfigNotFoundError(
"api_key or email not specified and file %s does not exist" % (config_file,)
f"api_key or email not specified and file {config_file} does not exist"
)
assert api_key is not None and email is not None
@ -461,7 +461,7 @@ class Client:
self.tls_verification = False # type: Union[bool, str]
elif cert_bundle is not None:
if not os.path.isfile(cert_bundle):
raise ConfigNotFoundError("tls bundle '%s' does not exist" % (cert_bundle,))
raise ConfigNotFoundError(f"tls bundle '{cert_bundle}' does not exist")
self.tls_verification = cert_bundle
else:
# Default behavior: verify against system CA certificates
@ -475,12 +475,10 @@ class Client:
)
else: # we have a client cert
if not os.path.isfile(client_cert):
raise ConfigNotFoundError("client cert '%s' does not exist" % (client_cert,))
raise ConfigNotFoundError(f"client cert '{client_cert}' does not exist")
if client_cert_key is not None:
if not os.path.isfile(client_cert_key):
raise ConfigNotFoundError(
"client cert key '%s' does not exist" % (client_cert_key,)
)
raise ConfigNotFoundError(f"client cert key '{client_cert_key}' does not exist")
self.client_cert = client_cert
self.client_cert_key = client_cert_key
@ -631,7 +629,7 @@ class Client:
# On 50x errors, try again after a short sleep
if str(res.status_code).startswith("5"):
if error_retry(" (server %s)" % (res.status_code,)):
if error_retry(f" (server {res.status_code})"):
continue
# Otherwise fall through and process the python-requests error normally
except (requests.exceptions.Timeout, requests.exceptions.SSLError) as e:
@ -650,7 +648,7 @@ class Client:
else:
end_error_retry(False)
return {
"msg": "Connection error:\n%s" % (traceback.format_exc(),),
"msg": f"Connection error:\n{traceback.format_exc()}",
"result": "connection-error",
}
except requests.exceptions.ConnectionError:
@ -665,13 +663,13 @@ class Client:
continue
end_error_retry(False)
return {
"msg": "Connection error:\n%s" % (traceback.format_exc(),),
"msg": f"Connection error:\n{traceback.format_exc()}",
"result": "connection-error",
}
except Exception:
# We'll split this out into more cases as we encounter new bugs.
return {
"msg": "Unexpected error:\n%s" % (traceback.format_exc(),),
"msg": f"Unexpected error:\n{traceback.format_exc()}",
"result": "unexpected-error",
}
@ -737,7 +735,7 @@ class Client:
res = self.register(event_types, narrow, **kwargs)
if "error" in res["result"]:
if self.verbose:
print("Server returned error:\n%s" % (res["msg"],))
print("Server returned error:\n{}".format(res["msg"]))
time.sleep(1)
else:
return (res["queue_id"], res["last_event_id"])
@ -762,7 +760,7 @@ class Client:
)
else:
if self.verbose:
print("Server returned error:\n%s" % (res["msg"],))
print("Server returned error:\n{}".format(res["msg"]))
# Eventually, we'll only want the
# BAD_EVENT_QUEUE_ID check, but we check for the
# old string to support legacy Zulip servers. We
@ -821,7 +819,7 @@ class Client:
"""
See examples/get-raw-message for example usage
"""
return self.call_endpoint(url="messages/{}".format(message_id), method="GET")
return self.call_endpoint(url=f"messages/{message_id}", method="GET")
def send_message(self, message_data: Dict[str, Any]) -> Dict[str, Any]:
"""
@ -861,7 +859,7 @@ class Client:
"""
See examples/delete-message for example usage.
"""
return self.call_endpoint(url="messages/{}".format(message_id), method="DELETE")
return self.call_endpoint(url=f"messages/{message_id}", method="DELETE")
def update_message_flags(self, update_data: Dict[str, Any]) -> Dict[str, Any]:
"""
@ -914,7 +912,7 @@ class Client:
"""
See examples/message-history for example usage.
"""
return self.call_endpoint(url="messages/{}/history".format(message_id), method="GET")
return self.call_endpoint(url=f"messages/{message_id}/history", method="GET")
def add_reaction(self, reaction_data: Dict[str, Any]) -> Dict[str, Any]:
"""
@ -965,9 +963,7 @@ class Client:
>>> client.upload_custom_emoji(emoji_name, file_obj)
{'result': 'success', 'msg': ''}
"""
return self.call_endpoint(
"realm/emoji/{}".format(emoji_name), method="POST", files=[file_obj]
)
return self.call_endpoint(f"realm/emoji/{emoji_name}", method="POST", files=[file_obj])
def delete_custom_emoji(self, emoji_name: str) -> Dict[str, Any]:
"""
@ -977,7 +973,7 @@ class Client:
{'result': 'success', 'msg': ''}
"""
return self.call_endpoint(
url="realm/emoji/{}".format(emoji_name),
url=f"realm/emoji/{emoji_name}",
method="DELETE",
)
@ -1027,7 +1023,7 @@ class Client:
{'result': 'success', 'msg': ''}
"""
return self.call_endpoint(
url="realm/filters/{}".format(filter_id),
url=f"realm/filters/{filter_id}",
method="DELETE",
)
@ -1064,7 +1060,7 @@ class Client:
{'result': 'success', 'msg': ''}
"""
return self.call_endpoint(
url="realm/profile_fields/{}".format(field_id),
url=f"realm/profile_fields/{field_id}",
method="DELETE",
)
@ -1089,7 +1085,7 @@ class Client:
{'result': 'success', 'msg': ''}
"""
return self.call_endpoint(
url="realm/profile_fields/{}".format(field_id),
url=f"realm/profile_fields/{field_id}",
method="PATCH",
request=request,
)
@ -1181,7 +1177,7 @@ class Client:
{'presence': {'website': {'timestamp': 1486799122, 'status': 'active'}}, 'result': 'success', 'msg': ''}
"""
return self.call_endpoint(
url="users/%s/presence" % (email,),
url=f"users/{email}/presence",
method="GET",
)
@ -1240,7 +1236,7 @@ class Client:
See examples/delete-stream for example usage.
"""
return self.call_endpoint(
url="streams/{}".format(stream_id),
url=f"streams/{stream_id}",
method="DELETE",
)
@ -1267,7 +1263,7 @@ class Client:
{'result': 'success', 'msg': '', 'user': [{...}, {...}]}
"""
return self.call_endpoint(
url="users/{}".format(user_id),
url=f"users/{user_id}",
method="GET",
request=request,
)
@ -1281,7 +1277,7 @@ class Client:
{'result': 'success', 'msg': ''}
"""
return self.call_endpoint(
url="users/{}".format(user_id),
url=f"users/{user_id}",
method="DELETE",
)
@ -1294,7 +1290,7 @@ class Client:
{'result': 'success', 'msg': ''}
"""
return self.call_endpoint(
url="users/{}/reactivate".format(user_id),
url=f"users/{user_id}/reactivate",
method="POST",
)
@ -1310,7 +1306,7 @@ class Client:
for key, value in request.items():
request[key] = json.dumps(value)
return self.call_endpoint(url="users/{}".format(user_id), method="PATCH", request=request)
return self.call_endpoint(url=f"users/{user_id}", method="PATCH", request=request)
def get_users(self, request: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
"""
@ -1399,7 +1395,7 @@ class Client:
{'result': 'success', 'msg': '', 'is_subscribed': False}
"""
return self.call_endpoint(
url="users/{}/subscriptions/{}".format(user_id, stream_id),
url=f"users/{user_id}/subscriptions/{stream_id}",
method="GET",
)
@ -1456,7 +1452,7 @@ class Client:
Example usage: client.get_stream_id('devel')
"""
stream_encoded = urllib.parse.quote(stream, safe="")
url = "get_stream_id?stream=%s" % (stream_encoded,)
url = f"get_stream_id?stream={stream_encoded}"
return self.call_endpoint(
url=url,
method="GET",
@ -1467,7 +1463,7 @@ class Client:
"""
See examples/get-stream-topics for example usage.
"""
return self.call_endpoint(url="users/me/{}/topics".format(stream_id), method="GET")
return self.call_endpoint(url=f"users/me/{stream_id}/topics", method="GET")
def get_user_groups(self) -> Dict[str, Any]:
"""
@ -1521,7 +1517,7 @@ class Client:
{'msg': '', 'result': 'success'}
"""
return self.call_endpoint(
url="user_groups/{}".format(group_id),
url=f"user_groups/{group_id}",
method="DELETE",
)
@ -1538,7 +1534,7 @@ class Client:
{'msg': '', 'result': 'success'}
"""
return self.call_endpoint(
url="user_groups/{}/members".format(user_group_id),
url=f"user_groups/{user_group_id}/members",
method="POST",
request=group_data,
)
@ -1683,7 +1679,7 @@ class Client:
return result
if len(result["messages"]) <= 0:
return {"result": "error", "msg": 'No messages found in topic: "{}"'.format(topic)}
return {"result": "error", "msg": f'No messages found in topic: "{topic}"'}
message_id = result["messages"][0]["id"]
@ -1696,7 +1692,7 @@ class Client:
"send_notification_to_new_thread": notify_new_topic,
}
return self.call_endpoint(
url="messages/{}".format(message_id),
url=f"messages/{message_id}",
method="PATCH",
request=request,
)

View file

@ -15,7 +15,7 @@ Example: edit-stream --stream-id=3 --history-public-to-subscribers
def quote(string: str) -> str:
return '"{}"'.format(string)
return f'"{string}"'
parser = zulip.add_default_arguments(argparse.ArgumentParser(usage=usage))

View file

@ -38,4 +38,4 @@ response = client.upload_file(file)
try:
print("File URI: {}".format(response["uri"]))
except KeyError:
print("Error! API response was: {}".format(response))
print(f"Error! API response was: {response}")

View file

@ -22,7 +22,7 @@ def do_send_message(client: zulip.Client, message_data: Dict[str, Any]) -> bool:
% (message_data["to"], message_data["subject"])
)
else:
log.info("Sending message to %s... " % (message_data["to"],))
log.info("Sending message to {}... ".format(message_data["to"]))
response = client.send_message(message_data)
if response["result"] == "success":
log.info("Message sent.")