mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge pull request #12448 from jmchilton/tool_panel_views_0
Easier to use static tool panel views.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
from enum import Enum
|
||||
from typing import List, Optional, Union
|
||||
from typing import Any, cast, List, Optional, Union
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from typing_extensions import Literal
|
||||
@@ -33,7 +33,7 @@ OptionalExclusionList = Optional[List[Exclusions]]
|
||||
|
||||
|
||||
class Tool(BaseModel):
|
||||
content_type: Literal['tool'] = Field(alias="type")
|
||||
content_type: Literal['tool'] = Field("tool", alias="type")
|
||||
id: str
|
||||
|
||||
class Config:
|
||||
@@ -78,13 +78,18 @@ SectionContent = Union[
|
||||
|
||||
|
||||
class HasItems:
|
||||
items: Optional[List[Any]]
|
||||
|
||||
@property
|
||||
def items_expanded(self):
|
||||
def items_expanded(self) -> Optional[List['ExpandedRootContent']]:
|
||||
if self.items is None:
|
||||
return None
|
||||
|
||||
# replace SectionAliases with individual SectionAlias objects
|
||||
# replace LabelShortcuts with Labels
|
||||
items = []
|
||||
items: List[ExpandedRootContent] = []
|
||||
for item in self.items:
|
||||
item = cast(RootContent, item)
|
||||
if isinstance(item, SectionAliases):
|
||||
for section in item.sections:
|
||||
section_alias = SectionAlias(
|
||||
@@ -138,14 +143,23 @@ RootContent = Union[
|
||||
ItemsFrom,
|
||||
]
|
||||
|
||||
ExpandedRootContent = Union[
|
||||
Section,
|
||||
SectionAlias,
|
||||
Tool,
|
||||
Label,
|
||||
Workflow,
|
||||
ItemsFrom,
|
||||
]
|
||||
|
||||
|
||||
class StaticToolBoxView(BaseModel, HasItems):
|
||||
id: str
|
||||
name: str
|
||||
description: Optional[str]
|
||||
view_type: StaticToolBoxViewTypeEnum = Field(alias="type")
|
||||
items: List[RootContent]
|
||||
excludes: Optional[List[Exclusions]]
|
||||
items: Optional[List[RootContent]] # if empty, use integrated tool panel
|
||||
excludes: OptionalExclusionList
|
||||
|
||||
@staticmethod
|
||||
def from_dict(as_dict):
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
import logging
|
||||
import re
|
||||
from typing import Optional
|
||||
|
||||
from .definitions import (
|
||||
ExcludeTool,
|
||||
ExcludeToolRegex,
|
||||
ExcludeTypes,
|
||||
ExpandedRootContent,
|
||||
Label,
|
||||
Section,
|
||||
SectionAlias,
|
||||
StaticToolBoxView,
|
||||
Tool,
|
||||
Workflow,
|
||||
)
|
||||
from .interface import (
|
||||
@@ -16,6 +21,7 @@ from .interface import (
|
||||
ToolPanelViewModelType,
|
||||
)
|
||||
from ..panel import (
|
||||
panel_item_types,
|
||||
ToolPanelElements,
|
||||
ToolSection,
|
||||
ToolSectionLabel,
|
||||
@@ -65,12 +71,15 @@ class StaticToolPanelView(ToolPanelView):
|
||||
def apply_view(self, base_tool_panel: ToolPanelElements, toolbox_registry: ToolBoxRegistry) -> ToolPanelElements:
|
||||
|
||||
def apply_filter(definition, elems):
|
||||
if definition.excludes:
|
||||
elems.apply_filter(build_filter(definition.excludes))
|
||||
excludes = self._all_excludes(definition)
|
||||
if excludes:
|
||||
elems.apply_filter(build_filter(excludes))
|
||||
|
||||
def definition_with_items_to_panel(definition, allow_sections: bool = True):
|
||||
def definition_with_items_to_panel(definition, allow_sections: bool = True, items=None):
|
||||
new_panel = ToolPanelElements()
|
||||
for element in definition.items_expanded:
|
||||
if items is None:
|
||||
items = definition.items_expanded
|
||||
for element in items:
|
||||
if element.content_type == "section":
|
||||
assert allow_sections
|
||||
section_def: Section = element
|
||||
@@ -145,12 +154,47 @@ class StaticToolPanelView(ToolPanelView):
|
||||
else:
|
||||
raise AssertionError("Unknown static toolbox configuration element encountered.")
|
||||
|
||||
if definition.excludes:
|
||||
new_panel.apply_filter(build_filter(definition.excludes))
|
||||
excludes = self._all_excludes(definition)
|
||||
if excludes:
|
||||
new_panel.apply_filter(build_filter(excludes))
|
||||
|
||||
return new_panel
|
||||
|
||||
return definition_with_items_to_panel(self._definition)
|
||||
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
|
||||
|
||||
def to_model(self) -> ToolPanelViewModel:
|
||||
model_id = self._definition.id
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
name: Globally Applied Filters
|
||||
type: activity
|
||||
items:
|
||||
- section: test
|
||||
excludes:
|
||||
- tool_id_regex: 'multi_data_.*'
|
||||
- tool_id_regex: '.*_text_option'
|
||||
@@ -0,0 +1,5 @@
|
||||
name: Globally Applied Filters
|
||||
type: activity
|
||||
excludes:
|
||||
- tool_id_regex: 'multi_data_.*'
|
||||
- tool_id_regex: '.*_text_option'
|
||||
@@ -95,6 +95,21 @@ class PanelViewsFromDirectoryIntegrationTestCase(integration_util.IntegrationTes
|
||||
assert len(index_as_list) == 2
|
||||
assert model_classes(index_as_list) == ["ToolSection", "ToolSection"]
|
||||
|
||||
def test_global_filters(self):
|
||||
index = self.galaxy_interactor.get("tools", data=dict(in_panel=True, view="custom_11"))
|
||||
verify_custom_regex_filtered(index)
|
||||
|
||||
def test_global_filters_on_integrated_panel(self):
|
||||
index = self.galaxy_interactor.get("tools", data=dict(in_panel=True, view="custom_12"))
|
||||
index.raise_for_status()
|
||||
index_as_list = index.json()
|
||||
sections = [x for x in index_as_list if x["model_class"] == "ToolSection"]
|
||||
assert len(sections) == 2
|
||||
section = sections[0]
|
||||
assert section["id"] == "test"
|
||||
tools = section["elems"]
|
||||
assert len(tools) == 2, len(tools)
|
||||
|
||||
|
||||
class PanelViewsFromConfigIntegrationTestCase(integration_util.IntegrationTestCase):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user