Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions client/src/components/Tool/ToolCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,16 @@ const { isOnlyPreference } = useStorageLocationConfiguration();
const { currentUser, isAnonymous } = storeToRefs(useUserStore());
const { isLoaded: isConfigLoaded, config } = storeToRefs(useConfigStore());
const hasUser = computed(() => !isAnonymous.value);
const versions = computed(() => props.options.versions);
const showVersions = computed(() => props.options.versions?.length > 1);
const versions = computed(() => props.options.versions ?? []);
const hiddenVersions = computed(() => props.options.hidden_versions ?? []);
const visibleVersions = computed(() => {
const filtered = versions.value.filter((v) => !hiddenVersions.value.includes(v));
if (props.version && !filtered.includes(props.version) && versions.value.includes(props.version)) {
filtered.push(props.version);
}
return filtered;
});
const showVersions = computed(() => visibleVersions.value.length > 1);

const storageLocationModalTitle = computed(() => {
if (isOnlyPreference.value) {
Expand Down Expand Up @@ -164,7 +172,7 @@ onBeforeMount(() => {
<ToolVersionsButton
v-if="showVersions"
:version="props.version"
:versions="versions"
:versions="visibleVersions"
@onChangeVersion="onChangeVersion" />
<ToolOptionsButton
:id="props.id"
Expand Down
63 changes: 17 additions & 46 deletions lib/galaxy/tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@
from galaxy.tools.parameters.wrapped_json import json_wrap
from galaxy.util import (
in_directory,
listify,
Params,
parse_xml_string,
rst_to_html,
Expand All @@ -202,7 +201,6 @@
from galaxy.util.compression_utils import get_fileobj_raw
from galaxy.util.dictifiable import UsesDictVisibleKeys
from galaxy.util.expressions import ExpressionContext
from galaxy.util.form_builder import SelectField
from galaxy.util.json import (
safe_loads,
swap_inf_nan,
Expand Down Expand Up @@ -687,33 +685,6 @@ def create_dynamic_tool(self, dynamic_tool: "DynamicTool") -> "Tool":
tool.name = tool.id
return tool

def get_tool_components(self, tool_id, tool_version=None, get_loaded_tools_by_lineage=False, set_selected=False):
"""
Retrieve all loaded versions of a tool from the toolbox and return a select list enabling
selection of a different version, the list of the tool's loaded versions, and the specified tool.
"""
tool_version_select_field = None
tools = []
tool = None
# Backwards compatibility for datasource tools that have default tool_id configured, but which
# are now using only GALAXY_URL.
tool_ids = listify(tool_id)
for tool_id in tool_ids:
if tool_id.endswith("/"):
# Some data sources send back redirects ending with `/`, this takes care of that case
tool_id = tool_id[:-1]
if get_loaded_tools_by_lineage:
tools = self.get_loaded_tools_by_lineage(tool_id)
else:
tools = self.get_tool(tool_id, tool_version=tool_version, get_all_versions=True)
if tools:
tool = self.get_tool(tool_id, tool_version=tool_version, get_all_versions=False)
assert tool
if len(tools) > 1:
tool_version_select_field = self.__build_tool_version_select_field(tools, tool.id, set_selected)
break
return tool_version_select_field, tools, tool

def _path_template_kwds(self):
return {
"model_tools_path": MODEL_TOOLS_PATH,
Expand Down Expand Up @@ -763,20 +734,6 @@ def _load_workflow(self, workflow_id: str) -> "Workflow":
stored = session.get_one(StoredWorkflow, id)
return stored.latest_workflow

def __build_tool_version_select_field(self, tools, tool_id, set_selected):
"""Build a SelectField whose options are the ids for the received list of tools."""
options: list[tuple[str, str]] = []
for tool in tools:
options.insert(0, (tool.version, tool.id))
select_field = SelectField(name="tool_id")
for option_tup in options:
selected = set_selected and option_tup[1] == tool_id
if selected:
select_field.add_option(f"version {option_tup[0]}", option_tup[1], selected=True)
else:
select_field.add_option(f"version {option_tup[0]}", option_tup[1])
return select_field


class DefaultToolState:
"""
Expand Down Expand Up @@ -1166,6 +1123,18 @@ def tool_versions(self):
else:
return []

@property
def hidden_tool_versions(self):
if not self.lineage or not self.id:
return []
versions_by_id = self.app.toolbox._tool_versions_by_id.get(self.id, {})
hidden_versions = []
for version in self.lineage.tool_versions:
tool = versions_by_id.get(version)
if tool and tool.hidden:
hidden_versions.append(version)
return hidden_versions

@property
def is_latest_version(self):
tool_versions = self.tool_versions
Expand Down Expand Up @@ -2967,6 +2936,8 @@ def to_dict(self, trans, link_details=False, io_details=False, tool_help=False):
tool_dict["hidden"] = self.hidden
tool_dict["is_workflow_compatible"] = self.is_workflow_compatible
tool_dict["xrefs"] = self.xrefs
tool_dict["versions"] = self.tool_versions
tool_dict["hidden_versions"] = self.hidden_tool_versions

if self.dynamic_tool:
tool_dict["uuid"] = str(self.dynamic_tool.uuid)
Expand Down Expand Up @@ -3120,6 +3091,7 @@ def to_json(
"message": tool_message,
"warnings": tool_warnings,
"versions": self.tool_versions,
"hidden_versions": self.hidden_tool_versions,
"requirements": [{"name": r.name, "version": r.version} for r in self.requirements],
"credentials": [credential.to_dict() for credential in self.credentials] if self.credentials else [],
"errors": state_errors,
Expand Down Expand Up @@ -3220,9 +3192,8 @@ def _compare_tool_version(self, job: Job):
return None
message = ""
try:
select_field, tools, tool = self.app.toolbox.get_tool_components(
tool_id, tool_version=tool_version, get_loaded_tools_by_lineage=False, set_selected=True
)
tools = self.app.toolbox.get_tool(tool_id, tool_version=tool_version, get_all_versions=True) or []
tool = self.app.toolbox.get_tool(tool_id, tool_version=tool_version) if tools else None
if tool is None:
raise exceptions.MessageException(
f"This dataset was created by an obsolete tool ({tool_id}). Can't re-run."
Expand Down
9 changes: 4 additions & 5 deletions lib/galaxy/webapps/galaxy/controllers/tool_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,10 @@ def default(self, trans, tool_id=None, **kwd):
"""Catches the tool id and redirects as needed"""
return self.index(trans, tool_id=tool_id, **kwd)

def __get_tool(self, tool_id, tool_version=None, get_loaded_tools_by_lineage=False, set_selected=False):
tool_version_select_field, tools, tool = self.get_toolbox().get_tool_components(
tool_id, tool_version, get_loaded_tools_by_lineage, set_selected
)
return tool
def __get_tool(self, tool_id, tool_version=None):
# Some data sources send back redirects ending with `/`, this takes care of that case
tool_id = tool_id.rstrip("/")
return self.get_toolbox().get_tool(tool_id, tool_version=tool_version)

@web.expose
def index(self, trans, tool_id=None, from_noframe=None, **kwd):
Expand Down
22 changes: 22 additions & 0 deletions lib/galaxy_test/api/test_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -1653,6 +1653,28 @@ def test_show_with_wrong_tool_version_in_tool_id(self):
# Return last version
assert tool_info["version"] == "0.2"

@skip_without_tool("multiple_versions_hidden")
def test_show_lists_hidden_versions_separately(self):
tool_info = self._show_valid_tool("multiple_versions_hidden", tool_version="0.1")
assert tool_info["version"] == "0.1"
assert tool_info["versions"] == ["0.1", "0.2"]
assert tool_info["hidden_versions"] == ["0.1"]

@skip_without_tool("multiple_versions_hidden")
def test_run_hidden_version(self):
with self.dataset_populator.test_history_for(self.test_run_hidden_version) as history_id:
outputs = self._run(
tool_id="multiple_versions_hidden",
history_id=history_id,
tool_version="0.1",
assert_ok=True,
wait_for_job=True,
)
assert len(outputs["outputs"]) == 1
output = outputs["outputs"][0]
output_content = self.dataset_populator.get_history_dataset_content(history_id, dataset=output)
assert output_content.strip() == "Hidden Version 0.1"

@skip_without_tool("cat1")
def test_run_cat1_single_meta_wrapper(self):
with self.dataset_populator.test_history_for(self.test_run_cat1_single_meta_wrapper) as history_id:
Expand Down
11 changes: 11 additions & 0 deletions test/functional/tools/multiple_versions_hidden_v01.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<tool id="multiple_versions_hidden" name="multiple_versions_hidden" version="0.1">
<command><![CDATA[
echo "Hidden Version 0.1" > '$out_file1'
]]></command>
<inputs>
<param name="inttest" value="1" type="integer" />
</inputs>
<outputs>
<data name="out_file1" format="txt" />
</outputs>
</tool>
11 changes: 11 additions & 0 deletions test/functional/tools/multiple_versions_hidden_v02.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<tool id="multiple_versions_hidden" name="multiple_versions_hidden" version="0.2">
<command><![CDATA[
echo "Hidden Version 0.2" > '$out_file1'
]]></command>
<inputs>
<param name="inttest" value="1" type="integer" />
</inputs>
<outputs>
<data name="out_file1" format="txt" />
</outputs>
</tool>
2 changes: 2 additions & 0 deletions test/functional/tools/sample_tool_conf.xml
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@
<tool file="multiple_versions_v01.xml" />
<tool file="multiple_versions_v01galaxy6.xml" />
<tool file="multiple_versions_v02.xml" />
<tool file="multiple_versions_hidden_v01.xml" hidden="true" />
<tool file="multiple_versions_hidden_v02.xml" />
<section id="test_section_multi" name="Test Section with Multiple Versions">
<tool file="multiple_versions_v01.xml" />
<tool file="multiple_versions_v01galaxy6.xml" />
Expand Down
Loading