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")