Merge pull request #15079 from jmchilton/tool_test_typing

Type some of tool test parsing code.
This commit is contained in:
David López
2022-11-30 10:05:11 +01:00
committed by GitHub
3 changed files with 53 additions and 18 deletions
+28 -1
View File
@@ -7,19 +7,46 @@ from abc import (
)
from os.path import join
from typing import (
Any,
Dict,
List,
Optional,
Tuple,
Union,
)
import packaging.version
from typing_extensions import TypedDict
from galaxy.util.path import safe_walk
from .util import _parse_name
NOT_IMPLEMENTED_MESSAGE = "Galaxy tool format does not yet support this tool feature."
AssertionDict = TypedDict(
"AssertionDict", {"tag": str, "attributes": Dict[str, Any], "children": Optional[List[Dict[str, Any]]]}
)
AssertionList = Optional[List[AssertionDict]]
XmlInt = Union[str, int]
ToolSourceTest = TypedDict(
"ToolSourceTest",
{
"inputs": Any,
"outputs": Any,
"output_collections": List[Any],
"stdout": AssertionList,
"stderr": AssertionList,
"expect_exit_code": Optional[XmlInt],
"expect_failure": bool,
"expect_test_failure": bool,
"maxseconds": Optional[XmlInt],
"expect_num_outputs": Optional[XmlInt],
"command": AssertionList,
"command_version": AssertionList,
},
)
ToolSourceTests = TypedDict("ToolSourceTests", {"tests": List[ToolSourceTest]})
class ToolSource(metaclass=ABCMeta):
"""This interface represents an abstract source to parse tool
@@ -268,7 +295,7 @@ class ToolSource(metaclass=ABCMeta):
paths_and_modtimes[self.source_path] = os.path.getmtime(self.source_path)
return paths_and_modtimes
def parse_tests_to_dict(self):
def parse_tests_to_dict(self) -> ToolSourceTests:
return {"tests": []}
def __str__(self):
+13 -7
View File
@@ -3,7 +3,10 @@ import logging
import math
import re
import uuid
from typing import Optional
from typing import (
List,
Optional,
)
import packaging.version
@@ -19,6 +22,7 @@ from galaxy.util import (
xml_to_string,
)
from .interface import (
AssertionList,
InputSource,
PageSource,
PagesSource,
@@ -26,6 +30,8 @@ from .interface import (
TestCollectionDef,
TestCollectionOutputDef,
ToolSource,
ToolSourceTest,
ToolSourceTests,
)
from .output_actions import ToolOutputActionGroup
from .output_collection_def import dataset_collector_descriptions_from_elem
@@ -537,10 +543,10 @@ class XmlToolSource(ToolSource):
def source_path(self):
return self._source_path
def parse_tests_to_dict(self):
def parse_tests_to_dict(self) -> ToolSourceTests:
tests_elem = self.root.find("tests")
tests = []
rval = dict(tests=tests)
tests: List[ToolSourceTest] = []
rval: ToolSourceTests = dict(tests=tests)
if tests_elem is not None:
for i, test_elem in enumerate(tests_elem.findall("test")):
@@ -587,8 +593,8 @@ class XmlToolSource(ToolSource):
return creators
def _test_elem_to_dict(test_elem, i, profile=None):
rval = dict(
def _test_elem_to_dict(test_elem, i, profile=None) -> ToolSourceTest:
rval: ToolSourceTest = dict(
outputs=__parse_output_elems(test_elem),
output_collections=__parse_output_collection_elems(test_elem, profile=profile),
inputs=__parse_input_elems(test_elem, i),
@@ -737,7 +743,7 @@ def __parse_assert_list(output_elem):
return __parse_assert_list_from_elem(assert_elem)
def __parse_assert_list_from_elem(assert_elem):
def __parse_assert_list_from_elem(assert_elem) -> AssertionList:
assert_list = None
def convert_elem(elem):
+12 -10
View File
@@ -12,10 +12,14 @@ from galaxy.tool_util.parser.util import (
DEFAULT_DELTA_FRAC,
)
from .interface import (
AssertionDict,
AssertionList,
InputSource,
PageSource,
PagesSource,
ToolSource,
ToolSourceTest,
ToolSourceTests,
)
from .output_collection_def import dataset_collector_descriptions_from_output_dict
from .output_objects import (
@@ -177,9 +181,9 @@ class YamlToolSource(ToolSource):
)
return output_collection
def parse_tests_to_dict(self):
tests = []
rval = dict(tests=tests)
def parse_tests_to_dict(self) -> ToolSourceTests:
tests: List[ToolSourceTest] = []
rval: ToolSourceTests = dict(tests=tests)
for i, test_dict in enumerate(self.root_dict.get("tests", [])):
tests.append(_parse_test(i, test_dict))
@@ -206,7 +210,7 @@ class YamlToolSource(ToolSource):
return json.dumps(self.root_dict)
def _parse_test(i, test_dict):
def _parse_test(i, test_dict) -> ToolSourceTest:
inputs = test_dict["inputs"]
if is_dict(inputs):
new_inputs = []
@@ -231,7 +235,7 @@ def _parse_test(i, test_dict):
name = output["name"]
value = output.get("file", None)
attributes = output
new_outputs.append((name, value, attributes))
new_outputs.append({"name": name, "value": value, "attributes": attributes})
for output in new_outputs:
attributes = output["attributes"]
@@ -246,8 +250,6 @@ def _parse_test(i, test_dict):
attributes["extra_files"] = []
# TODO
attributes["metadata"] = {}
# TODO
assert_list = []
assert_list = __to_test_assert_list(attributes.get("asserts", []))
attributes["assert_list"] = assert_list
_ensure_has(attributes, defaults)
@@ -264,7 +266,7 @@ def _parse_test(i, test_dict):
return test_dict
def __to_test_assert_list(assertions):
def __to_test_assert_list(assertions) -> AssertionList:
def expand_dict_form(item):
key, value = item
new_value = value.copy()
@@ -274,7 +276,7 @@ def __to_test_assert_list(assertions):
if is_dict(assertions):
assertions = map(expand_dict_form, assertions.items())
assert_list = []
assert_list: List[AssertionDict] = []
for assertion in assertions:
# TODO: not handling nested assertions correctly,
# not sure these are used though.
@@ -282,7 +284,7 @@ def __to_test_assert_list(assertions):
if "children" in assertion:
children = assertion["children"]
del assertion["children"]
assert_dict = dict(
assert_dict: AssertionDict = dict(
tag=assertion["that"],
attributes=assertion,
children=children,