Warning
This document is for an old release of Galaxy. You can alternatively view this page in the latest release if it exists or view the top of the latest release's documentation.
Source code for galaxy.tool_util.toolbox.panel
from abc import abstractmethod
from enum import Enum
from typing import (
Dict,
Optional,
Tuple,
)
from galaxy.util.dictifiable import Dictifiable
from galaxy.util.odict import odict
from .parser import ensure_tool_conf_item
[docs]class panel_item_types(str, Enum):
TOOL = "TOOL"
WORKFLOW = "WORKFLOW"
SECTION = "SECTION"
LABEL = "LABEL"
[docs]class HasPanelItems:
""" """
[docs] @abstractmethod
def panel_items(self):
"""Return an ordered dictionary-like object describing tool panel
items (such as workflows, tools, labels, and sections).
"""
[docs] def panel_items_iter(self):
"""Iterate through panel items each represented as a tuple of
(panel_key, panel_type, panel_content).
"""
for panel_key, panel_value in self.panel_items().items():
if panel_value is None:
continue
panel_type = panel_item_types.SECTION
if panel_key.startswith("tool_"):
panel_type = panel_item_types.TOOL
elif panel_key.startswith("label_"):
panel_type = panel_item_types.LABEL
elif panel_key.startswith("workflow_"):
panel_type = panel_item_types.WORKFLOW
yield (panel_key, panel_type, panel_value)
[docs]class ToolSection(Dictifiable, HasPanelItems):
"""
A group of tools with similar type/purpose that will be displayed as a
group in the user interface.
"""
dict_collection_visible_keys = ["id", "name", "version", "description", "links"]
[docs] def __init__(self, item=None):
"""Build a ToolSection from an ElementTree element or a dictionary."""
if item is None:
item = dict()
self.name = item.get("name") or ""
self.id = item.get("id") or ""
self.version = item.get("version") or ""
self.description = item.get("description") or None
self.links = item.get("links") or None
self.elems = ToolPanelElements()
[docs] def copy(self, merge_tools=False):
copy = ToolSection()
copy.name = self.name
copy.id = self.id
copy.version = self.version
copy.description = self.description
copy.links = self.links
for key, panel_type, value in self.panel_items_iter():
if panel_type == panel_item_types.TOOL and merge_tools:
tool = value
tool_lineage = tool.lineage
tool_copied = False
if tool_lineage is not None:
version_ids = tool_lineage.get_version_ids(reverse=True)
for version_id in version_ids:
if copy.elems.has_tool_with_id(version_id):
tool_copied = True
break
if self.elems.has_tool_with_id(version_id):
copy.elems.append_tool(self.elems.get_tool_with_id(version_id))
tool_copied = True
break
if not tool_copied:
copy.elems[key] = value
else:
copy.elems[key] = value
return copy
[docs] def to_dict(self, trans, link_details=False, tool_help=False, toolbox=None, only_ids=False):
"""Return a dict that includes section's attributes.
if `only_ids` is `True`, we store only the ids of the section's tools in `section.tools`
(also full `ToolSectionLabel` objects in `section.tools` if any are present)
if `only_ids` is `False`, we store the section's full `Tool` (and any other) objects in
`section.elems`
"""
section_dict = super().to_dict()
section_elts = []
kwargs = dict(trans=trans, link_details=link_details, tool_help=tool_help)
for elt in self.elems.values():
if hasattr(elt, "tool_type") and toolbox:
if only_ids:
section_elts.append(elt.id)
else:
section_elts.append(toolbox.get_tool_to_dict(trans, elt, tool_help=tool_help))
elif not only_ids or (only_ids and elt.text):
# if !only_ids or (only_ids & section has a ToolSectionLabel within it)
section_elts.append(elt.to_dict(**kwargs))
if only_ids:
section_dict["tools"] = section_elts
else:
section_dict["elems"] = section_elts
return section_dict
[docs]class ToolSectionLabel(Dictifiable):
"""
A label for a set of tools that can be displayed above groups of tools
and sections in the user interface
"""
dict_collection_visible_keys = ["id", "text", "version", "description", "links"]
[docs] def __init__(self, item):
"""Build a ToolSectionLabel from an ElementTree element or a
dictionary.
"""
item = ensure_tool_conf_item(item)
self.text = item.get("text")
self.id = item.get("id")
self.version = item.get("version") or ""
self.description = item.get("description") or None
self.links = item.get("links", None)
[docs]class ToolPanelElements(odict, HasPanelItems):
"""Represents an ordered dictionary of tool entries - abstraction
used both by tool panel itself (normal and integrated) and its sections.
"""
_section_by_tool: Dict[str, Tuple[str, str]] = {}
[docs] def record_section_for_tool_id(self, tool_id: str, key: str, val: str):
self._section_by_tool[tool_id] = (key, val)
[docs] def get_section_for_tool_id(self, tool_id: str) -> Tuple[Optional[str], Optional[str]]:
if tool_id in self._section_by_tool:
return self._section_by_tool[tool_id]
return (None, None)
[docs] def replace_tool_for_id(self, tool_id: str, new_tool) -> None:
tool_key = f"tool_{tool_id}"
for key, val in self.items():
if key == tool_key:
self[key] = new_tool
break
elif key.startswith("section"):
if tool_key in val.elems:
self[key].elems[tool_key] = new_tool
break
[docs] def get_or_create_section(
self, sec_id: str, sec_nm: str, description: Optional[str] = None, links: Optional[Dict[str, str]] = None
) -> ToolSection:
if sec_id not in self:
section = ToolSection(
{"id": sec_id, "name": sec_nm, "description": description, "version": "", "links": links}
)
self[sec_id] = section
else:
section = self[sec_id]
return section
[docs] def remove_tool(self, tool_id: str) -> None:
tool_key = f"tool_{tool_id}"
for key, val in self.items():
if key == tool_key:
del self[key]
break
elif key.startswith("section"):
if tool_key in val.elems:
del self[key].elems[tool_key]
break
[docs] def update_or_append(self, index: int, key: str, value) -> None:
if key in self or index is None:
self[key] = value
else:
self.insert(index, key, value)
[docs] def get_label(self, label: str) -> Optional[ToolSection]:
for element in self.values():
if isinstance(element, ToolSection) and element.name == label:
return element
return None
[docs] def replace_tool(self, previous_tool_id: str, new_tool_id: str, tool) -> None:
previous_key = f"tool_{previous_tool_id}"
new_key = f"tool_{new_tool_id}"
index = self.keys().index(previous_key)
del self[previous_key]
self.insert(index, new_key, tool)
[docs] def index_of_tool_id(self, tool_id: str) -> Optional[int]:
query_key = f"tool_{tool_id}"
for index, target_key in enumerate(self.keys()):
if query_key == target_key:
return index
return None
[docs] def insert_tool(self, index: int, tool) -> None:
key = f"tool_{tool.id}"
self.insert(index, key, tool)
[docs] def walk_sections(self):
for key, item in self.items():
if isinstance(item, ToolSection):
yield (key, item)
[docs] def closest_section(self, target_section_id: Optional[str], target_section_name: Optional[str]):
for section_id, section in self.walk_sections():
if section_id == target_section_id:
return section
for _, section in self.walk_sections():
if section.name == target_section_name:
return section
return None
[docs] def apply_filter(self, f):
to_remove = []
for key, item in self.items():
if not f(key, item):
to_remove.append(key)
for key in to_remove:
del self[key]
[docs] def copy(self) -> "ToolPanelElements":
the_copy = ToolPanelElements()
the_copy.update(self)
return the_copy
[docs] def has_item_recursive(self, item):
"""Check panel and section elements for supplied item."""
for value in self.values():
if value == item:
return True
if isinstance(value, ToolSection):
if item in value.elems.values():
return True
return False