Skip to content

Commit

Permalink
Merge pull request #15825 from bernt-matthias/validation_metadata
Browse files Browse the repository at this point in the history
Add ability to assert metadata properties on input dataset parameters
  • Loading branch information
mvdbeek authored Jul 29, 2023
2 parents 7cdb480 + 6bd654c commit fa64fc6
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 5 deletions.
20 changes: 20 additions & 0 deletions lib/galaxy/tool_util/linters/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
],
"filename": ["dataset_metadata_in_file"],
"metadata_name": [
"dataset_metadata_equal",
"dataset_metadata_in_data_table",
"dataset_metadata_not_in_data_table",
"dataset_metadata_in_file",
Expand All @@ -56,6 +57,8 @@
"exclude_max": ["in_range", "dataset_metadata_in_range"],
"split": ["dataset_metadata_in_file"],
"skip": ["metadata"],
"value": ["dataset_metadata_equal"],
"value_json": ["dataset_metadata_equal"],
}

PARAMETER_VALIDATOR_TYPE_COMPATIBILITY = {
Expand All @@ -66,6 +69,7 @@
"no_options",
"unspecified_build",
"dataset_ok_validator",
"dataset_metadata_equal",
"dataset_metadata_in_range",
"dataset_metadata_in_file",
"dataset_metadata_in_data_table",
Expand All @@ -77,6 +81,7 @@
"no_options",
"unspecified_build",
"dataset_ok_validator",
"dataset_metadata_equal",
"dataset_metadata_in_range",
"dataset_metadata_in_file",
"dataset_metadata_in_data_table",
Expand Down Expand Up @@ -415,6 +420,21 @@ def lint_inputs(tool_source: "ToolSource", lint_ctx: "LintContext"):
f"Parameter [{param_name}]: '{vtype}' validators need to define the 'min' or 'max' attribute(s)",
node=validator,
)
if vtype in ["dataset_metadata_equal"]:
if (
not ("value" in validator.attrib or "value_json" in validator.attrib)
or "metadata_name" not in validator.attrib
):
lint_ctx.error(
f"Parameter [{param_name}]: '{vtype}' validators need to define the 'value'/'value_json' and 'metadata_name' attributes",
node=validator,
)
if "value" in validator.attrib and "value_json" in validator.attrib:
lint_ctx.error(
f"Parameter [{param_name}]: '{vtype}' validators must not define the 'value' and the 'value_json' attributes",
node=validator,
)

if vtype in ["metadata"] and ("check" not in validator.attrib and "skip" not in validator.attrib):
lint_ctx.error(
f"Parameter [{param_name}]: '{vtype}' validators need to define the 'check' or 'skip' attribute(s)",
Expand Down
16 changes: 15 additions & 1 deletion lib/galaxy/tool_util/xsd/galaxy.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -4413,6 +4413,7 @@ Note that each data parameter has automatically a metadata validator that checks
if all non-optional metadata are set, i.e. ``<validator type="metadata/>``.
- ``unspecified_build``: Check of a build is defined.
- ``dataset_ok_validator``: Check if the data set is in state OK.
- ``dataset_metadata_equal``: Check if metadata (given by ``metadata_name``) is equal to a given string value (given by ``value``) or JSON encoded value (given by ``value_json``). ``value_json`` needs to be used for all non string types (e.g. int, float, list, dict).
- ``dataset_metadata_in_range``: Check if a numeric metadata value is within
a given range.
- ``dataset_metadata_in_data_table``: Check if a metadata value is contained in a column of a data table.
Expand Down Expand Up @@ -4501,7 +4502,7 @@ use in filenames may not contain ``..``.
<xs:annotation>
<xs:documentation xml:lang="en"><![CDATA[
Valid values are: ``expression``, ``regex``, ``in_range``, ``length``,
``metadata``, ``unspecified_build``, ``no_options``, ``empty_field``,
``metadata``, ``metadata_eq`` ``unspecified_build``, ``no_options``, ``empty_field``,
``dataset_metadata_in_data_table``, ``dataset_metadata_not_in_data_table``,
``value_in_data_table``, ``value_not_in_data_table``,
``dataset_ok_validator``, ``dataset_metadata_in_range``.
Expand Down Expand Up @@ -4600,6 +4601,18 @@ fields to skip if type is ``metadata``. If not specified, all non-optional
metadata fields will be checked unless ``check`` attribute is specified.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="value" type="xs:string">
<xs:annotation>
<xs:documentation xml:lang="en">Value to check the metadata against. Only
applicable to ``dataset_metadata_equal``. Mutually exclusive with ``value_json``.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="value_json" type="xs:string">
<xs:annotation>
<xs:documentation xml:lang="en">JSON encoded value to check the metadata against. Only
applicable to ``dataset_metadata_equal``. Mutually exclusive with ``value``.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="line_startswith" type="xs:string">
<xs:annotation>
<xs:documentation xml:lang="en">Deprecated. Used to indicate lines in the file
Expand Down Expand Up @@ -7069,6 +7082,7 @@ and ``bibtex`` are the only supported options.</xs:documentation>
<xs:enumeration value="in_range"/>
<xs:enumeration value="length"/>
<xs:enumeration value="metadata"/>
<xs:enumeration value="dataset_metadata_equal" gxdocs:added="23.1"/>
<xs:enumeration value="unspecified_build"/>
<xs:enumeration value="no_options"/>
<xs:enumeration value="empty_field"/>
Expand Down
40 changes: 39 additions & 1 deletion lib/galaxy/tools/parameters/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Classes related to parameter validation.
"""
import abc
import json
import logging
import os.path
import re
Expand Down Expand Up @@ -31,7 +32,7 @@ class Validator(abc.ABC):
@classmethod
def from_element(cls, param, elem):
"""
Initialize the appropiate Validator class
Initialize the appropriate Validator class
example call `validation.Validator.from_element(ToolParameter_object, Validator_object)`
Expand Down Expand Up @@ -559,6 +560,42 @@ def validate(self, value, trans=None):
super().validate(isinstance(value, model.DatasetInstance) and not missing, value_to_show=missing)


class MetadataEqualsValidator(Validator):
"""
Validator that checks for a metadata value for equality
metadata values that are lists are converted as comma separated string
everything else is converted to the string representation
"""

requires_dataset_metadata = True

def __init__(self, metadata_name=None, value=None, message=None, negate="false"):
if not message:
if not util.asbool(negate):
message = f"Metadata value for '{metadata_name}' must be '{value}', but it is '%s'."
else:
message = f"Metadata value for '{metadata_name}' must not be '{value}' but it is."
super().__init__(message, negate)
self.metadata_name = metadata_name
self.value = value

@classmethod
def from_element(cls, param, elem):
value = elem.get("value", None) or json.loads(elem.get("value_json", "null"))
return cls(
metadata_name=elem.get("metadata_name", None),
value=value,
message=elem.get("message", None),
negate=elem.get("negate", "false"),
)

def validate(self, value, trans=None):
if value:
metadata_value = getattr(value.metadata, self.metadata_name)
super().validate(metadata_value == self.value, value_to_show=metadata_value)


class UnspecifiedBuildValidator(Validator):
"""
Validator that checks for dbkey not equal to '?'
Expand Down Expand Up @@ -949,6 +986,7 @@ def validate(self, value, trans=None):
in_range=InRangeValidator,
length=LengthValidator,
metadata=MetadataValidator,
dataset_metadata_equal=MetadataEqualsValidator,
unspecified_build=UnspecifiedBuildValidator,
no_options=NoOptionsValidator,
empty_field=EmptyTextfieldValidator,
Expand Down
Loading

0 comments on commit fa64fc6

Please sign in to comment.