diff --git a/lib/galaxy/authnz/managers.py b/lib/galaxy/authnz/managers.py index 3fca049269f..0eaf0a9e59a 100644 --- a/lib/galaxy/authnz/managers.py +++ b/lib/galaxy/authnz/managers.py @@ -75,8 +75,8 @@ class AuthnzManager: for child in root: if child.tag != "Setter": log.error( - "Expect a node with `Setter` tag, found a node with `{}` tag instead; " - "skipping this node.".format(child.tag) + "Expect a node with `Setter` tag, found a node with `%s` tag instead; skipping this node.", + child.tag, ) continue if "Property" not in child.attrib or "Value" not in child.attrib or "Type" not in child.attrib: @@ -118,8 +118,8 @@ class AuthnzManager: for child in root: if child.tag != "provider": log.error( - "Expect a node with `provider` tag, found a node with `{}` tag instead; " - "skipping the node.".format(child.tag) + "Expect a node with `provider` tag, found a node with `%s` tag instead; skipping the node.", + child.tag, ) continue if "name" not in child.attrib: @@ -268,18 +268,22 @@ class AuthnzManager: config["id_token"] = cloudauthz.authn.get_id_token(strategy) except requests.exceptions.HTTPError as e: msg = ( - "Sign-out from Galaxy and remove its access from `{}`, then log back in using `{}` " - "account.".format(self._unify_provider_name(cloudauthz.authn.provider), cloudauthz.authn.uid) + f"Sign-out from Galaxy and remove its access from `{self._unify_provider_name(cloudauthz.authn.provider)}`, " + "then log back in using `{cloudauthz.authn.uid}` account." ) log.debug( - "Failed to get/refresh ID token for user with ID `{}` for assuming authz_id `{}`. " + "Failed to get/refresh ID token for user with ID `%s` for assuming authz_id `%s`. " "User may not have a refresh token. If the problem persists, set the `prompt` key to " - "`consent` in `oidc_backends_config.xml`, then restart Galaxy and ask user to: {}" - "Error Message: `{}`".format(user_id, cloudauthz.id, msg, e.response.text) + "`consent` in `oidc_backends_config.xml`, then restart Galaxy and ask user to: %s" + "Error Message: `%s`", + user_id, + cloudauthz.id, + msg, + e.response.text, ) raise exceptions.AuthenticationFailed( - err_msg="An error occurred getting your ID token. {}. If the problem persists, please " - "contact Galaxy admin.".format(msg) + err_msg=f"An error occurred getting your ID token. {msg}. If the problem persists, please " + "contact Galaxy admin." ) return config @@ -287,14 +291,13 @@ class AuthnzManager: def can_user_assume_authn(trans, authn_id): qres = trans.sa_session.query(model.UserAuthnzToken).get(authn_id) if qres is None: - msg = "Authentication record with the given `authn_id` (`{}`) not found.".format( - trans.security.encode_id(authn_id) - ) + msg = f"Authentication record with the given `authn_id` (`{trans.security.encode_id(authn_id)}`) not found." log.debug(msg) raise exceptions.ObjectNotFound(msg) if qres.user_id != trans.user.id: - msg = "The request authentication with ID `{}` is not accessible to user with ID " "`{}`.".format( - trans.security.encode_id(authn_id), trans.security.encode_id(trans.user.id) + msg = ( + f"The request authentication with ID `{trans.security.encode_id(authn_id)}` is not accessible to user with ID " + f"`{trans.security.encode_id(trans.user.id)}`." ) log.warning(msg) raise exceptions.ItemAccessibilityException(msg) @@ -322,8 +325,8 @@ class AuthnzManager: raise exceptions.ObjectNotFound("An authorization configuration with given ID not found.") if user_id != qres.user_id: msg = ( - "The request authorization configuration (with ID:`{}`) is not accessible for user with " - "ID:`{}`.".format(qres.id, user_id) + f"The request authorization configuration (with ID:`{qres.id}`) is not accessible for user with " + f"ID:`{user_id}`." ) log.warning(msg) raise exceptions.ItemAccessibilityException(msg) @@ -499,11 +502,7 @@ class AuthnzManager: return backend.disconnect(provider, trans, email, disconnect_redirect_url) return backend.disconnect(provider, trans, disconnect_redirect_url) except Exception: - msg = ( - "An error occurred when disconnecting authentication with `{}` identity provider for user `{}`".format( - provider, trans.user.username - ) - ) + msg = f"An error occurred when disconnecting authentication with `{provider}` identity provider for user `{trans.user.username}`" log.exception(msg) return False, msg, None @@ -543,9 +542,9 @@ class AuthnzManager: try: ca = CloudAuthz() log.info( - "Requesting credentials using CloudAuthz with config id `{}` on be half of user `{}`.".format( - cloudauthz.id, user_id - ) + "Requesting credentials using CloudAuthz with config id `%s` on be half of user `%s`.", + cloudauthz.id, + user_id, ) credentials = ca.authorize(cloudauthz.provider, config) return credentials @@ -594,8 +593,9 @@ class AuthnzManager: ) credentials = self.get_cloud_access_credentials(cloudauthz, sa_session, user_id, request) log.info( - "Writing credentials generated using CloudAuthz with config id `{}` to the following file: `{}`" - "".format(cloudauthz.id, filename) + "Writing credentials generated using CloudAuthz with config id `%s` to the following file: `%s`", + cloudauthz.id, + filename, ) with open(filename, "w") as f: f.write(json.dumps(credentials)) diff --git a/lib/galaxy/config/__init__.py b/lib/galaxy/config/__init__.py index ff3ea85a5ae..75c78f04c09 100644 --- a/lib/galaxy/config/__init__.py +++ b/lib/galaxy/config/__init__.py @@ -539,8 +539,12 @@ class BaseAppConfiguration(HasDynamicProperties): if self._path_exists(new_path): # That's a bingo! resolves_to = self.schema.paths_to_resolve.get(key) log.warning( - "Paths for the '{0}' option should be relative to '{1}'. To suppress this warning, " - "move '{0}' into '{1}', or set it's value to an absolute path.".format(key, resolves_to) + "Paths for the '%s' option should be relative to '%s'. To suppress this warning, " + "move '%s' into '%s', or set its value to an absolute path.", + key, + resolves_to, + key, + resolves_to, ) return new_path return current_path diff --git a/lib/galaxy/config/schema.py b/lib/galaxy/config/schema.py index cc090f3954c..10659cb76d6 100644 --- a/lib/galaxy/config/schema.py +++ b/lib/galaxy/config/schema.py @@ -92,8 +92,8 @@ class AppSchema(Schema): def check_exists(option, key): if not option: message = ( - "Invalid schema: property '{}' listed as path resolution target " - "for '{}' does not exist".format(resolves_to, key) + f"Invalid schema: property '{resolves_to}' listed as path resolution target " + f"for '{key}' does not exist" ) raise_error(message) diff --git a/lib/galaxy/datatypes/sequence.py b/lib/galaxy/datatypes/sequence.py index a727e167d91..c88abfcde5c 100644 --- a/lib/galaxy/datatypes/sequence.py +++ b/lib/galaxy/datatypes/sequence.py @@ -277,14 +277,7 @@ class Sequence(data.Text): start_chunk = -1 # extract, unzip, trim, recompress result.append( - "(dd bs=1 skip={} count={} if={} 2> /dev/null )| zcat | ( tail -n +{} 2> /dev/null) | head -{} | gzip -c >> {}".format( - start_copy, - end_copy - start_copy, - input_name, - skip_sequences * 4 + 1, - sequences_to_extract * 4, - output_name, - ) + f"(dd bs=1 skip={start_copy} count={end_copy - start_copy} if={input_name} 2> /dev/null )| zcat | ( tail -n +{skip_sequences * 4 + 1} 2> /dev/null) | head -{sequences_to_extract * 4} | gzip -c >> {output_name}" ) else: # whole section - add it to the start_chunk/end_chunk accumulator if start_chunk == -1: diff --git a/lib/galaxy/datatypes/sniff.py b/lib/galaxy/datatypes/sniff.py index 6fae059a47c..07c9026bdee 100644 --- a/lib/galaxy/datatypes/sniff.py +++ b/lib/galaxy/datatypes/sniff.py @@ -24,7 +24,6 @@ from typing import ( from typing_extensions import Protocol -from galaxy import util from galaxy.files.uris import stream_url_to_file as files_stream_url_to_file from galaxy.util import ( compression_utils, @@ -837,9 +836,7 @@ def handle_compressed_file( except OSError as e: os.remove(uncompressed.name) raise OSError( - "Problem uncompressing {} data, please try retrieving the data uncompressed: {}".format( - compressed_type, util.unicodify(e) - ) + f"Problem uncompressing {compressed_type} data, please try retrieving the data uncompressed: {e}" ) finally: is_compressed = False diff --git a/lib/galaxy/datatypes/upload_util.py b/lib/galaxy/datatypes/upload_util.py index 2fcc8739a4e..e83400f2c04 100644 --- a/lib/galaxy/datatypes/upload_util.py +++ b/lib/galaxy/datatypes/upload_util.py @@ -101,8 +101,8 @@ def handle_upload( if registry.is_extension_unsniffable_binary(upload_ext): stdout = ( "Warning: The file's datatype cannot be determined from its contents and was guessed based on" - " its extension, to avoid this warning, manually set the file 'Type' to '{ext}' when uploading" - " this type of file".format(ext=upload_ext) + f" its extension, to avoid this warning, manually set the file 'Type' to '{upload_ext}' when uploading" + " this type of file" ) ext = upload_ext else: diff --git a/lib/galaxy/dependencies/dev-requirements.txt b/lib/galaxy/dependencies/dev-requirements.txt index a56cad0c8c3..23bbb7c2568 100644 --- a/lib/galaxy/dependencies/dev-requirements.txt +++ b/lib/galaxy/dependencies/dev-requirements.txt @@ -45,8 +45,8 @@ httpcore==1.0.4 ; python_version >= "3.8" and python_version < "3.13" httpx==0.27.0 ; python_version >= "3.8" and python_version < "3.13" idna==3.6 ; python_version >= "3.8" and python_version < "3.13" imagesize==1.4.1 ; python_version >= "3.8" and python_version < "3.13" -importlib-metadata==7.0.1 ; python_version >= "3.8" and python_version < "3.13" -importlib-resources==6.1.2 ; python_version >= "3.8" and python_version < "3.10" +importlib-metadata==7.0.2 ; python_version >= "3.8" and python_version < "3.13" +importlib-resources==6.1.3 ; python_version >= "3.8" and python_version < "3.10" iniconfig==2.0.0 ; python_version >= "3.8" and python_version < "3.13" isodate==0.6.1 ; python_version >= "3.8" and python_version < "3.13" isort==5.13.2 ; python_version >= "3.8" and python_version < "3.13" @@ -76,13 +76,13 @@ nh3==0.2.15 ; python_version >= "3.8" and python_version < "3.13" numpy==1.24.4 ; python_version >= "3.8" and python_version < "3.9" numpy==1.26.4 ; python_version >= "3.9" and python_version < "3.13" outcome==1.3.0.post0 ; python_version >= "3.8" and python_version < "3.13" -packaging==23.2 ; python_version >= "3.8" and python_version < "3.13" +packaging==24.0 ; python_version >= "3.8" and python_version < "3.13" pathspec==0.12.1 ; python_version >= "3.8" and python_version < "3.13" pillow==10.2.0 ; python_version >= "3.8" and python_version < "3.13" pkce==1.0.3 ; python_version >= "3.8" and python_version < "3.13" pkginfo==1.10.0 ; python_version >= "3.8" and python_version < "3.13" platformdirs==4.2.0 ; python_version >= "3.8" and python_version < "3.13" -playwright==1.41.2 ; python_version >= "3.8" and python_version < "3.13" +playwright==1.42.0 ; python_version >= "3.8" and python_version < "3.13" pluggy==1.4.0 ; python_version >= "3.8" and python_version < "3.13" port-for==0.7.2 ; python_version >= "3.8" and python_version < "3.13" prettytable==3.10.0 ; python_version >= "3.8" and python_version < "3.13" @@ -95,10 +95,10 @@ pygithub==2.2.0 ; python_version >= "3.8" and python_version < "3.13" pygments==2.17.2 ; python_version >= "3.8" and python_version < "3.13" pyjwt[crypto]==2.8.0 ; python_version >= "3.8" and python_version < "3.13" pynacl==1.5.0 ; python_version >= "3.8" and python_version < "3.13" -pyparsing==3.1.1 ; python_version >= "3.8" and python_version < "3.13" +pyparsing==3.1.2 ; python_version >= "3.8" and python_version < "3.13" pyproject-hooks==1.0.0 ; python_version >= "3.8" and python_version < "3.13" pysocks==1.7.1 ; python_version >= "3.8" and python_version < "3.13" -pytest-asyncio==0.23.5 ; python_version >= "3.8" and python_version < "3.13" +pytest-asyncio==0.23.5.post1 ; python_version >= "3.8" and python_version < "3.13" pytest-base-url==2.1.0 ; python_version >= "3.8" and python_version < "3.13" pytest-celery==0.0.0 ; python_version >= "3.8" and python_version < "3.13" pytest-cov==4.1.0 ; python_version >= "3.8" and python_version < "3.13" @@ -108,7 +108,7 @@ pytest-json-report==1.5.0 ; python_version >= "3.8" and python_version < "3.13" pytest-metadata==3.1.1 ; python_version >= "3.8" and python_version < "3.13" pytest-mock==3.12.0 ; python_version >= "3.8" and python_version < "3.13" pytest-playwright==0.4.4 ; python_version >= "3.8" and python_version < "3.13" -pytest-postgresql==5.1.0 ; python_version >= "3.8" and python_version < "3.13" +pytest-postgresql==5.1.1 ; python_version >= "3.8" and python_version < "3.13" pytest-shard==0.1.2 ; python_version >= "3.8" and python_version < "3.13" pytest==7.4.4 ; python_version >= "3.8" and python_version < "3.13" python-dateutil==2.9.0.post0 ; python_version >= "3.8" and python_version < "3.13" @@ -155,7 +155,7 @@ tomli==2.0.1 ; python_version >= "3.8" and python_full_version <= "3.11.0a6" trio-websocket==0.11.1 ; python_version >= "3.8" and python_version < "3.13" trio==0.24.0 ; python_version >= "3.8" and python_version < "3.13" tuspy==1.0.3 ; python_version >= "3.8" and python_version < "3.13" -twill==3.2.2 ; python_version >= "3.8" and python_version < "3.13" +twill==3.2.3 ; python_version >= "3.8" and python_version < "3.13" twine==5.0.0 ; python_version >= "3.8" and python_version < "3.13" typing-extensions==4.10.0 ; python_version >= "3.8" and python_version < "3.13" tzdata==2024.1 ; python_version >= "3.8" and python_version < "3.13" diff --git a/lib/galaxy/dependencies/pinned-lint-requirements.txt b/lib/galaxy/dependencies/pinned-lint-requirements.txt index 6f7b4d23333..5535c679d0b 100644 --- a/lib/galaxy/dependencies/pinned-lint-requirements.txt +++ b/lib/galaxy/dependencies/pinned-lint-requirements.txt @@ -4,4 +4,4 @@ flake8-bugbear==24.2.6 mccabe==0.7.0 pycodestyle==2.11.1 pyflakes==3.2.0 -ruff==0.3.0 +ruff==0.3.2 diff --git a/lib/galaxy/dependencies/pinned-requirements.txt b/lib/galaxy/dependencies/pinned-requirements.txt index 606b59c2be5..003b60c29a0 100644 --- a/lib/galaxy/dependencies/pinned-requirements.txt +++ b/lib/galaxy/dependencies/pinned-requirements.txt @@ -2,7 +2,7 @@ a2wsgi==1.10.2 ; python_version >= "3.8" and python_version < "3.13" adal==1.2.7 ; python_version >= "3.8" and python_version < "3.13" -aiobotocore==2.12.0 ; python_version >= "3.8" and python_version < "3.13" +aiobotocore==2.12.1 ; python_version >= "3.8" and python_version < "3.13" aiodataloader==0.4.0 ; python_version >= "3.8" and python_version < "3.13" aiofiles==23.2.1 ; python_version >= "3.8" and python_version < "3.13" aiohttp==3.9.3 ; python_version >= "3.8" and python_version < "3.13" @@ -16,7 +16,7 @@ anyio==4.3.0 ; python_version >= "3.8" and python_version < "3.13" apispec==6.5.0 ; python_version >= "3.8" and python_version < "3.13" appdirs==1.4.4 ; python_version >= "3.8" and python_version < "3.13" arcp==0.2.1 ; python_version >= "3.8" and python_version < "3.13" -argcomplete==3.2.2 ; python_version >= "3.8" and python_version < "3.13" +argcomplete==3.2.3 ; python_version >= "3.8" and python_version < "3.13" async-timeout==4.0.3 ; python_version >= "3.8" and python_version < "3.11" attmap==0.13.2 ; python_version >= "3.8" and python_version < "3.13" attrs==23.2.0 ; python_version >= "3.8" and python_version < "3.13" @@ -87,8 +87,8 @@ h5grove==2.0.0 ; python_version >= "3.8" and python_version < "3.13" h5py==3.10.0 ; python_version >= "3.8" and python_version < "3.13" humanfriendly==10.0 ; python_version >= "3.8" and python_version < "3.13" idna==3.6 ; python_version >= "3.8" and python_version < "3.13" -importlib-metadata==7.0.1 ; python_version >= "3.8" and python_version < "3.13" -importlib-resources==6.1.2 ; python_version >= "3.8" and python_version < "3.9" +importlib-metadata==7.0.2 ; python_version >= "3.8" and python_version < "3.13" +importlib-resources==6.1.3 ; python_version >= "3.8" and python_version < "3.9" isa-rwval==0.10.10 ; python_version >= "3.8" and python_version < "3.13" isal==1.6.0 ; python_version >= "3.8" and python_version < "3.13" isodate==0.6.1 ; python_version >= "3.8" and python_version < "3.13" @@ -119,7 +119,7 @@ numpy==1.26.4 ; python_version >= "3.9" and python_version < "3.13" oauthlib==3.2.2 ; python_version >= "3.8" and python_version < "3.13" orjson==3.9.15 ; python_version >= "3.8" and python_version < "3.13" oyaml==1.0 ; python_version >= "3.8" and python_version < "3.13" -packaging==23.2 ; python_version >= "3.8" and python_version < "3.13" +packaging==24.0 ; python_version >= "3.8" and python_version < "3.13" paramiko==3.4.0 ; python_version >= "3.8" and python_version < "3.13" parsley==1.3 ; python_version >= "3.8" and python_version < "3.13" paste==3.7.1 ; python_version >= "3.8" and python_version < "3.13" @@ -147,7 +147,7 @@ pyjwt[crypto]==2.8.0 ; python_version >= "3.8" and python_version < "3.13" pykwalify==1.8.0 ; python_version >= "3.8" and python_version < "3.13" pylibmagic==0.5.0 ; python_version >= "3.8" and python_version < "3.13" pynacl==1.5.0 ; python_version >= "3.8" and python_version < "3.13" -pyparsing==3.1.1 ; python_version >= "3.8" and python_version < "3.13" +pyparsing==3.1.2 ; python_version >= "3.8" and python_version < "3.13" pyreadline3==3.4.1 ; sys_platform == "win32" and python_version >= "3.8" and python_version < "3.13" pysam==0.22.0 ; python_version >= "3.8" and python_version < "3.13" python-dateutil==2.9.0.post0 ; python_version >= "3.8" and python_version < "3.13" @@ -179,10 +179,10 @@ setuptools==69.1.1 ; python_version >= "3.8" and python_version < "3.13" shellescape==3.8.1 ; python_version >= "3.8" and python_version < "3.13" six==1.16.0 ; python_version >= "3.8" and python_version < "3.13" sniffio==1.3.1 ; python_version >= "3.8" and python_version < "3.13" -social-auth-core[openidconnect]==4.5.3 ; python_version >= "3.8" and python_version < "3.13" +social-auth-core==4.5.3 ; python_version >= "3.8" and python_version < "3.13" sortedcontainers==2.4.0 ; python_version >= "3.8" and python_version < "3.13" spython==0.3.13 ; python_version >= "3.8" and python_version < "3.13" -sqlalchemy==1.4.51 ; python_version >= "3.8" and python_version < "3.13" +sqlalchemy==1.4.52 ; python_version >= "3.8" and python_version < "3.13" sqlitedict==2.1.0 ; python_version >= "3.8" and python_version < "3.13" sqlparse==0.4.4 ; python_version >= "3.8" and python_version < "3.13" starlette-context==0.3.6 ; python_version >= "3.8" and python_version < "3.13" diff --git a/lib/galaxy/dependencies/pinned-typecheck-requirements.txt b/lib/galaxy/dependencies/pinned-typecheck-requirements.txt index e39291a2e71..877c102c0d2 100644 --- a/lib/galaxy/dependencies/pinned-typecheck-requirements.txt +++ b/lib/galaxy/dependencies/pinned-typecheck-requirements.txt @@ -3,7 +3,7 @@ cffi==1.16.0 ; python_version >= "3.8" and python_version < "3.13" and platform_ cryptography==42.0.5 ; python_version >= "3.8" and python_version < "3.13" lxml-stubs==0.5.1 ; python_version >= "3.8" and python_version < "3.13" mypy-extensions==1.0.0 ; python_version >= "3.8" and python_version < "3.13" -mypy==1.8.0 ; python_version >= "3.8" and python_version < "3.13" +mypy==1.9.0 ; python_version >= "3.8" and python_version < "3.13" pycparser==2.21 ; python_version >= "3.8" and python_version < "3.13" and platform_python_implementation != "PyPy" pydantic-core==2.14.6 ; python_version >= "3.8" and python_version < "3.13" pydantic==2.5.3 ; python_version >= "3.8" and python_version < "3.13" @@ -12,7 +12,7 @@ types-bleach==6.1.0.20240222 ; python_version >= "3.8" and python_version < "3.1 types-boto==2.49.18.20240205 ; python_version >= "3.8" and python_version < "3.13" types-contextvars==2.4.7.3 ; python_version >= "3.8" and python_version < "3.13" types-dataclasses==0.6.6 ; python_version >= "3.8" and python_version < "3.13" -types-docutils==0.20.0.20240304 ; python_version >= "3.8" and python_version < "3.13" +types-docutils==0.20.0.20240310 ; python_version >= "3.8" and python_version < "3.13" types-html5lib==1.1.11.20240228 ; python_version >= "3.8" and python_version < "3.13" types-markdown==3.5.0.20240129 ; python_version >= "3.8" and python_version < "3.13" types-paramiko==3.4.0.20240205 ; python_version >= "3.8" and python_version < "3.13" @@ -20,6 +20,6 @@ types-pkg-resources==0.1.3 ; python_version >= "3.8" and python_version < "3.13" types-python-dateutil==2.8.19.20240106 ; python_version >= "3.8" and python_version < "3.13" types-pyyaml==6.0.12.12 ; python_version >= "3.8" and python_version < "3.13" types-requests==2.31.0.6 ; python_version >= "3.8" and python_version < "3.13" -types-six==1.16.21.20240301 ; python_version >= "3.8" and python_version < "3.13" +types-six==1.16.21.20240310 ; python_version >= "3.8" and python_version < "3.13" types-urllib3==1.26.25.14 ; python_version >= "3.8" and python_version < "3.13" typing-extensions==4.10.0 ; python_version >= "3.8" and python_version < "3.13" diff --git a/lib/galaxy/job_metrics/instrumenters/cgroup.py b/lib/galaxy/job_metrics/instrumenters/cgroup.py index 66da4f9389f..406dcf0da0b 100644 --- a/lib/galaxy/job_metrics/instrumenters/cgroup.py +++ b/lib/galaxy/job_metrics/instrumenters/cgroup.py @@ -1,8 +1,6 @@ """The module describes the ``cgroup`` job metrics plugin.""" -import decimal import logging -import numbers from collections import namedtuple from typing import ( Any, @@ -123,8 +121,13 @@ class CgroupPluginFormatter(formatting.JobMetricFormatter): return formatting.FormattedMetric(title, nice_size(value)) except ValueError: pass - elif isinstance(value, (decimal.Decimal, numbers.Integral, numbers.Real)) and value == int(value): - value = int(value) + else: + try: + int_value = int(value) + if value == int_value: + value = int_value + except TypeError: + pass return formatting.FormattedMetric(title, str(value)) diff --git a/lib/galaxy/jobs/__init__.py b/lib/galaxy/jobs/__init__.py index b015cdd3819..407a1d6d3b0 100644 --- a/lib/galaxy/jobs/__init__.py +++ b/lib/galaxy/jobs/__init__.py @@ -640,10 +640,9 @@ class JobConfiguration(ConfiguresHandlers): fields = [] for field_name in fields_names: if field_name not in self.resource_parameters: - message = "Failed to find field for resource {} in resource parameters {}".format( - field_name, self.resource_parameters + raise KeyError( + f"Failed to find field for resource {field_name} in resource parameters {self.resource_parameters}" ) - raise KeyError(message) fields.append(parse_xml_string(self.resource_parameters[field_name])) if fields: @@ -2209,9 +2208,7 @@ class MinimalJobWrapper(HasResourceParameters): try: if not tmp_dir or util.asbool(tmp_dir): working_directory = self.working_directory - return """$([ ! -e '{0}/tmp' ] || mv '{0}/tmp' '{0}'/tmp.$(date +%Y%m%d-%H%M%S) ; mkdir '{0}/tmp'; echo '{0}/tmp')""".format( - working_directory - ) + return f"""$([ ! -e '{working_directory}/tmp' ] || mv '{working_directory}/tmp' '{working_directory}'/tmp.$(date +%Y%m%d-%H%M%S) ; mkdir '{working_directory}/tmp'; echo '{working_directory}/tmp')""" else: return tmp_dir except ValueError: diff --git a/lib/galaxy/jobs/command_factory.py b/lib/galaxy/jobs/command_factory.py index 1c2a67da86a..900fa50591e 100644 --- a/lib/galaxy/jobs/command_factory.py +++ b/lib/galaxy/jobs/command_factory.py @@ -181,13 +181,7 @@ def __externalize_commands( source_command = "" if container: source_command = container.source_environment - script_contents = "#!{}\n{}{}{}{}".format( - shell, - integrity_injection, - set_e, - source_command, - tool_commands, - ) + script_contents = f"#!{shell}\n{integrity_injection}{set_e}{source_command}{tool_commands}" write_script( local_container_script, script_contents, diff --git a/lib/galaxy/jobs/runners/kubernetes.py b/lib/galaxy/jobs/runners/kubernetes.py index a360f0c87aa..56fef20a0ec 100644 --- a/lib/galaxy/jobs/runners/kubernetes.py +++ b/lib/galaxy/jobs/runners/kubernetes.py @@ -1002,9 +1002,10 @@ class KubernetesJobRunner(AsynchronousJobRunner): except Exception as e: log.exception( - "({}/{}) User killed running job, but error encountered during termination: {}".format( - job.id, job.get_job_runner_external_id(), e - ) + "(%s/%s) User killed running job, but error encountered during termination: %s", + job.id, + job.get_job_runner_external_id(), + e, ) def recover(self, job, job_wrapper): @@ -1023,18 +1024,19 @@ class KubernetesJobRunner(AsynchronousJobRunner): ajs.command_line = job.command_line if job.state in (model.Job.states.RUNNING, model.Job.states.STOPPED): log.debug( - "({}/{}) is still in {} state, adding to the runner monitor queue".format( - job.id, job.job_runner_external_id, job.state - ) + "(%s/%s) is still in %s state, adding to the runner monitor queue", + job.id, + job.job_runner_external_id, + job.state, ) ajs.old_state = model.Job.states.RUNNING ajs.running = True self.monitor_queue.put(ajs) elif job.state == model.Job.states.QUEUED: log.debug( - "({}/{}) is still in queued state, adding to the runner monitor queue".format( - job.id, job.job_runner_external_id - ) + "(%s/%s) is still in queued state, adding to the runner monitor queue", + job.id, + job.job_runner_external_id, ) ajs.old_state = model.Job.states.QUEUED ajs.running = False diff --git a/lib/galaxy/managers/cloud.py b/lib/galaxy/managers/cloud.py index e9a939b3789..813b5690b7e 100644 --- a/lib/galaxy/managers/cloud.py +++ b/lib/galaxy/managers/cloud.py @@ -281,12 +281,14 @@ class CloudManager(sharable.SharableModelManager): ) if key is None: log.exception( - "Could not get object `{}` for user `{}`. Object may not exist, or the provided credentials are " - "invalid or not authorized to read the bucket/object.".format(obj, trans.user.id) + "Could not get object `%s` for user `%s`. Object may not exist, or the provided credentials are " + "invalid or not authorized to read the bucket/object.", + obj, + trans.user.id, ) raise ObjectNotFound( - "Could not get the object `{}`. Please check if the object exists, and credentials are valid and " - "authorized to read the bucket and object. ".format(obj) + f"Could not get the object `{obj}`. Please check if the object exists, and credentials are valid and " + "authorized to read the bucket and object. " ) params = Params(self._get_inputs(obj, key, input_args), sanitize=False) @@ -299,9 +301,7 @@ class CloudManager(sharable.SharableModelManager): job_errors = output.get("job_errors", []) if job_errors: raise ValueError( - "Following error occurred while getting the given object(s) from {}: {}".format( - cloudauthz.provider, job_errors - ) + f"Following error occurred while getting the given object(s) from {cloudauthz.provider}: {job_errors}" ) else: for d in output["out_data"]: @@ -391,9 +391,10 @@ class CloudManager(sharable.SharableModelManager): except Exception as e: err_msg = f"maybe invalid or unauthorized credentials. {util.unicodify(e)}" log.debug( - "Failed to send the dataset `{}` per user `{}` request to cloud, {}".format( - object_label, trans.user.id, err_msg - ) + "Failed to send the dataset `%s` per user `%s` request to cloud, %s", + object_label, + trans.user.id, + err_msg, ) failed.append(json.dumps({"object": object_label, "error": err_msg})) return sent, failed diff --git a/lib/galaxy/managers/markdown_util.py b/lib/galaxy/managers/markdown_util.py index 2827487de1f..af1adc7f685 100644 --- a/lib/galaxy/managers/markdown_util.py +++ b/lib/galaxy/managers/markdown_util.py @@ -849,42 +849,34 @@ def resolve_invocation_markdown(trans, invocation, workflow_markdown): continue if output_assoc.history_content_type == "dataset": - section_markdown += """#### Output Dataset: {} + section_markdown += f"""#### Output Dataset: {output_assoc.workflow_output.label} ```galaxy -history_dataset_display(output="{}") +history_dataset_display(output="{output_assoc.workflow_output.label}") ``` -""".format( - output_assoc.workflow_output.label, output_assoc.workflow_output.label - ) +""" else: - section_markdown += """#### Output Dataset Collection: {} + section_markdown += f"""#### Output Dataset Collection: {output_assoc.workflow_output.label} ```galaxy -history_dataset_collection_display(output="{}") +history_dataset_collection_display(output="{output_assoc.workflow_output.label}") ``` -""".format( - output_assoc.workflow_output.label, output_assoc.workflow_output.label - ) +""" elif container == "invocation_inputs": for input_assoc in invocation.input_associations: if not input_assoc.workflow_step.label: continue if input_assoc.history_content_type == "dataset": - section_markdown += """#### Input Dataset: {} + section_markdown += f"""#### Input Dataset: {input_assoc.workflow_step.label} ```galaxy -history_dataset_display(input="{}") +history_dataset_display(input="{input_assoc.workflow_step.label}") ``` -""".format( - input_assoc.workflow_step.label, input_assoc.workflow_step.label - ) +""" else: - section_markdown += """#### Input Dataset Collection: {} + section_markdown += f"""#### Input Dataset Collection: {input_assoc.workflow_step.label} ```galaxy -history_dataset_collection_display(input={}) +history_dataset_collection_display(input={input_assoc.workflow_step.label}) ``` -""".format( - input_assoc.workflow_step.label, input_assoc.workflow_step.label - ) +""" else: return line, False return section_markdown, True diff --git a/lib/galaxy/objectstore/cloud.py b/lib/galaxy/objectstore/cloud.py index 625b1f9547e..41d7f76df09 100644 --- a/lib/galaxy/objectstore/cloud.py +++ b/lib/galaxy/objectstore/cloud.py @@ -229,8 +229,9 @@ class Cloud(ConcreteObjectStore, CloudConfigMixin): raise Exception(msg) if len(missing_config) > 0: - msg = "The following configuration required for {} cloud backend " "are missing: {}".format( - provider, missing_config + msg = ( + f"The following configuration required for {provider} cloud backend " + f"are missing: {missing_config}" ) log.error(msg) raise Exception(msg) diff --git a/lib/galaxy/objectstore/irods.py b/lib/galaxy/objectstore/irods.py index c4fb79777cc..bb0bdead62b 100644 --- a/lib/galaxy/objectstore/irods.py +++ b/lib/galaxy/objectstore/irods.py @@ -302,9 +302,9 @@ class IRODSObjectStore(DiskObjectStore, CloudConfigMixin): # seconds ago, release the connection (as its stale) if (curr_time - conn.create_time).total_seconds() > refresh_time: log.debug( - "Idle connection with id {} was created more than {} seconds ago. Releasing the connection.".format( - id(conn), refresh_time - ) + "Idle connection with id %s was created more than %s seconds ago. Releasing the connection.", + id(conn), + refresh_time, ) self.session.pool.release_connection(conn, True) stop_connection_pool_monitor_event.wait(connection_pool_monitor_interval) diff --git a/lib/galaxy/objectstore/pithos.py b/lib/galaxy/objectstore/pithos.py index fdfb78bf6d9..4d04b64246c 100644 --- a/lib/galaxy/objectstore/pithos.py +++ b/lib/galaxy/objectstore/pithos.py @@ -420,10 +420,7 @@ class PithosObjectStore(ConcreteObjectStore): shutil.copy2(source_path, cache_path) self._fix_permissions(cache_path) except OSError: - log.exception( - 'Trouble copying source file "{source}" to cache "{cache}"' - "".format(source=source_path, cache=cache_path) - ) + log.exception('Trouble copying source file "%s" to cache "%s"', source_path, cache_path) else: with open(cache_path) as f: self.pithos.upload_object(obj, f) diff --git a/lib/galaxy/tool_shed/util/container_util.py b/lib/galaxy/tool_shed/util/container_util.py index efb5988ced7..ea3e4c984b5 100644 --- a/lib/galaxy/tool_shed/util/container_util.py +++ b/lib/galaxy/tool_shed/util/container_util.py @@ -25,19 +25,7 @@ def generate_repository_dependencies_key_for_repository( # of the Galaxy database for an installed repository. This value does not include the protocol, but does include # the port if there is one. tool_shed = remove_protocol_from_tool_shed_url(toolshed_base_url) - return "{}{}{}{}{}{}{}{}{}{}{}".format( - tool_shed, - STRSEP, - repository_name, - STRSEP, - repository_owner, - STRSEP, - changeset_revision, - STRSEP, - str(prior_installation_required), - STRSEP, - str(only_if_compiling_contained_td), - ) + return f"{tool_shed}{STRSEP}{repository_name}{STRSEP}{repository_owner}{STRSEP}{changeset_revision}{STRSEP}{prior_installation_required}{STRSEP}{only_if_compiling_contained_td}" def get_components_from_key(key: str) -> tuple: diff --git a/lib/galaxy/tool_shed/util/shed_util_common.py b/lib/galaxy/tool_shed/util/shed_util_common.py index 76c757082b8..cb16ee71e91 100644 --- a/lib/galaxy/tool_shed/util/shed_util_common.py +++ b/lib/galaxy/tool_shed/util/shed_util_common.py @@ -115,8 +115,8 @@ def get_tool_panel_config_tool_path_install_dir(app, repository): defined in a single shed-related tool panel config. """ tool_shed = common_util.remove_port_from_tool_shed_url(str(repository.tool_shed)) - relative_install_dir = "{}/repos/{}/{}/{}".format( - tool_shed, str(repository.owner), str(repository.name), str(repository.installed_changeset_revision) + relative_install_dir = ( + f"{tool_shed}/repos/{repository.owner}/{repository.name}/{repository.installed_changeset_revision}" ) # Get the relative tool installation paths from each of the shed tool configs. shed_config_dict = repository.get_shed_config_dict(app) @@ -149,13 +149,7 @@ def set_image_paths(app, text, encoded_repository_id=None, tool_shed_repository= # We're in the tool shed. route_to_images = f"/repository/static/images/{encoded_repository_id}" elif tool_shed_repository and tool_id and tool_version: - route_to_images = "shed_tool_static/{shed}/{owner}/{repo}/{tool}/{version}".format( - shed=tool_shed_repository.tool_shed, - owner=tool_shed_repository.owner, - repo=tool_shed_repository.name, - tool=tool_id, - version=tool_version, - ) + route_to_images = f"shed_tool_static/{tool_shed_repository.tool_shed}/{tool_shed_repository.owner}/{tool_shed_repository.name}/{tool_id}/{tool_version}" else: raise Exception( "encoded_repository_id or tool_shed_repository and tool_id and tool_version must be provided" diff --git a/lib/galaxy/tool_util/cwl/representation.py b/lib/galaxy/tool_util/cwl/representation.py index 3124f9010b3..740954fd875 100644 --- a/lib/galaxy/tool_util/cwl/representation.py +++ b/lib/galaxy/tool_util/cwl/representation.py @@ -369,9 +369,7 @@ def to_galaxy_parameters(tool, as_dict): type_representation_name = "null" elif as_dict_value is NOT_PRESENT or as_dict_value is None: raise RequestParameterInvalidException( - "Cannot translate CWL datatype - value [{}] of type [{}] with case_strings [{}]. Non-null property must be set.".format( - as_dict_value, type(as_dict_value), case_strings - ) + f"Cannot translate CWL datatype - value [{as_dict_value}] of type [{type(as_dict_value)}] with case_strings [{case_strings}]. Non-null property must be set." ) elif isinstance(as_dict_value, bool) and "boolean" in case_strings: type_representation_name = "boolean" @@ -406,9 +404,7 @@ def to_galaxy_parameters(tool, as_dict): type_representation_name = "json" else: raise RequestParameterInvalidException( - "Cannot translate CWL datatype - value [{}] of type [{}] with case_strings [{}].".format( - as_dict_value, type(as_dict_value), case_strings - ) + f"Cannot translate CWL datatype - value [{as_dict_value}] of type [{type(as_dict_value)}] with case_strings [{case_strings}]." ) galaxy_request[f"{input_name}|_cwl__type_"] = type_representation_name if type_representation_name != "null": diff --git a/lib/galaxy/tool_util/deps/resolvers/modules.py b/lib/galaxy/tool_util/deps/resolvers/modules.py index ffd5a30b1d3..ec52c20f737 100644 --- a/lib/galaxy/tool_util/deps/resolvers/modules.py +++ b/lib/galaxy/tool_util/deps/resolvers/modules.py @@ -227,9 +227,7 @@ class ModuleDependency(Dependency): module_to_load = self.module_name if self.module_version: module_to_load = f"{self.module_name}/{self.module_version}" - command = "MODULEPATH={}; export MODULEPATH; eval `{} sh load {}`".format( - self.module_dependency_resolver.modulepath, self.module_dependency_resolver.modulecmd, module_to_load - ) + command = f"MODULEPATH={self.module_dependency_resolver.modulepath}; export MODULEPATH; eval `{self.module_dependency_resolver.modulecmd} sh load {module_to_load}`" return command diff --git a/lib/galaxy/tools/error_reports/plugins/github.py b/lib/galaxy/tools/error_reports/plugins/github.py index 4debce7281a..d4747ff88cf 100644 --- a/lib/galaxy/tools/error_reports/plugins/github.py +++ b/lib/galaxy/tools/error_reports/plugins/github.py @@ -99,12 +99,7 @@ class GithubPlugin(BaseGitPlugin): else: self._append_issue(issue_cache_key, error_title, error_message) return ( - "Submitted error report to GitHub. Your issue number is [#{}]({}/{}/issues/{})".format( - self.issue_cache[issue_cache_key][error_title].number, - self.github_base_url, - github_projecturl, - self.issue_cache[issue_cache_key][error_title].number, - ), + f"Submitted error report to GitHub. Your issue number is [#{self.issue_cache[issue_cache_key][error_title].number}]({self.github_base_url}/{github_projecturl}/issues/{self.issue_cache[issue_cache_key][error_title].number})", "success", ) diff --git a/lib/galaxy/tools/error_reports/plugins/gitlab.py b/lib/galaxy/tools/error_reports/plugins/gitlab.py index f85c3b2fd2e..b8f2d923bad 100644 --- a/lib/galaxy/tools/error_reports/plugins/gitlab.py +++ b/lib/galaxy/tools/error_reports/plugins/gitlab.py @@ -185,12 +185,7 @@ class GitLabPlugin(BaseGitPlugin): ) return ( - "Submitted error report to GitLab. Your Issue number is [#{}]({}/{}/issues/{})".format( - self.issue_cache[issue_cache_key][error_title], - self.gitlab_base_url, - gitlab_projecturl, - self.issue_cache[issue_cache_key][error_title], - ), + f"Submitted error report to GitLab. Your Issue number is [#{self.issue_cache[issue_cache_key][error_title]}]({self.gitlab_base_url}/{gitlab_projecturl}/issues/{self.issue_cache[issue_cache_key][error_title]})", "success", ) diff --git a/lib/galaxy/tools/errors.py b/lib/galaxy/tools/errors.py index e1dc2052bb5..e6d3a79429f 100644 --- a/lib/galaxy/tools/errors.py +++ b/lib/galaxy/tools/errors.py @@ -248,9 +248,7 @@ class EmailErrorReporter(ErrorReporter): to += f", {email.strip()}" subject = f"Galaxy tool error report from {email}" try: - subject = "{} ({})".format( - subject, self.app.toolbox.get_tool(self.job.tool_id, self.job.tool_version).old_id - ) + subject = f"{subject} ({self.app.toolbox.get_tool(self.job.tool_id, self.job.tool_version).old_id})" except Exception: pass diff --git a/lib/galaxy/util/__init__.py b/lib/galaxy/util/__init__.py index f4b9050db27..b21ebac0b05 100644 --- a/lib/galaxy/util/__init__.py +++ b/lib/galaxy/util/__init__.py @@ -1412,9 +1412,12 @@ def umask_fix_perms(path, umask, unmasked_perms, gid=None): os.chmod(path, perms) except Exception as e: log.warning( - "Unable to honor umask ({}) for {}, tried to set: {} but mode remains {}, error was: {}".format( - oct(umask), path, oct(perms), oct(stat.S_IMODE(st.st_mode)), unicodify(e) - ) + "Unable to honor umask (%s) for %s, tried to set: %s but mode remains %s, error was: %s", + oct(umask), + path, + oct(perms), + oct(stat.S_IMODE(st.st_mode)), + e, ) # fix group if gid is not None and st.st_gid != gid: @@ -1428,9 +1431,11 @@ def umask_fix_perms(path, umask, unmasked_perms, gid=None): desired_group = gid current_group = st.st_gid log.warning( - "Unable to honor primary group ({}) for {}, group remains {}, error was: {}".format( - desired_group, path, current_group, unicodify(e) - ) + "Unable to honor primary group (%s) for %s, group remains %s, error was: %s", + desired_group, + path, + current_group, + e, ) diff --git a/lib/galaxy/web/framework/middleware/error.py b/lib/galaxy/web/framework/middleware/error.py index a7db108f96e..2d63a115832 100644 --- a/lib/galaxy/web/framework/middleware/error.py +++ b/lib/galaxy/web/framework/middleware/error.py @@ -450,13 +450,11 @@ def send_report(rep, exc_data, html=True): output = StringIO() traceback.print_exc(file=output) if html: - return """ -
Additionally an error occurred while sending the {} report: + return f""" +
Additionally an error occurred while sending the {markupsafe.escape(str(rep))} report: -
{}
- """.format(
- markupsafe.escape(str(rep)), output.getvalue()
- )
+ {output.getvalue()}
+ """
else:
return f"Additionally an error occurred while sending the {rep} report:\n{output.getvalue()}"
else:
diff --git a/lib/galaxy/web_stack/message.py b/lib/galaxy/web_stack/message.py
index d71f86100f8..f7ef7f7d2dd 100644
--- a/lib/galaxy/web_stack/message.py
+++ b/lib/galaxy/web_stack/message.py
@@ -149,9 +149,9 @@ class TaskMessage(ParamMessage):
def default_handler(self, msg):
"""Can be bound to an instance of any class that has message handling methods named like `_handle_{task}_method`"""
name = f"_handle_{msg.task}_msg"
- assert name in dir(self), "{cls} has no method _handle_{task}_msg, cannot handle message: {msg}".format(
- cls=self.__class__.__name__, task=msg.task, msg=msg
- )
+ assert name in dir(
+ self
+ ), f"{self.__class__.__name__} has no method _handle_{msg.task}_msg, cannot handle message: {msg}"
getattr(self, f"_handle_{msg.task}_msg")(**msg.params)
@property
diff --git a/lib/galaxy/webapps/galaxy/api/cloudauthz.py b/lib/galaxy/webapps/galaxy/api/cloudauthz.py
index f6813c1cf1f..dc5a1ecf540 100644
--- a/lib/galaxy/webapps/galaxy/api/cloudauthz.py
+++ b/lib/galaxy/webapps/galaxy/api/cloudauthz.py
@@ -143,8 +143,9 @@ class CloudAuthzController(BaseGalaxyAPIController):
for ca in trans.user.cloudauthz:
if ca.equals(trans.user.id, provider, authn_id, config):
log.debug(
- "Rejected user `{}`'s request to create cloud authorization because a similar config "
- "already exists.".format(trans.user.id)
+ "Rejected user `%s`'s request to create cloud authorization because a similar config "
+ "already exists.",
+ trans.user.id,
)
raise ActionInputError("A similar cloud authorization configuration is already defined.")
diff --git a/lib/galaxy/webapps/galaxy/api/library_datasets.py b/lib/galaxy/webapps/galaxy/api/library_datasets.py
index 5c98c57eb96..35cc5ae350f 100644
--- a/lib/galaxy/webapps/galaxy/api/library_datasets.py
+++ b/lib/galaxy/webapps/galaxy/api/library_datasets.py
@@ -501,9 +501,7 @@ class LibraryDatasetsController(BaseGalaxyAPIController, UsesVisualizationMixin,
path, allowlist=[full_dir] + trans.app.config.user_library_import_symlink_allowlist, username=username
):
# the path is a dir and contains files that symlink outside the user dir
- error = "User attempted to import a path that resolves to a path outside of their import dir: {} -> {}".format(
- path, os.path.realpath(path)
- )
+ error = f"User attempted to import a path that resolves to a path outside of their import dir: {path} -> {os.path.realpath(path)}"
if trans.app.config.user_library_import_check_permissions:
error += " or is not readable for them."
log.error(error)
diff --git a/lib/galaxy/webapps/galaxy/controllers/authnz.py b/lib/galaxy/webapps/galaxy/controllers/authnz.py
index f4c1becf1d2..1abcc722ce6 100644
--- a/lib/galaxy/webapps/galaxy/controllers/authnz.py
+++ b/lib/galaxy/webapps/galaxy/controllers/authnz.py
@@ -89,10 +89,10 @@ class OIDC(JSAppLauncher):
if not bool(kwargs):
log.error(f"OIDC callback received no data for provider `{provider}` and user `{user}`")
return trans.show_error_message(
- "Did not receive any information from the `{}` identity provider to complete user `{}` authentication "
+ f"Did not receive any information from the `{provider}` identity provider to complete user `{user}` authentication "
"flow. Please try again, and if the problem persists, contact the Galaxy instance admin. Also note "
"that this endpoint is to receive authentication callbacks only, and should not be called/reached by "
- "a user.".format(provider, user)
+ "a user."
)
if "error" in kwargs:
log.error(
@@ -127,9 +127,9 @@ class OIDC(JSAppLauncher):
user = user if user is not None else trans.user
if user is None:
return trans.show_error_message(
- "An unknown error occurred when handling the callback from `{}` "
+ f"An unknown error occurred when handling the callback from `{provider}` "
"identity provider. Please try again, and if the problem persists, "
- "contact the Galaxy instance admin.".format(provider)
+ "contact the Galaxy instance admin."
)
trans.handle_user_login(user)
# Record which idp provider was logged into, so we can logout of it later
@@ -152,9 +152,9 @@ class OIDC(JSAppLauncher):
user = user if user is not None else trans.user
if user is None:
return trans.show_error_message(
- "An unknown error occurred when handling the callback from `{}` "
+ f"An unknown error occurred when handling the callback from `{provider}` "
"identity provider. Please try again, and if the problem persists, "
- "contact the Galaxy instance admin.".format(provider)
+ "contact the Galaxy instance admin."
)
trans.handle_user_login(user)
# Record which idp provider was logged into, so we can logout of it later
diff --git a/lib/tool_shed/grids/repository_grids.py b/lib/tool_shed/grids/repository_grids.py
index 9eb430f0c8e..9673d2e185d 100644
--- a/lib/tool_shed/grids/repository_grids.py
+++ b/lib/tool_shed/grids/repository_grids.py
@@ -857,12 +857,7 @@ class RepositoriesWithInvalidToolsGrid(RepositoryGrid):
metadata = repository_metadata.metadata
if invalid_tools := metadata.get("invalid_tools", []):
for invalid_tool_config in invalid_tools:
- href_str = '{}'.format(
- trans.security.encode_id(repository.id),
- invalid_tool_config,
- repository_metadata.changeset_revision,
- invalid_tool_config,
- )
+ href_str = f'{invalid_tool_config}'
val += href_str
val += "