Unverified Commit ca1d2f57 authored by Marius van den Beek's avatar Marius van den Beek Committed by GitHub
Browse files

Merge pull request #14572 from bernt-matthias/topic/lint-data-options

[22.05] linter: allow options elements in data params
parents 7c8d732e 327e4221
Loading
Loading
Loading
Loading
+32 −1
Original line number Diff line number Diff line
@@ -109,7 +109,7 @@ PARAMETER_VALIDATOR_TYPE_COMPATIBILITY = {
}

PARAM_TYPE_CHILD_COMBINATIONS = [
    ("./options", ["select", "drill_down"]),
    ("./options", ["data", "select", "drill_down"]),
    ("./options/option", ["drill_down"]),
    ("./column", ["data_column"]),
]
@@ -168,6 +168,37 @@ def lint_inputs(tool_xml, lint_ctx):
                lint_ctx.warn(
                    f"Param input [{param_name}] with no format specified - 'data' format will be assumed.", node=param
                )
            options = param.findall("./options")
            has_options_filter_attribute = False
            if len(options) == 1:
                for oa in options[0].attrib:
                    if oa == "options_filter_attribute":
                        has_options_filter_attribute = True
                    else:
                        lint_ctx.error(f"Data parameter [{param_name}] uses invalid attribute: {oa}", node=param)
            elif len(options) > 1:
                lint_ctx.error(f"Data parameter [{param_name}] contains multiple options elements.", node=options[1])
            # for data params only filters with key='build' of type='data_meta' are allowed
            filters = param.findall("./options/filter")
            for f in filters:
                if not f.get("ref"):
                    lint_ctx.error(
                        f"Data parameter [{param_name}] filter needs to define a ref attribute",
                        node=f,
                    )
                if has_options_filter_attribute:
                    if f.get("type") != "data_meta":
                        lint_ctx.error(
                            f'Data parameter [{param_name}] for filters only type="data_meta" is allowed, found type="{f.get("type")}"',
                            node=f,
                        )
                else:
                    if f.get("key") != "dbkey" or f.get("type") != "data_meta":
                        lint_ctx.error(
                            f'Data parameter [{param_name}] for filters only type="data_meta" and key="dbkey" are allowed, found type="{f.get("type")}" and key="{f.get("key")}"',
                            node=f,
                        )

        elif param_type == "select":
            # get dynamic/statically defined options
            dynamic_options = param.get("dynamic_options", None)
+8 −5
Original line number Diff line number Diff line
@@ -3968,14 +3968,17 @@ dataset for the contained input of the type specified using the ``type`` tag.
  <xs:complexType name="ParamOptions">
    <xs:annotation>
      <xs:documentation xml:lang="en"><![CDATA[

See [/tools/extract/liftOver_wrapper.xml](https://github.com/galaxyproject/galaxy/blob/master/tools/extract/liftOver_wrapper.xml)
for an example of how to use this tag set. This tag set is optionally contained
within the ``<param>`` tag when the ``type`` attribute value is ``select`` or
``data`` and used to dynamically generated lists of options. This tag set
dynamically creates a list of options whose values can be
obtained from a predefined file stored locally or a dataset selected from the
current history.
``data`` and used to dynamically generated lists of options.

For data parameters this tag can be used to restrict possible input datasets to datasets that match the ``dbkey`` of another data input by including a ``data_meta`` filter. See for
instance here: [/tools/maf/interval2maf.xml](https://github.com/galaxyproject/galaxy/blob/master/tools/maf/interval2maf.xml)

For select parameters this tag set dynamically creates a list of options whose
values can be obtained from a predefined file stored locally or a dataset
selected from the current history.

There are at least five basic ways to use this tag - four of these correspond to
a ``from_XXX`` attribute on the ``options`` directive and the other is to
+74 −1
Original line number Diff line number Diff line
@@ -192,6 +192,43 @@ INPUTS_DATA_PARAM = """
</tool>
"""

INPUTS_DATA_PARAM_OPTIONS = """
<tool>
    <inputs>
        <param name="valid_name" type="data" format="txt">
            <options>
                <filter type="data_meta" key="dbkey" ref="input"/>
            </options>
        </param>
    </inputs>
</tool>
"""

INPUTS_DATA_PARAM_OPTIONS_FILTER_ATTRIBUTE = """
<tool>
    <inputs>
        <param name="valid_name" type="data" format="txt">
            <options options_filter_attribute="metadata.foo">
                <filter type="data_meta" key="foo" ref="input"/>
            </options>
        </param>
    </inputs>
</tool>
"""

INPUTS_DATA_PARAM_INVALIDOPTIONS = """
<tool>
    <inputs>
        <param name="valid_name" type="data" format="txt">
            <options/>
            <options from_file="blah">
                <filter type="expression"/>
            </options>
        </param>
    </inputs>
</tool>
"""

INPUTS_CONDITIONAL = """
<tool>
    <inputs>
@@ -1034,6 +1071,42 @@ def test_inputs_data_param(lint_ctx):
    assert not lint_ctx.error_messages


def test_inputs_data_param_options(lint_ctx):
    tool_source = get_xml_tool_source(INPUTS_DATA_PARAM_OPTIONS)
    run_lint(lint_ctx, inputs.lint_inputs, tool_source)
    assert not lint_ctx.valid_messages
    assert "Found 1 input parameters." in lint_ctx.info_messages
    assert len(lint_ctx.info_messages) == 1
    assert not lint_ctx.warn_messages
    assert not lint_ctx.error_messages


def test_inputs_data_param_options_filter_attribute(lint_ctx):
    tool_source = get_xml_tool_source(INPUTS_DATA_PARAM_OPTIONS_FILTER_ATTRIBUTE)
    run_lint(lint_ctx, inputs.lint_inputs, tool_source)
    assert not lint_ctx.valid_messages
    assert "Found 1 input parameters." in lint_ctx.info_messages
    assert len(lint_ctx.info_messages) == 1
    assert not lint_ctx.warn_messages
    assert not lint_ctx.error_messages


def test_inputs_data_param_invalid_options(lint_ctx):
    tool_source = get_xml_tool_source(INPUTS_DATA_PARAM_INVALIDOPTIONS)
    run_lint(lint_ctx, inputs.lint_inputs, tool_source)
    assert not lint_ctx.valid_messages
    assert "Found 1 input parameters." in lint_ctx.info_messages
    assert len(lint_ctx.info_messages) == 1
    assert not lint_ctx.warn_messages
    assert "Data parameter [valid_name] contains multiple options elements." in lint_ctx.error_messages
    assert "Data parameter [valid_name] filter needs to define a ref attribute" in lint_ctx.error_messages
    assert (
        'Data parameter [valid_name] for filters only type="data_meta" and key="dbkey" are allowed, found type="expression" and key="None"'
        in lint_ctx.error_messages
    )
    assert len(lint_ctx.error_messages) == 3


def test_inputs_conditional(lint_ctx):
    tool_source = get_xml_tool_source(INPUTS_CONDITIONAL)
    run_lint(lint_ctx, inputs.lint_inputs, tool_source)
@@ -1219,7 +1292,7 @@ def test_inputs_type_child_combinations(lint_ctx):
    assert not lint_ctx.valid_messages
    assert not lint_ctx.warn_messages
    assert (
        "Parameter [text_param] './options' tags are only allowed for parameters of type ['select', 'drill_down']"
        "Parameter [text_param] './options' tags are only allowed for parameters of type ['data', 'select', 'drill_down']"
        in lint_ctx.error_messages
    )
    assert (