diff --git a/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py b/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py index 2f99c2c0098..9c1c76a004a 100644 --- a/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py +++ b/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py @@ -372,7 +372,7 @@ class ToolPanelManager(object): new_tool_panel_section_label=new_tool_panel_section_label) return tool_section, tool_panel_section_key - def remove_from_shed_tool_config(self, shed_tool_conf_dict, guids_to_remove): + def remove_from_shed_tool_config(self, shed_tool_conf_dict, metadata): """ A tool shed repository is being uninstalled so change the shed_tool_conf file. Parse the config file to generate the entire list @@ -380,6 +380,13 @@ class ToolPanelManager(object): subset of the entire list if one or more repositories have been deactivated. """ + if 'tools' not in metadata: + return + # We need to use the tool path to uniquely identify the tools to remove, + # since multiple installable revisions of a repository can provide the + # same version of a tool (i.e. there may be another tool with the same + # guid that we should not remove from shed_tool_conf). + guid_paths_to_remove = [(_['guid'], _['tool_config']) for _ in metadata['tools']] shed_tool_conf = shed_tool_conf_dict['config_filename'] tool_path = shed_tool_conf_dict['tool_path'] config_elems = [] @@ -393,7 +400,7 @@ class ToolPanelManager(object): if config_elem.tag == 'section': tool_elems_to_remove = [] for tool_elem in config_elem: - if tool_elem.get('guid') in guids_to_remove: + if (tool_elem.get('guid'), tool_elem.get('file')) in guid_paths_to_remove: tool_elems_to_remove.append(tool_elem) for tool_elem in tool_elems_to_remove: # Remove all of the appropriate tool sub-elements from the section element. @@ -402,7 +409,7 @@ class ToolPanelManager(object): # Keep a list of all empty section elements so they can be removed. config_elems_to_remove.append(config_elem) elif config_elem.tag == 'tool': - if config_elem.get('guid') in guids_to_remove: + if (tool_elem.get('guid'), tool_elem.get('file')) in guid_paths_to_remove: config_elems_to_remove.append(config_elem) for config_elem in config_elems_to_remove: config_elems.remove(config_elem) @@ -424,18 +431,15 @@ class ToolPanelManager(object): # Create a list of guids for all tools that will be removed from the in-memory tool panel # and config file on disk. guids_to_remove = list(tool_panel_dict.keys()) - self.remove_guids(guids_to_remove, shed_tool_conf, uninstall) - - def remove_guids(self, guids_to_remove, shed_tool_conf, uninstall): toolbox = self.app.toolbox # Remove the tools from the toolbox's tools_by_id dictionary. for guid_to_remove in guids_to_remove: # remove_from_tool_panel to false, will handling that logic below. toolbox.remove_tool_by_id(guid_to_remove, remove_from_panel=False) shed_tool_conf_dict = self.get_shed_tool_conf_dict(shed_tool_conf) - # Always remove from the shed_tool_conf file on disk. Used to test for uninstall, not sure there is a legitimate use for this?! if uninstall: - self.remove_from_shed_tool_config(shed_tool_conf_dict, guids_to_remove) + # Remove from the shed_tool_conf file on disk. + self.remove_from_shed_tool_config(shed_tool_conf_dict, repository.metadata) def update_tool_panel_dict(self, tool_panel_dict, tool_panel_section_mapping, repository_tools_tups): for tool_guid in tool_panel_dict: diff --git a/test/unit/shed_unit/test_tool_panel_manager.py b/test/unit/shed_unit/test_tool_panel_manager.py index bf0ed4b319d..e8fd74ecfb5 100644 --- a/test/unit/shed_unit/test_tool_panel_manager.py +++ b/test/unit/shed_unit/test_tool_panel_manager.py @@ -128,7 +128,7 @@ class ToolPanelManagerTestCase(BaseToolBoxTestCase): assert "github.com/galaxyproject/example/test_tool/0.2" not in open(os.path.join(self.test_directory, "tool_conf.xml"), "r").read() self._verify_tool_confs() - self._remove_guids(["github.com/galaxyproject/example/test_tool/0.1"], uninstall=True) + self._remove_repository_contents("github.com/galaxyproject/example/test_tool/0.1", uninstall=True) # Now no versions of this tool are returned by new toolbox. new_toolbox = self.get_new_toolbox() @@ -144,7 +144,7 @@ class ToolPanelManagerTestCase(BaseToolBoxTestCase): self._setup_two_versions_in_config(section=True) self._setup_two_versions() self.toolbox - self._remove_guids(["github.com/galaxyproject/example/test_tool/0.2"], uninstall=uninstall) + self._remove_repository_contents("github.com/galaxyproject/example/test_tool/0.2", uninstall=uninstall) def _verify_version_2_removed_from_panel(self, section=True): # Check that test_tool now only has one version... @@ -164,9 +164,11 @@ class ToolPanelManagerTestCase(BaseToolBoxTestCase): next(iter(self.toolbox._tool_panel.values())).id == "github.com/galaxyproject/example/test_tool/0.1" assert "github.com/galaxyproject/example/test_tool/0.2" not in new_toolbox._integrated_tool_panel - def _remove_guids(self, guids, uninstall, shed_tool_conf="tool_conf.xml"): - self.tpm.remove_guids( - guids_to_remove=guids, + def _remove_repository_contents(self, guid, uninstall, shed_tool_conf="tool_conf.xml"): + tool = self.toolbox.get_tool(guid) + repository = tool.tool_shed_repository + self.tpm.remove_repository_contents( + repository=repository, shed_tool_conf=shed_tool_conf, uninstall=uninstall, ) diff --git a/test/unit/tools/test_toolbox.py b/test/unit/tools/test_toolbox.py index 50fb2722e54..5e10976ceab 100644 --- a/test/unit/tools/test_toolbox.py +++ b/test/unit/tools/test_toolbox.py @@ -71,7 +71,13 @@ class BaseToolBoxTestCase(unittest.TestCase, UsesApp, UsesTools): self.config_files = [] def _repo_install(self, changeset, config_filename=None): - metadata = {} + metadata = { + 'tools': [{ + 'add_to_tool_panel': False, # to have repository.includes_tools_for_display_in_tool_panel=False in InstalledRepositoryManager.activate_repository() + 'guid': "github.com/galaxyproject/example/test_tool/0.%s" % changeset, + 'tool_config': 'tool.xml' + }], + } if config_filename: metadata['shed_config_filename'] = config_filename repository = tool_shed_install.ToolShedRepository(metadata=metadata) @@ -98,7 +104,6 @@ class BaseToolBoxTestCase(unittest.TestCase, UsesApp, UsesTools): version2 = tool_shed_install.ToolVersion() version2.tool_id = "github.com/galaxyproject/example/test_tool/0.2" version2.repository = repository2 - self.app.install_model.context.add(version2) self.app.install_model.context.flush()