mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-11-02 03:33:04 +08:00
Found by running: ``` make pyupgrade ruff check --fix . ruff check --preview --unsafe-fixes --select=F401 --fix . make format make update-client-api-schema ``` The bulk of the changes are replacements of typing deprecated aliases such as `Dict` and `List` with the standard library classes. These aliases became redundant in Python 3.9 when the corresponding pre-existing classes were enhanced to support `[]`, see https://docs.python.org/3/library/typing.html#deprecated-aliases Also: - Update the `pyupgrade` Makefile target to use `--py38-plus` for the packages needed by Pulsar, including the new galaxy-tool-util-models package.
242 lines
12 KiB
Python
242 lines
12 KiB
Python
from string import Template
|
|
|
|
import lxml.etree as ET
|
|
import pytest
|
|
from pydantic import ValidationError
|
|
|
|
from galaxy.tool_util.verify.codegen import galaxy_xsd_path
|
|
from galaxy.tool_util.verify.parse import assertion_xml_els_to_models
|
|
from galaxy.tool_util_models.assertions import assertion_list
|
|
from galaxy.util.commands import shell
|
|
from galaxy.util.unittest_utils import skip_unless_executable
|
|
|
|
valid_assertions = [
|
|
{"that": "has_size", "size": "5G"},
|
|
{"that": "has_size", "size": 1},
|
|
{"that": "has_size", "size": "5Mi"},
|
|
{"that": "has_text", "text": "JBrowseDefaultMainPage"},
|
|
{"that": "has_line", "line": "'>Wildtype Staphylococcus aureus strain WT.'"},
|
|
{"that": "has_n_columns", "n": 2},
|
|
{"that": "is_valid_xml"},
|
|
{"that": "has_element_with_path", "path": "//el"},
|
|
{"that": "has_n_elements_with_path", "path": "//el", "n": 4},
|
|
{"that": "element_text_matches", "expression": "foob[a]r", "path": "//el"},
|
|
{"that": "element_text_is", "text": "foobar", "path": "//el"},
|
|
{
|
|
"that": "xml_element",
|
|
"path": "./elem/more[2]",
|
|
"children": [{"that": "has_text_matching", "expression": "foo$"}],
|
|
},
|
|
{"that": "xml_element", "path": "./elem/more[2]"},
|
|
{"that": "element_text", "path": "./elem/more[2]", "children": [{"that": "has_text", "text": "foo"}]},
|
|
{"that": "has_json_property_with_value", "property": "foobar", "value": "'6'"},
|
|
{"that": "has_json_property_with_text", "property": "foobar", "text": "cowdog"},
|
|
{"that": "has_archive_member", "path": ".*/my-file.txt"},
|
|
{"that": "has_archive_member", "path": ".*/my-file.txt", "children": [{"that": "has_text", "text": "1235abc"}]},
|
|
{"that": "has_image_width", "width": 560},
|
|
{"that": "has_image_width", "width": 560, "delta": 490},
|
|
{"that": "has_image_height", "height": 560, "delta": 490},
|
|
{"that": "has_image_height", "min": 45, "max": 90},
|
|
{"that": "has_image_channels", "channels": 3},
|
|
{"that": "has_image_channels", "channels": 3, "delta": 1},
|
|
{"that": "has_image_channels", "min": 1, "max": 4},
|
|
{"that": "has_image_channels", "min": 1, "max": 4, "negate": True},
|
|
{"that": "has_image_mean_intensity", "mean_intensity": 3.4},
|
|
{"that": "has_image_mean_intensity", "mean_intensity": 3.4, "eps": 0.2},
|
|
{"that": "has_image_mean_intensity", "mean_intensity": 3.4, "eps": 0.2, "channel": 1},
|
|
{"that": "has_image_mean_intensity", "min": 0.4, "max": 0.6, "channel": 1},
|
|
{"that": "has_image_center_of_mass", "center_of_mass": "511.07, 223.34"},
|
|
{"that": "has_image_center_of_mass", "center_of_mass": "511.07, 223.34", "channel": 1},
|
|
{"that": "has_image_center_of_mass", "center_of_mass": "511.07, 223.34", "channel": 1, "eps": 0.2},
|
|
{"that": "has_image_n_labels", "n": 85},
|
|
{"that": "has_image_n_labels", "labels": [1, 3, 4]},
|
|
{"that": "has_image_n_labels", "n": 9, "exclude_labels": [1, 3, 4]},
|
|
{"that": "has_image_n_labels", "n": 9, "exclude_labels": [1, 3, 4], "negate": True},
|
|
{"that": "has_image_mean_object_size", "mean_object_size": 9, "exclude_labels": [1, 3, 4]},
|
|
{"that": "has_image_mean_object_size", "mean_object_size": 9, "labels": [1, 3, 4]},
|
|
{"that": "has_image_mean_object_size", "mean_object_size": 9, "channel": 1, "eps": 0.2},
|
|
{"that": "has_json_property_with_value", "property": "skipped_columns", "value": "[1, 3, 5]"},
|
|
{"that": "has_json_property_with_text", "property": "color", "text": "red"},
|
|
{"that": "has_n_columns", "n": 30},
|
|
{"that": "has_n_columns", "n": 30, "delta": 4},
|
|
{"that": "has_n_columns", "n": 30, "delta": 4, "sep": " ", "comment": "####"},
|
|
]
|
|
|
|
valid_xml_assertions = [
|
|
"""<has_size value="5G" />""",
|
|
"""<has_size size="5G" />""",
|
|
"""<has_size size="5G" />""",
|
|
"""<has_text text="JBrowseDefaultMainPage" />""",
|
|
"""<has_line line="'>Wildtype Staphylococcus aureus strain WT.'" />""",
|
|
"""<xml_element path="./elem/more[2]" attribute="name"><has_text_matching expression="foo$"/></xml_element>""",
|
|
"""<xml_element path="./elem/more[2]" attribute="name"></xml_element>""",
|
|
"""<element_text path="./elem/more[2]"><has_text text="foo" /></element_text>""",
|
|
"""<has_element_with_path path="BlastOutput_param/Parameters/Parameters_matrix" />""",
|
|
r"""<element_text_matches path="BlastOutput_version" expression="BLASTP\s+2\.2.*"/>""",
|
|
"""<element_text_is path="BlastOutput_program" text="blastp" />""",
|
|
r"""<attribute_matches path="outerElement/innerElement2" attribute="foo2" expression="bar\d+" />""",
|
|
"""<element_text path="BlastOutput_iterations/Iteration/Iteration_hits/Hit/Hit_def"><not_has_text text="EDK72998.1" /></element_text>""",
|
|
"""<has_archive_member path=".*/my-file.txt"><not_has_text text="EDK72998.1"/></has_archive_member>""",
|
|
"""<has_archive_member path=".*/my-file.txt"></has_archive_member>""",
|
|
"""<has_image_n_labels n="85" />""",
|
|
"""<has_image_center_of_mass center_of_mass="511.07, 223.34" />""",
|
|
"""<has_image_center_of_mass center_of_mass="511.07, 223.34" eps=".2" />""",
|
|
"""<has_image_mean_intensity mean_intensity="0.83" />""",
|
|
"""<has_image_height height="512" delta="2" />""",
|
|
"""<has_image_width width="512" delta="2" />""",
|
|
"""<has_image_channels channels="3" />""",
|
|
"""<has_image_channels channels="3" delta="1" />""",
|
|
"""<has_image_channels min="3" max="5" />""",
|
|
"""<has_image_channels min="3" max="5" negate="true" />""",
|
|
"""<has_json_property_with_value property="skipped_columns" value="[1, 3, 5]" />""",
|
|
"""<has_json_property_with_text property="color" text="red" />""",
|
|
"""<has_n_columns n="30" />""",
|
|
"""<has_n_columns n="30" delta="4" />""",
|
|
"""<has_n_columns n="30" delta="4" sep=" " comment="###" />""",
|
|
"""<has_image_width min="500" />""",
|
|
"""<has_image_height min="500" />""",
|
|
]
|
|
|
|
invalid_assertions = [
|
|
{"that": "has_size", "size": "5Gigabytes"},
|
|
# negative sizes not allowed
|
|
{"that": "has_size", "size": -1},
|
|
{"that": "has_n_columns", "n": [2]},
|
|
{"that": "has_n_columns", "n": -2},
|
|
{"that": "is_valid_xml_foo"},
|
|
{"that": "has_element_with_path", "path": 45},
|
|
{"that": "has_n_elements_with_path", "n": 4},
|
|
{"that": "has_n_elements_with_path", "n": -4},
|
|
{"that": "element_text_matches", "expression": 12, "path": "//el"},
|
|
# unclosed regex group
|
|
{"that": "element_text_matches", "expression": "[12", "path": "//el"},
|
|
{"that": "xml_element", "path": "./elem/more[2]", "children": [{"that": "foobar"}]},
|
|
{
|
|
"that": "xml_element",
|
|
"path": "./elem/more[2]",
|
|
"children": [{"that": "has_text_matching", "line": "invalidprop"}],
|
|
},
|
|
# must specify children for element_text
|
|
{"that": "element_text", "path": "./elem/more[2]"},
|
|
{"that": "has_json_property_with_value", "property": 42, "value": "cowdog"},
|
|
{"that": "has_json_property_with_text", "property": "foobar", "text": 6},
|
|
{"that": "has_archive_member", "path": ".*/my-file.txt", "extra": "param"},
|
|
{"that": "has_archive_member", "path": ".*/my-file.txt", "children": [{"that": "invalid"}]},
|
|
{"that": "has_image_width", "width": "560"},
|
|
{"that": "has_image_width", "width": -560},
|
|
{"that": "has_image_width", "width": 560, "delta": "wrong"},
|
|
{"that": "has_image_height", "height": -560},
|
|
{"that": "has_image_center_of_mass", "center_of_mass": "511.07, 223.34, foobar"},
|
|
{"that": "has_image_center_of_mass", "center_of_mass": "511.07"},
|
|
{"that": "has_image_center_of_mass", "center_of_mass": "511.07, cow"},
|
|
# negative mean object sizes are not allowed
|
|
{"that": "has_image_n_labels", "n": -85},
|
|
{"that": "has_image_n_labels", "n": 85, "delta": -3},
|
|
# negative mean object sizes are not allowed
|
|
{"that": "has_image_mean_object_size", "mean_object_size": -9, "exclude_labels": [1, 3, 4]},
|
|
{"that": "has_image_mean_object_size", "mean_object_size": -9.0, "exclude_labels": [1, 3, 4]},
|
|
{"that": "has_image_mean_object_size", "mean_object_size": 9, "exclude_labels": [1, 3, 4], "eps": -0.2},
|
|
# looks a little odd in JSON but value is JSON loaded so must be a string
|
|
{"that": "has_json_property_with_value", "property": "skipped_columns", "value": [1, 3, 5]},
|
|
# missing property
|
|
{"that": "has_json_property_with_value", "property": "skipped_columns"},
|
|
{"that": "has_json_property_with_text", "property": "color"},
|
|
{"that": "has_n_columns", "n": 30, "delta": "wrongtype"},
|
|
{"that": "has_n_columns", "n": 30, "delta": -2},
|
|
{"that": "has_n_columns", "n": 30, "delta": 4, "sep": " ", "comment": "####", "extra": "param"},
|
|
]
|
|
|
|
invalid_xml_assertions = [
|
|
"""<has_n_columns n="cow" />""",
|
|
"""<has_text line="JBrowseDefaultMainPage" />""",
|
|
"""<has_line text="JBrowseDefaultMainPage" />""",
|
|
# at least one child assertion is required here...
|
|
"""<element_text path="./elem/more[2]"></element_text>""",
|
|
"""<has_archive_member path=".*/my-file.txt"><not_has_text line="EDK72998.1"/></has_archive_member>""",
|
|
"""<has_archive_member path=".*/my-file.txt"><foobar /></has_archive_member>""",
|
|
"""<has_image_center_of_mass center_of_mass="511.07, 223.34" extra="param" />""",
|
|
"""<has_image_center_of_mass center_of_mass="511.07, 223.34" eps="foobar" />""",
|
|
# negative numbers not allowed
|
|
"""<has_image_n_labels n="-85" />""",
|
|
"""<has_image_n_labels n="85" delta="-3" />""",
|
|
"""<has_image_mean_intensity mean_intensity="not_a_number" />""",
|
|
"""<has_image_mean_intensity mean_intensity=".83" extra="param" />""",
|
|
"""<has_image_height height="512" delta="notanumber" />""",
|
|
"""<has_image_width width="512" delta="2" extra="param" />""",
|
|
"""<has_image_height height="512" delta="-2" />""",
|
|
"""<has_image_width width="512" delta="-2" />""",
|
|
"""<has_image_height height="-512" />""",
|
|
"""<has_image_width width="-512" />""",
|
|
"""<has_image_channels channels="3" exclude="wrong" />""",
|
|
"""<has_image_channels channels="3" delta="not_a_number" />""",
|
|
"""<has_image_channels min="3" max="5" foo="bar" />""",
|
|
"""<has_image_channels min="3" max="5" negate="NOTABOOLEAN" />""",
|
|
# missing required arguments...
|
|
"""<has_json_property_with_value property="skipped_columns" />""",
|
|
"""<has_json_property_with_text property="color" />""",
|
|
"""<has_n_columns n="30" delta="wrong_type" />""",
|
|
"""<has_n_columns n="30" delta="4" sep=" " comment="###" extra="param"/>""",
|
|
]
|
|
|
|
|
|
TOOL_TEMPLATE = Template(
|
|
"""
|
|
<tool id="gx_test" name="gx_test" version="1.0.0">
|
|
<command><![CDATA[
|
|
echo '$parameter' >> '$output'
|
|
]]></command>
|
|
<inputs>
|
|
<param name="parameter" value="1" type="integer" />
|
|
</inputs>
|
|
<outputs>
|
|
<data name="output" format="txt" />
|
|
</outputs>
|
|
<tests>
|
|
<test>
|
|
<param name="parameter" value_json="12456" />
|
|
<output name="output">
|
|
<assert_contents>
|
|
$assertion_xml
|
|
</assert_contents>
|
|
</output>
|
|
</test>
|
|
</tests>
|
|
</tool>
|
|
"""
|
|
)
|
|
|
|
|
|
def test_valid_json_models_validate():
|
|
assertion_list.model_validate(valid_assertions)
|
|
|
|
|
|
def test_invalid_json_models_do_not_validate():
|
|
for invalid_assertion in invalid_assertions:
|
|
with pytest.raises(ValidationError):
|
|
assertion_list.model_validate([invalid_assertion])
|
|
|
|
|
|
@skip_unless_executable("xmllint")
|
|
def test_valid_xsd(tmp_path):
|
|
for assertion_xml in valid_xml_assertions:
|
|
tool_xml = TOOL_TEMPLATE.safe_substitute(assertion_xml=assertion_xml)
|
|
tool_path = tmp_path / "tool.xml"
|
|
tool_path.write_text(tool_xml)
|
|
ret = shell(["xmllint", "--nowarning", "--noout", "--schema", galaxy_xsd_path, str(tool_path)])
|
|
assert ret == 0, f"{assertion_xml} failed to validate"
|
|
|
|
|
|
@skip_unless_executable("xmllint")
|
|
def test_invalid_xsd(tmp_path):
|
|
for assertion_xml in invalid_xml_assertions:
|
|
tool_xml = TOOL_TEMPLATE.safe_substitute(assertion_xml=assertion_xml)
|
|
tool_path = tmp_path / "tool.xml"
|
|
tool_path.write_text(tool_xml)
|
|
ret = shell(["xmllint", "--nowarning", "--noout", "--schema", galaxy_xsd_path, str(tool_path)])
|
|
assert ret != 0, f"{assertion_xml} validated when error expected"
|
|
|
|
|
|
def test_valid_xml_models_validate_after_json_transform():
|
|
for assertion_xml in valid_xml_assertions:
|
|
assertion_xml_els_to_models([ET.fromstring(assertion_xml)])
|