diff --git a/lib/galaxy/tools/lazy_toolbox.py b/lib/galaxy/tools/lazy_toolbox.py index 9e5b073c8d8..276c7ca788d 100644 --- a/lib/galaxy/tools/lazy_toolbox.py +++ b/lib/galaxy/tools/lazy_toolbox.py @@ -1106,8 +1106,13 @@ class LazyToolBox(ToolBox): candidates: list[tuple[tuple[int, Any], Tool]] = [] for guid in sorted(self._shed_short_id_to_guids[tool_id]): loaded = self._load_tool_on_demand(guid, tool_version) - if loaded is None and tool_version: - # Unknown version on this guid — try its default. + if loaded is None and tool_version and not exact: + # Unknown version on this guid — try its default. Honor + # ``exact``: like the guid path above and eager + # ``AbstractToolBox.get_tool`` (``elif exact: continue``), + # a specific-version request must not substitute another + # version, so skip this candidate when exact and the + # requested version isn't available. default_entry = self._tool_index.entries.get(guid) if default_entry is not None: loaded = self._load_tool_on_demand(guid, default_entry.version or None) diff --git a/test/unit/app/tools/test_lazy_tool.py b/test/unit/app/tools/test_lazy_tool.py index e6114d7fba2..6ba39c0fb39 100644 --- a/test/unit/app/tools/test_lazy_tool.py +++ b/test/unit/app/tools/test_lazy_tool.py @@ -638,3 +638,20 @@ def test_guid_sibling_versions_reset_on_in_place_removal(): assert set(box._index_versions_for(f"{prefix}/0.20.1")) == {"0.20.1", "0.23.2"} box._remove_tool_in_memory(f"{prefix}/0.23.2") assert box._index_versions_for(f"{prefix}/0.20.1") == ["0.20.1"] + + +def test_get_tool_short_id_missing_version_honors_exact(): + box = _registry_box() + guid = "toolshed.example.com/repos/owner/repo/cat/1.0" + box._tool_index.add_entry(_entry(id=guid, version="1.0")) + box._shed_short_id_to_guids = {"cat": {guid}} + default_tool = _stub(_entry(id=guid, version="1.0")) + + def load(tool_id, tool_version=None): + if tool_id == guid and tool_version in (None, "1.0"): + return default_tool + return None + + box._load_tool_on_demand = load + assert box.get_tool("cat", tool_version="9.9", exact=True) is None + assert box.get_tool("cat", tool_version="9.9", exact=False) is default_tool