From 12a4464b4875814892d24ba8ccd2d0c686d8a82f Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Sun, 19 Mar 2023 18:40:32 +0100 Subject: [PATCH] finish metadata equal validator --- lib/galaxy/tool_util/linters/inputs.py | 11 +++++ lib/galaxy/tool_util/xsd/galaxy.xsd | 10 ++++- lib/galaxy/tools/parameters/validation.py | 36 ++++++++++----- test/functional/tools/metadata_check_eq.xml | 50 ++++++++++++++++----- test/unit/tool_util/test_tool_linters.py | 10 ++++- 5 files changed, 92 insertions(+), 25 deletions(-) diff --git a/lib/galaxy/tool_util/linters/inputs.py b/lib/galaxy/tool_util/linters/inputs.py index 4721d580644..5271bb8d23d 100644 --- a/lib/galaxy/tool_util/linters/inputs.py +++ b/lib/galaxy/tool_util/linters/inputs.py @@ -32,6 +32,7 @@ ATTRIB_VALIDATOR_COMPATIBILITY = { ], "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", @@ -51,6 +52,7 @@ ATTRIB_VALIDATOR_COMPATIBILITY = { "exclude_max": ["in_range", "dataset_metadata_in_range"], "split": ["dataset_metadata_in_file"], "skip": ["metadata"], + "value": ["dataset_metadata_equal"], } PARAMETER_VALIDATOR_TYPE_COMPATIBILITY = { @@ -61,6 +63,7 @@ PARAMETER_VALIDATOR_TYPE_COMPATIBILITY = { "no_options", "unspecified_build", "dataset_ok_validator", + "dataset_metadata_equal", "dataset_metadata_in_range", "dataset_metadata_in_file", "dataset_metadata_in_data_table", @@ -72,6 +75,7 @@ PARAMETER_VALIDATOR_TYPE_COMPATIBILITY = { "no_options", "unspecified_build", "dataset_ok_validator", + "dataset_metadata_equal", "dataset_metadata_in_range", "dataset_metadata_in_file", "dataset_metadata_in_data_table", @@ -392,6 +396,13 @@ def lint_inputs(tool_xml, lint_ctx): f"Parameter [{param_name}]: '{vtype}' validators need to define the 'min' or 'max' attribute(s)", node=validator, ) + if vtype in ["dataset_metadata_equal"] and ( + "value" not in validator.attrib or "metadata_name" not in validator.attrib + ): + lint_ctx.error( + f"Parameter [{param_name}]: '{vtype}' validators need to define the 'value' or 'metadata_name' 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)", diff --git a/lib/galaxy/tool_util/xsd/galaxy.xsd b/lib/galaxy/tool_util/xsd/galaxy.xsd index ce54c99c2d6..8a638fe61d4 100644 --- a/lib/galaxy/tool_util/xsd/galaxy.xsd +++ b/lib/galaxy/tool_util/xsd/galaxy.xsd @@ -4408,6 +4408,7 @@ Note that each data parameter has automatically a metadata validator that checks if all non-optional metadata are set, i.e. `` + + + Value of the metadata to check. Only +applicable to ``dataset_metadata_equal``. + + Deprecated. Used to indicate lines in the file @@ -7064,6 +7071,7 @@ and ``bibtex`` are the only supported options. + diff --git a/lib/galaxy/tools/parameters/validation.py b/lib/galaxy/tools/parameters/validation.py index f13658d302f..ba173a0df1e 100644 --- a/lib/galaxy/tools/parameters/validation.py +++ b/lib/galaxy/tools/parameters/validation.py @@ -31,7 +31,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)` @@ -561,30 +561,42 @@ class MetadataValidator(Validator): 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): + 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 - self.message = message or 'Metadata value for (%s) must be (%s) and is not.' % (metadata_name, value) @classmethod def from_element(cls, param, elem): return cls( - metadata_name=elem.get('metadata_name', None), - value=elem.get('value', None), - message=elem.get('message', None), + metadata_name=elem.get("metadata_name", None), + value=elem.get("value", None), + message=elem.get("message", None), + negate=elem.get("negate", "false"), ) - def validate( self, value, trans=None ): + def validate(self, value, trans=None): if value: - metdata_value = getattr(value.metadata, self.metadata_name) - if metdata_value != self.value: - raise ValueError( self.message ) + metadata_value = getattr(value.metadata, self.metadata_name) + if isinstance(metadata_value, list): + metadata_value = ",".join(metadata_value) + super().validate(str(metadata_value) == self.value, value_to_show=metadata_value) -class UnspecifiedBuildValidator( Validator ): +class UnspecifiedBuildValidator(Validator): """ Validator that checks for dbkey not equal to '?' @@ -974,7 +986,7 @@ validator_types = dict( in_range=InRangeValidator, length=LengthValidator, metadata=MetadataValidator, - metadata_eq=MetadataEqualsValidator, + dataset_metadata_equal=MetadataEqualsValidator, unspecified_build=UnspecifiedBuildValidator, no_options=NoOptionsValidator, empty_field=EmptyTextfieldValidator, diff --git a/test/functional/tools/metadata_check_eq.xml b/test/functional/tools/metadata_check_eq.xml index b156cbf8962..1ad44071600 100644 --- a/test/functional/tools/metadata_check_eq.xml +++ b/test/functional/tools/metadata_check_eq.xml @@ -1,29 +1,59 @@ - + + Tests whether asserting metadata equals something works. > '$output' && + #end if + #if $input + echo "columns $input.metadata.columns" >> '$output' && + echo "column_names $input.metadata.column_names" >> '$output' + #else + echo "columns $input_negate.metadata.columns" >> '$output' && + echo "column_names $input_negate.metadata.column_names" >> '$output' + #end if ]]> - - + + + + + + + - - + + + + - + - + + + + + + - + - + + + + + + + + + diff --git a/test/unit/tool_util/test_tool_linters.py b/test/unit/tool_util/test_tool_linters.py index e27a59536e7..a928bb91819 100644 --- a/test/unit/tool_util/test_tool_linters.py +++ b/test/unit/tool_util/test_tool_linters.py @@ -390,7 +390,7 @@ INPUTS_VALIDATOR_INCOMPATIBILITIES = """ - + @@ -401,8 +401,10 @@ INPUTS_VALIDATOR_CORRECT = """ + + @@ -1334,10 +1336,14 @@ def test_inputs_validator_incompatibilities(lint_ctx): "Parameter [param_name]: 'value_in_data_table' validators need to define the 'table_name' attribute" in lint_ctx.error_messages ) + assert ( + "Parameter [another_param_name]: attribute 'value' is incompatible with validator of type 'metadata'" + in lint_ctx.error_messages + ) assert len(lint_ctx.info_messages) == 1 assert not lint_ctx.valid_messages assert len(lint_ctx.warn_messages) == 1 - assert len(lint_ctx.error_messages) == 7 + assert len(lint_ctx.error_messages) == 8 def test_inputs_validator_correct(lint_ctx):