import os.path from galaxy.model import ( Dataset, History, HistoryDatasetAssociation, ) from galaxy.util import galaxy_directory from .util import BaseParameterTestCase def get_test_data_path(name: str): path = os.path.join(galaxy_directory(), "test-data", name) assert os.path.isfile(path), f"{path} is not a file" return path class TestParameterValidation(BaseParameterTestCase): def test_simple_ExpressionValidator(self): p = self._parameter_for(xml=""" value.lower() == "foo" """) p.validate("Foo") p.validate("foo") with self.assertRaisesRegex(ValueError, "Not gonna happen"): p.validate("Fop") def test_negated_ExpressionValidator(self): p = self._parameter_for(xml=""" value.lower() == "foo" """) with self.assertRaisesRegex(ValueError, "Not gonna happen"): p.validate("Foo") p.validate("Fop") def test_boolean_ExpressionValidator(self): p = self._parameter_for(xml=""" value """) p.validate("Foo") with self.assertRaisesRegex(ValueError, "Not gonna happen"): p.validate("") p = self._parameter_for(xml=""" value """) p.validate(3) with self.assertRaisesRegex(ValueError, "Not gonna happen"): p.validate(0) def test_ExpressionValidator_message(self): p = self._parameter_for(xml=""" value.lower() == "foo" """) with self.assertRaisesRegex( ValueError, r"Value 'Fop' does not evaluate to True for 'value.lower\(\) == \"foo\"'" ): p.validate("Fop") with self.assertRaisesRegex( ValueError, r"Validator 'value.lower\(\) == \"foo\"' could not be evaluated on '1'" ): p.validate(1) def test_NoOptionsValidator(self): p = self._parameter_for(xml=""" """) p.validate("foo") with self.assertRaisesRegex(ValueError, "Parameter 'index': No options available for selection"): p.validate(None) p = self._parameter_for(xml=""" """) with self.assertRaisesRegex(ValueError, "Parameter 'index': Options available for selection"): p.validate("foo") p.validate(None) def test_EmptyTextfieldValidator(self): p = self._parameter_for(xml=""" """) p.validate("foo") with self.assertRaisesRegex(ValueError, "Parameter 'blah': Field requires a value"): p.validate("") p = self._parameter_for(xml=""" """) with self.assertRaisesRegex(ValueError, "Parameter 'blah': Field must not set a value"): p.validate("foo") p.validate("") def test_RegexValidator(self): p = self._parameter_for(xml=""" [Ff]oo """) p.validate("Foo") p.validate("foo") with self.assertRaisesRegex( ValueError, r"Parameter 'blah': Value 'Fop' does not match regular expression '\[Ff\]oo'" ): p.validate("Fop") # test also valitation of lists (for select parameters) p.validate(["Foo", "foo"]) with self.assertRaisesRegex( ValueError, r"Parameter 'blah': Value 'Fop' does not match regular expression '\[Ff\]oo'" ): p.validate(["Foo", "Fop"]) p = self._parameter_for(xml=""" [Ff]oo """) with self.assertRaisesRegex( ValueError, r"Parameter 'blah': Value 'Foo' does match regular expression '\[Ff\]oo'" ): p.validate("Foo") with self.assertRaisesRegex( ValueError, r"Parameter 'blah': Value 'foo' does match regular expression '\[Ff\]oo'" ): p.validate("foo") p.validate("Fop") with self.assertRaisesRegex( ValueError, r"Parameter 'blah': Value 'foo' does match regular expression '\[Ff\]oo'" ): p.validate(["Fop", "foo"]) p.validate(["Fop", "fop"]) def test_LengthValidator(self): p = self._parameter_for(xml=""" """) p.validate("foo") p.validate("bar") with self.assertRaisesRegex(ValueError, "Parameter 'blah': Must have length of at least 2 and at most 8"): p.validate("f") with self.assertRaisesRegex(ValueError, "Parameter 'blah': Must have length of at least 2 and at most 8"): p.validate("foobarbaz") p = self._parameter_for(xml=""" """) with self.assertRaisesRegex(ValueError, "Parameter 'blah': Must not have length of at least 2 and at most 8"): p.validate("foo") with self.assertRaisesRegex(ValueError, "Parameter 'blah': Must not have length of at least 2 and at most 8"): p.validate("bar") p.validate("f") p.validate("foobarbaz") p = self._parameter_for(xml=""" """) with self.assertRaisesRegex(ValueError, "No value provided"): p.validate(None) def test_InRangeValidator(self): p = self._parameter_for(xml=""" """) with self.assertRaisesRegex(ValueError, "Parameter 'blah': Doh!! 10 not in range"): p.validate(10) p.validate(15) p.validate(20) with self.assertRaisesRegex(ValueError, "Parameter 'blah': Doh!! 21 not in range"): p.validate(21) p = self._parameter_for(xml=""" """) p.validate(10) with self.assertRaisesRegex( ValueError, r"Parameter 'blah': Value \('15'\) must not fulfill \(10 < value <= 20\)", ): p.validate(15) with self.assertRaisesRegex( ValueError, r"Parameter 'blah': Value \('20'\) must not fulfill \(10 < value <= 20\)", ): p.validate(20) p.validate(21) def test_DatasetOkValidator(self): sa_session = self.app.model.context hist = History() with sa_session.begin(): sa_session.add(hist) ok_hda = hist.add_dataset( HistoryDatasetAssociation(id=1, extension="interval", create_dataset=True, sa_session=sa_session) ) ok_hda.state = Dataset.states.OK notok_hda = hist.add_dataset( HistoryDatasetAssociation(id=2, extension="interval", create_dataset=True, sa_session=sa_session) ) notok_hda.state = Dataset.states.EMPTY p = self._parameter_for(xml=""" """) p.validate(ok_hda) with self.assertRaisesRegex( ValueError, "Parameter 'blah': The selected dataset is still being generated, select another dataset or wait until it is completed", ): p.validate(notok_hda) p = self._parameter_for(xml=""" """) with self.assertRaisesRegex(ValueError, "Parameter 'blah': The selected dataset must not be in state OK"): p.validate(ok_hda) p.validate(notok_hda) def test_DatasetEmptyValidator(self): sa_session = self.app.model.context hist = History() with sa_session.begin(): sa_session.add(hist) empty_dataset = Dataset(external_filename=get_test_data_path("empty.txt")) empty_hda = hist.add_dataset( HistoryDatasetAssociation(id=1, extension="interval", dataset=empty_dataset, sa_session=sa_session) ) full_dataset = Dataset(external_filename=get_test_data_path("1.interval")) full_hda = hist.add_dataset( HistoryDatasetAssociation(id=2, extension="interval", dataset=full_dataset, sa_session=sa_session) ) p = self._parameter_for(xml=""" """) p.validate(full_hda) with self.assertRaisesRegex( ValueError, "Parameter 'blah': The selected dataset is empty, this tool expects non-empty files." ): p.validate(empty_hda) p = self._parameter_for(xml=""" """) with self.assertRaisesRegex( ValueError, "Parameter 'blah': The selected dataset is non-empty, this tool expects empty files." ): p.validate(full_hda) p.validate(empty_hda) def test_DatasetExtraFilesPathEmptyValidator(self): sa_session = self.app.model.context hist = History() with sa_session.begin(): sa_session.add(hist) has_extra_hda = hist.add_dataset( HistoryDatasetAssociation(id=1, extension="interval", create_dataset=True, sa_session=sa_session) ) has_extra_hda.dataset.file_size = 10 has_extra_hda.dataset.total_size = 15 has_no_extra_hda = hist.add_dataset( HistoryDatasetAssociation(id=2, extension="interval", create_dataset=True, sa_session=sa_session) ) has_no_extra_hda.dataset.file_size = 10 has_no_extra_hda.dataset.total_size = 10 p = self._parameter_for(xml=""" """) p.validate(has_extra_hda) with self.assertRaisesRegex( ValueError, "Parameter 'blah': The selected dataset's extra_files_path directory is empty or does not exist, this tool expects non-empty extra_files_path directories associated with the selected input.", ): p.validate(has_no_extra_hda) p = self._parameter_for(xml=""" """) with self.assertRaisesRegex( ValueError, "Parameter 'blah': The selected dataset's extra_files_path directory is non-empty or does exist, this tool expects empty extra_files_path directories associated with the selected input.", ): p.validate(has_extra_hda) p.validate(has_no_extra_hda) def test_MetadataValidator(self): sa_session = self.app.model.context hist = History() with sa_session.begin(): sa_session.add(hist) hda = hist.add_dataset( HistoryDatasetAssociation( id=1, extension="bed", create_dataset=True, sa_session=sa_session, dataset=Dataset(external_filename=get_test_data_path("1.bed")), ) ) hda.state = Dataset.states.OK hda.set_meta() hda.metadata.strandCol = hda.metadata.spec["strandCol"].no_value param_xml = """ """ p = self._parameter_for(xml=param_xml.format(check="nameCol", skip="")) p.validate(hda) p = self._parameter_for(xml=param_xml.format(check="strandCol", skip="")) with self.assertRaisesRegex( ValueError, "Parameter 'blah': Metadata 'strandCol' missing, click the pencil icon in the history item to edit / save the metadata attributes", ): p.validate(hda) p = self._parameter_for(xml=param_xml.format(check="", skip="dbkey,comment_lines,column_names,strandCol")) p.validate(hda) p = self._parameter_for(xml=param_xml.format(check="", skip="dbkey,comment_lines,column_names,nameCol")) with self.assertRaisesRegex( ValueError, "Parameter 'blah': Metadata 'strandCol' missing, click the pencil icon in the history item to edit / save the metadata attributes", ): p.validate(hda) param_xml_negate = """ """ p = self._parameter_for(xml=param_xml_negate.format(check="strandCol", skip="")) p.validate(hda) p = self._parameter_for(xml=param_xml_negate.format(check="nameCol", skip="")) with self.assertRaisesRegex( ValueError, "Parameter 'blah': At least one of the checked metadata 'nameCol' is set, click the pencil icon in the history item to edit / save the metadata attributes", ): p.validate(hda) p = self._parameter_for(xml=param_xml_negate.format(check="", skip="dbkey,comment_lines,column_names,nameCol")) p.validate(hda) p = self._parameter_for( xml=param_xml_negate.format(check="", skip="dbkey,comment_lines,column_names,strandCol") ) with self.assertRaisesRegex( ValueError, "Parameter 'blah': At least one of the non skipped metadata 'dbkey,comment_lines,column_names,strandCol' is set, click the pencil icon in the history item to edit / save the metadata attributes", ): p.validate(hda) def test_UnspecifiedBuildValidator(self): sa_session = self.app.model.context hist = History() with sa_session.begin(): sa_session.add(hist) has_dbkey_hda = hist.add_dataset( HistoryDatasetAssociation(id=1, extension="interval", create_dataset=True, sa_session=sa_session) ) has_dbkey_hda.state = Dataset.states.OK has_dbkey_hda.metadata.dbkey = "hg19" has_no_dbkey_hda = hist.add_dataset( HistoryDatasetAssociation(id=2, extension="interval", create_dataset=True, sa_session=sa_session) ) has_no_dbkey_hda.state = Dataset.states.OK p = self._parameter_for(xml=""" """) p.validate(has_dbkey_hda) with self.assertRaisesRegex( ValueError, "Parameter 'blah': Unspecified genome build, click the pencil icon in the history item to set the genome build", ): p.validate(has_no_dbkey_hda) p = self._parameter_for(xml=""" """) with self.assertRaisesRegex( ValueError, "Parameter 'blah': Specified genome build, click the pencil icon in the history item to remove the genome build", ): p.validate(has_dbkey_hda) p.validate(has_no_dbkey_hda) def test_RegexValidator_global_flag_inline(self): # tests that global inline flags continue to work past python 3.10 p = self._parameter_for(xml=r""" ^(?ims)\s*select\s+.*\s+from\s+.*$ """) p.validate("select id from job where id = 1;") with self.assertRaises(ValueError): p.validate("not sql")