From 0695babce0f08bc97de2495ecb12b0a5a40f84f5 Mon Sep 17 00:00:00 2001 From: Nicola Soranzo Date: Mon, 2 Dec 2024 12:51:56 +0000 Subject: [PATCH 1/2] Don't unnecessarily copy list in listify() --- lib/galaxy/util/__init__.py | 4 +++- test/unit/util/test_utils.py | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/galaxy/util/__init__.py b/lib/galaxy/util/__init__.py index ed39a98f9e54..7445a06bb3aa 100644 --- a/lib/galaxy/util/__init__.py +++ b/lib/galaxy/util/__init__.py @@ -1109,7 +1109,9 @@ def listify(item: Any, do_strip: bool = False) -> List: """ if not item: return [] - elif isinstance(item, (list, tuple)): + elif isinstance(item, list): + return item + elif isinstance(item, tuple): return list(item) elif isinstance(item, str) and item.count(","): if do_strip: diff --git a/test/unit/util/test_utils.py b/test/unit/util/test_utils.py index 81d448dd4a1a..7c0440f8cbed 100644 --- a/test/unit/util/test_utils.py +++ b/test/unit/util/test_utils.py @@ -122,7 +122,8 @@ def test_listify() -> None: assert util.listify("foo") == ["foo"] assert util.listify("foo, bar") == ["foo", " bar"] assert util.listify("foo, bar", do_strip=True) == ["foo", "bar"] - assert util.listify([1, 2, 3]) == [1, 2, 3] + list_ = [1, 2, 3] + assert util.listify(list_) is list_ assert util.listify((1, 2, 3)) == [1, 2, 3] s = {1, 2, 3} assert util.listify(s) == [s] From d09d0b30fe5cf03d4d01fb4449f4cf753a21a7b5 Mon Sep 17 00:00:00 2001 From: Nicola Soranzo Date: Mon, 2 Dec 2024 13:43:07 +0000 Subject: [PATCH 2/2] Fix UP031 errors - Part 4 Also: - Add type annotations. --- lib/galaxy/datatypes/util/maf_utilities.py | 29 +++++-------- lib/galaxy/model/security.py | 43 ++++++++++--------- lib/galaxy/model/store/discover.py | 2 +- lib/galaxy/schema/__init__.py | 12 +++--- lib/galaxy/security/validate_user_input.py | 6 +-- lib/galaxy/selenium/navigates_galaxy.py | 6 +-- lib/galaxy/selenium/scripts/dump_tour.py | 4 +- .../installed_repository_metadata_manager.py | 4 +- lib/galaxy/tool_shed/util/repository_util.py | 4 +- lib/galaxy/tool_util/client/staging.py | 4 +- lib/galaxy/tool_util/data/__init__.py | 5 +-- lib/galaxy/tool_util/deps/brew_exts.py | 2 +- lib/galaxy/tool_util/deps/docker_util.py | 2 +- lib/galaxy/tool_util/output_checker.py | 6 +-- lib/galaxy/tool_util/parser/xml.py | 6 +-- lib/galaxy/tool_util/provided_metadata.py | 2 +- lib/galaxy/tool_util/verify/__init__.py | 30 +++++++------ lib/galaxy/tool_util/verify/parse.py | 6 +-- lib/galaxy/tools/actions/upload_common.py | 4 +- lib/galaxy/tools/execute.py | 2 +- lib/galaxy/tools/parameters/__init__.py | 10 ++--- lib/galaxy/tools/parameters/basic.py | 6 +-- .../tools/parameters/dynamic_options.py | 8 +++- lib/galaxy/tools/util/galaxyops/__init__.py | 10 +---- lib/galaxy_test/selenium/test_stock_tours.py | 2 +- 25 files changed, 102 insertions(+), 113 deletions(-) diff --git a/lib/galaxy/datatypes/util/maf_utilities.py b/lib/galaxy/datatypes/util/maf_utilities.py index 8ed6f1670c5b..29b420d36e86 100644 --- a/lib/galaxy/datatypes/util/maf_utilities.py +++ b/lib/galaxy/datatypes/util/maf_utilities.py @@ -12,6 +12,7 @@ import tempfile from copy import deepcopy from errno import EMFILE +from typing import Dict import bx.align.maf import bx.interval_index_file @@ -137,26 +138,23 @@ class RegionAlignment: DNA_COMPLEMENT = maketrans("ACGTacgt", "TGCAtgca") MAX_SEQUENCE_SIZE = sys.maxsize # Maximum length of sequence allowed - def __init__(self, size, species=None, temp_file_handler=None): + def __init__(self, size: int, species=None, temp_file_handler=None): assert ( size <= self.MAX_SEQUENCE_SIZE - ), "Maximum length allowed for an individual sequence has been exceeded (%i > %i)." % ( - size, - self.MAX_SEQUENCE_SIZE, - ) + ), f"Maximum length allowed for an individual sequence has been exceeded ({size} > {self.MAX_SEQUENCE_SIZE})." species = species or [] self.size = size if not temp_file_handler: temp_file_handler = TempFileHandler() self.temp_file_handler = temp_file_handler - self.sequences = {} + self.sequences: Dict[str, int] = {} if not isinstance(species, list): species = [species] for spec in species: self.add_species(spec) # add a species to the alignment - def add_species(self, species): + def add_species(self, species: str): # make temporary sequence files file_index, fh = self.temp_file_handler.get_open_tempfile() self.sequences[species] = file_index @@ -176,13 +174,13 @@ def get_species_names(self, skip=None): return names # returns the sequence for a species - def get_sequence(self, species): + def get_sequence(self, species: str): file_index, fh = self.temp_file_handler.get_open_tempfile(self.sequences[species]) fh.seek(0) return fh.read() # returns the reverse complement of the sequence for a species - def get_sequence_reverse_complement(self, species): + def get_sequence_reverse_complement(self, species: str): complement = list(self.get_sequence(species).translate(self.DNA_COMPLEMENT)) complement.reverse() return "".join(complement) @@ -195,9 +193,9 @@ def set_position(self, index, species, base): # sets a range for a species - def set_range(self, index, species, bases): + def set_range(self, index: int, species: str, bases): if index >= self.size or index < 0: - raise Exception("Your index (%i) is out of range (0 - %i)." % (index, self.size - 1)) + raise Exception(f"Your index ({index}) is out of range (0 - {self.size - 1}).") if len(bases) == 0: raise Exception("A set of genomic positions can only have a positive length.") if species not in self.sequences.keys(): @@ -219,7 +217,7 @@ def flush(self, species=None): class GenomicRegionAlignment(RegionAlignment): def __init__(self, start, end, species=None, temp_file_handler=None): species = species or [] - RegionAlignment.__init__(self, end - start, species, temp_file_handler=temp_file_handler) + super().__init__(end - start, species, temp_file_handler=temp_file_handler) self.start = start self.end = end @@ -734,12 +732,7 @@ def remove_temp_index_file(index_filename): def get_fasta_header(component, attributes=None, suffix=None): attributes = attributes or {} - header = ">%s(%s):%i-%i|" % ( - component.src, - component.strand, - component.get_forward_strand_start(), - component.get_forward_strand_end(), - ) + header = f">{component.src}({component.strand}):{component.get_forward_strand_start()}-{component.get_forward_strand_end()}|" for key, value in attributes.items(): header = f"{header}{key}={value}|" if suffix: diff --git a/lib/galaxy/model/security.py b/lib/galaxy/model/security.py index 85fcb7be8532..d3b35c046b8b 100644 --- a/lib/galaxy/model/security.py +++ b/lib/galaxy/model/security.py @@ -367,17 +367,21 @@ def get_actions_for_items(self, trans, action, permission_items): if len(base_result) == len(new_result): common_result = set(base_result).intersection(new_result) if len(common_result) == len(base_result): - log.debug("Match on permissions for id %d" % item.library_dataset_id) + log.debug("Match on permissions for id %d", item.library_dataset_id) # TODO: Fix this failure message: else: log.debug( - "Error: dataset %d; originally: %s; now: %s" - % (item.library_dataset_id, base_result, new_result) + "Error: dataset %d; originally: %s; now: %s", + item.library_dataset_id, + base_result, + new_result, ) else: log.debug( - "Error: dataset %d: had %d entries, now %d entries" - % (item.library_dataset_id, len(base_result), len(new_result)) + "Error: dataset %d: had %d entries, now %d entries", + item.library_dataset_id, + len(base_result), + len(new_result), ) log.debug("get_actions_for_items: Test end") except Exception as e: @@ -431,9 +435,9 @@ def allow_action_on_libitems(self, trans, user_roles, action, items): for item in items: orig_value = self.allow_action(user_roles, action, item) if orig_value == ret_allow_action[item.id]: - log.debug("Item %d: success" % item.id) + log.debug("Item %d: success", item.id) else: - log.debug("Item %d: fail: original: %s; new: %s" % (item.id, orig_value, ret_allow_action[item.id])) + log.debug("Item %d: fail: original: %s; new: %s", item.id, orig_value, ret_allow_action[item.id]) log.debug("allow_action_for_items: test end") return ret_allow_action @@ -1394,9 +1398,9 @@ def show_library_item(self, user, roles, library_item, actions_to_check, hidden_ if can_show: return True, hidden_folder_ids if hidden_folder_ids: - hidden_folder_ids = "%s,%d" % (hidden_folder_ids, folder.id) + hidden_folder_ids = f"{hidden_folder_ids},{folder.id}" else: - hidden_folder_ids = "%d" % folder.id + hidden_folder_ids = f"{folder.id}" return False, hidden_folder_ids def get_showable_folders( @@ -1650,9 +1654,9 @@ def check_folder_contents(self, user, roles, folder, hidden_folder_ids=""): if can_access: return True, hidden_folder_ids if hidden_folder_ids: - hidden_folder_ids = "%s,%d" % (hidden_folder_ids, sub_folder.id) + hidden_folder_ids = f"{hidden_folder_ids},{sub_folder.id}" else: - hidden_folder_ids = "%d" % sub_folder.id + hidden_folder_ids = f"{sub_folder.id}" return False, hidden_folder_ids @@ -1690,7 +1694,7 @@ def allow_action(self, addr, action, **kwd): if action == self.permitted_actions.DATASET_ACCESS and action.action not in [ dp.action for dp in hda.dataset.actions ]: - log.debug("Allowing access to public dataset with hda: %i." % hda.id) + log.debug("Allowing access to public dataset with hda: %d.", hda.id) return True # dataset has no roles associated with the access permission, thus is already public stmt = ( select(HistoryDatasetAssociationDisplayAtAuthorization) @@ -1699,9 +1703,7 @@ def allow_action(self, addr, action, **kwd): ) hdadaa = self.sa_session.scalars(stmt).first() if not hdadaa: - log.debug( - "Denying access to private dataset with hda: %i. No hdadaa record for this dataset." % hda.id - ) + log.debug("Denying access to private dataset with hda: %d. No hdadaa record for this dataset.", hda.id) return False # no auth # We could just look up the reverse of addr, but then we'd also # have to verify it with the forward address and special case any @@ -1719,17 +1721,18 @@ def allow_action(self, addr, action, **kwd): pass # can't resolve, try next else: log.debug( - "Denying access to private dataset with hda: %i. Remote addr is not a valid server for site: %s." - % (hda.id, hdadaa.site) + "Denying access to private dataset with hda: %d. Remote addr is not a valid server for site: %s.", + hda.id, + hdadaa.site, ) return False # remote addr is not in the server list if (datetime.utcnow() - hdadaa.update_time) > timedelta(seconds=60): log.debug( - "Denying access to private dataset with hda: %i. Authorization was granted, but has expired." - % hda.id + "Denying access to private dataset with hda: %d. Authorization was granted, but has expired.", + hda.id, ) return False # not authz'd in the last 60 seconds - log.debug("Allowing access to private dataset with hda: %i. Remote server is: %s." % (hda.id, server)) + log.debug("Allowing access to private dataset with hda: %d. Remote server is: %s.", hda.id, server) return True else: raise Exception("The dataset access permission is the only valid permission in the host security agent.") diff --git a/lib/galaxy/model/store/discover.py b/lib/galaxy/model/store/discover.py index 043ede46f5ef..4bee49056c61 100644 --- a/lib/galaxy/model/store/discover.py +++ b/lib/galaxy/model/store/discover.py @@ -1050,7 +1050,7 @@ def raw_element_identifiers(self): identifiers = [] i = 0 while True: - key = "identifier_%d" % i + key = f"identifier_{i}" if key in self.as_dict: identifiers.append(self.as_dict.get(key)) else: diff --git a/lib/galaxy/schema/__init__.py b/lib/galaxy/schema/__init__.py index 9228622c8aca..b5dac468e512 100644 --- a/lib/galaxy/schema/__init__.py +++ b/lib/galaxy/schema/__init__.py @@ -1,4 +1,3 @@ -import typing from copy import deepcopy from datetime import datetime from enum import Enum @@ -6,6 +5,7 @@ Any, Callable, Dict, + Iterable, List, Optional, Tuple, @@ -136,19 +136,17 @@ def partial_model( if exclude is None: exclude = [] - @typing.no_type_check # Mypy doesn't understand pydantic's create_model def decorator(model: Type[T]) -> Type[T]: def make_optional(field: FieldInfo, default: Any = None) -> Tuple[Any, FieldInfo]: new = deepcopy(field) new.default = default - new.annotation = Optional[field.annotation or Any] + new.annotation = Optional[field.annotation or Any] # type:ignore[assignment] return new.annotation, new - fields = model.model_fields if include is None: - fields = fields.items() + fields: Iterable[Tuple[str, FieldInfo]] = model.model_fields.items() else: - fields = ((k, v) for k, v in fields.items() if k in include) + fields = ((k, v) for k, v in model.model_fields.items() if k in include) return create_model( model.__name__, @@ -159,6 +157,6 @@ def make_optional(field: FieldInfo, default: Any = None) -> Tuple[Any, FieldInfo for field_name, field_info in fields if exclude is None or field_name not in exclude }, - ) + ) # type:ignore[call-overload] return decorator diff --git a/lib/galaxy/security/validate_user_input.py b/lib/galaxy/security/validate_user_input.py index 9e6ed7d4afc3..40ce61a5cfeb 100644 --- a/lib/galaxy/security/validate_user_input.py +++ b/lib/galaxy/security/validate_user_input.py @@ -50,13 +50,13 @@ def validate_email_str(email): if not (VALID_EMAIL_RE.match(email)): return "The format of the email address is not correct." elif len(email) > EMAIL_MAX_LEN: - return "Email address cannot be more than %d characters in length." % EMAIL_MAX_LEN + return f"Email address cannot be more than {EMAIL_MAX_LEN} characters in length." return "" def validate_password_str(password): if not password or len(password) < PASSWORD_MIN_LEN: - return "Use a password of at least %d characters." % PASSWORD_MIN_LEN + return f"Use a password of at least {PASSWORD_MIN_LEN} characters." return "" @@ -65,7 +65,7 @@ def validate_publicname_str(publicname): if not publicname: return "Public name cannot be empty" if len(publicname) > PUBLICNAME_MAX_LEN: - return "Public name cannot be more than %d characters in length." % (PUBLICNAME_MAX_LEN) + return f"Public name cannot be more than {PUBLICNAME_MAX_LEN} characters in length." if not (VALID_PUBLICNAME_RE.match(publicname)): return "Public name must contain only lower-case letters, numbers, '.', '_' and '-'." return "" diff --git a/lib/galaxy/selenium/navigates_galaxy.py b/lib/galaxy/selenium/navigates_galaxy.py index 04a9372723e6..9bbcad46c587 100644 --- a/lib/galaxy/selenium/navigates_galaxy.py +++ b/lib/galaxy/selenium/navigates_galaxy.py @@ -100,7 +100,7 @@ class WAIT_TYPES: class NullTourCallback: - def handle_step(self, step, step_index): + def handle_step(self, step, step_index: int): pass @@ -1634,7 +1634,7 @@ def workflow_run_specify_inputs(self, inputs: Dict[str, Any]): workflow_run = self.components.workflow_run for label, value in inputs.items(): input_div_element = workflow_run.input_data_div(label=label).wait_for_visible() - self.select_set_value(input_div_element, "%d: " % value["hid"]) + self.select_set_value(input_div_element, "{}: ".format(value["hid"])) def workflow_run_submit(self): self.components.workflow_run.run_workflow.wait_for_and_click() @@ -2207,7 +2207,7 @@ def assert_message(self, element, contains=None): def assert_no_error_message(self): self.components._.messages.error.assert_absent_or_hidden() - def run_tour_step(self, step, step_index, tour_callback): + def run_tour_step(self, step, step_index: int, tour_callback): element_str = step.get("element", None) if element_str is None: component = step.get("component", None) diff --git a/lib/galaxy/selenium/scripts/dump_tour.py b/lib/galaxy/selenium/scripts/dump_tour.py index 825dc1dedb10..c87fb6628776 100755 --- a/lib/galaxy/selenium/scripts/dump_tour.py +++ b/lib/galaxy/selenium/scripts/dump_tour.py @@ -34,9 +34,9 @@ def __init__(self, driver_wrapper, output): self.driver_wrapper = driver_wrapper self.output = output - def handle_step(self, step, step_index): + def handle_step(self, step, step_index: int): time.sleep(0.5) - self.driver_wrapper.driver.save_screenshot("%s/%i.png" % (self.output, step_index)) + self.driver_wrapper.driver.save_screenshot(f"{self.output}/{step_index}.png") time.sleep(0.5) diff --git a/lib/galaxy/tool_shed/galaxy_install/metadata/installed_repository_metadata_manager.py b/lib/galaxy/tool_shed/galaxy_install/metadata/installed_repository_metadata_manager.py index 02272ddfe06f..10e191c509ef 100644 --- a/lib/galaxy/tool_shed/galaxy_install/metadata/installed_repository_metadata_manager.py +++ b/lib/galaxy/tool_shed/galaxy_install/metadata/installed_repository_metadata_manager.py @@ -178,12 +178,12 @@ def reset_metadata_on_selected_repositories(self, user, **kwd): except Exception: log.exception("Error attempting to reset metadata on repository %s", str(repository.name)) unsuccessful_count += 1 - message = "Successfully reset metadata on %d %s. " % ( + message = "Successfully reset metadata on {} {}. ".format( successful_count, inflector.cond_plural(successful_count, "repository"), ) if unsuccessful_count: - message += "Error setting metadata on %d %s - see the galaxy log for details. " % ( + message += "Error setting metadata on {} {} - see the galaxy log for details. ".format( unsuccessful_count, inflector.cond_plural(unsuccessful_count, "repository"), ) diff --git a/lib/galaxy/tool_shed/util/repository_util.py b/lib/galaxy/tool_shed/util/repository_util.py index 22f13cd57762..1a06be79c7dd 100644 --- a/lib/galaxy/tool_shed/util/repository_util.py +++ b/lib/galaxy/tool_shed/util/repository_util.py @@ -61,8 +61,8 @@ def check_for_updates( repository_names_not_updated.append(f"{escape(str(repository.name))}") if updated: updated_count += 1 - message = "Checked the status in the tool shed for %d repositories. " % success_count - message += "Updated the tool shed status for %d repositories. " % updated_count + message = f"Checked the status in the tool shed for {success_count} repositories. " + message += f"Updated the tool shed status for {updated_count} repositories. " if repository_names_not_updated: message += "Unable to retrieve status from the tool shed for the following repositories:\n" message += ", ".join(repository_names_not_updated) diff --git a/lib/galaxy/tool_util/client/staging.py b/lib/galaxy/tool_util/client/staging.py index ca165d41bdf8..3d4d6ca73080 100644 --- a/lib/galaxy/tool_util/client/staging.py +++ b/lib/galaxy/tool_util/client/staging.py @@ -169,10 +169,10 @@ def _attach_file(upload_payload: Dict[str, Any], uri: str, index: int = 0) -> No uri = path_or_uri_to_uri(uri) is_path = uri.startswith("file://") if not is_path or use_path_paste: - upload_payload["inputs"]["files_%d|url_paste" % index] = uri + upload_payload["inputs"][f"files_{index}|url_paste"] = uri else: path = uri[len("file://") :] - upload_payload["__files"]["files_%d|file_data" % index] = self._attach_file(path) + upload_payload["__files"][f"files_{index}|file_data"] = self._attach_file(path) if isinstance(upload_target, FileUploadTarget): file_path = upload_target.path diff --git a/lib/galaxy/tool_util/data/__init__.py b/lib/galaxy/tool_util/data/__init__.py index 8e7629192837..c91ea86e68ec 100644 --- a/lib/galaxy/tool_util/data/__init__.py +++ b/lib/galaxy/tool_util/data/__init__.py @@ -578,10 +578,7 @@ def parse_file_fields( if self.largest_index < len(fields): rval.append(fields) else: - line_error = ( - "Line %i in tool data table '%s' is invalid (HINT: '%s' characters must be used to separate fields):\n%s" - % ((i + 1), self.name, separator_char, line) - ) + line_error = f"Line {i + 1} in tool data table '{self.name}' is invalid (HINT: '{separator_char}' characters must be used to separate fields):\n{line}" if errors is not None: errors.append(line_error) log.warning(line_error) diff --git a/lib/galaxy/tool_util/deps/brew_exts.py b/lib/galaxy/tool_util/deps/brew_exts.py index ce2adb760743..053008e3d26e 100755 --- a/lib/galaxy/tool_util/deps/brew_exts.py +++ b/lib/galaxy/tool_util/deps/brew_exts.py @@ -525,7 +525,7 @@ def recipe_cellar_path(cellar_path, recipe, version): if revision_paths: revisions = (int(x.rsplit("_", 1)[-1]) for x in revision_paths) max_revision = max(revisions) - recipe_path = "%s_%d" % (recipe_base_path, max_revision) + recipe_path = f"{recipe_base_path}_{max_revision}" else: recipe_path = recipe_base_path return recipe_path diff --git a/lib/galaxy/tool_util/deps/docker_util.py b/lib/galaxy/tool_util/deps/docker_util.py index 96c7e29f38d1..f2a7da73e379 100644 --- a/lib/galaxy/tool_util/deps/docker_util.py +++ b/lib/galaxy/tool_util/deps/docker_util.py @@ -160,7 +160,7 @@ def build_docker_run_command( euid = os.geteuid() egid = os.getgid() - user = "%d:%d" % (euid, egid) + user = f"{euid}:{egid}" command_parts.extend(["--user", user]) full_image = image if tag: diff --git a/lib/galaxy/tool_util/output_checker.py b/lib/galaxy/tool_util/output_checker.py index ca6dc11be40f..71f9a7d32fcd 100644 --- a/lib/galaxy/tool_util/output_checker.py +++ b/lib/galaxy/tool_util/output_checker.py @@ -102,11 +102,7 @@ def check_output( code_desc = stdio_exit_code.desc if None is code_desc: code_desc = "" - desc = "%s: Exit code %d (%s)" % ( - StdioErrorLevel.desc(stdio_exit_code.error_level), - tool_exit_code, - code_desc, - ) + desc = f"{StdioErrorLevel.desc(stdio_exit_code.error_level)}: Exit code {tool_exit_code} ({code_desc})" reason = { "type": "exit_code", "desc": desc, diff --git a/lib/galaxy/tool_util/parser/xml.py b/lib/galaxy/tool_util/parser/xml.py index aba5a6874248..863a316e45df 100644 --- a/lib/galaxy/tool_util/parser/xml.py +++ b/lib/galaxy/tool_util/parser/xml.py @@ -995,8 +995,8 @@ def __pull_up_params(parent_elem, child_elem): parent_elem.append(param_elem) -def __prefix_join(prefix, name, index=None): - name = name if index is None else "%s_%d" % (name, index) +def __prefix_join(prefix, name, index: Optional[int] = None): + name = name if index is None else f"{name}_{index}" return name if not prefix else f"{prefix}|{name}" @@ -1072,7 +1072,7 @@ def __parse_param_elem(param_elem, i=0) -> ToolSourceTestInput: if composite_data_name is None: # Generate a unique name; each test uses a # fresh history. - composite_data_name = "_COMPOSITE_RENAMED_t%d_%s" % (i, uuid.uuid1().hex) + composite_data_name = f"_COMPOSITE_RENAMED_t{i}_{uuid.uuid1().hex}" elif child.tag == "metadata": attrib["metadata"][child.get("name")] = child.get("value") elif child.tag == "edit_attributes": diff --git a/lib/galaxy/tool_util/provided_metadata.py b/lib/galaxy/tool_util/provided_metadata.py index 48df3f6287ef..6d05ba0711ca 100644 --- a/lib/galaxy/tool_util/provided_metadata.py +++ b/lib/galaxy/tool_util/provided_metadata.py @@ -202,7 +202,7 @@ def get_new_datasets(self, output_name): def _elements_to_datasets(self, elements, level=0): for element in elements: - extra_kwds = {"identifier_%d" % level: element["name"]} + extra_kwds = {f"identifier_{level}": element["name"]} if "elements" in element: for inner_element in self._elements_to_datasets(element["elements"], level=level + 1): dataset = extra_kwds.copy() diff --git a/lib/galaxy/tool_util/verify/__init__.py b/lib/galaxy/tool_util/verify/__init__.py index 6ddfefeb69f8..7df77d647812 100644 --- a/lib/galaxy/tool_util/verify/__init__.py +++ b/lib/galaxy/tool_util/verify/__init__.py @@ -270,12 +270,10 @@ def files_delta(file1, file2, attributes=None): s1 = os.path.getsize(file1) s2 = os.path.getsize(file2) if abs(s1 - s2) > delta: - raise AssertionError( - "Files %s=%db but %s=%db - compare by size (delta=%s) failed" % (file1, s1, file2, s2, delta) - ) + raise AssertionError(f"Files {file1}={s1}b but {file2}={s2}b - compare by size (delta={delta}) failed") if delta_frac is not None and not (s1 - (s1 * delta_frac) <= s2 <= s1 + (s1 * delta_frac)): raise AssertionError( - "Files %s=%db but %s=%db - compare by size (delta_frac=%s) failed" % (file1, s1, file2, s2, delta_frac) + f"Files {file1}={s1}b but {file2}={s2}b - compare by size (delta_frac={delta_frac}) failed" ) @@ -365,8 +363,12 @@ def get_lines_diff(diff): if not valid_diff: invalid_diff_lines += 1 log.info( - "## files diff on '%s' and '%s': lines_diff = %d, found diff = %d, found pdf invalid diff = %d" - % (file1, file2, allowed_diff_count, diff_lines, invalid_diff_lines) + "## files diff on '%s' and '%s': lines_diff = %d, found diff = %d, found pdf invalid diff = %d", + file1, + file2, + allowed_diff_count, + diff_lines, + invalid_diff_lines, ) if invalid_diff_lines > allowed_diff_count: # Print out diff_slice so we can see what failed @@ -374,8 +376,11 @@ def get_lines_diff(diff): raise AssertionError("".join(diff_slice)) else: log.info( - "## files diff on '%s' and '%s': lines_diff = %d, found diff = %d" - % (file1, file2, allowed_diff_count, diff_lines) + "## files diff on '%s' and '%s': lines_diff = %d, found diff = %d", + file1, + file2, + allowed_diff_count, + diff_lines, ) raise AssertionError("".join(diff_slice)) @@ -398,10 +403,9 @@ def files_re_match(file1, file2, attributes=None): history_data = fh.readlines() with open(file1, "rb") as fh: local_file = fh.readlines() - assert len(local_file) == len(history_data), ( - "Data File and Regular Expression File contain a different number of lines (%d != %d)\nHistory Data (first 40 lines):\n%s" - % (len(local_file), len(history_data), join_char.join(history_data[:40])) - ) + assert len(local_file) == len( + history_data + ), f"Data File and Regular Expression File contain a different number of lines ({len(local_file)} != {len(history_data)})\nHistory Data (first 40 lines):\n{join_char.join(history_data[:40])}" if attributes.get("sort", False): history_data.sort() local_file.sort() @@ -416,7 +420,7 @@ def files_re_match(file1, file2, attributes=None): diffs.append(f"Regular Expression: {regex_line}, Data file: {data_line}\n") if line_diff_count > lines_diff: raise AssertionError( - "Regular expression did not match data file (allowed variants=%i):\n%s" % (lines_diff, "".join(diffs)) + "Regular expression did not match data file (allowed variants={}):\n{}".format(lines_diff, "".join(diffs)) ) diff --git a/lib/galaxy/tool_util/verify/parse.py b/lib/galaxy/tool_util/verify/parse.py index 8dd51f525944..dd196f5d9899 100644 --- a/lib/galaxy/tool_util/verify/parse.py +++ b/lib/galaxy/tool_util/verify/parse.py @@ -342,7 +342,7 @@ def __init__(self, name: str, parent_context: AnyParamContext, index: Optional[i self.allow_unqualified_access = parent_context.allow_unqualified_access def for_state(self) -> str: - name = self.name if self.index is None else "%s_%d" % (self.name, self.index) + name = self.name if self.index is None else f"{self.name}_{self.index}" parent_for_state = self.parent_context.for_state() if parent_for_state: return f"{parent_for_state}|{name}" @@ -358,11 +358,11 @@ def param_names(self): else: for parent_context_param in self.parent_context.param_names(): if self.index is not None: - yield "%s|%s_%d" % (parent_context_param, self.name, self.index) + yield f"{parent_context_param}|{self.name}_{self.index}" else: yield f"{parent_context_param}|{self.name}" if self.index is not None: - yield "%s_%d" % (self.name, self.index) + yield f"{self.name}_{self.index}" else: yield self.name diff --git a/lib/galaxy/tools/actions/upload_common.py b/lib/galaxy/tools/actions/upload_common.py index 1d6d1b9a4c10..924bdc64a3b5 100644 --- a/lib/galaxy/tools/actions/upload_common.py +++ b/lib/galaxy/tools/actions/upload_common.py @@ -415,7 +415,7 @@ def create_job(trans, params, tool, json_file_path, outputs, folder=None, histor job.add_parameter(name, value) job.add_parameter("paramfile", dumps(json_file_path)) for i, output_object in enumerate(outputs): - output_name = "output%i" % i + output_name = f"output{i}" if hasattr(output_object, "collection"): job.add_output_dataset_collection(output_name, output_object) output_object.job = job @@ -434,7 +434,7 @@ def create_job(trans, params, tool, json_file_path, outputs, folder=None, histor output = {} for i, v in enumerate(outputs): if not hasattr(output_object, "collection_type"): - output["output%i" % i] = v + output[f"output{i}"] = v return job, output diff --git a/lib/galaxy/tools/execute.py b/lib/galaxy/tools/execute.py index 31369c948052..7cd2d814bac2 100644 --- a/lib/galaxy/tools/execute.py +++ b/lib/galaxy/tools/execute.py @@ -325,7 +325,7 @@ def record_error(self, error): def on_text(self) -> Optional[str]: collection_info = self.collection_info if self._on_text is None and collection_info is not None: - collection_names = ["collection %d" % c.hid for c in collection_info.collections.values()] + collection_names = [f"collection {c.hid}" for c in collection_info.collections.values()] self._on_text = on_text_for_names(collection_names) return self._on_text diff --git a/lib/galaxy/tools/parameters/__init__.py b/lib/galaxy/tools/parameters/__init__.py index ee3a8709817d..eb66a5bc1d25 100644 --- a/lib/galaxy/tools/parameters/__init__.py +++ b/lib/galaxy/tools/parameters/__init__.py @@ -206,8 +206,8 @@ def get_current_case(input, input_values): values = input_values[input.name] = input_values.get(input.name, []) for i, d in enumerate(values): d["__index__"] = i - new_name_prefix = name_prefix + "%s_%d|" % (input.name, i) - new_label_prefix = label_prefix + "%s %d > " % (input.title, i + 1) + new_name_prefix = name_prefix + f"{input.name}_{i}|" + new_label_prefix = label_prefix + f"{input.title} {i + 1} > " visit_input_values( input.inputs, d, @@ -356,7 +356,7 @@ def params_to_incoming(incoming, inputs, input_values, app, name_prefix=""): if isinstance(input, Repeat) or isinstance(input, UploadDataset): for d in input_values[input.name]: index = d["__index__"] - new_name_prefix = name_prefix + "%s_%d|" % (input.name, index) + new_name_prefix = name_prefix + f"{input.name}_{index}|" params_to_incoming(incoming, input.inputs, d, app, new_name_prefix) elif isinstance(input, Conditional): values = input_values[input.name] @@ -545,7 +545,7 @@ def _populate_state_legacy( rep_index = 0 del group_state[:] while True: - rep_prefix = "%s_%d" % (key, rep_index) + rep_prefix = f"{key}_{rep_index}" rep_min_default = repeat_input.default if repeat_input.default > repeat_input.min else repeat_input.min if ( not any(incoming_key.startswith(rep_prefix) for incoming_key in incoming.keys()) @@ -632,7 +632,7 @@ def _populate_state_legacy( group_state.append(new_state_upload) for rep_index, rep_state in enumerate(group_state): rep_index = rep_state.get("__index__", rep_index) - rep_prefix = "%s_%d|" % (key, rep_index) + rep_prefix = f"{key}_{rep_index}|" _populate_state_legacy( request_context, dataset_input.inputs, diff --git a/lib/galaxy/tools/parameters/basic.py b/lib/galaxy/tools/parameters/basic.py index 6b35473959e4..6f2e5e9965fd 100644 --- a/lib/galaxy/tools/parameters/basic.py +++ b/lib/galaxy/tools/parameters/basic.py @@ -2004,10 +2004,10 @@ def do_validate(v): if self.min is not None: if self.min > dataset_count: - raise ValueError("At least %d datasets are required for %s" % (self.min, self.name)) + raise ValueError(f"At least {self.min} datasets are required for {self.name}") if self.max is not None: if self.max < dataset_count: - raise ValueError("At most %d datasets are required for %s" % (self.max, self.name)) + raise ValueError(f"At most {self.max} datasets are required for {self.name}") def src_id_to_item( @@ -2520,7 +2520,7 @@ def to_text(self, value): if isinstance(value, HistoryDatasetCollectionAssociation): display_text = f"{value.hid}: {value.name}" else: - display_text = "Element %d:%s" % (value.identifier_index, value.identifier_name) + display_text = f"Element {value.identifier_index}:{value.identifier_name}" except AttributeError: display_text = "No dataset collection." return display_text diff --git a/lib/galaxy/tools/parameters/dynamic_options.py b/lib/galaxy/tools/parameters/dynamic_options.py index 452e058ff263..bb5f070bd60b 100644 --- a/lib/galaxy/tools/parameters/dynamic_options.py +++ b/lib/galaxy/tools/parameters/dynamic_options.py @@ -745,8 +745,12 @@ def parse_file_fields(self, reader): name = "a configuration file" # Perhaps this should be an error, but even a warning is useful. log.warning( - "Inconsistent number of fields (%i vs %i) in %s using separator %r, check line: %r" - % (field_count, len(fields), name, self.separator, line) + "Inconsistent number of fields (%i vs %i) in %s using separator %r, check line: %r", + field_count, + len(fields), + name, + self.separator, + line, ) rval.append(fields) return rval diff --git a/lib/galaxy/tools/util/galaxyops/__init__.py b/lib/galaxy/tools/util/galaxyops/__init__.py index 3dc2537d6406..1f0859db99b4 100644 --- a/lib/galaxy/tools/util/galaxyops/__init__.py +++ b/lib/galaxy/tools/util/galaxyops/__init__.py @@ -35,16 +35,10 @@ def parse_cols_arg(cols): def default_printer(stream, exc, obj): - print("%d: %s" % (obj.linenum, obj.current_line), file=stream) + print(f"{obj.linenum}: {obj.current_line}", file=stream) print(f"\tError: {unicodify(exc)}", file=stream) def skipped(reader, filedesc=""): first_line, line_contents, problem = reader.skipped_lines[0] - return 'Skipped %d invalid lines%s, 1st line #%d: "%s", problem: %s' % ( - reader.skipped, - filedesc, - first_line, - line_contents, - problem, - ) + return f'Skipped {reader.skipped} invalid lines{filedesc}, 1st line #{first_line}: "{line_contents}", problem: {problem}' diff --git a/lib/galaxy_test/selenium/test_stock_tours.py b/lib/galaxy_test/selenium/test_stock_tours.py index 943733eb3b33..9cb47e11a177 100644 --- a/lib/galaxy_test/selenium/test_stock_tours.py +++ b/lib/galaxy_test/selenium/test_stock_tours.py @@ -50,5 +50,5 @@ class TourCallback: def __init__(self, test_case: TestStockToursTestCase): self.test_case = test_case - def handle_step(self, step, step_index): + def handle_step(self, step, step_index: int): self.test_case.assert_baseline_accessibility()