"""This module is used to parse tool_conf files.
These files define tool lists, sections, labels, etc... the elements of the
Galaxy tool panel.
"""
from abc import (
ABCMeta,
abstractmethod,
)
import yaml
from galaxy.util import (
parse_xml,
string_as_bool,
)
from galaxy.util.path import StrPath
DEFAULT_MONITOR = False
class ToolConfSource(metaclass=ABCMeta):
"""Interface represents a container of tool references."""
@abstractmethod
def parse_items(self):
"""Return a list of ToolConfItem describing source."""
@abstractmethod
def parse_tool_path(self):
"""Return tool_path for tools in this toolbox or None."""
@abstractmethod
def is_shed_tool_conf(self):
"""Decide if this tool conf is a shed tool conf."""
def parse_monitor(self):
"""Monitor the toolbox configuration source for changes and reload."""
return DEFAULT_MONITOR
class XmlToolConfSource(ToolConfSource):
def __init__(self, config_filename: StrPath):
tree = parse_xml(config_filename)
self.root = tree.getroot()
def parse_tool_path(self):
return self.root.get("tool_path")
def parse_tool_cache_data_dir(self):
return self.root.get("tool_cache_data_dir")
def parse_items(self):
return [ensure_tool_conf_item(_) for _ in self.root]
def is_shed_tool_conf(self):
has_tool_path = self.parse_tool_path() is not None
is_shed_conf = string_as_bool(self.root.get("is_shed_conf", "True"))
return has_tool_path and is_shed_conf
def parse_monitor(self):
return string_as_bool(self.root.get("monitor", DEFAULT_MONITOR))
class YamlToolConfSource(ToolConfSource):
def __init__(self, config_filename: StrPath):
with open(config_filename) as f:
as_dict = yaml.safe_load(f)
self.as_dict = as_dict
def parse_tool_path(self):
return self.as_dict.get("tool_path")
def parse_tool_cache_data_dir(self):
return self.as_dict.get("tool_cache_data_dir")
def parse_items(self):
return [ToolConfItem.from_dict(_) for _ in self.as_dict.get("items")]
def parse_monitor(self):
return self.as_dict.get("monitor", DEFAULT_MONITOR)
def is_shed_tool_conf(self):
return False
class ToolConfItem:
"""Abstract description of a tool conf item.
These may include tools, labels, sections, and workflows.
"""
def __init__(self, type, attributes, elem=None):
self.type = type
self.attributes = attributes
self._elem = elem
@classmethod
def from_dict(cls, _as_dict):
as_dict = _as_dict.copy()
type = as_dict.get("type")
del as_dict["type"]
attributes = as_dict
if type == "section":
items = [cls.from_dict(_) for _ in as_dict["items"]]
del as_dict["items"]
item = ToolConfSection(attributes, items)
else:
item = ToolConfItem(type, attributes)
return item
def get(self, key, default=None):
return self.attributes.get(key, default)
@property
def has_elem(self):
return self._elem is not None
@property
def elem(self):
if self._elem is None:
raise Exception("item.elem called on toolbox element from non-XML source")
return self._elem
@property
def labels(self):
labels = None
if "labels" in self.attributes:
labels = [label.strip() for label in self.attributes["labels"].split(",")]
return labels
class ToolConfSection(ToolConfItem):
def __init__(self, attributes, items, elem=None):
super().__init__("section", attributes, elem)
self.items = items
__all__ = (
"get_toolbox_parser",
"ensure_tool_conf_item",
)