From 35f77afda79f8848766cb900500b497ca5f6137b Mon Sep 17 00:00:00 2001 From: Ahmed Awan Date: Thu, 5 Oct 2023 14:57:08 -0400 Subject: [PATCH 01/14] Disable button in `CopyModal` for histories when copying history --- client/src/components/History/Modals/CopyModal.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/History/Modals/CopyModal.vue b/client/src/components/History/Modals/CopyModal.vue index a146bc03f6f7..ed9a2124cf4a 100644 --- a/client/src/components/History/Modals/CopyModal.vue +++ b/client/src/components/History/Modals/CopyModal.vue @@ -36,7 +36,7 @@
Cancel - + {{ saveTitle | localize }}
From 911460d90ba90149fa3ee011d593bb560ee4e1d2 Mon Sep 17 00:00:00 2001 From: Martin Cech Date: Sat, 7 Oct 2023 14:28:09 -0400 Subject: [PATCH 02/14] move history and tool panel tooltips out of the way also make them noninteractive so they don't stay in way --- client/src/components/Common/DelayedInput.vue | 4 ++-- .../CurrentHistory/HistoryFilters/HistoryFilters.vue | 4 ++-- .../components/History/CurrentHistory/HistoryNavigation.vue | 6 +++--- client/src/components/Panels/Buttons/FavoritesButton.vue | 2 +- client/src/components/Panels/Buttons/PanelViewButton.vue | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/client/src/components/Common/DelayedInput.vue b/client/src/components/Common/DelayedInput.vue index bb36d5f8fb92..50456f7688d2 100644 --- a/client/src/components/Common/DelayedInput.vue +++ b/client/src/components/Common/DelayedInput.vue @@ -13,7 +13,7 @@ History Date: Sat, 7 Oct 2023 16:06:22 -0400 Subject: [PATCH 03/14] Fix tool panel views for versionless tool ids --- lib/galaxy/tool_util/toolbox/base.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/galaxy/tool_util/toolbox/base.py b/lib/galaxy/tool_util/toolbox/base.py index 4529f85d40db..4742e7b7c32f 100644 --- a/lib/galaxy/tool_util/toolbox/base.py +++ b/lib/galaxy/tool_util/toolbox/base.py @@ -96,7 +96,12 @@ def __init__(self, toolbox: "AbstractToolBox"): def has_tool(self, tool_id: str) -> bool: toolbox = self.__toolbox - return tool_id in toolbox._tools_by_id or tool_id in toolbox._tools_by_old_id + # tool_id could be full guid, old tool id (no toolshed and version info) or versionless guid. + return ( + tool_id in toolbox._tools_by_id + or tool_id in toolbox._tools_by_old_id + or bool(toolbox._lineage_map.lineage_map.get(tool_id)) + ) def get_tool(self, tool_id: str): return self.__toolbox.get_tool(tool_id) From 44903311b59632f6fdd105a99facbf3e435ecf85 Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Sun, 8 Oct 2023 09:35:44 -0400 Subject: [PATCH 04/14] Avoid AttributeError when accessing toolbox Fixes: ``` Traceback (most recent call last): File "/cvmfs/test.galaxyproject.org/galaxy/lib/galaxy/webapps/galaxy/buildapp.py", line 59, in app_pair app = galaxy.app.UniverseApplication(global_conf=global_conf, is_webapp=True, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/cvmfs/test.galaxyproject.org/galaxy/lib/galaxy/app.py", line 691, in __init__ self._configure_toolbox() File "/cvmfs/test.galaxyproject.org/galaxy/lib/galaxy/app.py", line 309, in _configure_toolbox self._toolbox = tools.ToolBox(self.config.tool_configs, self.config.tool_path, self) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/cvmfs/test.galaxyproject.org/galaxy/lib/galaxy/tools/__init__.py", line 420, in __init__ super().__init__( File "/cvmfs/test.galaxyproject.org/galaxy/lib/galaxy/tool_util/toolbox/base.py", line 237, in __init__ self._load_tool_panel_views() File "/cvmfs/test.galaxyproject.org/galaxy/lib/galaxy/tool_util/toolbox/base.py", line 600, in _load_tool_panel_views self._tool_panel_view_rendered[key] = view.apply_view(self._integrated_tool_panel, registry) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/cvmfs/test.galaxyproject.org/galaxy/lib/galaxy/tool_util/toolbox/views/static.py", line 195, in apply_view return definition_with_items_to_panel(root_defintion, items=root_items) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/cvmfs/test.galaxyproject.org/galaxy/lib/galaxy/tool_util/toolbox/views/static.py", line 87, in definition_with_items_to_panel panel = definition_with_items_to_panel(section_def, allow_sections=False) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/cvmfs/test.galaxyproject.org/galaxy/lib/galaxy/tool_util/toolbox/views/static.py", line 142, in definition_with_items_to_panel tool = toolbox_registry.get_tool(tool_id) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/cvmfs/test.galaxyproject.org/galaxy/lib/galaxy/tool_util/toolbox/base.py", line 107, in get_tool return self.__toolbox.get_tool(tool_id) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/cvmfs/test.galaxyproject.org/galaxy/lib/galaxy/tool_util/toolbox/base.py", line 719, in get_tool tool_lineage = self._lineage_map.get(tool_id) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/cvmfs/test.galaxyproject.org/galaxy/lib/galaxy/tool_util/toolbox/lineages/factory.py", line 47, in get tool = self.app.toolbox._tools_by_id.get(tool_id) ^^^^^^^^^^^^^^^^ File "/cvmfs/test.galaxyproject.org/galaxy/lib/galaxy/app.py", line 351, in toolbox return self._toolbox ^^^^^^^^^^^^^ AttributeError: 'UniverseApplication' object has no attribute '_toolbox' ``` when attempting to apply a panel view that contains tools that aren't installed on a server. --- lib/galaxy/tool_util/toolbox/lineages/factory.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/galaxy/tool_util/toolbox/lineages/factory.py b/lib/galaxy/tool_util/toolbox/lineages/factory.py index 96efb51d77d1..2a68c32b2ee4 100644 --- a/lib/galaxy/tool_util/toolbox/lineages/factory.py +++ b/lib/galaxy/tool_util/toolbox/lineages/factory.py @@ -44,7 +44,15 @@ def get(self, tool_id) -> Optional[ToolLineage]: if lineage: return lineage if tool_id not in self.lineage_map: - tool = self.app.toolbox._tools_by_id.get(tool_id) + toolbox = None + try: + toolbox = self.app.toolbox + except AttributeError: + # We're building the lineage map while building the toolbox, + # so app.toolbox may not be available. + # TODO: is the fallback really needed / can it be fixed by improving _get_versionless ? + pass + tool = toolbox and toolbox._tools_by_id.get(tool_id) if tool: lineage = ToolLineage.from_tool(tool) if lineage: From 4df49010b37d79dc8f167d099b236c97ae7aefed Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Mon, 9 Oct 2023 12:07:34 -0400 Subject: [PATCH 05/14] Fix parameter display for tools with sections Fixes: ``` Message Uncaught exception in exposed API method: Stack Trace(most recent call first) TypeError: Object of type method is not JSON serializable File "galaxy/util/json.py", line 74, in safe_dumps dumped = json.dumps(obj, allow_nan=False, **kwargs) File "__init__.py", line 234, in dumps return cls( File "json/encoder.py", line 199, in encode chunks = self.iterencode(o, _one_shot=True) File "json/encoder.py", line 257, in iterencode return _iterencode(o, 0) File "json/encoder.py", line 179, in default raise TypeError(f'Object of type {o.__class__.__name__} ' TypeError: Object of type method is not JSON serializable File "galaxy/web/framework/decorators.py", line 341, in decorator rval = format_return_as_json(rval, jsonp_callback, pretty=trans.debug) File "galaxy/web/framework/decorators.py", line 378, in format_return_as_json json = safe_dumps(rval, **dumps_kwargs) File "galaxy/util/json.py", line 77, in safe_dumps dumped = json.dumps(obj, allow_nan=False, **kwargs) File "__init__.py", line 234, in dumps return cls( File "json/encoder.py", line 199, in encode chunks = self.iterencode(o, _one_shot=True) File "json/encoder.py", line 257, in iterencode return _iterencode(o, 0) File "json/encoder.py", line 179, in default raise TypeError(f'Object of type {o.__class__.__name__} ' ``` from https://sentry.galaxyproject.org/share/issue/665556bc240f4a04978f7c81c2be629c/ --- lib/galaxy/managers/jobs.py | 2 -- lib/galaxy/tools/parameters/grouping.py | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/galaxy/managers/jobs.py b/lib/galaxy/managers/jobs.py index e76208ce91d2..3254396fcf78 100644 --- a/lib/galaxy/managers/jobs.py +++ b/lib/galaxy/managers/jobs.py @@ -965,8 +965,6 @@ def inputs_recursive(input_params, param_values, depth=1, upgrade_messages=None) # Get parameter label. if input.type == "conditional": label = input.test_param.label - elif input.type == "repeat": - label = input.label() else: label = input.label or input.name rval.append( diff --git a/lib/galaxy/tools/parameters/grouping.py b/lib/galaxy/tools/parameters/grouping.py index 14383ae2fd06..5428ca836295 100644 --- a/lib/galaxy/tools/parameters/grouping.py +++ b/lib/galaxy/tools/parameters/grouping.py @@ -102,6 +102,7 @@ def title(self, value): def title_plural(self): return inflector.pluralize(self.title) + @property def label(self): return f"Repeat ({self.title})" @@ -183,6 +184,7 @@ def __init__(self): def title_plural(self): return inflector.pluralize(self.title) + @property def label(self): return f"Section ({self.title})" From 455d9e6b47ae7096511a598b81b9bd651ef492ef Mon Sep 17 00:00:00 2001 From: Martin Cech Date: Fri, 6 Oct 2023 14:44:00 -0400 Subject: [PATCH 06/14] remove the email and username redacting frmo the role loop I guess this worked because user is guaranteed to have a role? --- lib/galaxy/managers/users.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/galaxy/managers/users.py b/lib/galaxy/managers/users.py index f656a1634929..62790853a857 100644 --- a/lib/galaxy/managers/users.py +++ b/lib/galaxy/managers/users.py @@ -209,7 +209,7 @@ def purge(self, user, flush=True): # Deleting multiple times will re-hash the username/email email_hash = new_secure_hash_v2(user.email + pseudorandom_value) uname_hash = new_secure_hash_v2(user.username + pseudorandom_value) - # We must also redact username + # Redact all roles user has for role in user.all_roles(): if self.app.config.redact_username_during_deletion: role.name = role.name.replace(user.username, uname_hash) @@ -218,11 +218,12 @@ def purge(self, user, flush=True): if self.app.config.redact_email_during_deletion: role.name = role.name.replace(user.email, email_hash) role.description = role.description.replace(user.email, email_hash) - user.email = email_hash - user.username = uname_hash private_role.name = email_hash private_role.description = f"Private Role for {email_hash}" self.session().add(private_role) + # Redact user's email and username + user.email = email_hash + user.username = uname_hash # Redact user addresses as well if self.app.config.redact_user_address_during_deletion: user_addresses = ( From a25f98d38a45db9ff668cd0b5fe82a952d71f542 Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Fri, 6 Oct 2023 13:57:39 -0400 Subject: [PATCH 07/14] Use AlignedSegment.to_string --- lib/galaxy/datatypes/binary.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/galaxy/datatypes/binary.py b/lib/galaxy/datatypes/binary.py index 022631195215..6ff176063f4a 100644 --- a/lib/galaxy/datatypes/binary.py +++ b/lib/galaxy/datatypes/binary.py @@ -664,7 +664,7 @@ def get_chunk(self, trans, dataset: HasFileName, offset: int = 0, ck_size: Optio break offset = bamfile.tell() - bamline = alignment.tostring(bamfile) + bamline = alignment.to_string(bamfile) # With multiple tags, Galaxy would display each as a separate column # because the 'tostring()' function uses tabs also between tags. # Below code will turn these extra tabs into spaces. From 14fc85cc4eeb5195c8a4344c2aece03414f68e49 Mon Sep 17 00:00:00 2001 From: Marius van den Beek Date: Fri, 6 Oct 2023 14:06:56 -0400 Subject: [PATCH 08/14] Update outdated comment Co-authored-by: Dannon --- lib/galaxy/datatypes/binary.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/galaxy/datatypes/binary.py b/lib/galaxy/datatypes/binary.py index 6ff176063f4a..46f4385cd5e3 100644 --- a/lib/galaxy/datatypes/binary.py +++ b/lib/galaxy/datatypes/binary.py @@ -666,7 +666,7 @@ def get_chunk(self, trans, dataset: HasFileName, offset: int = 0, ck_size: Optio offset = bamfile.tell() bamline = alignment.to_string(bamfile) # With multiple tags, Galaxy would display each as a separate column - # because the 'tostring()' function uses tabs also between tags. + # because the 'to_string()' function uses tabs also between tags. # Below code will turn these extra tabs into spaces. n_tabs = bamline.count("\t") if n_tabs > 11: From f15c4c42f0acb77b6c4fb544eb926df6c4d0c3cf Mon Sep 17 00:00:00 2001 From: Martin Cech Date: Sat, 7 Oct 2023 21:49:17 +0200 Subject: [PATCH 09/14] fix the call arguments https://pysam.readthedocs.io/en/v0.21.0/api.html?highlight=AlignedSegment#pysam.AlignedSegment.tostring --- lib/galaxy/datatypes/binary.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/galaxy/datatypes/binary.py b/lib/galaxy/datatypes/binary.py index 46f4385cd5e3..c15b2213a94c 100644 --- a/lib/galaxy/datatypes/binary.py +++ b/lib/galaxy/datatypes/binary.py @@ -664,7 +664,7 @@ def get_chunk(self, trans, dataset: HasFileName, offset: int = 0, ck_size: Optio break offset = bamfile.tell() - bamline = alignment.to_string(bamfile) + bamline = alignment.to_string() # With multiple tags, Galaxy would display each as a separate column # because the 'to_string()' function uses tabs also between tags. # Below code will turn these extra tabs into spaces. From af7d63b60fd1f90e4367395bf0691947e5cef35a Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Sun, 8 Oct 2023 12:07:05 +0200 Subject: [PATCH 10/14] Increase length of CustosAuthnzToken.external_user_id --- lib/galaxy/model/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/galaxy/model/__init__.py b/lib/galaxy/model/__init__.py index 02d1ec958a4f..6652ff72814d 100644 --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -9534,7 +9534,7 @@ class CustosAuthnzToken(Base, RepresentById): id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey("galaxy_user.id")) - external_user_id = Column(String(64)) + external_user_id = Column(String(255)) provider = Column(String(255)) access_token = Column(Text) id_token = Column(Text) From 239fd3987951c2f2ffee87abde15398321766a85 Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Sun, 8 Oct 2023 12:43:22 +0200 Subject: [PATCH 11/14] Add DB migration to increase external_user_id length --- ...c5d0b47a9_alter_column_external_user_id.py | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 lib/galaxy/model/migrations/alembic/versions_gxy/e93c5d0b47a9_alter_column_external_user_id.py diff --git a/lib/galaxy/model/migrations/alembic/versions_gxy/e93c5d0b47a9_alter_column_external_user_id.py b/lib/galaxy/model/migrations/alembic/versions_gxy/e93c5d0b47a9_alter_column_external_user_id.py new file mode 100644 index 000000000000..ccd1bc33cbd5 --- /dev/null +++ b/lib/galaxy/model/migrations/alembic/versions_gxy/e93c5d0b47a9_alter_column_external_user_id.py @@ -0,0 +1,30 @@ +"""alter column CustosAuthnzToken.external_user_id to increase length + +Revision ID: e93c5d0b47a9 +Revises: e0561d5fc8c7 +Create Date: 2023-10-08 12:11:02.024669 + +""" +import sqlalchemy as sa + +from galaxy.model.migrations.util import alter_column + +# revision identifiers, used by Alembic. +revision = "e93c5d0b47a9" +down_revision = "e0561d5fc8c7" +branch_labels = None +depends_on = None + +table_name = "custos_authnz_token" +column_name = "external_user_id" + +LONGER_LENGTH = 255 + + +def upgrade(): + alter_column(table_name, column_name, type_=sa.String(LONGER_LENGTH)) + + +def downgrade(): + # No need to downgrade, this is a one-way migration. Otherwise, existing data would be truncated or lost. + pass From 97356338b87fea7d3433488aa4fc2cf994deeaa6 Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Sun, 8 Oct 2023 12:54:07 +0200 Subject: [PATCH 12/14] Update db revision tags for 23.1 --- lib/galaxy/model/migrations/dbscript.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/galaxy/model/migrations/dbscript.py b/lib/galaxy/model/migrations/dbscript.py index b55dd79c4349..721907b852ed 100644 --- a/lib/galaxy/model/migrations/dbscript.py +++ b/lib/galaxy/model/migrations/dbscript.py @@ -36,8 +36,8 @@ "22.05": "186d4835587b", "release_23.0": "caa7742f7bca", "23.0": "caa7742f7bca", - "release_23.1": "e0561d5fc8c7", - "23.1": "e0561d5fc8c7", + "release_23.1": "e93c5d0b47a9", + "23.1": "e93c5d0b47a9", } From d989ec37ccddd80ac84dae16e81d09e735b11bd3 Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Tue, 10 Oct 2023 20:37:56 -0400 Subject: [PATCH 13/14] Fix display of tools where parameter values have been added --- lib/galaxy/managers/workflows.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/galaxy/managers/workflows.py b/lib/galaxy/managers/workflows.py index 4d84e834cd85..1f1467d5b330 100644 --- a/lib/galaxy/managers/workflows.py +++ b/lib/galaxy/managers/workflows.py @@ -1057,7 +1057,15 @@ def do_inputs(inputs, values, prefix, step, other_values=None): except KeyError: continue else: - row_for_param(input_dict, input, values[input.name], other_values, prefix, step) + row_for_param( + input_dict, + input, + # Use values.get so that unspecified param values don't blow up the display + values.get(input.name), + other_values, + prefix, + step, + ) input_dicts.append(input_dict) return input_dicts From 7fc41423d2ed85098ee98d9248753bc2e60016a3 Mon Sep 17 00:00:00 2001 From: Nicola Soranzo Date: Wed, 11 Oct 2023 13:08:59 +0100 Subject: [PATCH 14/14] Fix create/install commands for conda 23.9.0 The `--experimental-solver` option was removed. --- lib/galaxy/tool_util/deps/conda_util.py | 27 +++++++++++++++---------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/galaxy/tool_util/deps/conda_util.py b/lib/galaxy/tool_util/deps/conda_util.py index 1d9c1f74523e..6ccad9680c8e 100644 --- a/lib/galaxy/tool_util/deps/conda_util.py +++ b/lib/galaxy/tool_util/deps/conda_util.py @@ -21,6 +21,7 @@ ) import packaging.version +from packaging.version import Version from galaxy.util import ( commands, @@ -88,7 +89,7 @@ class CondaContext(installable.InstallableContext): installable_description = "Conda" _conda_build_available: Optional[bool] _conda_version: Optional[Union[packaging.version.Version, packaging.version.LegacyVersion]] - _experimental_solver_available: Optional[bool] + _libmamba_solver_available: Optional[bool] def __init__( self, @@ -129,7 +130,7 @@ def __init__( def _reset_conda_properties(self) -> None: self._conda_version = None self._conda_build_available = None - self._experimental_solver_available = None + self._libmamba_solver_available = None @property def conda_version(self) -> Union[packaging.version.Version, packaging.version.LegacyVersion]: @@ -167,13 +168,17 @@ def _override_channels_args(self) -> List[str]: return override_channels_args @property - def _experimental_solver_args(self) -> List[str]: - if self._experimental_solver_available is None: - self._experimental_solver_available = self.conda_version >= packaging.version.parse( - "4.12.0" - ) and self.is_package_installed("conda-libmamba-solver") - if self._experimental_solver_available: - return ["--experimental-solver", "libmamba"] + def _solver_args(self) -> List[str]: + if self._libmamba_solver_available is None: + self._libmamba_solver_available = self.conda_version >= Version("4.12.0") and self.is_package_installed( + "conda-libmamba-solver" + ) + if self._libmamba_solver_available: + # The "--solver" option was introduced in conda 22.11.0, when the + # "--experimental-solver" option was deprecated. + # The "--experimental-solver" option was removed in conda 23.9.0 . + solver_option = "--solver" if self.conda_version >= Version("22.11.0") else "--experimental-solver" + return [solver_option, "libmamba"] else: return [] @@ -288,7 +293,7 @@ def exec_create(self, args: Iterable[str], allow_local: bool = True, stdout_path continue if allow_local and self.use_local: create_args.append("--use-local") - create_args.extend(self._experimental_solver_args) + create_args.extend(self._solver_args) create_args.extend(self._override_channels_args) create_args.extend(args) ret = self.exec_command("create", create_args, stdout_path=stdout_path) @@ -319,7 +324,7 @@ def exec_install(self, args: Iterable[str], allow_local: bool = True, stdout_pat continue if allow_local and self.use_local: install_args.append("--use-local") - install_args.extend(self._experimental_solver_args) + install_args.extend(self._solver_args) install_args.extend(self._override_channels_args) install_args.extend(args) ret = self.exec_command("install", install_args, stdout_path=stdout_path)