Skip to content

Commit

Permalink
Bring tool source one iteration closer to XML decouple dynamic options.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmchilton committed Jul 18, 2024
1 parent 3ba28f2 commit 5e1b7ab
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 11 deletions.
6 changes: 5 additions & 1 deletion lib/galaxy/tool_util/parameters/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,11 @@ def _from_input_source_galaxy(input_source: InputSource) -> ToolParameterT:
# Function... example in devteam cummeRbund.
optional = input_source.parse_optional()
dynamic_options = input_source.get("dynamic_options", None)
dynamic_options_elem = input_source.parse_dynamic_options_elem()
dynamic_options_config = input_source.parse_dynamic_options()
if dynamic_options_config:
dynamic_options_elem = dynamic_options.elem()
else:
dynamic_options_elem = None
multiple = input_source.get_bool("multiple", False)
is_static = dynamic_options is None and dynamic_options_elem is None
options: Optional[List[LabelValue]] = None
Expand Down
26 changes: 24 additions & 2 deletions lib/galaxy/tool_util/parser/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from pydantic import BaseModel
from typing_extensions import TypedDict

from galaxy.util import Element
from galaxy.util.path import safe_walk
from .util import _parse_name

Expand Down Expand Up @@ -362,6 +363,23 @@ def inputs_defined(self):
return True


class DynamicOptions(metaclass=ABCMeta):

def elem(self) -> Element:
# For things in transition that still depend on XML - provide a way
# to grab it and just throw an error if feature is attempted to be
# used with other tool sources.
raise NotImplementedError(NOT_IMPLEMENTED_MESSAGE)

@abstractmethod
def get_data_table_name(self) -> Optional[str]:
"""If dynamic options are loaded from a data table, return the name."""

@abstractmethod
def get_index_file_name(self) -> Optional[str]:
"""If dynamic options are loaded from an index file, return the name."""


class InputSource(metaclass=ABCMeta):
default_optional = False

Expand Down Expand Up @@ -421,8 +439,12 @@ def parse_optional(self, default=None):
default = self.default_optional
return self.get_bool("optional", default)

def parse_dynamic_options_elem(self):
"""Return an XML element describing dynamic options."""
def parse_dynamic_options(self) -> Optional[DynamicOptions]:
"""Return an optional element describing dynamic options.
These options are still very XML based but as they are adapted to the infrastructure, the return
type here will evolve.
"""
return None

def parse_static_options(self) -> List[Tuple[str, str, bool]]:
Expand Down
25 changes: 20 additions & 5 deletions lib/galaxy/tool_util/parser/xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from .interface import (
AssertionList,
Citation,
DynamicOptions,
InputSource,
PageSource,
PagesSource,
Expand Down Expand Up @@ -1217,6 +1218,22 @@ def parse_input_sources(self):
return list(map(XmlInputSource, self.parent_elem))


class XmlDynamicOptions(DynamicOptions):

def __init__(self, options_elem: Element):
self._options_elem = options_elem

def elem(self) -> Element:
return self._options_elem

def get_data_table_name(self) -> Optional[str]:
"""If dynamic options are loaded from a data table, return the name."""
return self._options_elem.get("from_data_table")

def get_index_file_name(self) -> Optional[str]:
return self._options_elem.get("from_file")


class XmlInputSource(InputSource):
def __init__(self, input_elem):
self.input_elem = input_elem
Expand Down Expand Up @@ -1246,12 +1263,10 @@ def parse_sanitizer_elem(self):
def parse_validator_elems(self):
return self.input_elem.findall("validator")

def parse_dynamic_options_elem(self):
"""Return a galaxy.tools.parameters.dynamic_options.DynamicOptions
if appropriate.
"""
def parse_dynamic_options(self) -> Optional[XmlDynamicOptions]:
"""Return a XmlDynamicOptions to describe dynamic options if options elem is available."""
options_elem = self.input_elem.find("options")
return options_elem
return XmlDynamicOptions(options_elem) if options_elem is not None else None

def parse_static_options(self) -> List[Tuple[str, str, bool]]:
"""
Expand Down
8 changes: 5 additions & 3 deletions lib/galaxy/tools/parameters/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,11 @@ def is_runtime_context(trans, other_values):


def parse_dynamic_options(param, input_source):
if (options_elem := input_source.parse_dynamic_options_elem()) is not None:
return dynamic_options.DynamicOptions(options_elem, param)
return None
dynamic_options_config = input_source.parse_dynamic_options()
if not dynamic_options_config:
return None
options_elem = dynamic_options_config.elem()
return dynamic_options.DynamicOptions(options_elem, param)


# Describe a parameter value error where there is no actual supplied
Expand Down

0 comments on commit 5e1b7ab

Please sign in to comment.