Source code for galaxy.tool_util.toolbox.views.static
import logging
import re
from typing import Optional
from .definitions import (
ExcludeTool,
ExcludeToolRegex,
ExcludeTypes,
ExpandedRootContent,
Label,
Section,
SectionAlias,
StaticToolBoxView,
Tool,
Workflow,
)
from .interface import (
ToolBoxRegistry,
ToolPanelView,
ToolPanelViewModel,
ToolPanelViewModelType,
)
from ..panel import (
panel_item_types,
ToolPanelElements,
ToolSection,
ToolSectionLabel,
)
log = logging.getLogger(__name__)
[docs]def build_filter(excludes_):
excludes = excludes_ or []
def filter_function(panel_key, panel_value):
for exclude in excludes:
if panel_key.startswith("tool_"):
if isinstance(exclude, ExcludeTool):
if panel_value.id == exclude.tool_id:
return False
if panel_value.old_id == exclude.tool_id:
return False
if isinstance(exclude, ExcludeToolRegex):
if re.match(exclude.tool_id_regex, panel_value.id):
return False
if re.match(exclude.tool_id_regex, panel_value.old_id):
return False
if isinstance(exclude, ExcludeTypes):
if panel_key.startswith("label_") and "label" in exclude.types:
return False
if panel_key.startswith("tool_") and "tool" in exclude.types:
return False
if panel_key.startswith("workflow_") and "workflow" in exclude.types:
return False
return True
return filter_function
[docs]class StaticToolPanelView(ToolPanelView):
_definition: StaticToolBoxView
[docs] def apply_view(self, base_tool_panel: ToolPanelElements, toolbox_registry: ToolBoxRegistry) -> ToolPanelElements:
def apply_filter(definition, elems):
excludes = self._all_excludes(definition)
if excludes:
elems.apply_filter(build_filter(excludes))
def definition_with_items_to_panel(definition, allow_sections: bool = True, items=None):
new_panel = ToolPanelElements()
if items is None:
items = definition.items_expanded
for element in items:
if element.content_type == "section":
assert allow_sections
section_def: Section = element
section: ToolSection
assert section_def.id is not None or section_def.name is not None
if element.items:
panel = definition_with_items_to_panel(section_def, allow_sections=False)
section = ToolSection()
if section_def.name is not None:
name = section_def.name
else:
assert section_def.id is not None
name = section_def.id
section.name = name
if section_def.id is not None:
section.id = section_def.id
else:
# TODO: there has to be tool shed code to do this in a consistent way... where is it?
section.id = name.replace(" ", "-").lower()
section.elems = panel
else:
closest_section = base_tool_panel.closest_section(section_def.id, section_def.name)
if closest_section is None:
log.warning(
f"Failed to find matching section for (id, name) = ({section_def.id}, {section_def.name})"
)
continue
section = closest_section.copy(merge_tools=True)
if section_def.id is not None:
section.id = section_def.id
if section_def.name is not None:
section.name = section_def.name
apply_filter(section_def, section.elems)
new_panel.append_section(section.id, section)
elif element.content_type == "section_alias":
assert allow_sections
closest_section = base_tool_panel.closest_section(element.section, element.section)
if closest_section is None:
log.warning(
f"Failed to find matching section for (id, name) = ({element.section}, {element.section})"
)
continue
section = closest_section.copy(merge_tools=True)
apply_filter(element, section.elems)
new_panel.append_section(section.id, section)
elif element.content_type == "label":
as_dict = {
"id": element.id or element.text.lower().replace(" ", "-"),
"text": element.text,
"type": "label",
}
label = ToolSectionLabel(as_dict)
key = f"label_{label.id}"
new_panel[key] = label
elif element.content_type == "tool":
tool_id = element.id
if not toolbox_registry.has_tool(tool_id):
log.warning(
f"Failed to find tool_id {tool_id} from parent toolbox, cannot load into panel view"
)
continue
tool = toolbox_registry.get_tool(tool_id)
toolbox_registry.add_tool_to_tool_panel_view(tool, new_panel)
elif element.content_type == "workflow":
workflow_def: Workflow = element
workflow = toolbox_registry.get_workflow(element.id)
panel_id = f"workflow_{workflow_def.id}"
new_panel[panel_id] = workflow
elif element.content_type == "items_from":
closest_section = base_tool_panel.closest_section(element.items_from, element.items_from)
if closest_section is None:
log.warning(f"Failed to find matching section for (id, name) = ({element.items_from}, None)")
continue
section = closest_section.copy(merge_tools=True)
elems = section.elems
apply_filter(element, elems)
for key, item in elems.items():
new_panel[key] = item
else:
raise AssertionError("Unknown static toolbox configuration element encountered.")
excludes = self._all_excludes(definition)
if excludes:
new_panel.apply_filter(build_filter(excludes))
return new_panel
root_defintion = self._definition
root_items = root_defintion.items_expanded
if root_items is None:
root_items = []
# No items found, use base tool panel and apply filters to that...
for _, panel_type, panel_value in base_tool_panel.panel_items_iter():
item: Optional[ExpandedRootContent] = None
if panel_type == panel_item_types.TOOL:
item = Tool(
id=panel_value.id,
)
elif panel_type == panel_item_types.SECTION:
item = SectionAlias(
section=panel_value.id,
)
elif panel_type == panel_item_types.LABEL:
item = Label(
id=panel_value.id,
text=panel_value.text,
)
elif panel_type == panel_item_types.WORKFLOW:
item = Workflow(
id=panel_value.id,
)
if item is None:
raise Exception("Unknown panel item type encountered.")
root_items.append(item)
return definition_with_items_to_panel(root_defintion, items=root_items)
def _all_excludes(self, has_excludes):
excludes = has_excludes.excludes or []
if has_excludes != self._definition and self._definition.excludes:
excludes.extend(self._definition.excludes)
return excludes
[docs] def to_model(self) -> ToolPanelViewModel:
model_id = self._definition.id
name = self._definition.name
description = self._definition.description
view_type = ToolPanelViewModelType[self._definition.view_type.value]
model_class = self.__class__.__name__
return ToolPanelViewModel(
id=model_id,
name=name,
description=description,
model_class=model_class,
view_type=view_type,
searchable=True,
)