diff --git a/changelogs/fragments/11908-convert-percent-to-fstrings.yml b/changelogs/fragments/11908-convert-percent-to-fstrings.yml new file mode 100644 index 0000000000..83c9a31da5 --- /dev/null +++ b/changelogs/fragments/11908-convert-percent-to-fstrings.yml @@ -0,0 +1,13 @@ +minor_changes: + - campfire - minor code cleanup (https://github.com/ansible-collections/community.general/pull/11908). + - decompress - minor code cleanup (https://github.com/ansible-collections/community.general/pull/11908). + - grove - minor code cleanup (https://github.com/ansible-collections/community.general/pull/11908). + - ini_file - minor code cleanup (https://github.com/ansible-collections/community.general/pull/11908). + - lxca_cmms - minor code cleanup (https://github.com/ansible-collections/community.general/pull/11908). + - lxca_nodes - minor code cleanup (https://github.com/ansible-collections/community.general/pull/11908). + - rocketchat - minor code cleanup (https://github.com/ansible-collections/community.general/pull/11908). + - slack - minor code cleanup (https://github.com/ansible-collections/community.general/pull/11908). + - keys_filter plugin utils - minor code cleanup (https://github.com/ansible-collections/community.general/pull/11908). + - redfish_utils module utils - minor code cleanup (https://github.com/ansible-collections/community.general/pull/11908). + - lists filter plugin - minor code cleanup (https://github.com/ansible-collections/community.general/pull/11908). + - lists_mergeby filter plugin - minor code cleanup (https://github.com/ansible-collections/community.general/pull/11908). diff --git a/plugins/filter/lists.py b/plugins/filter/lists.py index 0c6154075f..8544635eb4 100644 --- a/plugins/filter/lists.py +++ b/plugins/filter/lists.py @@ -32,8 +32,7 @@ def flatten_list(lst): result = [] for sublist in lst: if not is_sequence(sublist): - msg = "All arguments must be lists. %s is %s" - raise AnsibleFilterError(msg % (sublist, type(sublist))) + raise AnsibleFilterError(f"All arguments must be lists. {sublist} is {type(sublist)}") if len(sublist) > 0: if all(is_sequence(sub) for sub in sublist): for item in sublist: diff --git a/plugins/filter/lists_mergeby.py b/plugins/filter/lists_mergeby.py index 06b02bd531..dea54ef417 100644 --- a/plugins/filter/lists_mergeby.py +++ b/plugins/filter/lists_mergeby.py @@ -212,8 +212,9 @@ def list_mergeby(x, y, index, recursive=False, list_merge="replace"): for lst in (x, y): for elem in lst: if not isinstance(elem, Mapping): - msg = "Elements of list arguments for lists_mergeby must be dictionaries. %s is %s" - raise AnsibleFilterError(msg % (elem, type(elem))) + raise AnsibleFilterError( + f"Elements of list arguments for lists_mergeby must be dictionaries. {elem} is {type(elem)}" + ) if index in elem.keys(): d[elem[index]].update(merge_hash(d[elem[index]], elem, recursive, list_merge)) return sorted(d.values(), key=itemgetter(index)) @@ -236,8 +237,9 @@ def lists_mergeby(*terms, **kwargs): flat_list = [] for sublist in terms[:-1]: if not isinstance(sublist, Sequence): - msg = "All arguments before the argument index for community.general.lists_mergeby must be lists. %s is %s" - raise AnsibleFilterError(msg % (sublist, type(sublist))) + raise AnsibleFilterError( + f"All arguments before the argument index for community.general.lists_mergeby must be lists. {sublist} is {type(sublist)}" + ) if len(sublist) > 0: if all(isinstance(lst, Sequence) for lst in sublist): for item in sublist: @@ -255,8 +257,9 @@ def lists_mergeby(*terms, **kwargs): index = terms[-1] if not isinstance(index, str): - msg = "First argument after the lists for community.general.lists_mergeby must be string. %s is %s" - raise AnsibleFilterError(msg % (index, type(index))) + raise AnsibleFilterError( + f"First argument after the lists for community.general.lists_mergeby must be string. {index} is {type(index)}" + ) high_to_low_prio_list_iterator = reversed(lists) result = next(high_to_low_prio_list_iterator) diff --git a/plugins/module_utils/_redfish_utils.py b/plugins/module_utils/_redfish_utils.py index 063e07cda2..7f01aabfd6 100644 --- a/plugins/module_utils/_redfish_utils.py +++ b/plugins/module_utils/_redfish_utils.py @@ -4122,8 +4122,10 @@ class RedfishUtils: # Get Registries URI if "Bios" not in server_details: - msg = "Getting BIOS URI failed, Key 'Bios' not found in /redfish/v1/Systems/1/ response: %s" - return {"ret": False, "msg": msg % str(server_details)} + return { + "ret": False, + "msg": f"Getting BIOS URI failed, Key 'Bios' not found in /redfish/v1/Systems/1/ response: {server_details}", + } bios_uri = server_details["Bios"]["@odata.id"] bios_resp = self.get_request(self.root_uri + bios_uri) @@ -4169,8 +4171,10 @@ class RedfishUtils: if isinstance(loc["Uri"], dict) and "extref" in loc["Uri"].keys(): rsp_uri = loc["Uri"]["extref"] if not rsp_uri: - msg = "Language 'en' not found in BIOS Attribute Registries location, URI: %s, response: %s" - return {"ret": False, "msg": msg % (resp_uri, str(resp_data))} + return { + "ret": False, + "msg": f"Language 'en' not found in BIOS Attribute Registries location, URI: {resp_uri}, response: {resp_data}", + } res = self.get_request(self.root_uri + rsp_uri) if res["ret"] is False: diff --git a/plugins/modules/campfire.py b/plugins/modules/campfire.py index 6736f049e3..e4ed036aab 100644 --- a/plugins/modules/campfire.py +++ b/plugins/modules/campfire.py @@ -184,8 +184,6 @@ def main(): notify = module.params["notify"] URI = f"https://{subscription}.campfirenow.com" - NSTR = "SoundMessage%s" - MSTR = "%s" AGENT = "Ansible/1.2" # Hack to add basic auth username and password the way fetch_url expects @@ -197,14 +195,21 @@ def main(): # Send some audible notification if requested if notify: - response, info = fetch_url(module, target_url, data=NSTR % html_escape(notify), headers=headers) + response, info = fetch_url( + module, + target_url, + data=f"SoundMessage{html_escape(notify)}", + headers=headers, + ) if info["status"] not in [200, 201]: module.fail_json( msg=f"unable to send msg: '{notify}', campfire api returned error code: '{info['status']}'" ) # Send the message - response, info = fetch_url(module, target_url, data=MSTR % html_escape(msg), headers=headers) + response, info = fetch_url( + module, target_url, data=f"{html_escape(msg)}", headers=headers + ) if info["status"] not in [200, 201]: module.fail_json(msg=f"unable to send msg: '{msg}', campfire api returned error code: '{info['status']}'") diff --git a/plugins/modules/decompress.py b/plugins/modules/decompress.py index 3292c7dfa0..db343f6caf 100644 --- a/plugins/modules/decompress.py +++ b/plugins/modules/decompress.py @@ -120,7 +120,6 @@ def decompress(b_src, b_dest, handler): class Decompress(ModuleHelper): - destination_filename_template = "%s_decompressed" output_params = "dest" module = dict( @@ -189,7 +188,7 @@ class Decompress(ModuleHelper): if src.endswith(fmt_extension) and len(src) > len(fmt_extension): filename = src[: -len(fmt_extension)] else: - filename = Decompress.destination_filename_template % src + filename = f"{src}_decompressed" return filename diff --git a/plugins/modules/grove.py b/plugins/modules/grove.py index 0885f6d353..6693f1e21e 100644 --- a/plugins/modules/grove.py +++ b/plugins/modules/grove.py @@ -65,14 +65,12 @@ from urllib.parse import urlencode from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.urls import fetch_url -BASE_URL = "https://grove.io/api/notice/%s/" - # ============================================================== # do_notify_grove def do_notify_grove(module, channel_token, service, message, url=None, icon_url=None): - my_url = BASE_URL % (channel_token,) + my_url = f"https://grove.io/api/notice/{channel_token}/" my_data = dict(service=service, message=message) if url is not None: diff --git a/plugins/modules/ini_file.py b/plugins/modules/ini_file.py index 20037b052d..a8aa9d5f69 100644 --- a/plugins/modules/ini_file.py +++ b/plugins/modules/ini_file.py @@ -391,10 +391,7 @@ def do_ini( within_section = not section section_start = section_end = 0 msg = "OK" - if no_extra_spaces: - assignment_format = "%s=%s\n" - else: - assignment_format = "%s = %s\n" + sep = "=" if no_extra_spaces else " = " option_no_value_present = False @@ -453,7 +450,7 @@ def do_ini( option_no_value_present = True else: # replace existing option=value line(s) - newline = assignment_format % (option, matched_value) + newline = f"{option}{sep}{matched_value}\n" (changed, msg) = update_section_line( option, changed, section_lines, index, changed_lines, ignore_spaces, newline, msg ) @@ -472,7 +469,7 @@ def do_ini( if len(values) > 0: for index, line in enumerate(section_lines): if not changed_lines[index] and match_function(option, line): - newline = assignment_format % (option, values.pop(0)) + newline = f"{option}{sep}{values.pop(0)}\n" (changed, msg) = update_section_line( option, changed, section_lines, index, changed_lines, ignore_spaces, newline, msg ) @@ -498,7 +495,7 @@ def do_ini( # otherwise some of their options might appear in reverse order for whatever fancy reason ¯\_(ツ)_/¯ if element is not None: # insert option=value line - section_lines.insert(index, assignment_format % (option, element)) + section_lines.insert(index, f"{option}{sep}{element}\n") msg = "option added" changed = True elif element is None and allow_no_value: @@ -555,7 +552,7 @@ def do_ini( if condition["option"] != option: if len(condition["values"]) > 0: for value in condition["values"]: - ini_lines.append(assignment_format % (condition["option"], value)) + ini_lines.append(f"{condition['option']}{sep}{value}\n") elif allow_no_value: ini_lines.append(f"{condition['option']}\n") elif not exclusive: @@ -564,7 +561,7 @@ def do_ini( values.append(value) if option and values: for value in values: - ini_lines.append(assignment_format % (option, value)) + ini_lines.append(f"{option}{sep}{value}\n") elif option and not values and allow_no_value: ini_lines.append(f"{option}\n") else: diff --git a/plugins/modules/lxca_cmms.py b/plugins/modules/lxca_cmms.py index 3a80e24273..a12cab6988 100644 --- a/plugins/modules/lxca_cmms.py +++ b/plugins/modules/lxca_cmms.py @@ -107,7 +107,6 @@ except ImportError: UUID_REQUIRED = "UUID of device is required for cmms_by_uuid command." CHASSIS_UUID_REQUIRED = "UUID of chassis is required for cmms_by_chassis_uuid command." -SUCCESS_MSG = "Success %s result" def _cmms(module, lxca_con): @@ -160,7 +159,7 @@ def execute_module(module): try: with connection_object(module) as lxca_con: result = FUNC_DICT[module.params["command_options"]](module, lxca_con) - module.exit_json(changed=False, msg=SUCCESS_MSG % module.params["command_options"], result=result) + module.exit_json(changed=False, msg=f"Success {module.params['command_options']} result", result=result) except Exception as exception: error_msg = "; ".join((e) for e in exception.args) module.fail_json(msg=error_msg, exception=traceback.format_exc()) diff --git a/plugins/modules/lxca_nodes.py b/plugins/modules/lxca_nodes.py index de109b0726..8db2571bc7 100644 --- a/plugins/modules/lxca_nodes.py +++ b/plugins/modules/lxca_nodes.py @@ -126,7 +126,6 @@ except ImportError: UUID_REQUIRED = "UUID of device is required for nodes_by_uuid command." CHASSIS_UUID_REQUIRED = "UUID of chassis is required for nodes_by_chassis_uuid command." -SUCCESS_MSG = "Success %s result" def _nodes(module, lxca_con): @@ -192,7 +191,7 @@ def execute_module(module): try: with connection_object(module) as lxca_con: result = FUNC_DICT[module.params["command_options"]](module, lxca_con) - module.exit_json(changed=False, msg=SUCCESS_MSG % module.params["command_options"], result=result) + module.exit_json(changed=False, msg=f"Success {module.params['command_options']} result", result=result) except Exception as exception: error_msg = "; ".join(exception.args) module.fail_json(msg=error_msg, exception=traceback.format_exc()) diff --git a/plugins/modules/rocketchat.py b/plugins/modules/rocketchat.py index 520e66c44f..e7fd89dc45 100644 --- a/plugins/modules/rocketchat.py +++ b/plugins/modules/rocketchat.py @@ -160,8 +160,6 @@ EXAMPLES = r""" from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.urls import fetch_url -ROCKETCHAT_INCOMING_WEBHOOK = "%s://%s/hooks/%s" - def build_payload_for_rocketchat( module, text, channel, username, icon_url, icon_emoji, link_names, color, attachments, is_pre740 @@ -205,7 +203,7 @@ def do_notify_rocketchat(module, domain, token, protocol, payload, is_pre740): if token.count("/") < 1: module.fail_json(msg="Invalid Token specified, provide a valid token") - rocketchat_incoming_webhook = ROCKETCHAT_INCOMING_WEBHOOK % (protocol, domain, token) + rocketchat_incoming_webhook = f"{protocol}://{domain}/hooks/{token}" headers = None if not is_pre740: diff --git a/plugins/modules/slack.py b/plugins/modules/slack.py index bf8d6a2780..13ef1caa4e 100644 --- a/plugins/modules/slack.py +++ b/plugins/modules/slack.py @@ -269,12 +269,6 @@ from urllib.parse import urlencode from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.urls import fetch_url -OLD_SLACK_INCOMING_WEBHOOK = "https://%s/services/hooks/incoming-webhook?token=%s" -SLACK_INCOMING_WEBHOOK = "https://hooks.%s/services/%s" -SLACK_POSTMESSAGE_WEBAPI = "https://%s/api/chat.postMessage" -SLACK_UPDATEMESSAGE_WEBAPI = "https://%s/api/chat.update" -SLACK_CONVERSATIONS_HISTORY_WEBAPI = "https://%s/api/conversations.history" - # Escaping quotes and apostrophes to avoid ending string prematurely in ansible call. # We do not escape other characters used as Slack metacharacters (e.g. &, <, >). escape_table = { @@ -402,7 +396,7 @@ def get_slack_message(module, domain, token, channel, ts): } ) domain = validate_slack_domain(domain) - url = f"{SLACK_CONVERSATIONS_HISTORY_WEBAPI % domain}?{qs}" + url = f"https://{domain}/api/conversations.history?{qs}" response, info = fetch_url(module=module, url=url, headers=headers, method="GET") if info["status"] != 200: module.fail_json(msg="failed to get slack message") @@ -421,10 +415,10 @@ def do_notify_slack(module, domain, token, payload): if token.count("/") >= 2: # New style webhook token domain = validate_slack_domain(domain) - slack_uri = SLACK_INCOMING_WEBHOOK % (domain, token) + slack_uri = f"https://hooks.{domain}/services/{token}" elif re.match(r"^xox[abp]-\S+$", token): domain = validate_slack_domain(domain) - slack_uri = (SLACK_UPDATEMESSAGE_WEBAPI if "ts" in payload else SLACK_POSTMESSAGE_WEBAPI) % domain + slack_uri = f"https://{domain}/api/{'chat.update' if 'ts' in payload else 'chat.postMessage'}" use_webapi = True else: if not domain: @@ -432,7 +426,7 @@ def do_notify_slack(module, domain, token, payload): msg="Slack has updated its webhook API. You need to specify a token of the form " "XXXX/YYYY/ZZZZ in your playbook" ) - slack_uri = OLD_SLACK_INCOMING_WEBHOOK % (domain, token) + slack_uri = f"https://{domain}/services/hooks/incoming-webhook?token={token}" headers = { "Content-Type": "application/json; charset=UTF-8", @@ -448,7 +442,7 @@ def do_notify_slack(module, domain, token, payload): if use_webapi: obscured_incoming_webhook = slack_uri else: - obscured_incoming_webhook = SLACK_INCOMING_WEBHOOK % (domain, "[obscured]") + obscured_incoming_webhook = f"https://hooks.{domain}/services/[obscured]" module.fail_json(msg=f" failed to send {data} to {obscured_incoming_webhook}: {info['msg']}") # each API requires different handling diff --git a/plugins/plugin_utils/_keys_filter.py b/plugins/plugin_utils/_keys_filter.py index 4a4c8e2714..c420d0aece 100644 --- a/plugins/plugin_utils/_keys_filter.py +++ b/plugins/plugin_utils/_keys_filter.py @@ -137,10 +137,8 @@ def _keys_filter_target_dict( tr = map(re.compile, before) return list(zip(tr, after)) except re.error as e: - msg = ( - "The attributes before must be valid regex if matching_parameter=regex." - " Not all items are valid regex in: %s" - ) - raise AnsibleFilterError(msg % before) from e + raise AnsibleFilterError( + f"The attributes before must be valid regex if matching_parameter=regex. Not all items are valid regex in: {before}" + ) from e else: return list(zip(before, after)) diff --git a/tests/unit/plugins/modules/test_rhsm_repository.py b/tests/unit/plugins/modules/test_rhsm_repository.py index 1925f4023f..4afa2bc0f4 100644 --- a/tests/unit/plugins/modules/test_rhsm_repository.py +++ b/tests/unit/plugins/modules/test_rhsm_repository.py @@ -45,12 +45,6 @@ class Repos: _SUBMAN_OUT_HEADER = """+----------------------------------------------------------+ Available Repositories in /etc/yum.repos.d/redhat.repo +----------------------------------------------------------+ -""" - _SUBMAN_OUT_ENTRY = """Repo ID: %s -Repo Name: %s -Repo URL: %s -Enabled: %s - """ def __init__(self, repos): @@ -62,11 +56,12 @@ Enabled: %s """ out = self._SUBMAN_OUT_HEADER for repo in self.repos: - out += self._SUBMAN_OUT_ENTRY % ( - repo["id"], - repo["name"], - repo["url"], - "1" if repo["enabled"] else "0", + out += ( + f"Repo ID: {repo['id']}\n" + f"Repo Name: {repo['name']}\n" + f"Repo URL: {repo['url']}\n" + f"Enabled: {'1' if repo['enabled'] else '0'}\n" + "\n" ) return out