Skip to content
Snippets Groups Projects
Commit 87bbc01b authored by John Chilton's avatar John Chilton
Browse files

Initial work on defining XML markup for validating Galaxy tool commands and configfile contents.

parent 3c5edcbe
No related branches found
No related tags found
No related merge requests found
from xml.etree.ElementTree import fromstring
from re import escape, compile
from os.path import join
class ExpressionValidator(object):
def __init__(self, xml_el):
if type(xml_el) == str:
xml_el = fromstring(xml_el)
self.xml_el = xml_el
def validate(self, job_directory, string):
regex = "^%s$" % self._expression_to_regex(job_directory, self.xml_el)
return compile(regex).match(string) is not None
def _expression_to_regex(self, job_directory, element):
return r"\s+".join([self._element_to_regex(child, job_directory) for child in list(element)])
def _element_to_regex(self, element, job_directory):
tag = element.tag
method_name = "_%s_to_regex" % tag
try:
method = getattr(self, method_name)
except NameError:
raise NameError("Unknown XML validation tag [%s]" % tag)
return method(element, job_directory)
def _literal_to_regex(self, element, job_directory):
return escape(self.__value_or_text(element))
def _parameter_to_regex(self, element, job_directory):
parameter_name = element.get('name')
value_regex = self._expression_to_regex(job_directory, element)
return r"%s(?:=|\s+)%s" % (parameter_name, value_regex)
def _integer_to_regex(self, element, job_directory):
return r"\d+"
def _float_to_regex(self, element, job_directory):
# http://stackoverflow.com/a/9392612
return r"[-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?"
def _tool_wrapper_to_regex(self, element, job_directory):
wrapper_name = self.__value_or_text(element, "name")
path = join(job_directory.path, "tool_files", wrapper_name)
return escape(path)
def _configfile_to_regex(self, element, job_directory):
wrapper_name = self.__value_or_text(element, "name")
path = join(job_directory.path, "configs", wrapper_name)
return escape(path)
def __value_or_text(self, element, attribute="value"):
value = element.get(attribute, None)
if value is None:
value = element.text
return value
......@@ -3,6 +3,19 @@ from lwr.tools import ToolBox
from os import pardir
from os.path import join, dirname
from unittest import TestCase
from tempfile import mkdtemp
from shutil import rmtree
class TempDirectoryTestCase(TestCase):
def setUp(self):
self.temp_directory = mkdtemp()
def tearDown(self):
rmtree(self.temp_directory)
def get_test_toolbox():
toolbox_path = join(dirname(__file__), pardir, "test_data", "test_shed_toolbox.xml")
......
from test_utils import TempDirectoryTestCase
from lwr.util import JobDirectory
from lwr.tools.validator import ExpressionValidator
from os.path import join
class ValidatorTest(TempDirectoryTestCase):
def test_literal(self):
xml = """
<expression>
<literal value="tophat2" />
</expression>"""
self.__assertValid(xml, "tophat2")
self.__assertInvalid(xml, "bowtie")
def test_two_literals(self):
xml = """
<expression>
<literal value="python" />
<literal value="setup.py" />
</expression>"""
self.__assertValid(xml, "python setup.py")
self.__assertInvalid(xml, "pythonsetup.py")
def test_parameter(self):
xml = """
<expression>
<literal value="tophat2" />
<parameter name="--mate-std-dev">
<literal value="4" />
</parameter>
</expression>"""
self.__assertValid(xml, "tophat2 --mate-std-dev 4")
self.__assertValid(xml, "tophat2 --mate-std-dev=4")
self.__assertInvalid(xml, "tophat2 --mate-std-dev=5")
def test_integer(self):
xml = """
<expression>
<literal value="tophat2" />
<parameter name="--mate-std-dev">
<integer />
</parameter>
</expression>"""
self.__assertValid(xml, "tophat2 --mate-std-dev 4")
self.__assertValid(xml, "tophat2 --mate-std-dev=4")
self.__assertInvalid(xml, "tophat2 --mate-std-dev=5.0")
def test_float(self):
xml = """
<expression>
<literal value="tophat2" />
<parameter name="--mate-std-dev">
<float />
</parameter>
</expression>"""
self.__assertValid(xml, "tophat2 --mate-std-dev 4")
self.__assertValid(xml, "tophat2 --mate-std-dev=4")
self.__assertValid(xml, "tophat2 --mate-std-dev=5.0")
self.__assertValid(xml, "tophat2 --mate-std-dev=4e10")
self.__assertValid(xml, "tophat2 --mate-std-dev=-1.0e10")
self.__assertValid(xml, "tophat2 --mate-std-dev=-.0e10")
self.__assertInvalid(xml, "tophat2 --mate-std-dev=cat")
def test_tool_wrapper(self):
xml = """
<expression>
<tool_wrapper name="tool1_wrapper.py" />
</expression>
"""
self.__assertValid(xml, "%s" % join(self.temp_directory, '1', 'tool_files', 'tool1_wrapper.py'))
self.__assertInvalid(xml, "tool1_wrapper.py")
def test_config_file(self):
xml = """
<expression>
<literal value="tophat2" />
<configfile name="top_opts" />
</expression>
"""
self.__assertValid(xml, "tophat2 %s" % join(self.temp_directory, '1', 'configs', 'top_opts'))
self.__assertInvalid(xml, "tophat2 ../%s" % join(self.temp_directory, '1', 'configs', 'top_opts'))
self.__assertInvalid(xml, "tophat2 %s" % join(self.temp_directory, '1', 'configs', 'top_optsX'))
def __validator(self, xml):
return ExpressionValidator(xml)
@property
def job_directory(self):
return JobDirectory(self.temp_directory, '1')
def __is_valid(self, xml, contents):
return self.__validator(xml).validate(self.job_directory, contents)
def __assertValid(self, xml, contents):
self.assertTrue(self.__is_valid(xml, contents), "%s did not validate against %s" % (contents, xml))
def __assertInvalid(self, xml, contents):
self.assertFalse(self.__is_valid(xml, contents), "%s falsely validated against %s" % (contents, xml))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment