diff --git a/tools/custom_check.py b/tools/custom_check.py index c4ae2f5..dea7edc 100644 --- a/tools/custom_check.py +++ b/tools/custom_check.py @@ -13,7 +13,7 @@ whitespace_rules = [ ] # type: List[Rule] markdown_whitespace_rules = list( - [rule for rule in whitespace_rules if rule["pattern"] != r"\s+$"] + rule for rule in whitespace_rules if rule["pattern"] != r"\s+$" ) + [ # Two spaces trailing a line with other content is okay--it's a markdown line break. # This rule finds one space trailing a non-space, three or more trailing spaces, and diff --git a/tools/deploy b/tools/deploy index 8afd721..711d73d 100755 --- a/tools/deploy +++ b/tools/deploy @@ -31,14 +31,14 @@ def pack(options: argparse.Namespace) -> None: print("tools/deploy: No main bot file specified.") sys.exit(1) if not os.path.isfile(options.config): - print("pack: Config file not found at path: {}.".format(options.config)) + print(f"pack: Config file not found at path: {options.config}.") sys.exit(1) if not os.path.isdir(options.path): - print("pack: Bot folder not found at path: {}.".format(options.path)) + print(f"pack: Bot folder not found at path: {options.path}.") sys.exit(1) main_path = os.path.join(options.path, options.main) if not os.path.isfile(main_path): - print("pack: Bot main file not found at path: {}.".format(main_path)) + print(f"pack: Bot main file not found at path: {main_path}.") sys.exit(1) # Main logic for packing the bot. @@ -65,7 +65,7 @@ def pack(options: argparse.Namespace) -> None: ) zip_file.writestr("config.ini", bot_config) zip_file.close() - print("pack: Created zip file at: {}.".format(zip_file_path)) + print(f"pack: Created zip file at: {zip_file_path}.") def check_common_options(options: argparse.Namespace) -> None: @@ -83,7 +83,7 @@ def handle_common_response_without_data( return handle_common_response( response=response, operation=operation, - success_handler=lambda r: print("{}: {}".format(operation, success_message)), + success_handler=lambda r: print(f"{operation}: {success_message}"), ) @@ -99,12 +99,12 @@ def handle_common_response( print("{}: {}".format(operation, response_data["message"])) return False else: - print("{}: Unexpected success response format".format(operation)) + print(f"{operation}: Unexpected success response format") return False if response.status_code == requests.codes.unauthorized: - print("{}: Authentication error with the server. Aborting.".format(operation)) + print(f"{operation}: Authentication error with the server. Aborting.") else: - print("{}: Error {}. Aborting.".format(operation, response.status_code)) + print(f"{operation}: Error {response.status_code}. Aborting.") return False @@ -112,7 +112,7 @@ def upload(options: argparse.Namespace) -> None: check_common_options(options) file_path = os.path.join(bots_dir, options.botname + ".zip") if not os.path.exists(file_path): - print("upload: Could not find bot package at {}.".format(file_path)) + print(f"upload: Could not find bot package at {file_path}.") sys.exit(1) files = {"file": open(file_path, "rb")} headers = {"key": options.token} @@ -129,9 +129,9 @@ def clean(options: argparse.Namespace) -> None: file_path = os.path.join(bots_dir, options.botname + ".zip") if os.path.exists(file_path): os.remove(file_path) - print("clean: Removed {}.".format(file_path)) + print(f"clean: Removed {file_path}.") else: - print("clean: File '{}' not found.".format(file_path)) + print(f"clean: File '{file_path}' not found.") def process(options: argparse.Namespace) -> None: @@ -341,7 +341,7 @@ To list user's bots, use: if options.command in commands: commands[options.command](options) else: - print("tools/deploy: No command '{}' found.".format(options.command)) + print(f"tools/deploy: No command '{options.command}' found.") if __name__ == "__main__": diff --git a/tools/provision b/tools/provision index b110f36..0ca5436 100755 --- a/tools/provision +++ b/tools/provision @@ -41,7 +41,7 @@ the Python version this command is executed with.""" # The output has the format "Python 1.2.3" py_version_list = py_version_output.split()[1].split(".") py_version = tuple(int(num) for num in py_version_list[0:2]) - venv_name = "zulip-api-py{}-venv".format(py_version[0]) + venv_name = f"zulip-api-py{py_version[0]}-venv" if py_version <= (3, 1) and (not options.force): print( diff --git a/tools/release-packages b/tools/release-packages index 73bd45a..d58f3aa 100755 --- a/tools/release-packages +++ b/tools/release-packages @@ -62,11 +62,11 @@ def cleanup(package_dir): build_dir = os.path.join(package_dir, "build") temp_dir = os.path.join(package_dir, "temp") dist_dir = os.path.join(package_dir, "dist") - egg_info = os.path.join(package_dir, "{}.egg-info".format(os.path.basename(package_dir))) + egg_info = os.path.join(package_dir, f"{os.path.basename(package_dir)}.egg-info") def _rm_if_it_exists(directory): if os.path.isdir(directory): - print(crayons.green("Removing {}/*".format(directory), bold=True)) + print(crayons.green(f"Removing {directory}/*", bold=True)) shutil.rmtree(directory) _rm_if_it_exists(build_dir) @@ -91,7 +91,7 @@ def set_variable(fp, variable, value): os.remove(fp) shutil.move(temp_abs_path, fp) - message = "Set {variable} in {fp} to {value}.".format(fp=fp, variable=variable, value=value) + message = f"Set {variable} in {fp} to {value}." print(crayons.white(message, bold=True)) @@ -122,8 +122,8 @@ def update_requirements_in_zulip_repo(zulip_repo_dir, version, hash_or_tag): _edit_reqs_file(prod, zulip_bots_line, zulip_line) _edit_reqs_file(dev, zulip_bots_line, zulip_line) - editable_zulip = '-e "{}"\n'.format(url_zulip.rstrip()) - editable_zulip_bots = '-e "{}"\n'.format(url_zulip_bots.rstrip()) + editable_zulip = f'-e "{url_zulip.rstrip()}"\n' + editable_zulip_bots = f'-e "{url_zulip_bots.rstrip()}"\n' _edit_reqs_file( common, diff --git a/tools/review b/tools/review index fff44e8..cb28232 100755 --- a/tools/review +++ b/tools/review @@ -35,7 +35,7 @@ def check_git_pristine() -> None: def ensure_on_clean_master() -> None: branch = get_git_branch() if branch != "master": - exit("You are still on a feature branch: %s" % (branch,)) + exit(f"You are still on a feature branch: {branch}") check_git_pristine() run("git fetch upstream master") run("git rebase upstream/master") @@ -43,7 +43,7 @@ def ensure_on_clean_master() -> None: def create_pull_branch(pull_id: int) -> None: run("git fetch upstream pull/%d/head" % (pull_id,)) - run("git checkout -B review-%s FETCH_HEAD" % (pull_id,)) + run(f"git checkout -B review-{pull_id} FETCH_HEAD") run("git rebase upstream/master") run("git log upstream/master.. --oneline") run("git diff upstream/master.. --name-status") diff --git a/tools/run-mypy b/tools/run-mypy index dbaf03c..3c47e21 100755 --- a/tools/run-mypy +++ b/tools/run-mypy @@ -207,7 +207,7 @@ if args.quick: # run mypy status = 0 for repo, python_files in repo_python_files.items(): - print("Running mypy for `{}`.".format(repo), flush=True) + print(f"Running mypy for `{repo}`.", flush=True) if python_files: result = subprocess.call([mypy_command] + extra_args + python_files) if result != 0: diff --git a/tools/server_lib/test_handler.py b/tools/server_lib/test_handler.py index fc235e0..823979f 100644 --- a/tools/server_lib/test_handler.py +++ b/tools/server_lib/test_handler.py @@ -11,7 +11,7 @@ os.chdir(os.path.dirname(TOOLS_DIR)) def handle_input_and_run_tests_for_package(package_name, path_list): - parser = argparse.ArgumentParser(description="Run tests for {}.".format(package_name)) + parser = argparse.ArgumentParser(description=f"Run tests for {package_name}.") parser.add_argument( "--coverage", nargs="?", @@ -31,7 +31,7 @@ def handle_input_and_run_tests_for_package(package_name, path_list): ) options = parser.parse_args() - test_session_title = " Running tests for {} ".format(package_name) + test_session_title = f" Running tests for {package_name} " header = test_session_title.center(shutil.get_terminal_size().columns, "#") print(header) diff --git a/tools/test-bots b/tools/test-bots index ba83289..cad9c51 100755 --- a/tools/test-bots +++ b/tools/test-bots @@ -97,7 +97,7 @@ def main(): if options.pytest: excluded_bots = ["merels"] - pytest_bots_to_test = sorted([bot for bot in bots_to_test if bot not in excluded_bots]) + pytest_bots_to_test = sorted(bot for bot in bots_to_test if bot not in excluded_bots) pytest_options = [ "-s", # show output from tests; this hides the progress bar though "-x", # stop on first test failure diff --git a/zulip/integrations/bridge_with_irc/irc_mirror_backend.py b/zulip/integrations/bridge_with_irc/irc_mirror_backend.py index c9ba7e1..9ad2fcb 100644 --- a/zulip/integrations/bridge_with_irc/irc_mirror_backend.py +++ b/zulip/integrations/bridge_with_irc/irc_mirror_backend.py @@ -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}", } ) ) diff --git a/zulip/integrations/bridge_with_matrix/matrix_bridge.py b/zulip/integrations/bridge_with_matrix/matrix_bridge.py index 79df2f2..6c0b873 100644 --- a/zulip/integrations/bridge_with_matrix/matrix_bridge.py +++ b/zulip/integrations/bridge_with_matrix/matrix_bridge.py @@ -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() diff --git a/zulip/integrations/bridge_with_matrix/test_matrix.py b/zulip/integrations/bridge_with_matrix/test_matrix.py index 43cd51f..296d9ef 100644 --- a/zulip/integrations/bridge_with_matrix/test_matrix.py +++ b/zulip/integrations/bridge_with_matrix/test_matrix.py @@ -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) diff --git a/zulip/integrations/bridge_with_slack/run-slack-bridge b/zulip/integrations/bridge_with_slack/run-slack-bridge index a61cc6b..93b0c83 100755 --- a/zulip/integrations/bridge_with_slack/run-slack-bridge +++ b/zulip/integrations/bridge_with_slack/run-slack-bridge @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- import argparse import os diff --git a/zulip/integrations/codebase/zulip_codebase_mirror b/zulip/integrations/codebase/zulip_codebase_mirror index fd9d717..88264ca 100755 --- a/zulip/integrations/codebase/zulip_codebase_mirror +++ b/zulip/integrations/codebase/zulip_codebase_mirror @@ -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)) diff --git a/zulip/integrations/git/post-receive b/zulip/integrations/git/post-receive index 19b9bb8..74b5110 100755 --- a/zulip/integrations/git/post-receive +++ b/zulip/integrations/git/post-receive @@ -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", diff --git a/zulip/integrations/git/zulip_git_config.py b/zulip/integrations/git/zulip_git_config.py index 93e734b..0f7fe7a 100644 --- a/zulip/integrations/git/zulip_git_config.py +++ b/zulip/integrations/git/zulip_git_config.py @@ -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 diff --git a/zulip/integrations/google/google-calendar b/zulip/integrations/google/google-calendar index d19b737..311d94f 100755 --- a/zulip/integrations/google/google-calendar +++ b/zulip/integrations/google/google-calendar @@ -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) diff --git a/zulip/integrations/hg/zulip_changegroup.py b/zulip/integrations/hg/zulip_changegroup.py index 60085be..21cc4bd 100755 --- a/zulip/integrations/hg/zulip_changegroup.py +++ b/zulip/integrations/hg/zulip_changegroup.py @@ -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. diff --git a/zulip/integrations/jabber/jabber_mirror_backend.py b/zulip/integrations/jabber/jabber_mirror_backend.py index 0d29c6b..e70a52e 100755 --- a/zulip/integrations/jabber/jabber_mirror_backend.py +++ b/zulip/integrations/jabber/jabber_mirror_backend.py @@ -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)) diff --git a/zulip/integrations/log2zulip/log2zulip b/zulip/integrations/log2zulip/log2zulip index 55a4aaf..5526c6c 100755 --- a/zulip/integrations/log2zulip/log2zulip +++ b/zulip/integrations/log2zulip/log2zulip @@ -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() diff --git a/zulip/integrations/nagios/nagios-notify-zulip b/zulip/integrations/nagios/nagios-notify-zulip index acb1930..670d9bf 100755 --- a/zulip/integrations/nagios/nagios-notify-zulip +++ b/zulip/integrations/nagios/nagios-notify-zulip @@ -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. diff --git a/zulip/integrations/openshift/zulip_openshift_config.py b/zulip/integrations/openshift/zulip_openshift_config.py index e191ebe..13d0462 100755 --- a/zulip/integrations/openshift/zulip_openshift_config.py +++ b/zulip/integrations/openshift/zulip_openshift_config.py @@ -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 diff --git a/zulip/integrations/perforce/zulip_perforce_config.py b/zulip/integrations/perforce/zulip_perforce_config.py index bae73a7..da9b03b 100644 --- a/zulip/integrations/perforce/zulip_perforce_config.py +++ b/zulip/integrations/perforce/zulip_perforce_config.py @@ -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 diff --git a/zulip/integrations/rss/rss-bot b/zulip/integrations/rss/rss-bot index f03d7d7..bbe6a1d 100755 --- a/zulip/integrations/rss/rss-bot +++ b/zulip/integrations/rss/rss-bot @@ -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 diff --git a/zulip/integrations/svn/zulip_svn_config.py b/zulip/integrations/svn/zulip_svn_config.py index 0f61370..f851ae2 100644 --- a/zulip/integrations/svn/zulip_svn_config.py +++ b/zulip/integrations/svn/zulip_svn_config.py @@ -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 diff --git a/zulip/integrations/trac/zulip_trac.py b/zulip/integrations/trac/zulip_trac.py index fb92fdd..bb16dd2 100644 --- a/zulip/integrations/trac/zulip_trac.py +++ b/zulip/integrations/trac/zulip_trac.py @@ -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) diff --git a/zulip/integrations/trello/zulip_trello.py b/zulip/integrations/trello/zulip_trello.py index f9a5678..eb1e7dd 100755 --- a/zulip/integrations/trello/zulip_trello.py +++ b/zulip/integrations/trello/zulip_trello.py @@ -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) diff --git a/zulip/integrations/twitter/twitter-bot b/zulip/integrations/twitter/twitter-bot index 2aa591b..15823f4 100755 --- a/zulip/integrations/twitter/twitter-bot +++ b/zulip/integrations/twitter/twitter-bot @@ -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) diff --git a/zulip/integrations/zephyr/check-mirroring b/zulip/integrations/zephyr/check-mirroring index c70a5e6..33d63c6 100755 --- a/zulip/integrations/zephyr/check-mirroring +++ b/zulip/integrations/zephyr/check-mirroring @@ -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() diff --git a/zulip/integrations/zephyr/process_ccache b/zulip/integrations/zephyr/process_ccache index 9ebf1cc..52688d3 100755 --- a/zulip/integrations/zephyr/process_ccache +++ b/zulip/integrations/zephyr/process_ccache @@ -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 diff --git a/zulip/integrations/zephyr/zephyr_mirror.py b/zulip/integrations/zephyr/zephyr_mirror.py index 38a2c7d..d4450b4 100755 --- a/zulip/integrations/zephyr/zephyr_mirror.py +++ b/zulip/integrations/zephyr/zephyr_mirror.py @@ -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): diff --git a/zulip/integrations/zephyr/zephyr_mirror_backend.py b/zulip/integrations/zephyr/zephyr_mirror_backend.py index b524953..2d42335 100755 --- a/zulip/integrations/zephyr/zephyr_mirror_backend.py +++ b/zulip/integrations/zephyr/zephyr_mirror_backend.py @@ -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) diff --git a/zulip/zulip/__init__.py b/zulip/zulip/__init__.py index e86b9b8..725896e 100644 --- a/zulip/zulip/__init__.py +++ b/zulip/zulip/__init__.py @@ -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, ) diff --git a/zulip/zulip/examples/edit-stream b/zulip/zulip/examples/edit-stream index 306010e..bbee0bb 100755 --- a/zulip/zulip/examples/edit-stream +++ b/zulip/zulip/examples/edit-stream @@ -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)) diff --git a/zulip/zulip/examples/upload-file b/zulip/zulip/examples/upload-file index 48fe8aa..bdb1415 100755 --- a/zulip/zulip/examples/upload-file +++ b/zulip/zulip/examples/upload-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}") diff --git a/zulip/zulip/send.py b/zulip/zulip/send.py index fb846f7..fc58048 100755 --- a/zulip/zulip/send.py +++ b/zulip/zulip/send.py @@ -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.") diff --git a/zulip_bots/setup.py b/zulip_bots/setup.py index ddeafe6..9ab6ca1 100644 --- a/zulip_bots/setup.py +++ b/zulip_bots/setup.py @@ -90,11 +90,11 @@ except ImportError: except (ImportError, AssertionError): if version is not None: print( - "{name}>={version} is not installed.".format(name=module_name, version=version), + f"{module_name}>={version} is not installed.", file=sys.stderr, ) else: - print("{name} is not installed.".format(name=module_name), file=sys.stderr) + print(f"{module_name} is not installed.", file=sys.stderr) sys.exit(1) check_dependency_manually("zulip") diff --git a/zulip_bots/zulip_bots/bots/baremetrics/baremetrics.py b/zulip_bots/zulip_bots/bots/baremetrics/baremetrics.py index 0bf6a41..c6d303d 100644 --- a/zulip_bots/zulip_bots/bots/baremetrics/baremetrics.py +++ b/zulip_bots/zulip_bots/bots/baremetrics/baremetrics.py @@ -73,7 +73,7 @@ class BaremetricsHandler: if content == ["list-commands"]: response = "**Available Commands:** \n" for command, description in zip(self.commands, self.descriptions): - response += " - {} : {}\n".format(command, description) + response += f" - {command} : {description}\n" bot_handler.send_reply(message, response) return @@ -148,7 +148,7 @@ class BaremetricsHandler: return response def get_plans(self, source_id: str) -> str: - url = "https://api.baremetrics.com/v1/{}/plans".format(source_id) + url = f"https://api.baremetrics.com/v1/{source_id}/plans" plans_response = requests.get(url, headers=self.auth_header) plans_data = plans_response.json() @@ -174,7 +174,7 @@ class BaremetricsHandler: return "\n".join(response) def get_customers(self, source_id: str) -> str: - url = "https://api.baremetrics.com/v1/{}/customers".format(source_id) + url = f"https://api.baremetrics.com/v1/{source_id}/customers" customers_response = requests.get(url, headers=self.auth_header) customers_data = customers_response.json() @@ -203,7 +203,7 @@ class BaremetricsHandler: return "\n".join(response) def get_subscriptions(self, source_id: str) -> str: - url = "https://api.baremetrics.com/v1/{}/subscriptions".format(source_id) + url = f"https://api.baremetrics.com/v1/{source_id}/subscriptions" subscriptions_response = requests.get(url, headers=self.auth_header) subscriptions_data = subscriptions_response.json() @@ -250,7 +250,7 @@ class BaremetricsHandler: "interval_count": int(parameters[6]), } # type: Any - url = "https://api.baremetrics.com/v1/{}/plans".format(parameters[0]) + url = f"https://api.baremetrics.com/v1/{parameters[0]}/plans" create_plan_response = requests.post(url, data=data_header, headers=self.auth_header) if "error" not in create_plan_response.json(): return "Plan Created." diff --git a/zulip_bots/zulip_bots/bots/beeminder/beeminder.py b/zulip_bots/zulip_bots/bots/beeminder/beeminder.py index 468fb7f..d15c796 100644 --- a/zulip_bots/zulip_bots/bots/beeminder/beeminder.py +++ b/zulip_bots/zulip_bots/bots/beeminder/beeminder.py @@ -70,7 +70,7 @@ at syntax by: @mention-botname help" r.status_code ) # Occures in case of unprocessable entity else: - datapoint_link = "https://www.beeminder.com/{}/{}".format(username, goalname) + datapoint_link = f"https://www.beeminder.com/{username}/{goalname}" return "[Datapoint]({}) created.".format( datapoint_link ) # Handles the case of successful datapoint creation diff --git a/zulip_bots/zulip_bots/bots/chessbot/chessbot.py b/zulip_bots/zulip_bots/bots/chessbot/chessbot.py index d43e6af..177c3d1 100644 --- a/zulip_bots/zulip_bots/bots/chessbot/chessbot.py +++ b/zulip_bots/zulip_bots/bots/chessbot/chessbot.py @@ -376,7 +376,7 @@ def make_draw_response(reason: str) -> str: Returns: The draw response string. """ - return "It's a draw because of {}!".format(reason) + return f"It's a draw because of {reason}!" def make_loss_response(board: chess.Board, reason: str) -> str: @@ -525,7 +525,7 @@ def make_str(board: chess.Board, is_white_on_bottom: bool) -> str: replaced_and_guided_str if is_white_on_bottom else replaced_and_guided_str[::-1] ) trimmed_str = trim_whitespace_before_newline(properly_flipped_str) - monospaced_str = "```\n{}\n```".format(trimmed_str) + monospaced_str = f"```\n{trimmed_str}\n```" return monospaced_str diff --git a/zulip_bots/zulip_bots/bots/define/define.py b/zulip_bots/zulip_bots/bots/define/define.py index 522747c..073afb2 100644 --- a/zulip_bots/zulip_bots/bots/define/define.py +++ b/zulip_bots/zulip_bots/bots/define/define.py @@ -51,7 +51,7 @@ class DefineHandler: if not to_define_lower: return self.EMPTY_WORD_REQUEST_ERROR_MESSAGE else: - response = "**{}**:\n".format(to_define) + response = f"**{to_define}**:\n" try: # Use OwlBot API to fetch definition. diff --git a/zulip_bots/zulip_bots/bots/dialogflow/dialogflow.py b/zulip_bots/zulip_bots/bots/dialogflow/dialogflow.py index b3f667b..592180b 100644 --- a/zulip_bots/zulip_bots/bots/dialogflow/dialogflow.py +++ b/zulip_bots/zulip_bots/bots/dialogflow/dialogflow.py @@ -36,7 +36,7 @@ def get_bot_result(message_content: str, config: Dict[str, str], sender_id: str) return res_json["result"]["fulfillment"]["speech"] except Exception as e: logging.exception(str(e)) - return "Error. {}.".format(str(e)) + return f"Error. {str(e)}." class DialogFlowHandler: diff --git a/zulip_bots/zulip_bots/bots/dropbox_share/dropbox_share.py b/zulip_bots/zulip_bots/bots/dropbox_share/dropbox_share.py index 9fbdceb..930ac0e 100644 --- a/zulip_bots/zulip_bots/bots/dropbox_share/dropbox_share.py +++ b/zulip_bots/zulip_bots/bots/dropbox_share/dropbox_share.py @@ -117,7 +117,7 @@ def syntax_help(cmd_name: str) -> str: cmd = cmd_name + " " + arg_syntax else: cmd = cmd_name - return "syntax: {}".format(cmd) + return f"syntax: {cmd}" def dbx_help(client: Any, cmd_name: str) -> str: @@ -197,7 +197,7 @@ def dbx_read(client: Any, fn: str) -> str: try: result = client.files_download(fn) - msg = "**{}** :\n{}".format(result[0].name, result[1].text) + msg = f"**{result[0].name}** :\n{result[1].text}" except Exception: msg = ( "Please provide a correct file path\nUsage: `read ` to read content of a file" diff --git a/zulip_bots/zulip_bots/bots/file_uploader/file_uploader.py b/zulip_bots/zulip_bots/bots/file_uploader/file_uploader.py index ccac2ac..9690803 100644 --- a/zulip_bots/zulip_bots/bots/file_uploader/file_uploader.py +++ b/zulip_bots/zulip_bots/bots/file_uploader/file_uploader.py @@ -27,14 +27,14 @@ class FileUploaderHandler: path = Path(os.path.expanduser(content)) if not path.is_file(): - bot_handler.send_reply(message, "File `{}` not found".format(content)) + bot_handler.send_reply(message, f"File `{content}` not found") return path = path.resolve() upload = bot_handler.upload_file_from_path(str(path)) if upload["result"] != "success": msg = upload["msg"] - bot_handler.send_reply(message, "Failed to upload `{}` file: {}".format(path, msg)) + bot_handler.send_reply(message, f"Failed to upload `{path}` file: {msg}") return uploaded_file_reply = "[{}]({})".format(path.name, upload["uri"]) diff --git a/zulip_bots/zulip_bots/bots/followup/followup.py b/zulip_bots/zulip_bots/bots/followup/followup.py index 8f49256..47c3c54 100644 --- a/zulip_bots/zulip_bots/bots/followup/followup.py +++ b/zulip_bots/zulip_bots/bots/followup/followup.py @@ -52,7 +52,7 @@ class FollowupHandler: def get_bot_followup_response(self, message: Dict[str, str]) -> str: original_content = message["content"] original_sender = message["sender_email"] - temp_content = "from %s: " % (original_sender,) + temp_content = f"from {original_sender}: " new_content = temp_content + original_content return new_content diff --git a/zulip_bots/zulip_bots/bots/front/front.py b/zulip_bots/zulip_bots/bots/front/front.py index d17f9e7..2f89c91 100644 --- a/zulip_bots/zulip_bots/bots/front/front.py +++ b/zulip_bots/zulip_bots/bots/front/front.py @@ -35,7 +35,7 @@ class FrontHandler: def help(self, bot_handler: BotHandler) -> str: response = "" for command, description in self.COMMANDS: - response += "`{}` {}\n".format(command, description) + response += f"`{command}` {description}\n" return response diff --git a/zulip_bots/zulip_bots/bots/front/test_front.py b/zulip_bots/zulip_bots/bots/front/test_front.py index 3e0e369..6c0e9ef 100644 --- a/zulip_bots/zulip_bots/bots/front/test_front.py +++ b/zulip_bots/zulip_bots/bots/front/test_front.py @@ -78,9 +78,9 @@ class TestFrontBot(BotTestCase, DefaultTests): def _test_command_error(self, command_name: str, command_arg: Optional[str] = None) -> None: bot_command = command_name if command_arg: - bot_command += " {}".format(command_arg) + bot_command += f" {command_arg}" with self.mock_config_info({"api_key": "TEST"}): - with self.mock_http_conversation("{}_error".format(command_name)): + with self.mock_http_conversation(f"{command_name}_error"): self.verify_reply(bot_command, "Something went wrong.") diff --git a/zulip_bots/zulip_bots/bots/game_handler_bot/test_game_handler_bot.py b/zulip_bots/zulip_bots/bots/game_handler_bot/test_game_handler_bot.py index e38011e..a437c65 100644 --- a/zulip_bots/zulip_bots/bots/game_handler_bot/test_game_handler_bot.py +++ b/zulip_bots/zulip_bots/bots/game_handler_bot/test_game_handler_bot.py @@ -1,6 +1,5 @@ from typing import Any, Dict, List - -from mock import patch +from unittest.mock import patch from zulip_bots.game_handler import GameInstance from zulip_bots.test_lib import BotTestCase, DefaultTests @@ -66,8 +65,8 @@ class TestGameHandlerBot(BotTestCase, DefaultTests): if bot is None: bot, bot_handler = self._get_handlers() message = { - "sender_email": "{}@example.com".format(name), - "sender_full_name": "{}".format(name), + "sender_email": f"{name}@example.com", + "sender_full_name": f"{name}", } bot.add_user_to_cache(message) return bot diff --git a/zulip_bots/zulip_bots/bots/github_detail/github_detail.py b/zulip_bots/zulip_bots/bots/github_detail/github_detail.py index df30135..726e50b 100644 --- a/zulip_bots/zulip_bots/bots/github_detail/github_detail.py +++ b/zulip_bots/zulip_bots/bots/github_detail/github_detail.py @@ -42,8 +42,8 @@ class GithubHandler: status = details["state"].title() message_string = ( - "**[{owner}/{repo}#{id}]".format(owner=owner, repo=repo, id=number), - "({link}) - {title}**\n".format(title=title, link=link), + 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 diff --git a/zulip_bots/zulip_bots/bots/google_search/google_search.py b/zulip_bots/zulip_bots/bots/google_search/google_search.py index a3cafc7..dc981d5 100644 --- a/zulip_bots/zulip_bots/bots/google_search/google_search.py +++ b/zulip_bots/zulip_bots/bots/google_search/google_search.py @@ -32,7 +32,7 @@ def google_search(keywords: str) -> List[Dict[str, str]]: if a.text.strip() == "Cached" and "webcache.googleusercontent.com" in a["href"]: continue # a.text: The name of the page - result = {"url": "https://www.google.com{}".format(link), "name": a.text} + result = {"url": f"https://www.google.com{link}", "name": a.text} results.append(result) return results @@ -61,7 +61,7 @@ def get_google_result(search_keywords: str) -> str: return "Found Result: [{}]({})".format(results[0]["name"], results[0]["url"]) except Exception as e: logging.exception(str(e)) - return "Error: Search failed. {}.".format(e) + return f"Error: Search failed. {e}." class GoogleSearchHandler: diff --git a/zulip_bots/zulip_bots/bots/google_translate/google_translate.py b/zulip_bots/zulip_bots/bots/google_translate/google_translate.py index 7552065..579bc0d 100644 --- a/zulip_bots/zulip_bots/bots/google_translate/google_translate.py +++ b/zulip_bots/zulip_bots/bots/google_translate/google_translate.py @@ -107,12 +107,12 @@ def get_translate_bot_response(message_content, config_file, author, all_languag text_to_translate, config_file["key"], target_language, source_language ) except requests.exceptions.ConnectionError as conn_err: - return "Could not connect to Google Translate. {}.".format(conn_err) + return f"Could not connect to Google Translate. {conn_err}." except TranslateError as tr_err: - return "Translate Error. {}.".format(tr_err) + return f"Translate Error. {tr_err}." except Exception as err: - return "Error. {}.".format(err) - return "{} (from {})".format(translated_text, author) + return f"Error. {err}." + return f"{translated_text} (from {author})" handler_class = GoogleTranslateHandler diff --git a/zulip_bots/zulip_bots/bots/idonethis/idonethis.py b/zulip_bots/zulip_bots/bots/idonethis/idonethis.py index 870d17d..a84346f 100644 --- a/zulip_bots/zulip_bots/bots/idonethis/idonethis.py +++ b/zulip_bots/zulip_bots/bots/idonethis/idonethis.py @@ -64,12 +64,12 @@ def api_list_team() -> List[Dict[str, str]]: def api_show_team(hash_id: str) -> Dict[str, str]: - return make_API_request("/teams/{}".format(hash_id)) + return make_API_request(f"/teams/{hash_id}") # NOTE: This function is not currently used def api_show_users(hash_id: str) -> Any: - return make_API_request("/teams/{}/members".format(hash_id)) + return make_API_request(f"/teams/{hash_id}/members") def api_list_entries(team_id: Optional[str] = None) -> List[Dict[str, Any]]: @@ -105,7 +105,7 @@ def team_info(team_name: str) -> str: def entries_list(team_name: str) -> str: if team_name: data = api_list_entries(get_team_hash(team_name)) - response = "Entries for {}:".format(team_name) + response = f"Entries for {team_name}:" else: data = api_list_entries() response = "Entries for all teams:" diff --git a/zulip_bots/zulip_bots/bots/incident/incident.py b/zulip_bots/zulip_bots/bots/incident/incident.py index 9a78fc2..f4f8919 100644 --- a/zulip_bots/zulip_bots/bots/incident/incident.py +++ b/zulip_bots/zulip_bots/bots/incident/incident.py @@ -39,7 +39,7 @@ class IncidentHandler: bot_response = "Invalid answer format" bot_handler.send_reply(message, bot_response) return - bot_response = "Incident %s\n status = %s" % (ticket_id, answer) + bot_response = f"Incident {ticket_id}\n status = {answer}" bot_handler.send_reply(message, bot_response) else: bot_response = 'type "new " for a new incident' @@ -125,15 +125,13 @@ 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" - ] + "* **{code}** {answer}".format( + code=code, + answer=ANSWERS[code], + ) + for code in "1234" ) - how_to_respond = """**reply**: answer {ticket_id} """.format(ticket_id=ticket_id) + how_to_respond = f"""**reply**: answer {ticket_id} """ content = """ Incident: {incident} diff --git a/zulip_bots/zulip_bots/bots/jira/jira.py b/zulip_bots/zulip_bots/bots/jira/jira.py index 8176e7a..7c3c81c 100644 --- a/zulip_bots/zulip_bots/bots/jira/jira.py +++ b/zulip_bots/zulip_bots/bots/jira/jira.py @@ -183,7 +183,7 @@ class JiraHandler: UNKNOWN_VAL = "*unknown*" jira_response = requests.get( self.domain_with_protocol - + "/rest/api/2/search?jql={}&fields=key,summary,status".format(jql_query), + + f"/rest/api/2/search?jql={jql_query}&fields=key,summary,status", headers={"Authorization": self.auth}, ).json() @@ -194,7 +194,7 @@ class JiraHandler: if errors: response = "Oh no! Jira raised an error:\n > " + ", ".join(errors) else: - response = "*Found {} results*\n\n".format(results) + response = f"*Found {results} results*\n\n" for issue in jira_response.get("issues", []): fields = issue.get("fields", {}) summary = fields.get("summary", UNKNOWN_VAL) @@ -314,12 +314,12 @@ class JiraHandler: response = "Issue *" + key + "* was edited! " + url elif search_match: search_term = search_match.group("search_term") - search_results = self.jql_search("summary ~ {}".format(search_term)) - response = '**Search results for "{}"**\n\n{}'.format(search_term, search_results) + search_results = self.jql_search(f"summary ~ {search_term}") + response = f'**Search results for "{search_term}"**\n\n{search_results}' elif jql_match: jql_query = jql_match.group("jql_query") search_results = self.jql_search(jql_query) - response = '**Search results for "{}"**\n\n{}'.format(jql_query, search_results) + response = f'**Search results for "{jql_query}"**\n\n{search_results}' elif help_match: response = HELP_RESPONSE else: diff --git a/zulip_bots/zulip_bots/bots/merels/libraries/game.py b/zulip_bots/zulip_bots/bots/merels/libraries/game.py index 8b6f84e..7ee44e0 100644 --- a/zulip_bots/zulip_bots/bots/merels/libraries/game.py +++ b/zulip_bots/zulip_bots/bots/merels/libraries/game.py @@ -197,5 +197,5 @@ def check_win(topic_name, merels_storage): win = mechanics.who_won(topic_name, merels_storage) if win != "None": merels.remove_game(topic_name) - return "{} wins the game!".format(win) + return f"{win} wins the game!" return "" diff --git a/zulip_bots/zulip_bots/bots/merels/libraries/mechanics.py b/zulip_bots/zulip_bots/bots/merels/libraries/mechanics.py index 4621ad1..ecd2d75 100644 --- a/zulip_bots/zulip_bots/bots/merels/libraries/mechanics.py +++ b/zulip_bots/zulip_bots/bots/merels/libraries/mechanics.py @@ -278,7 +278,7 @@ def create_room(topic_name, merels_storage): if merels.create_new_game(topic_name): response = "" - response += "A room has been created in {0}. Starting game now.\n".format(topic_name) + response += f"A room has been created in {topic_name}. Starting game now.\n" response += display_game(topic_name, merels_storage) return response @@ -404,7 +404,7 @@ def put_man(topic_name, v, h, merels_storage): data.hill_uid, data.take_mode, ) - return "Put a man to ({}, {}) for {}.".format(v, h, data.turn) + return f"Put a man to ({v}, {h}) for {data.turn}." else: raise BadMoveException("Failed: That's not a legal put. Please try again.") @@ -448,7 +448,7 @@ def take_man(topic_name, v, h, merels_storage): data.hill_uid, data.take_mode, ) - return "Taken a man from ({}, {}) for {}.".format(v, h, data.turn) + return f"Taken a man from ({v}, {h}) for {data.turn}." else: raise BadMoveException("Failed: That's not a legal take. Please try again.") diff --git a/zulip_bots/zulip_bots/bots/merels/merels.py b/zulip_bots/zulip_bots/bots/merels/merels.py index 900a078..e40832e 100644 --- a/zulip_bots/zulip_bots/bots/merels/merels.py +++ b/zulip_bots/zulip_bots/bots/merels/merels.py @@ -44,7 +44,7 @@ class MerelsModel: if self.storage.get(self.topic) == '["X", 0, 0, "NNNNNNNNNNNNNNNNNNNNNNNN", "", 0]': self.storage.put( self.topic, - '["{}", 0, 0, "NNNNNNNNNNNNNNNNNNNNNNNN", "", 0]'.format(self.token[player_number]), + f'["{self.token[player_number]}", 0, 0, "NNNNNNNNNNNNNNNNNNNNNNNN", "", 0]', ) self.current_board, same_player_move = game.beat(move, self.topic, self.storage) if same_player_move != "": diff --git a/zulip_bots/zulip_bots/bots/merels/test_merels.py b/zulip_bots/zulip_bots/bots/merels/test_merels.py index 71deb89..c64d86f 100644 --- a/zulip_bots/zulip_bots/bots/merels/test_merels.py +++ b/zulip_bots/zulip_bots/bots/merels/test_merels.py @@ -60,8 +60,8 @@ class TestMerelsBot(BotTestCase, DefaultTests): if bot is None: bot, bot_handler = self._get_handlers() message = { - "sender_email": "{}@example.com".format(name), - "sender_full_name": "{}".format(name), + "sender_email": f"{name}@example.com", + "sender_full_name": f"{name}", } bot.add_user_to_cache(message) return bot diff --git a/zulip_bots/zulip_bots/bots/monkeytestit/lib/report.py b/zulip_bots/zulip_bots/bots/monkeytestit/lib/report.py index 7890c45..9b0e2f0 100644 --- a/zulip_bots/zulip_bots/bots/monkeytestit/lib/report.py +++ b/zulip_bots/zulip_bots/bots/monkeytestit/lib/report.py @@ -25,15 +25,15 @@ def compose(results: Dict) -> str: response = "" - response += "{}\n".format(print_status(results)) + response += f"{print_status(results)}\n" if "success" in response.lower(): - response += "{}".format(print_test_id(results)) + response += f"{print_test_id(results)}" return response - response += "{}\n".format(print_enabled_checkers(results)) - response += "{}\n".format(print_failures_checkers(results)) - response += "{}".format(print_more_info_url(results)) + response += f"{print_enabled_checkers(results)}\n" + response += f"{print_failures_checkers(results)}\n" + response += f"{print_more_info_url(results)}" return response @@ -81,11 +81,11 @@ def print_failures_checkers(results: Dict) -> str: ] # [('seo', 3), ..] failures_checkers_messages = [ - "{} ({})".format(fail_checker[0], fail_checker[1]) for fail_checker in failures_checkers + f"{fail_checker[0]} ({fail_checker[1]})" for fail_checker in failures_checkers ] failures_checkers_message = ", ".join(failures_checkers_messages) - return "Failures from checkers: {}".format(failures_checkers_message) + return f"Failures from checkers: {failures_checkers_message}" def get_enabled_checkers(results: Dict) -> List: diff --git a/zulip_bots/zulip_bots/bots/salesforce/salesforce.py b/zulip_bots/zulip_bots/bots/salesforce/salesforce.py index aff079e..87fad94 100644 --- a/zulip_bots/zulip_bots/bots/salesforce/salesforce.py +++ b/zulip_bots/zulip_bots/bots/salesforce/salesforce.py @@ -57,17 +57,17 @@ def format_result( output += "**[{}]({}{})**\n".format(record["Name"], login_url, record["Id"]) for key, value in record.items(): if key not in exclude_keys: - output += ">**{}**: {}\n".format(key, value) + output += f">**{key}**: {value}\n" else: for i, record in enumerate(result["records"]): if rank_output: - output += "{}) ".format(i + 1) + output += f"{i + 1}) " output += "**[{}]({}{})**\n".format(record["Name"], login_url, record["Id"]) added_keys = False for key, value in record.items(): if key in force_keys or (show_all_keys and key not in exclude_keys): added_keys = True - output += ">**{}**: {}\n".format(key, value) + output += f">**{key}**: {value}\n" if added_keys: output += "\n" return output @@ -88,7 +88,7 @@ def query_salesforce( limit = re_limit.search(raw_arg) if limit: limit_num = int(limit.group().rsplit(" ", 1)[1]) - logging.info("Searching with limit {}".format(limit_num)) + logging.info(f"Searching with limit {limit_num}") query = default_query if "query" in command.keys(): query = command["query"] @@ -170,14 +170,14 @@ class SalesforceHandler: security_token=self.config_info["security_token"], ) except simple_salesforce.exceptions.SalesforceAuthenticationFailed as err: - bot_handler.quit("Failed to log in to Salesforce. {} {}".format(err.code, err.message)) + bot_handler.quit(f"Failed to log in to Salesforce. {err.code} {err.message}") def handle_message(self, message: Dict[str, Any], bot_handler: BotHandler) -> None: try: bot_response = self.get_salesforce_response(message["content"]) bot_handler.send_reply(message, bot_response) except Exception as e: - bot_handler.send_reply(message, "Error. {}.".format(e), bot_response) + bot_handler.send_reply(message, f"Error. {e}.", bot_response) handler_class = SalesforceHandler diff --git a/zulip_bots/zulip_bots/bots/tictactoe/test_tictactoe.py b/zulip_bots/zulip_bots/bots/tictactoe/test_tictactoe.py index fb2a9ab..21e004b 100644 --- a/zulip_bots/zulip_bots/bots/tictactoe/test_tictactoe.py +++ b/zulip_bots/zulip_bots/bots/tictactoe/test_tictactoe.py @@ -151,8 +151,8 @@ class TestTicTacToeBot(BotTestCase, DefaultTests): if bot is None: bot, bot_handler = self._get_handlers() message = { - "sender_email": "{}@example.com".format(name), - "sender_full_name": "{}".format(name), + "sender_email": f"{name}@example.com", + "sender_full_name": f"{name}", } bot.add_user_to_cache(message) return bot diff --git a/zulip_bots/zulip_bots/bots/tictactoe/tictactoe.py b/zulip_bots/zulip_bots/bots/tictactoe/tictactoe.py index 11f07b6..0ab6298 100644 --- a/zulip_bots/zulip_bots/bots/tictactoe/tictactoe.py +++ b/zulip_bots/zulip_bots/bots/tictactoe/tictactoe.py @@ -241,14 +241,14 @@ class TicTacToeMessageHandler: def parse_board(self, board: Any) -> str: """Takes the board as a nested list and returns a nice version for the user.""" - return "".join([self.parse_row(r, r_num) for r_num, r in enumerate(board)]) + return "".join(self.parse_row(r, r_num) for r_num, r in enumerate(board)) def get_player_color(self, turn: int) -> str: return self.tokens[turn] def alert_move_message(self, original_player: str, move_info: str) -> str: move_info = move_info.replace("move ", "") - return "{} put a token at {}".format(original_player, move_info) + return f"{original_player} put a token at {move_info}" def game_start_message(self) -> str: return ( @@ -299,7 +299,7 @@ def coords_from_command(cmd: str) -> str: """As there are various ways to input a coordinate (with/without parentheses, with/without spaces, etc.) the input is stripped to just the numbers before being used in the program.""" cmd_num = int(cmd.replace("move ", "")) - 1 - cmd = "{},{}".format((cmd_num % 3) + 1, (cmd_num // 3) + 1) + cmd = f"{(cmd_num % 3) + 1},{(cmd_num // 3) + 1}" return cmd diff --git a/zulip_bots/zulip_bots/bots/trello/trello.py b/zulip_bots/zulip_bots/bots/trello/trello.py index 9dd0340..effb6e4 100644 --- a/zulip_bots/zulip_bots/bots/trello/trello.py +++ b/zulip_bots/zulip_bots/bots/trello/trello.py @@ -30,7 +30,7 @@ class TrelloHandler: def check_access_token(self, bot_handler: BotHandler) -> None: test_query_response = requests.get( - "https://api.trello.com/1/members/{}/".format(self.user_name), params=self.auth_params + f"https://api.trello.com/1/members/{self.user_name}/", params=self.auth_params ) if test_query_response.text == "invalid key": @@ -75,12 +75,12 @@ class TrelloHandler: def get_all_supported_commands(self) -> str: bot_response = "**Commands:** \n" for index, (command, desc) in enumerate(supported_commands): - bot_response += "{}. **{}**: {}\n".format(index + 1, command, desc) + bot_response += f"{index + 1}. **{command}**: {desc}\n" return bot_response def get_all_boards(self) -> str: - get_board_ids_url = "https://api.trello.com/1/members/{}/".format(self.user_name) + get_board_ids_url = f"https://api.trello.com/1/members/{self.user_name}/" board_ids_response = requests.get(get_board_ids_url, params=self.auth_params) try: @@ -112,7 +112,7 @@ class TrelloHandler: return INVALID_ARGUMENTS_ERROR_MESSAGE board_id = content[1] - get_cards_url = "https://api.trello.com/1/boards/{}/cards".format(board_id) + get_cards_url = f"https://api.trello.com/1/boards/{board_id}/cards" cards_response = requests.get(get_cards_url, params=self.auth_params) try: @@ -133,7 +133,7 @@ class TrelloHandler: return INVALID_ARGUMENTS_ERROR_MESSAGE card_id = content[1] - get_checklists_url = "https://api.trello.com/1/cards/{}/checklists/".format(card_id) + get_checklists_url = f"https://api.trello.com/1/cards/{card_id}/checklists/" checklists_response = requests.get(get_checklists_url, params=self.auth_params) try: @@ -160,7 +160,7 @@ class TrelloHandler: return INVALID_ARGUMENTS_ERROR_MESSAGE board_id = content[1] - get_lists_url = "https://api.trello.com/1/boards/{}/lists".format(board_id) + get_lists_url = f"https://api.trello.com/1/boards/{board_id}/lists" lists_response = requests.get(get_lists_url, params=self.auth_params) try: diff --git a/zulip_bots/zulip_bots/bots/trivia_quiz/trivia_quiz.py b/zulip_bots/zulip_bots/bots/trivia_quiz/trivia_quiz.py index 1ebc07e..ac444f1 100644 --- a/zulip_bots/zulip_bots/bots/trivia_quiz/trivia_quiz.py +++ b/zulip_bots/zulip_bots/bots/trivia_quiz/trivia_quiz.py @@ -191,15 +191,13 @@ 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" - ] + "* **{letter}** {answer}".format( + letter=letter, + answer=answers[letter], + ) + for letter in "ABCD" ) - how_to_respond = """**reply**: answer {quiz_id} """.format(quiz_id=quiz_id) + how_to_respond = f"""**reply**: answer {quiz_id} """ content = """ Q: {question} diff --git a/zulip_bots/zulip_bots/bots/twitpost/twitpost.py b/zulip_bots/zulip_bots/bots/twitpost/twitpost.py index 6c2f0ad..ad6b258 100644 --- a/zulip_bots/zulip_bots/bots/twitpost/twitpost.py +++ b/zulip_bots/zulip_bots/bots/twitpost/twitpost.py @@ -48,7 +48,7 @@ class TwitpostBot: status = self.post(" ".join(content[1:])) screen_name = status["user"]["screen_name"] id_str = status["id_str"] - bot_reply = "https://twitter.com/{}/status/{}".format(screen_name, id_str) + bot_reply = f"https://twitter.com/{screen_name}/status/{id_str}" bot_reply = "Tweet Posted\n" + bot_reply bot_handler.send_reply(message, bot_reply) diff --git a/zulip_bots/zulip_bots/bots/virtual_fs/virtual_fs.py b/zulip_bots/zulip_bots/bots/virtual_fs/virtual_fs.py index 68fe83c..a514e31 100644 --- a/zulip_bots/zulip_bots/bots/virtual_fs/virtual_fs.py +++ b/zulip_bots/zulip_bots/bots/virtual_fs/virtual_fs.py @@ -25,7 +25,7 @@ class VirtualFsHandler: recipient = message["display_recipient"] if isinstance(recipient, list): # If not a stream, then hash on list of emails - recipient = " ".join([x["email"] for x in recipient]) + recipient = " ".join(x["email"] for x in recipient) storage = bot_handler.storage if not storage.contains(recipient): @@ -34,7 +34,7 @@ class VirtualFsHandler: if sender not in fs["user_paths"]: fs["user_paths"][sender] = "/" fs, msg = fs_command(fs, sender, command) - prependix = "{}:\n".format(sender) + prependix = f"{sender}:\n" msg = prependix + msg storage.put(recipient, fs) @@ -170,7 +170,7 @@ def syntax_help(cmd_name: str) -> str: cmd = cmd_name + " " + arg_syntax else: cmd = cmd_name - return "syntax: {}".format(cmd) + return f"syntax: {cmd}" def fs_new() -> Dict[str, Any]: @@ -190,7 +190,7 @@ def fs_mkdir(fs: Dict[str, Any], user: str, fn: str) -> Tuple[Dict[str, Any], An return fs, "ERROR: file already exists" dir_path = os.path.dirname(path) if not is_directory(fs, dir_path): - msg = "ERROR: {} is not a directory".format(dir_path) + msg = f"ERROR: {dir_path} is not a directory" return fs, msg new_fs = fs.copy() new_dir = directory({path}.union(fs[dir_path]["fns"])) @@ -211,7 +211,7 @@ def fs_ls(fs: Dict[str, Any], user: str, fn: str) -> Tuple[Dict[str, Any], Any]: msg = "ERROR: file does not exist" return fs, msg if not is_directory(fs, path): - return fs, "ERROR: {} is not a directory".format(path) + return fs, f"ERROR: {path} is not a directory" fns = fs[path]["fns"] if not fns: return fs, "WARNING: directory is empty" @@ -233,7 +233,7 @@ def fs_rm(fs: Dict[str, Any], user: str, fn: str) -> Tuple[Dict[str, Any], Any]: msg = "ERROR: file does not exist" return fs, msg if fs[path]["kind"] == "dir": - msg = "ERROR: {} is a directory, file required".format(nice_path(fs, path)) + msg = f"ERROR: {nice_path(fs, path)} is a directory, file required" return fs, msg new_fs = fs.copy() new_fs.pop(path) @@ -251,7 +251,7 @@ def fs_rmdir(fs: Dict[str, Any], user: str, fn: str) -> Tuple[Dict[str, Any], An msg = "ERROR: directory does not exist" return fs, msg if fs[path]["kind"] == "text": - msg = "ERROR: {} is a file, directory required".format(nice_path(fs, path)) + msg = f"ERROR: {nice_path(fs, path)} is a file, directory required" return fs, msg new_fs = fs.copy() new_fs.pop(path) @@ -273,7 +273,7 @@ def fs_write(fs: Dict[str, Any], user: str, fn: str, content: str) -> Tuple[Dict return fs, msg dir_path = os.path.dirname(path) if not is_directory(fs, dir_path): - msg = "ERROR: {} is not a directory".format(dir_path) + msg = f"ERROR: {dir_path} is not a directory" return fs, msg new_fs = fs.copy() new_dir = directory({path}.union(fs[dir_path]["fns"])) @@ -291,7 +291,7 @@ def fs_read(fs: Dict[str, Any], user: str, fn: str) -> Tuple[Dict[str, Any], Any msg = "ERROR: file does not exist" return fs, msg if fs[path]["kind"] == "dir": - msg = "ERROR: {} is a directory, file required".format(nice_path(fs, path)) + msg = f"ERROR: {nice_path(fs, path)} is a directory, file required" return fs, msg val = fs[path]["content"] return fs, val @@ -305,17 +305,17 @@ def fs_cd(fs: Dict[str, Any], user: str, fn: str) -> Tuple[Dict[str, Any], Any]: msg = "ERROR: invalid path" return fs, msg if fs[path]["kind"] == "text": - msg = "ERROR: {} is a file, directory required".format(nice_path(fs, path)) + msg = f"ERROR: {nice_path(fs, path)} is a file, directory required" return fs, msg fs["user_paths"][user] = path - return fs, "Current path: {}".format(nice_path(fs, path)) + return fs, f"Current path: {nice_path(fs, path)}" def make_path(fs: Dict[str, Any], user: str, leaf: str) -> List[str]: if leaf == "/": return ["/", ""] if leaf.endswith("/"): - return ["", "ERROR: {} is not a valid name".format(leaf)] + return ["", f"ERROR: {leaf} is not a valid name"] if leaf.startswith("/"): return [leaf, ""] path = fs["user_paths"][user] @@ -331,9 +331,9 @@ def nice_path(fs: Dict[str, Any], path: str) -> str: if path not in fs: return "ERROR: the current directory does not exist" if fs[path]["kind"] == "text": - path_nice = "{}*{}*".format(path[: slash + 1], path[slash + 1 :]) + path_nice = f"{path[: slash + 1]}*{path[slash + 1 :]}*" elif path != "/": - path_nice = "{}/".format(path) + path_nice = f"{path}/" return path_nice diff --git a/zulip_bots/zulip_bots/bots/xkcd/xkcd.py b/zulip_bots/zulip_bots/bots/xkcd/xkcd.py index a4c484d..ee1b607 100644 --- a/zulip_bots/zulip_bots/bots/xkcd/xkcd.py +++ b/zulip_bots/zulip_bots/bots/xkcd/xkcd.py @@ -79,19 +79,15 @@ def get_xkcd_bot_response(message: Dict[str, str], quoted_name: str) -> str: elif command.isdigit(): fetched = fetch_xkcd_query(XkcdBotCommand.COMIC_ID, command) else: - return commands_help % ( - "xkcd bot only supports these commands, not `%s`:" % (command,), - ) + return commands_help % (f"xkcd bot only supports these commands, not `{command}`:",) except (requests.exceptions.ConnectionError, XkcdServerError): logging.exception("Connection error occurred when trying to connect to xkcd server") return "Sorry, I cannot process your request right now, please try again later!" except XkcdNotFoundError: - logging.exception( - "XKCD server responded 404 when trying to fetch comic with id %s" % (command,) - ) - return "Sorry, there is likely no xkcd comic strip with id: #%s" % (command,) + logging.exception(f"XKCD server responded 404 when trying to fetch comic with id {command}") + return f"Sorry, there is likely no xkcd comic strip with id: #{command}" else: - return "#%s: **%s**\n[%s](%s)" % ( + return "#{}: **{}**\n[{}]({})".format( fetched["num"], fetched["title"], fetched["alt"], diff --git a/zulip_bots/zulip_bots/bots/youtube/youtube.py b/zulip_bots/zulip_bots/bots/youtube/youtube.py index 8bd368b..7e58300 100644 --- a/zulip_bots/zulip_bots/bots/youtube/youtube.py +++ b/zulip_bots/zulip_bots/bots/youtube/youtube.py @@ -130,7 +130,7 @@ def get_bot_response( ).strip() for title, id in video_list: - reply = reply + "\n * %s - [Watch now](https://www.youtube.com/watch/%s)" % (title, id) + reply = reply + f"\n * {title} - [Watch now](https://www.youtube.com/watch/{id})" # Using link https://www.youtube.com/watch/ to # prevent showing multiple previews return reply diff --git a/zulip_bots/zulip_bots/game_handler.py b/zulip_bots/zulip_bots/game_handler.py index b3ede21..4377496 100644 --- a/zulip_bots/zulip_bots/game_handler.py +++ b/zulip_bots/zulip_bots/game_handler.py @@ -229,7 +229,7 @@ class GameAdapter: if sender not in self.user_cache.keys(): self.add_user_to_cache(message) - logging.info("Added {} to user cache".format(sender)) + logging.info(f"Added {sender} to user cache") if self.is_single_player: if content.lower().startswith("start game with") or content.lower().startswith( @@ -300,7 +300,7 @@ class GameAdapter: self.send_reply(message, self.help_message()) except Exception as e: logging.exception(str(e)) - self.bot_handler.send_reply(message, "Error {}.".format(e)) + self.bot_handler.send_reply(message, f"Error {e}.") def is_user_in_game(self, user_email: str) -> str: for instance in self.instances.values(): @@ -344,7 +344,7 @@ class GameAdapter: self.send_reply(message, self.confirm_invitation_accepted(game_id)) self.broadcast( game_id, - "@**{}** has accepted the invitation.".format(self.get_username_by_email(sender)), + f"@**{self.get_username_by_email(sender)}** has accepted the invitation.", ) self.start_game_if_ready(game_id) @@ -365,7 +365,7 @@ class GameAdapter: if len(users) + 1 > self.max_players: self.send_reply( message, - "The maximum number of players for this game is {}.".format(self.max_players), + f"The maximum number of players for this game is {self.max_players}.", ) return game_id = self.generate_game_id() @@ -411,7 +411,7 @@ class GameAdapter: self.broadcast(game_id, "Wait... That's me!", include_private=True) if message["type"] == "stream": self.broadcast( - game_id, "@**{}** accept".format(self.get_bot_username()), include_private=False + game_id, f"@**{self.get_bot_username()}** accept", include_private=False ) game_id = self.set_invite_by_user(self.email, True, {"type": "stream"}) self.start_game_if_ready(game_id) @@ -427,7 +427,7 @@ class GameAdapter: self.send_reply(message, self.confirm_invitation_declined(game_id)) self.broadcast( game_id, - "@**{}** has declined the invitation.".format(self.get_username_by_email(sender)), + f"@**{self.get_username_by_email(sender)}** has declined the invitation.", ) if len(self.get_players(game_id, parameter="")) < self.min_players: self.cancel_game(game_id) @@ -440,7 +440,7 @@ class GameAdapter: if game_id == "": self.send_reply(message, "You are not in a game. Type `help` for all commands.") sender_name = self.get_username_by_email(sender) - self.cancel_game(game_id, reason="**{}** quit.".format(sender_name)) + self.cancel_game(game_id, reason=f"**{sender_name}** quit.") def command_join(self, message: Dict[str, Any], sender: str, content: str) -> None: if not self.is_user_not_player(sender, message): @@ -472,7 +472,7 @@ class GameAdapter: else: self.send_reply( message, - "Join {} more players to start the game".format(self.max_players - num_players), + f"Join {self.max_players - num_players} more players to start the game", ) def command_leaderboard(self, message: Dict[str, Any], sender: str, content: str) -> None: @@ -483,9 +483,9 @@ class GameAdapter: raw_headers = ["games_won", "games_drawn", "games_lost", "total_games"] headers = ["Player"] + [key.replace("_", " ").title() for key in raw_headers] response += " | ".join(headers) - response += "\n" + " | ".join([" --- " for header in headers]) + response += "\n" + " | ".join(" --- " for header in headers) for player, stat in top_stats: - response += "\n **{}** | ".format(self.get_username_by_email(player)) + response += f"\n **{self.get_username_by_email(player)}** | " values = [str(stat[key]) for key in raw_headers] response += " | ".join(values) self.send_reply(message, response) @@ -536,7 +536,7 @@ class GameAdapter: self.instances[game_id] = GameInstance(self, False, subject, game_id, players, stream) self.broadcast( game_id, - "The game has started in #{} {}".format(stream, self.instances[game_id].subject) + f"The game has started in #{stream} {self.instances[game_id].subject}" + "\n" + self.get_formatted_game_object(game_id), ) @@ -564,7 +564,7 @@ class GameAdapter: return self.invites[game_id].update({user_email: "a"}) self.broadcast( - game_id, "@**{}** has joined the game".format(self.get_username_by_email(user_email)) + game_id, f"@**{self.get_username_by_email(user_email)}** has joined the game" ) self.start_game_if_ready(game_id) @@ -873,7 +873,7 @@ class GameInstance: def get_player_text(self) -> str: player_text = "" for player in self.players: - player_text += " @**{}**".format(self.gameAdapter.get_username_by_email(player)) + player_text += f" @**{self.gameAdapter.get_username_by_email(player)}**" return player_text def get_start_message(self) -> str: @@ -890,7 +890,7 @@ class GameInstance: def handle_message(self, content: str, player_email: str) -> None: if content == "forfeit": player_name = self.gameAdapter.get_username_by_email(player_email) - self.broadcast("**{}** forfeited!".format(player_name)) + self.broadcast(f"**{player_name}** forfeited!") self.end_game("except:" + player_email) return if content == "draw": @@ -1032,7 +1032,7 @@ class GameInstance: loser = winner.lstrip("except:") else: winner_name = self.gameAdapter.get_username_by_email(winner) - self.broadcast("**{}** won! :tada:".format(winner_name)) + self.broadcast(f"**{winner_name}** won! :tada:") for u in self.players: values = {"total_games": 1, "games_won": 0, "games_lost": 0, "games_drawn": 0} if loser == "": diff --git a/zulip_bots/zulip_bots/lib.py b/zulip_bots/zulip_bots/lib.py index 4cbad4b..d6d79f7 100644 --- a/zulip_bots/zulip_bots/lib.py +++ b/zulip_bots/zulip_bots/lib.py @@ -139,13 +139,13 @@ class StateHandler: self._client = client self.marshal = lambda obj: json.dumps(obj) self.demarshal = lambda obj: json.loads(obj) - self.state_ = dict() + self.state_: Dict[str, Any] = dict() def put(self, key: str, value: Any) -> None: self.state_[key] = self.marshal(value) response = self._client.update_storage({"storage": {key: self.state_[key]}}) if response["result"] != "success": - raise StateHandlerError("Error updating state: {}".format(str(response))) + raise StateHandlerError(f"Error updating state: {str(response)}") def get(self, key: str) -> Any: if key in self.state_: @@ -423,8 +423,8 @@ def is_private_message_but_not_group_pm( def display_config_file_errors(error_msg: str, config_file: str) -> None: file_contents = open(config_file).read() - print("\nERROR: {} seems to be broken:\n\n{}".format(config_file, file_contents)) - print("\nMore details here:\n\n{}\n".format(error_msg)) + print(f"\nERROR: {config_file} seems to be broken:\n\n{file_contents}") + print(f"\nMore details here:\n\n{error_msg}\n") def prepare_message_handler(bot: str, bot_handler: BotHandler, bot_lib_module: Any) -> Any: @@ -459,7 +459,7 @@ def run_message_handler_for_bot( bot_details.update(getattr(lib_module.handler_class, "META", {})) # Make sure you set up your ~/.zuliprc - client_name = "Zulip{}Bot".format(bot_name.capitalize()) + client_name = f"Zulip{bot_name.capitalize()}Bot" try: client = Client(config_file=config_file, client=client_name) @@ -479,9 +479,7 @@ def run_message_handler_for_bot( if hasattr(message_handler, "usage"): print(message_handler.usage()) else: - print( - "WARNING: {} is missing usage handler, please add one eventually".format(bot_name) - ) + print(f"WARNING: {bot_name} is missing usage handler, please add one eventually") def handle_message(message: Dict[str, Any], flags: List[str]) -> None: logging.info("waiting for next message") diff --git a/zulip_bots/zulip_bots/provision.py b/zulip_bots/zulip_bots/provision.py index 2f873e9..d2cde0e 100755 --- a/zulip_bots/zulip_bots/provision.py +++ b/zulip_bots/zulip_bots/provision.py @@ -21,7 +21,7 @@ def provision_bot(path_to_bot: str, force: bool) -> None: req_path = os.path.join(path_to_bot, "requirements.txt") if os.path.isfile(req_path): bot_name = os.path.basename(path_to_bot) - logging.info("Installing dependencies for {}...".format(bot_name)) + logging.info(f"Installing dependencies for {bot_name}...") # pip install -r $BASEDIR/requirements.txt -t $BASEDIR/bot_dependencies --quiet rcode = subprocess.call(["pip", "install", "-r", req_path]) diff --git a/zulip_bots/zulip_bots/run.py b/zulip_bots/zulip_bots/run.py index 9b2a5a4..6d8bf76 100755 --- a/zulip_bots/zulip_bots/run.py +++ b/zulip_bots/zulip_bots/run.py @@ -63,7 +63,7 @@ def exit_gracefully_if_zulip_config_is_missing(config_file: Optional[str]) -> No # but we'll catch those later. return else: - error_msg = "ERROR: %s does not exist." % (config_file,) + error_msg = f"ERROR: {config_file} does not exist." else: if zulip_env_vars_are_present(): diff --git a/zulip_bots/zulip_bots/simple_lib.py b/zulip_bots/zulip_bots/simple_lib.py index 8b908cb..24c2c76 100644 --- a/zulip_bots/zulip_bots/simple_lib.py +++ b/zulip_bots/zulip_bots/simple_lib.py @@ -33,15 +33,13 @@ class MockMessageServer: return message def add_reaction(self, reaction_data): - return dict( - result="success", msg="", uri="https://server/messages/{}/reactions".format(uuid4()) - ) + return dict(result="success", msg="", uri=f"https://server/messages/{uuid4()}/reactions") def update(self, message): self.messages[message["message_id"]] = message def upload_file(self, file): - return dict(result="success", msg="", uri="https://server/user_uploads/{}".format(uuid4())) + return dict(result="success", msg="", uri=f"https://server/user_uploads/{uuid4()}") class TerminalBotHandler: diff --git a/zulip_bots/zulip_bots/terminal.py b/zulip_bots/zulip_bots/terminal.py index 9e327a0..7eca1c8 100644 --- a/zulip_bots/zulip_bots/terminal.py +++ b/zulip_bots/zulip_bots/terminal.py @@ -44,7 +44,7 @@ def main(): if lib_module is None: raise OSError except OSError: - print("Could not find and import bot '{}'".format(bot_name)) + print(f"Could not find and import bot '{bot_name}'") sys.exit(1) try: diff --git a/zulip_bots/zulip_bots/test_file_utils.py b/zulip_bots/zulip_bots/test_file_utils.py index f109377..ff1ee1e 100644 --- a/zulip_bots/zulip_bots/test_file_utils.py +++ b/zulip_bots/zulip_bots/test_file_utils.py @@ -27,7 +27,7 @@ def read_bot_fixture_data(bot_name: str, test_name: str) -> Dict[str, Any]: base_path = os.path.realpath( os.path.join(os.path.dirname(os.path.abspath(__file__)), "bots", bot_name, "fixtures") ) - http_data_path = os.path.join(base_path, "{}.json".format(test_name)) + http_data_path = os.path.join(base_path, f"{test_name}.json") with open(http_data_path, encoding="utf-8") as f: content = f.read() http_data = json.loads(content) diff --git a/zulip_botserver/setup.py b/zulip_botserver/setup.py index 5764f76..ec786a6 100644 --- a/zulip_botserver/setup.py +++ b/zulip_botserver/setup.py @@ -72,11 +72,11 @@ except ImportError: except (ImportError, AssertionError): if version is not None: print( - "{name}>={version} is not installed.".format(name=module_name, version=version), + f"{module_name}>={version} is not installed.", file=sys.stderr, ) else: - print("{name} is not installed.".format(name=module_name), file=sys.stderr) + print(f"{module_name} is not installed.", file=sys.stderr) sys.exit(1) check_dependency_manually("zulip") diff --git a/zulip_botserver/tests/server_test_lib.py b/zulip_botserver/tests/server_test_lib.py index 1dce222..fc64d18 100644 --- a/zulip_botserver/tests/server_test_lib.py +++ b/zulip_botserver/tests/server_test_lib.py @@ -1,9 +1,7 @@ import configparser import json from typing import Any, Dict, List, Optional -from unittest import TestCase - -import mock +from unittest import TestCase, mock from zulip_botserver import server diff --git a/zulip_botserver/tests/test_server.py b/zulip_botserver/tests/test_server.py index 3077e09..1b1b6fe 100644 --- a/zulip_botserver/tests/test_server.py +++ b/zulip_botserver/tests/test_server.py @@ -6,8 +6,7 @@ from importlib import import_module from pathlib import Path from types import ModuleType from typing import Any, Dict - -import mock +from unittest import mock from zulip_bots.lib import BotHandler from zulip_botserver import server diff --git a/zulip_botserver/zulip_botserver/server.py b/zulip_botserver/zulip_botserver/server.py index 59fe9cd..7dc9abf 100644 --- a/zulip_botserver/zulip_botserver/server.py +++ b/zulip_botserver/zulip_botserver/server.py @@ -98,7 +98,7 @@ def read_config_file( ignored_sections = parser.sections()[1:] if len(ignored_sections) > 0: - logging.warning("Sections except the '{}' will be ignored".format(bot_section)) + logging.warning(f"Sections except the '{bot_section}' will be ignored") return bots_config @@ -106,7 +106,7 @@ def read_config_file( def parse_config_file(config_file_path: str) -> configparser.ConfigParser: config_file_path = os.path.abspath(os.path.expanduser(config_file_path)) if not os.path.isfile(config_file_path): - raise OSError("Could not read config file {}: File not found.".format(config_file_path)) + raise OSError(f"Could not read config file {config_file_path}: File not found.") parser = configparser.ConfigParser() parser.read(config_file_path) return parser