From ec5cfe6cce60f0df554ed7f1b8fa6f63af52a8f5 Mon Sep 17 00:00:00 2001 From: John Chilton Date: Sun, 5 Apr 2026 15:30:17 -0400 Subject: [PATCH] narrow YAML tool parameter schema for UserToolSource Introduce lib/galaxy/tool_util_models/yaml_parameters.py with a narrow YamlGalaxyToolParameter union (extra=forbid) used for UserToolSource.inputs and ToolSourceBase.inputs. v1 supports boolean, integer, float, text, select, color, data, data_collection, conditional, repeat, section. XML-only fields (truevalue, falsevalue, argument, is_dynamic, hidden, parameter_type) and unsupported types (hidden, drill_down, data_column, genomebuild, group_tag, baseurl, rules, directory) now reject at parse time. to_internal() maps each YAML model onto the existing internal parameter metamodel so no downstream pipeline needs to change shape. Production path keeps re-parsing via YamlToolSource (plan option a). UserToolSource envelope also gets extra=forbid - stray top-level keys like argument: at the tool level fail fast. Regenerated ToolSourceSchema.json is 32KB (was 77KB); Monaco no longer autocompletes the leaked fields. runtimeify() gains yaml_origin flag; evaluation.py passes it based on tool_source.parse_class(). assert_yaml_v1_parameters() hard-fails on any out-of-v1 type inside a YAML-origin bundle, recursing through whens/repeat/ section. XML path untouched. doc/source/admin/user_defined_tools.md documents the supported set and rejected types. 34 new tests in test_yaml_parameters.py cover red cases, green round-trips, structural groups, the runtimeify guard, and a snapshot blacklist on the published schema. test_parsing.py still green (83 tests). No compat shim for existing beta DB rows that contain XML-only fields - those will now fail validation on load and need to be recreated. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/components/Panels/UserToolPanel.vue | 2 +- .../src/components/Tool/ToolSourceSchema.json | 2 +- doc/source/admin/user_defined_tools.md | 60 +++ lib/galaxy/tool_util/parameters/convert.py | 47 +++ lib/galaxy/tool_util/parser/interface.py | 30 +- lib/galaxy/tool_util/parser/xml.py | 6 +- lib/galaxy/tool_util/parser/yaml.py | 16 +- lib/galaxy/tool_util/verify/_types.py | 6 +- lib/galaxy/tool_util/verify/interactor.py | 6 +- lib/galaxy/tool_util_models/__init__.py | 140 +++++-- lib/galaxy/tool_util_models/assertions.py | 32 +- lib/galaxy/tool_util_models/testing_types.py | 42 +++ .../tool_util_models/yaml_parameters.py | 324 ++++++++++++++++ lib/galaxy/tools/evaluation.py | 9 +- lib/galaxy_test/api/test_tools.py | 8 +- .../tools/parameters/gx_boolean_user.yml | 3 +- .../gx_data_collection_sample_sheet.yml | 2 +- .../app/managers/test_DynamicToolManager.py | 11 +- .../test_user_tool_source_fixtures.py | 71 ++++ test/unit/tool_util/test_yaml_parameters.py | 355 ++++++++++++++++++ 20 files changed, 1069 insertions(+), 103 deletions(-) create mode 100644 lib/galaxy/tool_util_models/testing_types.py create mode 100644 lib/galaxy/tool_util_models/yaml_parameters.py create mode 100644 test/unit/tool_util/test_user_tool_source_fixtures.py create mode 100644 test/unit/tool_util/test_yaml_parameters.py diff --git a/client/src/components/Panels/UserToolPanel.vue b/client/src/components/Panels/UserToolPanel.vue index 1bc41930be7..0afb120457e 100644 --- a/client/src/components/Panels/UserToolPanel.vue +++ b/client/src/components/Panels/UserToolPanel.vue @@ -81,7 +81,7 @@ function getToolBadges(tool: UnprivilegedToolResponse) { return [ { id: "version", - label: tool.representation.version, + label: tool.representation.version ?? "", title: "Version of this custom tool", }, ]; diff --git a/client/src/components/Tool/ToolSourceSchema.json b/client/src/components/Tool/ToolSourceSchema.json index 5d83e110d14..e1b1a921268 100644 --- a/client/src/components/Tool/ToolSourceSchema.json +++ b/client/src/components/Tool/ToolSourceSchema.json @@ -1 +1 @@ -{"$defs": {"BaseUrlParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_baseurl", "default": "gx_baseurl", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "baseurl", "title": "type", "type": "string"}}, "required": ["name", "type"], "title": "BaseUrlParameterModel", "type": "object"}, "BooleanParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_boolean", "default": "gx_boolean", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "boolean", "title": "type", "type": "string"}, "value": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "default": false, "title": "value"}, "truevalue": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "truevalue"}, "falsevalue": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "falsevalue"}}, "required": ["name", "type"], "title": "BooleanParameterModel", "type": "object"}, "Citation": {"properties": {"type": {"title": "type", "type": "string"}, "content": {"title": "content", "type": "string"}}, "required": ["type", "content"], "title": "Citation", "type": "object"}, "ColorParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_color", "default": "gx_color", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "color", "title": "type", "type": "string"}, "value": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "value"}}, "required": ["name", "type"], "title": "ColorParameterModel", "type": "object"}, "ConditionalParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_conditional", "default": "gx_conditional", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "conditional", "title": "type", "type": "string"}, "test_parameter": {"anyOf": [{"$ref": "#/$defs/BooleanParameterModel"}, {"$ref": "#/$defs/SelectParameterModel"}], "title": "test_parameter"}, "whens": {"items": {"$ref": "#/$defs/ConditionalWhen"}, "title": "whens", "type": "array"}}, "required": ["name", "type", "test_parameter", "whens"], "title": "ConditionalParameterModel", "type": "object"}, "ConditionalWhen": {"additionalProperties": false, "properties": {"discriminator": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "title": "Discriminator"}, "parameters": {"items": {"anyOf": [{"$ref": "#/$defs/CwlIntegerParameterModel"}, {"$ref": "#/$defs/CwlFloatParameterModel"}, {"$ref": "#/$defs/CwlStringParameterModel"}, {"$ref": "#/$defs/CwlBooleanParameterModel"}, {"$ref": "#/$defs/CwlNullParameterModel"}, {"$ref": "#/$defs/CwlFileParameterModel"}, {"$ref": "#/$defs/CwlDirectoryParameterModel"}, {"$ref": "#/$defs/CwlUnionParameterModel"}, {"$ref": "#/$defs/CwlAnyParameterModel"}, {"$ref": "#/$defs/CwlEnumParameterModel"}, {"$ref": "#/$defs/CwlArrayParameterModel"}, {"$ref": "#/$defs/CwlRecordParameterModel"}, {"$ref": "#/$defs/TextParameterModel"}, {"$ref": "#/$defs/IntegerParameterModel"}, {"$ref": "#/$defs/FloatParameterModel"}, {"$ref": "#/$defs/BooleanParameterModel"}, {"$ref": "#/$defs/HiddenParameterModel"}, {"$ref": "#/$defs/SelectParameterModel"}, {"$ref": "#/$defs/DataParameterModel"}, {"$ref": "#/$defs/DataCollectionParameterModel"}, {"$ref": "#/$defs/DataColumnParameterModel"}, {"$ref": "#/$defs/DirectoryUriParameterModel"}, {"$ref": "#/$defs/RulesParameterModel"}, {"$ref": "#/$defs/DrillDownParameterModel"}, {"$ref": "#/$defs/GroupTagParameterModel"}, {"$ref": "#/$defs/BaseUrlParameterModel"}, {"$ref": "#/$defs/GenomeBuildParameterModel"}, {"$ref": "#/$defs/ColorParameterModel"}, {"$ref": "#/$defs/ConditionalParameterModel"}, {"$ref": "#/$defs/RepeatParameterModel"}, {"$ref": "#/$defs/SectionParameterModel"}]}, "title": "Parameters", "type": "array"}, "is_default_when": {"title": "Is Default When", "type": "boolean"}}, "required": ["discriminator", "parameters", "is_default_when"], "title": "ConditionalWhen", "type": "object"}, "Container": {"properties": {"type": {"enum": ["docker", "singularity"], "title": "type", "type": "string"}, "container_id": {"title": "container_id", "type": "string"}}, "required": ["type", "container_id"], "title": "Container", "type": "object"}, "ContainerRequirement": {"properties": {"type": {"const": "container", "title": "type", "type": "string"}, "container": {"$ref": "#/$defs/Container", "title": "container"}}, "required": ["type", "container"], "title": "ContainerRequirement", "type": "object"}, "CwlAnyParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "cwl_any", "default": "cwl_any", "title": "parameter_type", "type": "string"}, "has_default": {"default": false, "title": "has_default", "type": "boolean"}, "default_value": {"anyOf": [{}, {"type": "null"}], "default": null, "title": "default_value"}}, "required": ["name"], "title": "CwlAnyParameterModel", "type": "object"}, "CwlArrayParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "cwl_array", "default": "cwl_array", "title": "parameter_type", "type": "string"}, "item_type": {"anyOf": [{"$ref": "#/$defs/CwlIntegerParameterModel"}, {"$ref": "#/$defs/CwlFloatParameterModel"}, {"$ref": "#/$defs/CwlStringParameterModel"}, {"$ref": "#/$defs/CwlBooleanParameterModel"}, {"$ref": "#/$defs/CwlNullParameterModel"}, {"$ref": "#/$defs/CwlFileParameterModel"}, {"$ref": "#/$defs/CwlDirectoryParameterModel"}, {"$ref": "#/$defs/CwlUnionParameterModel"}, {"$ref": "#/$defs/CwlAnyParameterModel"}, {"$ref": "#/$defs/CwlEnumParameterModel"}, {"$ref": "#/$defs/CwlArrayParameterModel"}, {"$ref": "#/$defs/CwlRecordParameterModel"}], "title": "item_type"}, "has_default": {"default": false, "title": "has_default", "type": "boolean"}, "default_value": {"anyOf": [{}, {"type": "null"}], "default": null, "title": "default_value"}}, "required": ["name", "item_type"], "title": "CwlArrayParameterModel", "type": "object"}, "CwlBooleanParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "cwl_boolean", "default": "cwl_boolean", "title": "parameter_type", "type": "string"}, "has_default": {"default": false, "title": "has_default", "type": "boolean"}, "default_value": {"anyOf": [{}, {"type": "null"}], "default": null, "title": "default_value"}}, "required": ["name"], "title": "CwlBooleanParameterModel", "type": "object"}, "CwlDirectoryParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "cwl_directory", "default": "cwl_directory", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "has_default": {"default": false, "title": "has_default", "type": "boolean"}, "default_value": {"anyOf": [{}, {"type": "null"}], "default": null, "title": "default_value"}}, "required": ["name"], "title": "CwlDirectoryParameterModel", "type": "object"}, "CwlEnumParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "cwl_enum", "default": "cwl_enum", "title": "parameter_type", "type": "string"}, "symbols": {"items": {"type": "string"}, "title": "symbols", "type": "array"}, "has_default": {"default": false, "title": "has_default", "type": "boolean"}, "default_value": {"anyOf": [{}, {"type": "null"}], "default": null, "title": "default_value"}}, "required": ["name", "symbols"], "title": "CwlEnumParameterModel", "type": "object"}, "CwlFileParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "cwl_file", "default": "cwl_file", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "has_default": {"default": false, "title": "has_default", "type": "boolean"}, "default_value": {"anyOf": [{}, {"type": "null"}], "default": null, "title": "default_value"}}, "required": ["name"], "title": "CwlFileParameterModel", "type": "object"}, "CwlFloatParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "cwl_float", "default": "cwl_float", "title": "parameter_type", "type": "string"}, "has_default": {"default": false, "title": "has_default", "type": "boolean"}, "default_value": {"anyOf": [{}, {"type": "null"}], "default": null, "title": "default_value"}}, "required": ["name"], "title": "CwlFloatParameterModel", "type": "object"}, "CwlIntegerParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "cwl_integer", "default": "cwl_integer", "title": "parameter_type", "type": "string"}, "has_default": {"default": false, "title": "has_default", "type": "boolean"}, "default_value": {"anyOf": [{}, {"type": "null"}], "default": null, "title": "default_value"}}, "required": ["name"], "title": "CwlIntegerParameterModel", "type": "object"}, "CwlNullParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "cwl_null", "default": "cwl_null", "title": "parameter_type", "type": "string"}, "has_default": {"default": false, "title": "has_default", "type": "boolean"}}, "required": ["name"], "title": "CwlNullParameterModel", "type": "object"}, "CwlRecordParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "cwl_record", "default": "cwl_record", "title": "parameter_type", "type": "string"}, "fields": {"items": {"anyOf": [{"$ref": "#/$defs/CwlIntegerParameterModel"}, {"$ref": "#/$defs/CwlFloatParameterModel"}, {"$ref": "#/$defs/CwlStringParameterModel"}, {"$ref": "#/$defs/CwlBooleanParameterModel"}, {"$ref": "#/$defs/CwlNullParameterModel"}, {"$ref": "#/$defs/CwlFileParameterModel"}, {"$ref": "#/$defs/CwlDirectoryParameterModel"}, {"$ref": "#/$defs/CwlUnionParameterModel"}, {"$ref": "#/$defs/CwlAnyParameterModel"}, {"$ref": "#/$defs/CwlEnumParameterModel"}, {"$ref": "#/$defs/CwlArrayParameterModel"}, {"$ref": "#/$defs/CwlRecordParameterModel"}]}, "title": "fields", "type": "array"}, "has_default": {"default": false, "title": "has_default", "type": "boolean"}, "default_value": {"anyOf": [{}, {"type": "null"}], "default": null, "title": "default_value"}}, "required": ["name", "fields"], "title": "CwlRecordParameterModel", "type": "object"}, "CwlStringParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "cwl_string", "default": "cwl_string", "title": "parameter_type", "type": "string"}, "has_default": {"default": false, "title": "has_default", "type": "boolean"}, "default_value": {"anyOf": [{}, {"type": "null"}], "default": null, "title": "default_value"}}, "required": ["name"], "title": "CwlStringParameterModel", "type": "object"}, "CwlUnionParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "cwl_union", "default": "cwl_union", "title": "parameter_type", "type": "string"}, "parameters": {"items": {"anyOf": [{"$ref": "#/$defs/CwlIntegerParameterModel"}, {"$ref": "#/$defs/CwlFloatParameterModel"}, {"$ref": "#/$defs/CwlStringParameterModel"}, {"$ref": "#/$defs/CwlBooleanParameterModel"}, {"$ref": "#/$defs/CwlNullParameterModel"}, {"$ref": "#/$defs/CwlFileParameterModel"}, {"$ref": "#/$defs/CwlDirectoryParameterModel"}, {"$ref": "#/$defs/CwlUnionParameterModel"}, {"$ref": "#/$defs/CwlAnyParameterModel"}, {"$ref": "#/$defs/CwlEnumParameterModel"}, {"$ref": "#/$defs/CwlArrayParameterModel"}, {"$ref": "#/$defs/CwlRecordParameterModel"}]}, "title": "parameters", "type": "array"}, "has_default": {"default": false, "title": "has_default", "type": "boolean"}, "default_value": {"anyOf": [{}, {"type": "null"}], "default": null, "title": "default_value"}}, "required": ["name", "parameters"], "title": "CwlUnionParameterModel", "type": "object"}, "DataCollectionParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_data_collection", "default": "gx_data_collection", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "data_collection", "title": "type", "type": "string"}, "collection_type": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "collection_type"}, "extensions": {"default": ["data"], "items": {"type": "string"}, "title": "extensions", "type": "array"}, "value": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "title": "value"}}, "required": ["name", "type", "value"], "title": "DataCollectionParameterModel", "type": "object"}, "DataColumnParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_data_column", "default": "gx_data_column", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "data_column", "title": "type", "type": "string"}, "multiple": {"title": "multiple", "type": "boolean"}, "value": {"anyOf": [{"type": "integer"}, {"items": {"type": "integer"}, "type": "array"}, {"type": "null"}], "default": null, "title": "value"}}, "required": ["name", "type", "multiple"], "title": "DataColumnParameterModel", "type": "object"}, "DataParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_data", "default": "gx_data", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "data", "title": "type", "type": "string"}, "extensions": {"default": ["data"], "description": "Limit inputs to datasets with these extensions. Use 'data' to allow all input datasets.", "examples": ["txt", "tabular", "tiff"], "items": {"type": "string"}, "title": "extensions", "type": "array"}, "multiple": {"default": false, "description": "Allow multiple values to be selected.", "title": "multiple", "type": "boolean"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "max"}}, "required": ["name", "type"], "title": "DataParameterModel", "type": "object"}, "DirectoryUriParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_directory_uri", "default": "gx_directory_uri", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "directory", "title": "type", "type": "string"}, "validators": {"default": [], "items": {"anyOf": [{"$ref": "#/$defs/LengthParameterValidatorModel"}, {"$ref": "#/$defs/RegexParameterValidatorModel"}, {"$ref": "#/$defs/ExpressionParameterValidatorModel"}, {"$ref": "#/$defs/EmptyFieldParameterValidatorModel"}]}, "title": "validators", "type": "array"}}, "required": ["name", "type"], "title": "DirectoryUriParameterModel", "type": "object"}, "DrillDownOptionsDict": {"properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "name"}, "value": {"title": "value", "type": "string"}, "options": {"items": {"$ref": "#/$defs/DrillDownOptionsDict"}, "title": "options", "type": "array"}, "selected": {"title": "selected", "type": "boolean"}}, "required": ["name", "value", "options", "selected"], "title": "DrillDownOptionsDict", "type": "object"}, "DrillDownParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_drill_down", "default": "gx_drill_down", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "drill_down", "title": "type", "type": "string"}, "options": {"anyOf": [{"items": {"$ref": "#/$defs/DrillDownOptionsDict"}, "type": "array"}, {"type": "null"}], "default": null, "title": "options"}, "multiple": {"title": "multiple", "type": "boolean"}, "hierarchy": {"enum": ["recurse", "exact"], "title": "hierarchy", "type": "string"}}, "required": ["name", "type", "multiple", "hierarchy"], "title": "DrillDownParameterModel", "type": "object"}, "EmptyFieldParameterValidatorModel": {"additionalProperties": false, "properties": {"type": {"const": "empty_field", "default": "empty_field", "title": "Type", "type": "string"}, "message": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Message"}, "implicit": {"default": false, "title": "Implicit", "type": "boolean"}, "negate": {"default": false, "title": "Negate", "type": "boolean"}}, "title": "EmptyFieldParameterValidatorModel", "type": "object"}, "ExpressionParameterValidatorModel": {"additionalProperties": false, "description": "Check if a one line python expression given expression evaluates to True.\n\nThe expression is given is the content of the validator tag.", "properties": {"type": {"const": "expression", "default": "expression", "title": "Type", "type": "string"}, "message": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Message"}, "implicit": {"default": false, "title": "Implicit", "type": "boolean"}, "negate": {"default": false, "title": "Negate", "type": "boolean"}, "expression": {"title": "Expression", "type": "string"}}, "required": ["expression"], "title": "ExpressionParameterValidatorModel", "type": "object"}, "FilePatternDatasetCollectionDescription": {"properties": {"discover_via": {"const": "pattern", "title": "discover_via", "type": "string"}, "format": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "format"}, "visible": {"title": "visible", "type": "boolean"}, "assign_primary_output": {"title": "assign_primary_output", "type": "boolean"}, "directory": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "directory"}, "recurse": {"title": "recurse", "type": "boolean"}, "match_relative_path": {"title": "match_relative_path", "type": "boolean"}, "sort_key": {"enum": ["filename", "name", "designation", "dbkey"], "title": "sort_key", "type": "string"}, "sort_comp": {"enum": ["lexical", "numeric"], "title": "sort_comp", "type": "string"}, "sort_reverse": {"default": false, "title": "sort_reverse", "type": "boolean"}, "pattern": {"title": "pattern", "type": "string"}}, "required": ["discover_via", "format", "visible", "assign_primary_output", "directory", "recurse", "match_relative_path", "sort_key", "sort_comp", "pattern"], "title": "FilePatternDatasetCollectionDescription", "type": "object"}, "FloatParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_float", "default": "gx_float", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "float", "title": "type", "type": "string"}, "value": {"anyOf": [{"type": "number"}, {"type": "null"}], "default": null, "title": "value"}, "min": {"anyOf": [{"type": "number"}, {"type": "null"}], "default": null, "title": "min"}, "max": {"anyOf": [{"type": "number"}, {"type": "null"}], "default": null, "title": "max"}, "validators": {"default": [], "items": {"$ref": "#/$defs/InRangeParameterValidatorModel"}, "title": "validators", "type": "array"}}, "required": ["name", "type"], "title": "FloatParameterModel", "type": "object"}, "GalaxyToolParameterModel": {"discriminator": {"mapping": {"baseurl": "#/$defs/BaseUrlParameterModel", "boolean": "#/$defs/BooleanParameterModel", "color": "#/$defs/ColorParameterModel", "conditional": "#/$defs/ConditionalParameterModel", "data": "#/$defs/DataParameterModel", "data_collection": "#/$defs/DataCollectionParameterModel", "data_column": "#/$defs/DataColumnParameterModel", "directory": "#/$defs/DirectoryUriParameterModel", "drill_down": "#/$defs/DrillDownParameterModel", "float": "#/$defs/FloatParameterModel", "genomebuild": "#/$defs/GenomeBuildParameterModel", "group_tag": "#/$defs/GroupTagParameterModel", "hidden": "#/$defs/HiddenParameterModel", "integer": "#/$defs/IntegerParameterModel", "repeat": "#/$defs/RepeatParameterModel", "rules": "#/$defs/RulesParameterModel", "section": "#/$defs/SectionParameterModel", "select": "#/$defs/SelectParameterModel", "text": "#/$defs/TextParameterModel"}, "propertyName": "type"}, "oneOf": [{"$ref": "#/$defs/TextParameterModel"}, {"$ref": "#/$defs/IntegerParameterModel"}, {"$ref": "#/$defs/FloatParameterModel"}, {"$ref": "#/$defs/BooleanParameterModel"}, {"$ref": "#/$defs/HiddenParameterModel"}, {"$ref": "#/$defs/SelectParameterModel"}, {"$ref": "#/$defs/DataParameterModel"}, {"$ref": "#/$defs/DataCollectionParameterModel"}, {"$ref": "#/$defs/DataColumnParameterModel"}, {"$ref": "#/$defs/DirectoryUriParameterModel"}, {"$ref": "#/$defs/RulesParameterModel"}, {"$ref": "#/$defs/DrillDownParameterModel"}, {"$ref": "#/$defs/GroupTagParameterModel"}, {"$ref": "#/$defs/BaseUrlParameterModel"}, {"$ref": "#/$defs/GenomeBuildParameterModel"}, {"$ref": "#/$defs/ColorParameterModel"}, {"$ref": "#/$defs/ConditionalParameterModel"}, {"$ref": "#/$defs/RepeatParameterModel"}, {"$ref": "#/$defs/SectionParameterModel"}], "title": "GalaxyToolParameterModel"}, "GenomeBuildParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_genomebuild", "default": "gx_genomebuild", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "genomebuild", "title": "type", "type": "string"}, "multiple": {"title": "multiple", "type": "boolean"}}, "required": ["name", "type", "multiple"], "title": "GenomeBuildParameterModel", "type": "object"}, "GroupTagParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_group_tag", "default": "gx_group_tag", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "group_tag", "title": "type", "type": "string"}, "multiple": {"title": "multiple", "type": "boolean"}}, "required": ["name", "type", "multiple"], "title": "GroupTagParameterModel", "type": "object"}, "HelpContent": {"properties": {"format": {"enum": ["restructuredtext", "plain_text", "markdown"], "title": "format", "type": "string"}, "content": {"title": "content", "type": "string"}}, "required": ["format", "content"], "title": "HelpContent", "type": "object"}, "HiddenParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_hidden", "default": "gx_hidden", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "hidden", "title": "type", "type": "string"}, "value": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "value"}, "validators": {"default": [], "items": {"anyOf": [{"$ref": "#/$defs/LengthParameterValidatorModel"}, {"$ref": "#/$defs/RegexParameterValidatorModel"}, {"$ref": "#/$defs/ExpressionParameterValidatorModel"}, {"$ref": "#/$defs/EmptyFieldParameterValidatorModel"}]}, "title": "validators", "type": "array"}}, "required": ["name", "type", "value"], "title": "HiddenParameterModel", "type": "object"}, "InRangeParameterValidatorModel": {"additionalProperties": false, "properties": {"type": {"const": "in_range", "default": "in_range", "title": "Type", "type": "string"}, "message": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Message"}, "implicit": {"default": false, "title": "Implicit", "type": "boolean"}, "min": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "Min"}, "max": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "Max"}, "exclude_min": {"default": false, "title": "Exclude Min", "type": "boolean"}, "exclude_max": {"default": false, "title": "Exclude Max", "type": "boolean"}, "negate": {"default": false, "title": "Negate", "type": "boolean"}}, "title": "InRangeParameterValidatorModel", "type": "object"}, "IncomingToolOutputCollection": {"properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Parameter name. Used when referencing parameter in workflows.", "title": "name"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Output label. Will be used as dataset name in history.", "title": "label"}, "hidden": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "default": null, "description": "If true, the output will not be shown in the history.", "title": "hidden"}, "type": {"const": "collection", "title": "type", "type": "string"}, "structure": {"$ref": "#/$defs/ToolOutputCollectionStructure", "title": "structure"}}, "required": ["type", "structure"], "title": "IncomingToolOutputCollection", "type": "object"}, "IncomingToolOutputDataset": {"properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Parameter name. Used when referencing parameter in workflows.", "title": "name"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Output label. Will be used as dataset name in history.", "title": "label"}, "hidden": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "default": null, "description": "If true, the output will not be shown in the history.", "title": "hidden"}, "type": {"const": "data", "title": "type", "type": "string"}, "format": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "The short name for the output datatype.", "title": "format"}, "format_source": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "This sets the data type of the output dataset(s) to be the same format as that of the specified tool input.", "title": "format_source"}, "metadata_source": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "This copies the metadata information from the tool\u2019s input dataset to serve as default for information that cannot be detected from the output. One prominent use case is interval data with a non-standard column order that cannot be deduced from a header line, but which is known to be identical in the input and output datasets.", "title": "metadata_source"}, "discover_datasets": {"anyOf": [{"items": {"anyOf": [{"$ref": "#/$defs/FilePatternDatasetCollectionDescription"}, {"$ref": "#/$defs/ToolProvidedMetadataDatasetCollection"}]}, "type": "array"}, {"type": "null"}], "default": null, "title": "discover_datasets"}, "from_work_dir": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Relative path to a file produced by the tool in its working directory. Output\u2019s contents are set to this file\u2019s contents.", "title": "from_work_dir"}, "precreate_directory": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "default": false, "title": "precreate_directory"}}, "required": ["type"], "title": "IncomingToolOutputDataset", "type": "object"}, "IntegerParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_integer", "default": "gx_integer", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "title": "optional", "type": "boolean"}, "type": {"const": "integer", "title": "type", "type": "string"}, "value": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "value"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "max"}, "validators": {"default": [], "items": {"$ref": "#/$defs/InRangeParameterValidatorModel"}, "title": "validators", "type": "array"}}, "required": ["name", "type"], "title": "IntegerParameterModel", "type": "object"}, "JavascriptRequirement": {"properties": {"type": {"const": "javascript", "title": "type", "type": "string"}, "expression_lib": {"anyOf": [{"items": {"description": "Provide Javascript/ECMAScript 5.1 code here that will be available for expressions inside the `shell_command` field.", "examples": ["function pickValue() {\n if (inputs.conditional_parameter.test_parameter == \"a\") {\n return inputs.conditional_parameter.integer_parameter\n } else {\n return inputs.conditional_parameter.boolean_parameter\n }\n}"], "title": "expression_lib", "type": "string"}, "type": "array"}, {"type": "null"}], "title": "expression_lib"}}, "required": ["type", "expression_lib"], "title": "JavascriptRequirement", "type": "object"}, "LabelValue": {"properties": {"label": {"title": "Label", "type": "string"}, "value": {"title": "Value", "type": "string"}, "selected": {"title": "Selected", "type": "boolean"}}, "required": ["label", "value", "selected"], "title": "LabelValue", "type": "object"}, "LengthParameterValidatorModel": {"additionalProperties": false, "properties": {"type": {"const": "length", "default": "length", "title": "Type", "type": "string"}, "message": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Message"}, "implicit": {"default": false, "title": "Implicit", "type": "boolean"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "Max"}, "negate": {"default": false, "title": "Negate", "type": "boolean"}}, "title": "LengthParameterValidatorModel", "type": "object"}, "NoOptionsParameterValidatorModel": {"additionalProperties": false, "properties": {"type": {"const": "no_options", "default": "no_options", "title": "Type", "type": "string"}, "message": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Message"}, "implicit": {"default": false, "title": "Implicit", "type": "boolean"}, "negate": {"default": false, "title": "Negate", "type": "boolean"}}, "title": "NoOptionsParameterValidatorModel", "type": "object"}, "RegexParameterValidatorModel": {"additionalProperties": false, "description": "Check if a regular expression **matches** the value, i.e. appears\nat the beginning of the value. To enforce a match of the complete value use\n``$`` at the end of the expression. The expression is given is the content\nof the validator tag. Note that for ``selects`` each option is checked\nseparately.", "properties": {"type": {"const": "regex", "default": "regex", "title": "Type", "type": "string"}, "message": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Message"}, "implicit": {"default": false, "title": "Implicit", "type": "boolean"}, "negate": {"default": false, "title": "Negate", "type": "boolean"}, "expression": {"title": "Expression", "type": "string"}}, "required": ["expression"], "title": "RegexParameterValidatorModel", "type": "object"}, "RepeatParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_repeat", "default": "gx_repeat", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "repeat", "title": "type", "type": "string"}, "parameters": {"items": {"anyOf": [{"$ref": "#/$defs/CwlIntegerParameterModel"}, {"$ref": "#/$defs/CwlFloatParameterModel"}, {"$ref": "#/$defs/CwlStringParameterModel"}, {"$ref": "#/$defs/CwlBooleanParameterModel"}, {"$ref": "#/$defs/CwlNullParameterModel"}, {"$ref": "#/$defs/CwlFileParameterModel"}, {"$ref": "#/$defs/CwlDirectoryParameterModel"}, {"$ref": "#/$defs/CwlUnionParameterModel"}, {"$ref": "#/$defs/CwlAnyParameterModel"}, {"$ref": "#/$defs/CwlEnumParameterModel"}, {"$ref": "#/$defs/CwlArrayParameterModel"}, {"$ref": "#/$defs/CwlRecordParameterModel"}, {"$ref": "#/$defs/TextParameterModel"}, {"$ref": "#/$defs/IntegerParameterModel"}, {"$ref": "#/$defs/FloatParameterModel"}, {"$ref": "#/$defs/BooleanParameterModel"}, {"$ref": "#/$defs/HiddenParameterModel"}, {"$ref": "#/$defs/SelectParameterModel"}, {"$ref": "#/$defs/DataParameterModel"}, {"$ref": "#/$defs/DataCollectionParameterModel"}, {"$ref": "#/$defs/DataColumnParameterModel"}, {"$ref": "#/$defs/DirectoryUriParameterModel"}, {"$ref": "#/$defs/RulesParameterModel"}, {"$ref": "#/$defs/DrillDownParameterModel"}, {"$ref": "#/$defs/GroupTagParameterModel"}, {"$ref": "#/$defs/BaseUrlParameterModel"}, {"$ref": "#/$defs/GenomeBuildParameterModel"}, {"$ref": "#/$defs/ColorParameterModel"}, {"$ref": "#/$defs/ConditionalParameterModel"}, {"$ref": "#/$defs/RepeatParameterModel"}, {"$ref": "#/$defs/SectionParameterModel"}]}, "title": "parameters", "type": "array"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "max"}}, "required": ["name", "type", "parameters"], "title": "RepeatParameterModel", "type": "object"}, "ResourceRequirement": {"properties": {"type": {"const": "resource", "title": "type", "type": "string"}, "cores_min": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": 1, "description": "Minimum reserved number of CPU cores.\nMay be a fractional value to indicate to a scheduling algorithm that one core can be allocated to multiple jobs. For example, a value of 0.25 indicates that up to 4 jobs may run in parallel on 1 core. A value of 1.25 means that up to 3 jobs can run on a 4 core system (4/1.25 \u2248 3).\nThe reported number of CPU cores reserved for the process is a non-zero integer calculated by rounding up the cores request to the next whole number.\n", "title": "cores_min"}, "cores_max": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "Maximum reserved number of CPU cores.\nMay be a fractional value to indicate to a scheduling algorithm that one core can be allocated to multiple jobs. For example, a value of 0.25 indicates that up to 4 jobs may run in parallel on 1 core. A value of 1.25 means that up to 3 jobs can run on a 4 core system (4/1.25 \u2248 3).\nThe reported number of CPU cores reserved for the process is a non-zero integer calculated by rounding up the cores request to the next whole number.\n", "title": "cores_max"}, "ram_min": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": 256, "description": "Minimum reserved RAM in mebibytes (2**20).\nMay be a fractional value. If so, the actual RAM request is rounded up to the next whole number. The reported amount of RAM reserved for the process is a non-zero integer.", "title": "ram_min"}, "ram_max": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "Maximum reserved RAM in mebibytes (2**20).\nMay be a fractional value. If so, the actual RAM request is rounded up to the next whole number. The reported amount of RAM reserved for the process is a non-zero integer.", "title": "ram_max"}, "tmpdir_min": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "tmpdir_min"}, "tmpdir_max": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "tmpdir_max"}, "cuda_version_min": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "cuda_version_min"}, "cuda_compute_capability": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "cuda_compute_capability"}, "gpu_memory_min": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "gpu_memory_min"}, "cuda_device_count_min": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "cuda_device_count_min"}, "cuda_device_count_max": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "cuda_device_count_max"}, "shm_size": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "shm_size"}, "timelimit": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "Maximum time in seconds the tool is allowed to run. Job will be terminated if exceeded.", "title": "timelimit"}}, "required": ["type"], "title": "ResourceRequirement", "type": "object"}, "RulesParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_rules", "default": "gx_rules", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "rules", "title": "type", "type": "string"}}, "required": ["name", "type"], "title": "RulesParameterModel", "type": "object"}, "SectionParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_section", "default": "gx_section", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "section", "title": "type", "type": "string"}, "parameters": {"items": {"anyOf": [{"$ref": "#/$defs/CwlIntegerParameterModel"}, {"$ref": "#/$defs/CwlFloatParameterModel"}, {"$ref": "#/$defs/CwlStringParameterModel"}, {"$ref": "#/$defs/CwlBooleanParameterModel"}, {"$ref": "#/$defs/CwlNullParameterModel"}, {"$ref": "#/$defs/CwlFileParameterModel"}, {"$ref": "#/$defs/CwlDirectoryParameterModel"}, {"$ref": "#/$defs/CwlUnionParameterModel"}, {"$ref": "#/$defs/CwlAnyParameterModel"}, {"$ref": "#/$defs/CwlEnumParameterModel"}, {"$ref": "#/$defs/CwlArrayParameterModel"}, {"$ref": "#/$defs/CwlRecordParameterModel"}, {"$ref": "#/$defs/TextParameterModel"}, {"$ref": "#/$defs/IntegerParameterModel"}, {"$ref": "#/$defs/FloatParameterModel"}, {"$ref": "#/$defs/BooleanParameterModel"}, {"$ref": "#/$defs/HiddenParameterModel"}, {"$ref": "#/$defs/SelectParameterModel"}, {"$ref": "#/$defs/DataParameterModel"}, {"$ref": "#/$defs/DataCollectionParameterModel"}, {"$ref": "#/$defs/DataColumnParameterModel"}, {"$ref": "#/$defs/DirectoryUriParameterModel"}, {"$ref": "#/$defs/RulesParameterModel"}, {"$ref": "#/$defs/DrillDownParameterModel"}, {"$ref": "#/$defs/GroupTagParameterModel"}, {"$ref": "#/$defs/BaseUrlParameterModel"}, {"$ref": "#/$defs/GenomeBuildParameterModel"}, {"$ref": "#/$defs/ColorParameterModel"}, {"$ref": "#/$defs/ConditionalParameterModel"}, {"$ref": "#/$defs/RepeatParameterModel"}, {"$ref": "#/$defs/SectionParameterModel"}]}, "title": "parameters", "type": "array"}}, "required": ["name", "type", "parameters"], "title": "SectionParameterModel", "type": "object"}, "SelectParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_select", "default": "gx_select", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "select", "title": "type", "type": "string"}, "options": {"anyOf": [{"items": {"$ref": "#/$defs/LabelValue"}, "type": "array"}, {"type": "null"}], "default": null, "title": "options"}, "multiple": {"default": false, "title": "multiple", "type": "boolean"}, "validators": {"default": [], "items": {"$ref": "#/$defs/NoOptionsParameterValidatorModel"}, "title": "validators", "type": "array"}}, "required": ["name", "type"], "title": "SelectParameterModel", "type": "object"}, "TextParameterModel": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows or inside command templating.", "title": "name", "type": "string"}, "parameter_type": {"const": "gx_text", "default": "gx_text", "title": "parameter_type", "type": "string"}, "hidden": {"default": false, "title": "hidden", "type": "boolean"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Will be displayed on the tool page as the label of the parameter.", "title": "label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Short bit of text, rendered on the tool form just below the associated field to provide information about the field.", "title": "help"}, "argument": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "If the parameter reflects just one command line argument of a certain tool, this tag should be set to that particular argument. It is rendered in parenthesis after the help section, and it will create the name attribute (if not given explicitly) from the argument attribute by stripping leading dashes and replacing all remaining dashes by underscores (e.g. if argument=\"--long-parameter\" then name=\"long_parameter\" is implicit).", "title": "argument"}, "is_dynamic": {"default": false, "title": "is_dynamic", "type": "boolean"}, "optional": {"default": false, "description": "If `false`, parameter must have a value.", "title": "optional", "type": "boolean"}, "type": {"const": "text", "title": "type", "type": "string"}, "area": {"default": false, "title": "area", "type": "boolean"}, "value": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "default_value"}, "default_options": {"default": [], "items": {"$ref": "#/$defs/LabelValue"}, "title": "default_options", "type": "array"}, "validators": {"default": [], "items": {"anyOf": [{"$ref": "#/$defs/LengthParameterValidatorModel"}, {"$ref": "#/$defs/RegexParameterValidatorModel"}, {"$ref": "#/$defs/ExpressionParameterValidatorModel"}, {"$ref": "#/$defs/EmptyFieldParameterValidatorModel"}]}, "title": "validators", "type": "array"}}, "required": ["name", "type"], "title": "TextParameterModel", "type": "object"}, "ToolOutputBoolean": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows.", "title": "name"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Output label. Will be used as dataset name in history.", "title": "label"}, "hidden": {"description": "If true, the output will not be shown in the history.", "title": "hidden"}, "type": {"const": "boolean", "title": "type", "type": "string"}}, "required": ["name", "hidden", "type"], "title": "ToolOutputBoolean", "type": "object"}, "ToolOutputCollectionStructure": {"properties": {"collection_type": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "collection_type"}, "collection_type_source": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "collection_type_source"}, "collection_type_from_rules": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "collection_type_from_rules"}, "structured_like": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "structured_like"}, "discover_datasets": {"anyOf": [{"items": {"anyOf": [{"$ref": "#/$defs/FilePatternDatasetCollectionDescription"}, {"$ref": "#/$defs/ToolProvidedMetadataDatasetCollection"}]}, "type": "array"}, {"type": "null"}], "default": null, "title": "discover_datasets"}}, "title": "ToolOutputCollectionStructure", "type": "object"}, "ToolOutputFloat": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows.", "title": "name"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Output label. Will be used as dataset name in history.", "title": "label"}, "hidden": {"description": "If true, the output will not be shown in the history.", "title": "hidden"}, "type": {"const": "float", "title": "type", "type": "string"}}, "required": ["name", "hidden", "type"], "title": "ToolOutputFloat", "type": "object"}, "ToolOutputInteger": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows.", "title": "name"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Output label. Will be used as dataset name in history.", "title": "label"}, "hidden": {"description": "If true, the output will not be shown in the history.", "title": "hidden"}, "type": {"const": "integer", "title": "type", "type": "string"}}, "required": ["name", "hidden", "type"], "title": "ToolOutputInteger", "type": "object"}, "ToolOutputText": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows.", "title": "name"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Output label. Will be used as dataset name in history.", "title": "label"}, "hidden": {"description": "If true, the output will not be shown in the history.", "title": "hidden"}, "type": {"const": "text", "title": "type", "type": "string"}}, "required": ["name", "hidden", "type"], "title": "ToolOutputText", "type": "object"}, "ToolProvidedMetadataDatasetCollection": {"properties": {"discover_via": {"const": "tool_provided_metadata", "title": "discover_via", "type": "string"}, "format": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "format"}, "visible": {"title": "visible", "type": "boolean"}, "assign_primary_output": {"title": "assign_primary_output", "type": "boolean"}, "directory": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "directory"}, "recurse": {"title": "recurse", "type": "boolean"}, "match_relative_path": {"title": "match_relative_path", "type": "boolean"}}, "required": ["discover_via", "format", "visible", "assign_primary_output", "directory", "recurse", "match_relative_path"], "title": "ToolProvidedMetadataDatasetCollection", "type": "object"}, "XrefDict": {"properties": {"value": {"title": "value", "type": "string"}, "type": {"title": "type", "type": "string"}}, "required": ["value", "type"], "title": "XrefDict", "type": "object"}, "YamlTemplateConfigFile": {"properties": {"content": {"title": "content", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "name"}, "filename": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "filename"}, "eval_engine": {"const": "ecmascript", "default": "ecmascript", "title": "eval_engine", "type": "string"}}, "required": ["content"], "title": "YamlTemplateConfigFile", "type": "object"}}, "properties": {"class": {"const": "GalaxyUserTool", "title": "class_", "type": "string"}, "id": {"description": "Unique identifier for the tool. Should be all lower-case and should not include whitespace.", "examples": ["my-cool-tool"], "maxLength": 255, "minLength": 3, "title": "id", "type": "string"}, "version": {"description": "Version for the tool.", "examples": ["0.1.0"], "title": "version", "type": "string"}, "name": {"description": "The name of the tool, displayed in the tool menu. This is not the same as the tool id, which is a unique identifier for the tool.", "title": "name", "type": "string"}, "description": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "The description is displayed in the tool menu immediately following the hyperlink for the tool.", "title": "description"}, "configfiles": {"anyOf": [{"items": {"$ref": "#/$defs/YamlTemplateConfigFile"}, "type": "array"}, {"type": "null"}], "default": null, "description": "A list of config files for this tool.", "title": "configfiles"}, "container": {"description": "Container image to use for this tool.", "examples": ["quay.io/biocontainers/python:3.13"], "title": "container", "type": "string"}, "requirements": {"anyOf": [{"items": {"anyOf": [{"$ref": "#/$defs/JavascriptRequirement"}, {"$ref": "#/$defs/ResourceRequirement"}, {"$ref": "#/$defs/ContainerRequirement"}]}, "type": "array"}, {"type": "null"}], "default": [], "description": "A list of requirements needed to execute this tool. These can be javascript expressions, resource requirements or container images.", "title": "requirements"}, "shell_command": {"description": "A string that contains the command to be executed. Parameters can be referenced inside $().", "examples": ["head -n '$(inputs.n_lines)' '$(inputs.data_input.path)'"], "title": "shell_command", "type": "string"}, "inputs": {"default": [], "items": {"$ref": "#/$defs/GalaxyToolParameterModel"}, "title": "inputs", "type": "array"}, "outputs": {"default": [], "items": {"discriminator": {"mapping": {"boolean": "#/$defs/ToolOutputBoolean", "collection": "#/$defs/IncomingToolOutputCollection", "data": "#/$defs/IncomingToolOutputDataset", "float": "#/$defs/ToolOutputFloat", "integer": "#/$defs/ToolOutputInteger", "text": "#/$defs/ToolOutputText"}, "propertyName": "type"}, "oneOf": [{"$ref": "#/$defs/IncomingToolOutputDataset"}, {"$ref": "#/$defs/IncomingToolOutputCollection"}, {"$ref": "#/$defs/ToolOutputText"}, {"$ref": "#/$defs/ToolOutputInteger"}, {"$ref": "#/$defs/ToolOutputFloat"}, {"$ref": "#/$defs/ToolOutputBoolean"}]}, "title": "outputs", "type": "array"}, "citations": {"anyOf": [{"items": {"$ref": "#/$defs/Citation"}, "type": "array"}, {"type": "null"}], "default": null, "title": "citations"}, "license": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "A full URI or a a short [SPDX](https://spdx.org/licenses/) identifier for a license for this tool wrapper. The tool wrapper license can be independent of the underlying tool license. This license covers the tool yaml and associated scripts shipped with the tool.", "examples": ["MIT"], "title": "license"}, "edam_operations": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "default": null, "title": "edam_operations"}, "edam_topics": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "default": null, "title": "edam_topics"}, "xrefs": {"anyOf": [{"items": {"$ref": "#/$defs/XrefDict"}, "type": "array"}, {"type": "null"}], "default": null, "title": "xrefs"}, "help": {"anyOf": [{"$ref": "#/$defs/HelpContent"}, {"type": "null"}], "default": null, "description": "Help text shown below the tool interface.", "title": "help"}}, "required": ["class", "id", "version", "name", "container", "shell_command"], "title": "UserToolSource", "type": "object"} +{"$defs": {"Citation": {"properties": {"type": {"title": "type", "type": "string"}, "content": {"title": "content", "type": "string"}}, "required": ["type", "content"], "title": "Citation", "type": "object"}, "CollectionAttributes": {"additionalProperties": false, "properties": {"collection_type": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "collection_type"}}, "title": "CollectionAttributes", "type": "object"}, "Container": {"properties": {"type": {"enum": ["docker", "singularity"], "title": "type", "type": "string"}, "container_id": {"title": "container_id", "type": "string"}}, "required": ["type", "container_id"], "title": "Container", "type": "object"}, "ContainerRequirement": {"properties": {"type": {"const": "container", "title": "type", "type": "string"}, "container": {"$ref": "#/$defs/Container", "title": "container"}}, "required": ["type", "container"], "title": "ContainerRequirement", "type": "object"}, "EmptyFieldParameterValidatorModel": {"additionalProperties": false, "properties": {"type": {"const": "empty_field", "default": "empty_field", "title": "Type", "type": "string"}, "message": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Message"}, "implicit": {"default": false, "title": "Implicit", "type": "boolean"}, "negate": {"default": false, "title": "Negate", "type": "boolean"}}, "title": "EmptyFieldParameterValidatorModel", "type": "object"}, "FilePatternDatasetCollectionDescription": {"properties": {"discover_via": {"const": "pattern", "title": "discover_via", "type": "string"}, "format": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "format"}, "visible": {"title": "visible", "type": "boolean"}, "assign_primary_output": {"title": "assign_primary_output", "type": "boolean"}, "directory": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "directory"}, "recurse": {"title": "recurse", "type": "boolean"}, "match_relative_path": {"title": "match_relative_path", "type": "boolean"}, "sort_key": {"enum": ["filename", "name", "designation", "dbkey"], "title": "sort_key", "type": "string"}, "sort_comp": {"enum": ["lexical", "numeric"], "title": "sort_comp", "type": "string"}, "sort_reverse": {"default": false, "title": "sort_reverse", "type": "boolean"}, "pattern": {"title": "pattern", "type": "string"}}, "required": ["discover_via", "format", "visible", "assign_primary_output", "directory", "recurse", "match_relative_path", "sort_key", "sort_comp", "pattern"], "title": "FilePatternDatasetCollectionDescription", "type": "object"}, "HelpContent": {"properties": {"format": {"enum": ["restructuredtext", "plain_text", "markdown"], "title": "format", "type": "string"}, "content": {"title": "content", "type": "string"}}, "required": ["format", "content"], "title": "HelpContent", "type": "object"}, "InRangeParameterValidatorModel": {"additionalProperties": false, "properties": {"type": {"const": "in_range", "default": "in_range", "title": "Type", "type": "string"}, "message": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Message"}, "implicit": {"default": false, "title": "Implicit", "type": "boolean"}, "min": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "Min"}, "max": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "Max"}, "exclude_min": {"default": false, "title": "Exclude Min", "type": "boolean"}, "exclude_max": {"default": false, "title": "Exclude Max", "type": "boolean"}, "negate": {"default": false, "title": "Negate", "type": "boolean"}}, "title": "InRangeParameterValidatorModel", "type": "object"}, "IncomingToolOutputCollection": {"properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Parameter name. Used when referencing parameter in workflows.", "title": "name"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Output label. Will be used as dataset name in history.", "title": "label"}, "hidden": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "default": null, "description": "If true, the output will not be shown in the history.", "title": "hidden"}, "type": {"const": "collection", "title": "type", "type": "string"}, "structure": {"$ref": "#/$defs/ToolOutputCollectionStructure", "title": "structure"}}, "required": ["type", "structure"], "title": "IncomingToolOutputCollection", "type": "object"}, "IncomingToolOutputDataset": {"properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Parameter name. Used when referencing parameter in workflows.", "title": "name"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Output label. Will be used as dataset name in history.", "title": "label"}, "hidden": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "default": null, "description": "If true, the output will not be shown in the history.", "title": "hidden"}, "type": {"const": "data", "title": "type", "type": "string"}, "format": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "The short name for the output datatype.", "title": "format"}, "format_source": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "This sets the data type of the output dataset(s) to be the same format as that of the specified tool input.", "title": "format_source"}, "metadata_source": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "This copies the metadata information from the tool\u2019s input dataset to serve as default for information that cannot be detected from the output. One prominent use case is interval data with a non-standard column order that cannot be deduced from a header line, but which is known to be identical in the input and output datasets.", "title": "metadata_source"}, "discover_datasets": {"anyOf": [{"items": {"anyOf": [{"$ref": "#/$defs/FilePatternDatasetCollectionDescription"}, {"$ref": "#/$defs/ToolProvidedMetadataDatasetCollection"}]}, "type": "array"}, {"type": "null"}], "default": null, "title": "discover_datasets"}, "from_work_dir": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Relative path to a file produced by the tool in its working directory. Output\u2019s contents are set to this file\u2019s contents.", "title": "from_work_dir"}, "precreate_directory": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "default": false, "title": "precreate_directory"}}, "required": ["type"], "title": "IncomingToolOutputDataset", "type": "object"}, "JavascriptRequirement": {"properties": {"type": {"const": "javascript", "title": "type", "type": "string"}, "expression_lib": {"anyOf": [{"items": {"description": "Provide Javascript/ECMAScript 5.1 code here that will be available for expressions inside the `shell_command` field.", "examples": ["function pickValue() {\n if (inputs.conditional_parameter.test_parameter == \"a\") {\n return inputs.conditional_parameter.integer_parameter\n } else {\n return inputs.conditional_parameter.boolean_parameter\n }\n}"], "title": "expression_lib", "type": "string"}, "type": "array"}, {"type": "null"}], "title": "expression_lib"}}, "required": ["type", "expression_lib"], "title": "JavascriptRequirement", "type": "object"}, "LengthParameterValidatorModel": {"additionalProperties": false, "properties": {"type": {"const": "length", "default": "length", "title": "Type", "type": "string"}, "message": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Message"}, "implicit": {"default": false, "title": "Implicit", "type": "boolean"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "Max"}, "negate": {"default": false, "title": "Negate", "type": "boolean"}}, "title": "LengthParameterValidatorModel", "type": "object"}, "NoOptionsParameterValidatorModel": {"additionalProperties": false, "properties": {"type": {"const": "no_options", "default": "no_options", "title": "Type", "type": "string"}, "message": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Message"}, "implicit": {"default": false, "title": "Implicit", "type": "boolean"}, "negate": {"default": false, "title": "Negate", "type": "boolean"}}, "title": "NoOptionsParameterValidatorModel", "type": "object"}, "OutputCompareType": {"enum": ["diff", "re_match", "sim_size", "re_match_multiline", "contains", "image_diff"], "title": "OutputCompareType", "type": "string"}, "RegexParameterValidatorModel": {"additionalProperties": false, "description": "Check if a regular expression **matches** the value, i.e. appears\nat the beginning of the value. To enforce a match of the complete value use\n``$`` at the end of the expression. The expression is given is the content\nof the validator tag. Note that for ``selects`` each option is checked\nseparately.", "properties": {"type": {"const": "regex", "default": "regex", "title": "Type", "type": "string"}, "message": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Message"}, "implicit": {"default": false, "title": "Implicit", "type": "boolean"}, "negate": {"default": false, "title": "Negate", "type": "boolean"}, "expression": {"title": "Expression", "type": "string"}}, "required": ["expression"], "title": "RegexParameterValidatorModel", "type": "object"}, "ResourceRequirement": {"properties": {"type": {"const": "resource", "title": "type", "type": "string"}, "cores_min": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": 1, "description": "Minimum reserved number of CPU cores.\nMay be a fractional value to indicate to a scheduling algorithm that one core can be allocated to multiple jobs. For example, a value of 0.25 indicates that up to 4 jobs may run in parallel on 1 core. A value of 1.25 means that up to 3 jobs can run on a 4 core system (4/1.25 \u2248 3).\nThe reported number of CPU cores reserved for the process is a non-zero integer calculated by rounding up the cores request to the next whole number.\n", "title": "cores_min"}, "cores_max": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "Maximum reserved number of CPU cores.\nMay be a fractional value to indicate to a scheduling algorithm that one core can be allocated to multiple jobs. For example, a value of 0.25 indicates that up to 4 jobs may run in parallel on 1 core. A value of 1.25 means that up to 3 jobs can run on a 4 core system (4/1.25 \u2248 3).\nThe reported number of CPU cores reserved for the process is a non-zero integer calculated by rounding up the cores request to the next whole number.\n", "title": "cores_max"}, "ram_min": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": 256, "description": "Minimum reserved RAM in mebibytes (2**20).\nMay be a fractional value. If so, the actual RAM request is rounded up to the next whole number. The reported amount of RAM reserved for the process is a non-zero integer.", "title": "ram_min"}, "ram_max": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "Maximum reserved RAM in mebibytes (2**20).\nMay be a fractional value. If so, the actual RAM request is rounded up to the next whole number. The reported amount of RAM reserved for the process is a non-zero integer.", "title": "ram_max"}, "tmpdir_min": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "tmpdir_min"}, "tmpdir_max": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "tmpdir_max"}, "cuda_version_min": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "cuda_version_min"}, "cuda_compute_capability": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "cuda_compute_capability"}, "gpu_memory_min": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "gpu_memory_min"}, "cuda_device_count_min": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "cuda_device_count_min"}, "cuda_device_count_max": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "cuda_device_count_max"}, "shm_size": {"anyOf": [{"type": "number"}, {"type": "integer"}, {"type": "null"}], "default": null, "title": "shm_size"}, "timelimit": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "Maximum time in seconds the tool is allowed to run. Job will be terminated if exceeded.", "title": "timelimit"}}, "required": ["type"], "title": "ResourceRequirement", "type": "object"}, "RootModel_List_Union_Annotated_Union_has_line_model__has_line_matching_model__has_n_lines_model__has_text_model__has_text_matching_model__not_has_text_model__has_n_columns_model__attribute_is_model__attribute_matches_model__element_text_model__element_text_is_model__element_text_matches_model__has_element_with_path_model__has_n_elements_with_path_model__is_valid_xml_model__xml_element_model__has_json_property_with_text_model__has_json_property_with_value_model__has_h5_attribute_model__has_h5_keys_model__has_archive_member_model__has_size_model__has_image_center_of_mass_model__has_image_channels_model__has_image_depth_model__has_image_frames_model__has_image_height_model__has_image_mean_intensity_model__has_image_mean_object_size_model__has_image_n_labels_model__has_image_width_model___FieldInfo_annotation_NoneType__required_True__discriminator__that_____has_line_model_nested__has_line_matching_model_nested__has_n_lines_model_nested__has_text_model_nested__has_text_matching_model_nested__not_has_text_model_nested__has_n_columns_model_nested__attribute_is_model_nested__attribute_matches_model_nested__element_text_model_nested__element_text_is_model_nested__element_text_matches_model_nested__has_element_with_path_model_nested__has_n_elements_with_path_model_nested__is_valid_xml_model_nested__xml_element_model_nested__has_json_property_with_text_model_nested__has_json_property_with_value_model_nested__has_h5_attribute_model_nested__has_h5_keys_model_nested__has_archive_member_model_nested__has_size_model_nested__has_image_center_of_mass_model_nested__has_image_channels_model_nested__has_image_depth_model_nested__has_image_frames_model_nested__has_image_height_model_nested__has_image_mean_intensity_model_nested__has_image_mean_object_size_model_nested__has_image_n_labels_model_nested__has_image_width_model_nested___": {"items": {"anyOf": [{"discriminator": {"mapping": {"attribute_is": "#/$defs/attribute_is_model", "attribute_matches": "#/$defs/attribute_matches_model", "element_text": "#/$defs/element_text_model", "element_text_is": "#/$defs/element_text_is_model", "element_text_matches": "#/$defs/element_text_matches_model", "has_archive_member": "#/$defs/has_archive_member_model", "has_element_with_path": "#/$defs/has_element_with_path_model", "has_h5_attribute": "#/$defs/has_h5_attribute_model", "has_h5_keys": "#/$defs/has_h5_keys_model", "has_image_center_of_mass": "#/$defs/has_image_center_of_mass_model", "has_image_channels": "#/$defs/has_image_channels_model", "has_image_depth": "#/$defs/has_image_depth_model", "has_image_frames": "#/$defs/has_image_frames_model", "has_image_height": "#/$defs/has_image_height_model", "has_image_mean_intensity": "#/$defs/has_image_mean_intensity_model", "has_image_mean_object_size": "#/$defs/has_image_mean_object_size_model", "has_image_n_labels": "#/$defs/has_image_n_labels_model", "has_image_width": "#/$defs/has_image_width_model", "has_json_property_with_text": "#/$defs/has_json_property_with_text_model", "has_json_property_with_value": "#/$defs/has_json_property_with_value_model", "has_line": "#/$defs/has_line_model", "has_line_matching": "#/$defs/has_line_matching_model", "has_n_columns": "#/$defs/has_n_columns_model", "has_n_elements_with_path": "#/$defs/has_n_elements_with_path_model", "has_n_lines": "#/$defs/has_n_lines_model", "has_size": "#/$defs/has_size_model", "has_text": "#/$defs/has_text_model", "has_text_matching": "#/$defs/has_text_matching_model", "is_valid_xml": "#/$defs/is_valid_xml_model", "not_has_text": "#/$defs/not_has_text_model", "xml_element": "#/$defs/xml_element_model"}, "propertyName": "that"}, "oneOf": [{"$ref": "#/$defs/has_line_model"}, {"$ref": "#/$defs/has_line_matching_model"}, {"$ref": "#/$defs/has_n_lines_model"}, {"$ref": "#/$defs/has_text_model"}, {"$ref": "#/$defs/has_text_matching_model"}, {"$ref": "#/$defs/not_has_text_model"}, {"$ref": "#/$defs/has_n_columns_model"}, {"$ref": "#/$defs/attribute_is_model"}, {"$ref": "#/$defs/attribute_matches_model"}, {"$ref": "#/$defs/element_text_model"}, {"$ref": "#/$defs/element_text_is_model"}, {"$ref": "#/$defs/element_text_matches_model"}, {"$ref": "#/$defs/has_element_with_path_model"}, {"$ref": "#/$defs/has_n_elements_with_path_model"}, {"$ref": "#/$defs/is_valid_xml_model"}, {"$ref": "#/$defs/xml_element_model"}, {"$ref": "#/$defs/has_json_property_with_text_model"}, {"$ref": "#/$defs/has_json_property_with_value_model"}, {"$ref": "#/$defs/has_h5_attribute_model"}, {"$ref": "#/$defs/has_h5_keys_model"}, {"$ref": "#/$defs/has_archive_member_model"}, {"$ref": "#/$defs/has_size_model"}, {"$ref": "#/$defs/has_image_center_of_mass_model"}, {"$ref": "#/$defs/has_image_channels_model"}, {"$ref": "#/$defs/has_image_depth_model"}, {"$ref": "#/$defs/has_image_frames_model"}, {"$ref": "#/$defs/has_image_height_model"}, {"$ref": "#/$defs/has_image_mean_intensity_model"}, {"$ref": "#/$defs/has_image_mean_object_size_model"}, {"$ref": "#/$defs/has_image_n_labels_model"}, {"$ref": "#/$defs/has_image_width_model"}]}, {"$ref": "#/$defs/has_line_model_nested"}, {"$ref": "#/$defs/has_line_matching_model_nested"}, {"$ref": "#/$defs/has_n_lines_model_nested"}, {"$ref": "#/$defs/has_text_model_nested"}, {"$ref": "#/$defs/has_text_matching_model_nested"}, {"$ref": "#/$defs/not_has_text_model_nested"}, {"$ref": "#/$defs/has_n_columns_model_nested"}, {"$ref": "#/$defs/attribute_is_model_nested"}, {"$ref": "#/$defs/attribute_matches_model_nested"}, {"$ref": "#/$defs/element_text_model_nested"}, {"$ref": "#/$defs/element_text_is_model_nested"}, {"$ref": "#/$defs/element_text_matches_model_nested"}, {"$ref": "#/$defs/has_element_with_path_model_nested"}, {"$ref": "#/$defs/has_n_elements_with_path_model_nested"}, {"$ref": "#/$defs/is_valid_xml_model_nested"}, {"$ref": "#/$defs/xml_element_model_nested"}, {"$ref": "#/$defs/has_json_property_with_text_model_nested"}, {"$ref": "#/$defs/has_json_property_with_value_model_nested"}, {"$ref": "#/$defs/has_h5_attribute_model_nested"}, {"$ref": "#/$defs/has_h5_keys_model_nested"}, {"$ref": "#/$defs/has_archive_member_model_nested"}, {"$ref": "#/$defs/has_size_model_nested"}, {"$ref": "#/$defs/has_image_center_of_mass_model_nested"}, {"$ref": "#/$defs/has_image_channels_model_nested"}, {"$ref": "#/$defs/has_image_depth_model_nested"}, {"$ref": "#/$defs/has_image_frames_model_nested"}, {"$ref": "#/$defs/has_image_height_model_nested"}, {"$ref": "#/$defs/has_image_mean_intensity_model_nested"}, {"$ref": "#/$defs/has_image_mean_object_size_model_nested"}, {"$ref": "#/$defs/has_image_n_labels_model_nested"}, {"$ref": "#/$defs/has_image_width_model_nested"}]}, "title": "RootModel[List[Union[Annotated[Union[has_line_model, has_line_matching_model, has_n_lines_model, has_text_model, has_text_matching_model, not_has_text_model, has_n_columns_model, attribute_is_model, attribute_matches_model, element_text_model, element_text_is_model, element_text_matches_model, has_element_with_path_model, has_n_elements_with_path_model, is_valid_xml_model, xml_element_model, has_json_property_with_text_model, has_json_property_with_value_model, has_h5_attribute_model, has_h5_keys_model, has_archive_member_model, has_size_model, has_image_center_of_mass_model, has_image_channels_model, has_image_depth_model, has_image_frames_model, has_image_height_model, has_image_mean_intensity_model, has_image_mean_object_size_model, has_image_n_labels_model, has_image_width_model], FieldInfo(annotation=NoneType, required=True, discriminator='that')], has_line_model_nested, has_line_matching_model_nested, has_n_lines_model_nested, has_text_model_nested, has_text_matching_model_nested, not_has_text_model_nested, has_n_columns_model_nested, attribute_is_model_nested, attribute_matches_model_nested, element_text_model_nested, element_text_is_model_nested, element_text_matches_model_nested, has_element_with_path_model_nested, has_n_elements_with_path_model_nested, is_valid_xml_model_nested, xml_element_model_nested, has_json_property_with_text_model_nested, has_json_property_with_value_model_nested, has_h5_attribute_model_nested, has_h5_keys_model_nested, has_archive_member_model_nested, has_size_model_nested, has_image_center_of_mass_model_nested, has_image_channels_model_nested, has_image_depth_model_nested, has_image_frames_model_nested, has_image_height_model_nested, has_image_mean_intensity_model_nested, has_image_mean_object_size_model_nested, has_image_n_labels_model_nested, has_image_width_model_nested]]]", "type": "array"}, "TestCollectionCollectionElementAssertions": {"additionalProperties": false, "properties": {"elements": {"anyOf": [{"additionalProperties": {"anyOf": [{"$ref": "#/$defs/TestCollectionDatasetElementAssertions"}, {"$ref": "#/$defs/TestCollectionCollectionElementAssertions"}]}, "type": "object"}, {"type": "null"}], "default": null, "title": "elements"}, "element_tests": {"anyOf": [{"additionalProperties": {"anyOf": [{"$ref": "#/$defs/TestCollectionDatasetElementAssertions"}, {"$ref": "#/$defs/TestCollectionCollectionElementAssertions"}]}, "type": "object"}, {"type": "null"}], "default": null, "title": "element_tests"}}, "title": "TestCollectionCollectionElementAssertions", "type": "object"}, "TestCollectionDatasetElementAssertions": {"additionalProperties": false, "properties": {"file": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "file"}, "path": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "path"}, "location": {"anyOf": [{"format": "uri", "minLength": 1, "type": "string"}, {"type": "null"}], "default": null, "title": "location"}, "ftype": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "ftype"}, "sort": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "default": null, "title": "sort"}, "compare": {"anyOf": [{"$ref": "#/$defs/OutputCompareType"}, {"type": "null"}], "default": null, "title": "compare"}, "checksum": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "checksum"}, "metadata": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "default": null, "title": "metadata"}, "asserts": {"anyOf": [{"$ref": "#/$defs/RootModel_List_Union_Annotated_Union_has_line_model__has_line_matching_model__has_n_lines_model__has_text_model__has_text_matching_model__not_has_text_model__has_n_columns_model__attribute_is_model__attribute_matches_model__element_text_model__element_text_is_model__element_text_matches_model__has_element_with_path_model__has_n_elements_with_path_model__is_valid_xml_model__xml_element_model__has_json_property_with_text_model__has_json_property_with_value_model__has_h5_attribute_model__has_h5_keys_model__has_archive_member_model__has_size_model__has_image_center_of_mass_model__has_image_channels_model__has_image_depth_model__has_image_frames_model__has_image_height_model__has_image_mean_intensity_model__has_image_mean_object_size_model__has_image_n_labels_model__has_image_width_model___FieldInfo_annotation_NoneType__required_True__discriminator__that_____has_line_model_nested__has_line_matching_model_nested__has_n_lines_model_nested__has_text_model_nested__has_text_matching_model_nested__not_has_text_model_nested__has_n_columns_model_nested__attribute_is_model_nested__attribute_matches_model_nested__element_text_model_nested__element_text_is_model_nested__element_text_matches_model_nested__has_element_with_path_model_nested__has_n_elements_with_path_model_nested__is_valid_xml_model_nested__xml_element_model_nested__has_json_property_with_text_model_nested__has_json_property_with_value_model_nested__has_h5_attribute_model_nested__has_h5_keys_model_nested__has_archive_member_model_nested__has_size_model_nested__has_image_center_of_mass_model_nested__has_image_channels_model_nested__has_image_depth_model_nested__has_image_frames_model_nested__has_image_height_model_nested__has_image_mean_intensity_model_nested__has_image_mean_object_size_model_nested__has_image_n_labels_model_nested__has_image_width_model_nested___"}, {"$ref": "#/$defs/assertion_dict"}, {"type": "null"}], "default": null, "title": "asserts"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "delta"}, "delta_frac": {"anyOf": [{"type": "number"}, {"type": "null"}], "default": null, "title": "delta_frac"}, "lines_diff": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "lines_diff"}, "decompress": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "default": null, "title": "decompress"}}, "title": "TestCollectionDatasetElementAssertions", "type": "object"}, "TestCollectionOutputAssertions": {"additionalProperties": false, "properties": {"class": {"anyOf": [{"const": "Collection", "type": "string"}, {"type": "null"}], "default": "Collection", "title": "class_"}, "elements": {"anyOf": [{"additionalProperties": {"anyOf": [{"$ref": "#/$defs/TestCollectionDatasetElementAssertions"}, {"$ref": "#/$defs/TestCollectionCollectionElementAssertions"}]}, "type": "object"}, {"type": "null"}], "default": null, "title": "elements"}, "element_tests": {"anyOf": [{"additionalProperties": {"anyOf": [{"$ref": "#/$defs/TestCollectionDatasetElementAssertions"}, {"$ref": "#/$defs/TestCollectionCollectionElementAssertions"}]}, "type": "object"}, {"type": "null"}], "default": null, "title": "element_tests"}, "element_count": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "element_count"}, "attributes": {"anyOf": [{"$ref": "#/$defs/CollectionAttributes"}, {"type": "null"}], "default": null, "title": "attributes"}, "collection_type": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "collection_type"}}, "title": "TestCollectionOutputAssertions", "type": "object"}, "TestDataOutputAssertions": {"additionalProperties": false, "properties": {"file": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "file"}, "path": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "path"}, "location": {"anyOf": [{"format": "uri", "minLength": 1, "type": "string"}, {"type": "null"}], "default": null, "title": "location"}, "ftype": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "ftype"}, "sort": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "default": null, "title": "sort"}, "compare": {"anyOf": [{"$ref": "#/$defs/OutputCompareType"}, {"type": "null"}], "default": null, "title": "compare"}, "checksum": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "checksum"}, "metadata": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "default": null, "title": "metadata"}, "asserts": {"anyOf": [{"$ref": "#/$defs/RootModel_List_Union_Annotated_Union_has_line_model__has_line_matching_model__has_n_lines_model__has_text_model__has_text_matching_model__not_has_text_model__has_n_columns_model__attribute_is_model__attribute_matches_model__element_text_model__element_text_is_model__element_text_matches_model__has_element_with_path_model__has_n_elements_with_path_model__is_valid_xml_model__xml_element_model__has_json_property_with_text_model__has_json_property_with_value_model__has_h5_attribute_model__has_h5_keys_model__has_archive_member_model__has_size_model__has_image_center_of_mass_model__has_image_channels_model__has_image_depth_model__has_image_frames_model__has_image_height_model__has_image_mean_intensity_model__has_image_mean_object_size_model__has_image_n_labels_model__has_image_width_model___FieldInfo_annotation_NoneType__required_True__discriminator__that_____has_line_model_nested__has_line_matching_model_nested__has_n_lines_model_nested__has_text_model_nested__has_text_matching_model_nested__not_has_text_model_nested__has_n_columns_model_nested__attribute_is_model_nested__attribute_matches_model_nested__element_text_model_nested__element_text_is_model_nested__element_text_matches_model_nested__has_element_with_path_model_nested__has_n_elements_with_path_model_nested__is_valid_xml_model_nested__xml_element_model_nested__has_json_property_with_text_model_nested__has_json_property_with_value_model_nested__has_h5_attribute_model_nested__has_h5_keys_model_nested__has_archive_member_model_nested__has_size_model_nested__has_image_center_of_mass_model_nested__has_image_channels_model_nested__has_image_depth_model_nested__has_image_frames_model_nested__has_image_height_model_nested__has_image_mean_intensity_model_nested__has_image_mean_object_size_model_nested__has_image_n_labels_model_nested__has_image_width_model_nested___"}, {"$ref": "#/$defs/assertion_dict"}, {"type": "null"}], "default": null, "title": "asserts"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "delta"}, "delta_frac": {"anyOf": [{"type": "number"}, {"type": "null"}], "default": null, "title": "delta_frac"}, "lines_diff": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "lines_diff"}, "decompress": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "default": null, "title": "decompress"}, "class": {"anyOf": [{"const": "File", "type": "string"}, {"type": "null"}], "default": "File", "title": "class_"}}, "title": "TestDataOutputAssertions", "type": "object"}, "ToolOutputBoolean": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows.", "title": "name"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Output label. Will be used as dataset name in history.", "title": "label"}, "hidden": {"description": "If true, the output will not be shown in the history.", "title": "hidden"}, "type": {"const": "boolean", "title": "type", "type": "string"}}, "required": ["name", "hidden", "type"], "title": "ToolOutputBoolean", "type": "object"}, "ToolOutputCollectionStructure": {"properties": {"collection_type": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "collection_type"}, "collection_type_source": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "collection_type_source"}, "collection_type_from_rules": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "collection_type_from_rules"}, "structured_like": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "structured_like"}, "discover_datasets": {"anyOf": [{"items": {"anyOf": [{"$ref": "#/$defs/FilePatternDatasetCollectionDescription"}, {"$ref": "#/$defs/ToolProvidedMetadataDatasetCollection"}]}, "type": "array"}, {"type": "null"}], "default": null, "title": "discover_datasets"}}, "title": "ToolOutputCollectionStructure", "type": "object"}, "ToolOutputFloat": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows.", "title": "name"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Output label. Will be used as dataset name in history.", "title": "label"}, "hidden": {"description": "If true, the output will not be shown in the history.", "title": "hidden"}, "type": {"const": "float", "title": "type", "type": "string"}}, "required": ["name", "hidden", "type"], "title": "ToolOutputFloat", "type": "object"}, "ToolOutputInteger": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows.", "title": "name"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Output label. Will be used as dataset name in history.", "title": "label"}, "hidden": {"description": "If true, the output will not be shown in the history.", "title": "hidden"}, "type": {"const": "integer", "title": "type", "type": "string"}}, "required": ["name", "hidden", "type"], "title": "ToolOutputInteger", "type": "object"}, "ToolOutputText": {"properties": {"name": {"description": "Parameter name. Used when referencing parameter in workflows.", "title": "name"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Output label. Will be used as dataset name in history.", "title": "label"}, "hidden": {"description": "If true, the output will not be shown in the history.", "title": "hidden"}, "type": {"const": "text", "title": "type", "type": "string"}}, "required": ["name", "hidden", "type"], "title": "ToolOutputText", "type": "object"}, "ToolProvidedMetadataDatasetCollection": {"properties": {"discover_via": {"const": "tool_provided_metadata", "title": "discover_via", "type": "string"}, "format": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "format"}, "visible": {"title": "visible", "type": "boolean"}, "assign_primary_output": {"title": "assign_primary_output", "type": "boolean"}, "directory": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "directory"}, "recurse": {"title": "recurse", "type": "boolean"}, "match_relative_path": {"title": "match_relative_path", "type": "boolean"}}, "required": ["discover_via", "format", "visible", "assign_primary_output", "directory", "recurse", "match_relative_path"], "title": "ToolProvidedMetadataDatasetCollection", "type": "object"}, "XrefDict": {"additionalProperties": false, "properties": {"value": {"title": "value", "type": "string"}, "type": {"title": "type", "type": "string"}}, "required": ["value", "type"], "title": "XrefDict", "type": "object"}, "YamlBooleanParameter": {"additionalProperties": false, "properties": {"name": {"title": "Name", "type": "string"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Help"}, "optional": {"default": false, "title": "Optional", "type": "boolean"}, "type": {"const": "boolean", "title": "Type", "type": "string"}, "value": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "default": false, "title": "Value"}}, "required": ["name", "type"], "title": "YamlBooleanParameter", "type": "object"}, "YamlColorParameter": {"additionalProperties": false, "properties": {"name": {"title": "Name", "type": "string"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Help"}, "optional": {"default": false, "title": "Optional", "type": "boolean"}, "type": {"const": "color", "title": "Type", "type": "string"}, "value": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Value"}}, "required": ["name", "type"], "title": "YamlColorParameter", "type": "object"}, "YamlConditionalParameter": {"additionalProperties": false, "properties": {"name": {"title": "Name", "type": "string"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Help"}, "optional": {"default": false, "title": "Optional", "type": "boolean"}, "type": {"const": "conditional", "title": "Type", "type": "string"}, "test_parameter": {"discriminator": {"mapping": {"boolean": "#/$defs/YamlBooleanParameter", "select": "#/$defs/YamlSelectParameter"}, "propertyName": "type"}, "oneOf": [{"$ref": "#/$defs/YamlBooleanParameter"}, {"$ref": "#/$defs/YamlSelectParameter"}], "title": "Test Parameter"}, "whens": {"items": {"$ref": "#/$defs/YamlConditionalWhen"}, "minItems": 1, "title": "Whens", "type": "array"}}, "required": ["name", "type", "test_parameter", "whens"], "title": "YamlConditionalParameter", "type": "object"}, "YamlConditionalWhen": {"additionalProperties": false, "properties": {"discriminator": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "title": "Discriminator"}, "parameters": {"default": [], "items": {"$ref": "#/$defs/YamlGalaxyToolParameter"}, "title": "Parameters", "type": "array"}}, "required": ["discriminator"], "title": "YamlConditionalWhen", "type": "object"}, "YamlDataCollectionParameter": {"additionalProperties": false, "properties": {"name": {"title": "Name", "type": "string"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Help"}, "optional": {"default": false, "title": "Optional", "type": "boolean"}, "type": {"const": "data_collection", "title": "Type", "type": "string"}, "collection_type": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Collection Type"}, "format": {"default": ["data"], "items": {"type": "string"}, "title": "Format", "type": "array"}}, "required": ["name", "type"], "title": "YamlDataCollectionParameter", "type": "object"}, "YamlDataParameter": {"additionalProperties": false, "properties": {"name": {"title": "Name", "type": "string"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Help"}, "optional": {"default": false, "title": "Optional", "type": "boolean"}, "type": {"const": "data", "title": "Type", "type": "string"}, "format": {"default": ["data"], "items": {"type": "string"}, "title": "Format", "type": "array"}, "multiple": {"default": false, "title": "Multiple", "type": "boolean"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "Max"}}, "required": ["name", "type"], "title": "YamlDataParameter", "type": "object"}, "YamlFloatParameter": {"additionalProperties": false, "properties": {"name": {"title": "Name", "type": "string"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Help"}, "optional": {"default": false, "title": "Optional", "type": "boolean"}, "type": {"const": "float", "title": "Type", "type": "string"}, "value": {"anyOf": [{"type": "number"}, {"type": "null"}], "default": null, "title": "Value"}, "min": {"anyOf": [{"type": "number"}, {"type": "null"}], "default": null, "title": "Min"}, "max": {"anyOf": [{"type": "number"}, {"type": "null"}], "default": null, "title": "Max"}, "validators": {"default": [], "items": {"$ref": "#/$defs/InRangeParameterValidatorModel"}, "title": "Validators", "type": "array"}}, "required": ["name", "type"], "title": "YamlFloatParameter", "type": "object"}, "YamlGalaxyToolParameter": {"discriminator": {"mapping": {"boolean": "#/$defs/YamlBooleanParameter", "color": "#/$defs/YamlColorParameter", "conditional": "#/$defs/YamlConditionalParameter", "data": "#/$defs/YamlDataParameter", "data_collection": "#/$defs/YamlDataCollectionParameter", "float": "#/$defs/YamlFloatParameter", "integer": "#/$defs/YamlIntegerParameter", "repeat": "#/$defs/YamlRepeatParameter", "section": "#/$defs/YamlSectionParameter", "select": "#/$defs/YamlSelectParameter", "text": "#/$defs/YamlTextParameter"}, "propertyName": "type"}, "oneOf": [{"$ref": "#/$defs/YamlBooleanParameter"}, {"$ref": "#/$defs/YamlIntegerParameter"}, {"$ref": "#/$defs/YamlFloatParameter"}, {"$ref": "#/$defs/YamlTextParameter"}, {"$ref": "#/$defs/YamlSelectParameter"}, {"$ref": "#/$defs/YamlColorParameter"}, {"$ref": "#/$defs/YamlDataParameter"}, {"$ref": "#/$defs/YamlDataCollectionParameter"}, {"$ref": "#/$defs/YamlConditionalParameter"}, {"$ref": "#/$defs/YamlRepeatParameter"}, {"$ref": "#/$defs/YamlSectionParameter"}], "title": "YamlGalaxyToolParameter"}, "YamlIntegerParameter": {"additionalProperties": false, "properties": {"name": {"title": "Name", "type": "string"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Help"}, "optional": {"default": false, "title": "Optional", "type": "boolean"}, "type": {"const": "integer", "title": "Type", "type": "string"}, "value": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "Value"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "Max"}, "validators": {"default": [], "items": {"$ref": "#/$defs/InRangeParameterValidatorModel"}, "title": "Validators", "type": "array"}}, "required": ["name", "type"], "title": "YamlIntegerParameter", "type": "object"}, "YamlLabelValue": {"description": "YAML-friendly option model \u2014 ``selected`` defaults to ``False``.", "properties": {"label": {"title": "Label", "type": "string"}, "value": {"title": "Value", "type": "string"}, "selected": {"default": false, "title": "Selected", "type": "boolean"}}, "required": ["label", "value"], "title": "YamlLabelValue", "type": "object"}, "YamlRepeatParameter": {"additionalProperties": false, "properties": {"name": {"title": "Name", "type": "string"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Help"}, "optional": {"default": false, "title": "Optional", "type": "boolean"}, "type": {"const": "repeat", "title": "Type", "type": "string"}, "parameters": {"default": [], "items": {"$ref": "#/$defs/YamlGalaxyToolParameter"}, "title": "Parameters", "type": "array"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "Max"}}, "required": ["name", "type"], "title": "YamlRepeatParameter", "type": "object"}, "YamlSectionParameter": {"additionalProperties": false, "properties": {"name": {"title": "Name", "type": "string"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Help"}, "optional": {"default": false, "title": "Optional", "type": "boolean"}, "type": {"const": "section", "title": "Type", "type": "string"}, "parameters": {"default": [], "items": {"$ref": "#/$defs/YamlGalaxyToolParameter"}, "title": "Parameters", "type": "array"}}, "required": ["name", "type"], "title": "YamlSectionParameter", "type": "object"}, "YamlSelectParameter": {"additionalProperties": false, "properties": {"name": {"title": "Name", "type": "string"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Help"}, "optional": {"default": false, "title": "Optional", "type": "boolean"}, "type": {"const": "select", "title": "Type", "type": "string"}, "options": {"items": {"$ref": "#/$defs/YamlLabelValue"}, "minItems": 1, "title": "Options", "type": "array"}, "multiple": {"default": false, "title": "Multiple", "type": "boolean"}, "validators": {"default": [], "items": {"$ref": "#/$defs/NoOptionsParameterValidatorModel"}, "title": "Validators", "type": "array"}}, "required": ["name", "type", "options"], "title": "YamlSelectParameter", "type": "object"}, "YamlTemplateConfigFile": {"properties": {"content": {"title": "content", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "name"}, "filename": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "filename"}, "eval_engine": {"const": "ecmascript", "default": "ecmascript", "title": "eval_engine", "type": "string"}}, "required": ["content"], "title": "YamlTemplateConfigFile", "type": "object"}, "YamlTextParameter": {"additionalProperties": false, "properties": {"name": {"title": "Name", "type": "string"}, "label": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Label"}, "help": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Help"}, "optional": {"default": false, "title": "Optional", "type": "boolean"}, "type": {"const": "text", "title": "Type", "type": "string"}, "value": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Value"}, "area": {"default": false, "title": "Area", "type": "boolean"}, "validators": {"default": [], "items": {"anyOf": [{"$ref": "#/$defs/LengthParameterValidatorModel"}, {"$ref": "#/$defs/RegexParameterValidatorModel"}, {"$ref": "#/$defs/EmptyFieldParameterValidatorModel"}]}, "title": "Validators", "type": "array"}}, "required": ["name", "type"], "title": "YamlTextParameter", "type": "object"}, "YamlToolTest": {"additionalProperties": false, "description": "In-tool test case as authored in YAML tool fixtures.\n\nMirrors ``TestJob`` (the workflow test schema) but uses ``inputs``\ninstead of ``job`` and adds tool-specific assertion fields\n(``assert_stdout``, ``assert_stderr``, ``command``, etc.). Output\nassertions reuse the same ``TestOutputAssertions`` union so the\ntyping is shared between workflow tests and tool tests.", "properties": {"doc": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Doc"}, "inputs": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "default": null, "title": "Inputs"}, "outputs": {"additionalProperties": {"anyOf": [{"$ref": "#/$defs/TestCollectionOutputAssertions"}, {"$ref": "#/$defs/TestDataOutputAssertions"}, {"type": "boolean"}, {"type": "integer"}, {"type": "number"}, {"type": "string"}]}, "default": {}, "title": "Outputs", "type": "object"}, "assert_stdout": {"anyOf": [{"items": {}, "type": "array"}, {"type": "null"}], "default": null, "title": "Assert Stdout"}, "assert_stderr": {"anyOf": [{"items": {}, "type": "array"}, {"type": "null"}], "default": null, "title": "Assert Stderr"}, "command": {"anyOf": [{"items": {}, "type": "array"}, {"type": "null"}], "default": null, "title": "Command"}, "expect_exit_code": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "title": "Expect Exit Code"}, "expect_failure": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "default": null, "title": "Expect Failure"}, "expect_test_failure": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "default": null, "title": "Expect Test Failure"}, "credentials": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"items": {}, "type": "array"}, {"type": "null"}], "default": null, "title": "Credentials"}}, "title": "YamlToolTest", "type": "object"}, "assertion_dict": {"additionalProperties": false, "properties": {"has_line": {"anyOf": [{"$ref": "#/$defs/base_has_line_model"}, {"type": "null"}], "default": null}, "has_line_matching": {"anyOf": [{"$ref": "#/$defs/base_has_line_matching_model"}, {"type": "null"}], "default": null}, "has_n_lines": {"anyOf": [{"$ref": "#/$defs/base_has_n_lines_model"}, {"type": "null"}], "default": null}, "has_text": {"anyOf": [{"$ref": "#/$defs/base_has_text_model"}, {"type": "null"}], "default": null}, "has_text_matching": {"anyOf": [{"$ref": "#/$defs/base_has_text_matching_model"}, {"type": "null"}], "default": null}, "not_has_text": {"anyOf": [{"$ref": "#/$defs/base_not_has_text_model"}, {"type": "null"}], "default": null}, "has_n_columns": {"anyOf": [{"$ref": "#/$defs/base_has_n_columns_model"}, {"type": "null"}], "default": null}, "attribute_is": {"anyOf": [{"$ref": "#/$defs/base_attribute_is_model"}, {"type": "null"}], "default": null}, "attribute_matches": {"anyOf": [{"$ref": "#/$defs/base_attribute_matches_model"}, {"type": "null"}], "default": null}, "element_text": {"anyOf": [{"$ref": "#/$defs/base_element_text_model"}, {"type": "null"}], "default": null}, "element_text_is": {"anyOf": [{"$ref": "#/$defs/base_element_text_is_model"}, {"type": "null"}], "default": null}, "element_text_matches": {"anyOf": [{"$ref": "#/$defs/base_element_text_matches_model"}, {"type": "null"}], "default": null}, "has_element_with_path": {"anyOf": [{"$ref": "#/$defs/base_has_element_with_path_model"}, {"type": "null"}], "default": null}, "has_n_elements_with_path": {"anyOf": [{"$ref": "#/$defs/base_has_n_elements_with_path_model"}, {"type": "null"}], "default": null}, "is_valid_xml": {"anyOf": [{"$ref": "#/$defs/base_is_valid_xml_model"}, {"type": "null"}], "default": null}, "xml_element": {"anyOf": [{"$ref": "#/$defs/base_xml_element_model"}, {"type": "null"}], "default": null}, "has_json_property_with_text": {"anyOf": [{"$ref": "#/$defs/base_has_json_property_with_text_model"}, {"type": "null"}], "default": null}, "has_json_property_with_value": {"anyOf": [{"$ref": "#/$defs/base_has_json_property_with_value_model"}, {"type": "null"}], "default": null}, "has_h5_attribute": {"anyOf": [{"$ref": "#/$defs/base_has_h5_attribute_model"}, {"type": "null"}], "default": null}, "has_h5_keys": {"anyOf": [{"$ref": "#/$defs/base_has_h5_keys_model"}, {"type": "null"}], "default": null}, "has_archive_member": {"anyOf": [{"$ref": "#/$defs/base_has_archive_member_model"}, {"type": "null"}], "default": null}, "has_size": {"anyOf": [{"$ref": "#/$defs/base_has_size_model"}, {"type": "null"}], "default": null}, "has_image_center_of_mass": {"anyOf": [{"$ref": "#/$defs/base_has_image_center_of_mass_model"}, {"type": "null"}], "default": null}, "has_image_channels": {"anyOf": [{"$ref": "#/$defs/base_has_image_channels_model"}, {"type": "null"}], "default": null}, "has_image_depth": {"anyOf": [{"$ref": "#/$defs/base_has_image_depth_model"}, {"type": "null"}], "default": null}, "has_image_frames": {"anyOf": [{"$ref": "#/$defs/base_has_image_frames_model"}, {"type": "null"}], "default": null}, "has_image_height": {"anyOf": [{"$ref": "#/$defs/base_has_image_height_model"}, {"type": "null"}], "default": null}, "has_image_mean_intensity": {"anyOf": [{"$ref": "#/$defs/base_has_image_mean_intensity_model"}, {"type": "null"}], "default": null}, "has_image_mean_object_size": {"anyOf": [{"$ref": "#/$defs/base_has_image_mean_object_size_model"}, {"type": "null"}], "default": null}, "has_image_n_labels": {"anyOf": [{"$ref": "#/$defs/base_has_image_n_labels_model"}, {"type": "null"}], "default": null}, "has_image_width": {"anyOf": [{"$ref": "#/$defs/base_has_image_width_model"}, {"type": "null"}], "default": null}}, "title": "assertion_dict", "type": "object"}, "attribute_is_model": {"additionalProperties": false, "description": "Asserts the XML ``attribute`` for the element (or tag) with the specified\nXPath-like ``path`` is the specified ``text``.\n\nFor example:\n\n```xml\n\n```\n\nThe assertion implicitly also asserts that an element matching ``path`` exists.\nWith ``negate`` the result of the assertion (on the equality) can be inverted (the\nimplicit assertion on the existence of the path is not affected).", "properties": {"path": {"description": "The Python xpath-like expression to find the target element.", "title": "Path", "type": "string"}, "attribute": {"description": "The XML attribute name to test against from the target XML element.", "title": "Attribute", "type": "string"}, "text": {"description": "The expected attribute value to test against on the target XML element", "title": "Text", "type": "string"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "attribute_is", "default": "attribute_is", "title": "That", "type": "string"}}, "required": ["path", "attribute", "text"], "title": "attribute_is_model", "type": "object"}, "attribute_is_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"attribute_is": {"$ref": "#/$defs/base_attribute_is_model"}}, "required": ["attribute_is"], "title": "attribute_is_model_nested", "type": "object"}, "attribute_matches_model": {"additionalProperties": false, "description": "Asserts the XML ``attribute`` for the element (or tag) with the specified\nXPath-like ``path`` matches the regular expression specified by ``expression``.\n\nFor example:\n\n```xml\n\n```\n\nThe assertion implicitly also asserts that an element matching ``path`` exists.\nWith ``negate`` the result of the assertion (on the matching) can be inverted (the\nimplicit assertion on the existence of the path is not affected).", "properties": {"path": {"description": "The Python xpath-like expression to find the target element.", "title": "Path", "type": "string"}, "attribute": {"description": "The XML attribute name to test against from the target XML element.", "title": "Attribute", "type": "string"}, "expression": {"description": "The regular expressions to apply against the named attribute on the target XML element.", "title": "Expression", "type": "string"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "attribute_matches", "default": "attribute_matches", "title": "That", "type": "string"}}, "required": ["path", "attribute", "expression"], "title": "attribute_matches_model", "type": "object"}, "attribute_matches_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"attribute_matches": {"$ref": "#/$defs/base_attribute_matches_model"}}, "required": ["attribute_matches"], "title": "attribute_matches_model_nested", "type": "object"}, "base_attribute_is_model": {"additionalProperties": false, "description": "base model for attribute_is describing attributes.", "properties": {"path": {"description": "The Python xpath-like expression to find the target element.", "title": "Path", "type": "string"}, "attribute": {"description": "The XML attribute name to test against from the target XML element.", "title": "Attribute", "type": "string"}, "text": {"description": "The expected attribute value to test against on the target XML element", "title": "Text", "type": "string"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "required": ["path", "attribute", "text"], "title": "base_attribute_is_model", "type": "object"}, "base_attribute_matches_model": {"additionalProperties": false, "description": "base model for attribute_matches describing attributes.", "properties": {"path": {"description": "The Python xpath-like expression to find the target element.", "title": "Path", "type": "string"}, "attribute": {"description": "The XML attribute name to test against from the target XML element.", "title": "Attribute", "type": "string"}, "expression": {"description": "The regular expressions to apply against the named attribute on the target XML element.", "title": "Expression", "type": "string"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "required": ["path", "attribute", "expression"], "title": "base_attribute_matches_model", "type": "object"}, "base_element_text_is_model": {"additionalProperties": false, "description": "base model for element_text_is describing attributes.", "properties": {"path": {"description": "The Python xpath-like expression to find the target element.", "title": "Path", "type": "string"}, "text": {"description": "The expected element text (body of the XML tag) to test against on the target XML element", "title": "Text", "type": "string"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "required": ["path", "text"], "title": "base_element_text_is_model", "type": "object"}, "base_element_text_matches_model": {"additionalProperties": false, "description": "base model for element_text_matches describing attributes.", "properties": {"path": {"description": "The Python xpath-like expression to find the target element.", "title": "Path", "type": "string"}, "expression": {"description": "The regular expressions to apply against the target element.", "title": "Expression", "type": "string"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "required": ["path", "expression"], "title": "base_element_text_matches_model", "type": "object"}, "base_element_text_model": {"additionalProperties": false, "description": "base model for element_text describing attributes.", "properties": {"path": {"description": "The Python xpath-like expression to find the target element.", "title": "Path", "type": "string"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "children": {"anyOf": [{"$ref": "#/$defs/RootModel_List_Union_Annotated_Union_has_line_model__has_line_matching_model__has_n_lines_model__has_text_model__has_text_matching_model__not_has_text_model__has_n_columns_model__attribute_is_model__attribute_matches_model__element_text_model__element_text_is_model__element_text_matches_model__has_element_with_path_model__has_n_elements_with_path_model__is_valid_xml_model__xml_element_model__has_json_property_with_text_model__has_json_property_with_value_model__has_h5_attribute_model__has_h5_keys_model__has_archive_member_model__has_size_model__has_image_center_of_mass_model__has_image_channels_model__has_image_depth_model__has_image_frames_model__has_image_height_model__has_image_mean_intensity_model__has_image_mean_object_size_model__has_image_n_labels_model__has_image_width_model___FieldInfo_annotation_NoneType__required_True__discriminator__that_____has_line_model_nested__has_line_matching_model_nested__has_n_lines_model_nested__has_text_model_nested__has_text_matching_model_nested__not_has_text_model_nested__has_n_columns_model_nested__attribute_is_model_nested__attribute_matches_model_nested__element_text_model_nested__element_text_is_model_nested__element_text_matches_model_nested__has_element_with_path_model_nested__has_n_elements_with_path_model_nested__is_valid_xml_model_nested__xml_element_model_nested__has_json_property_with_text_model_nested__has_json_property_with_value_model_nested__has_h5_attribute_model_nested__has_h5_keys_model_nested__has_archive_member_model_nested__has_size_model_nested__has_image_center_of_mass_model_nested__has_image_channels_model_nested__has_image_depth_model_nested__has_image_frames_model_nested__has_image_height_model_nested__has_image_mean_intensity_model_nested__has_image_mean_object_size_model_nested__has_image_n_labels_model_nested__has_image_width_model_nested___"}, {"type": "null"}], "default": null}, "asserts": {"anyOf": [{"$ref": "#/$defs/RootModel_List_Union_Annotated_Union_has_line_model__has_line_matching_model__has_n_lines_model__has_text_model__has_text_matching_model__not_has_text_model__has_n_columns_model__attribute_is_model__attribute_matches_model__element_text_model__element_text_is_model__element_text_matches_model__has_element_with_path_model__has_n_elements_with_path_model__is_valid_xml_model__xml_element_model__has_json_property_with_text_model__has_json_property_with_value_model__has_h5_attribute_model__has_h5_keys_model__has_archive_member_model__has_size_model__has_image_center_of_mass_model__has_image_channels_model__has_image_depth_model__has_image_frames_model__has_image_height_model__has_image_mean_intensity_model__has_image_mean_object_size_model__has_image_n_labels_model__has_image_width_model___FieldInfo_annotation_NoneType__required_True__discriminator__that_____has_line_model_nested__has_line_matching_model_nested__has_n_lines_model_nested__has_text_model_nested__has_text_matching_model_nested__not_has_text_model_nested__has_n_columns_model_nested__attribute_is_model_nested__attribute_matches_model_nested__element_text_model_nested__element_text_is_model_nested__element_text_matches_model_nested__has_element_with_path_model_nested__has_n_elements_with_path_model_nested__is_valid_xml_model_nested__xml_element_model_nested__has_json_property_with_text_model_nested__has_json_property_with_value_model_nested__has_h5_attribute_model_nested__has_h5_keys_model_nested__has_archive_member_model_nested__has_size_model_nested__has_image_center_of_mass_model_nested__has_image_channels_model_nested__has_image_depth_model_nested__has_image_frames_model_nested__has_image_height_model_nested__has_image_mean_intensity_model_nested__has_image_mean_object_size_model_nested__has_image_n_labels_model_nested__has_image_width_model_nested___"}, {"type": "null"}], "default": null}}, "required": ["path"], "title": "base_element_text_model", "type": "object"}, "base_has_archive_member_model": {"additionalProperties": false, "description": "base model for has_archive_member describing attributes.", "properties": {"path": {"description": "The regular expression specifying the archive member.", "title": "Path", "type": "string"}, "all": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "Check the sub-assertions for all paths matching the path. Default: false, i.e. only the first", "title": "All"}, "n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "children": {"anyOf": [{"$ref": "#/$defs/RootModel_List_Union_Annotated_Union_has_line_model__has_line_matching_model__has_n_lines_model__has_text_model__has_text_matching_model__not_has_text_model__has_n_columns_model__attribute_is_model__attribute_matches_model__element_text_model__element_text_is_model__element_text_matches_model__has_element_with_path_model__has_n_elements_with_path_model__is_valid_xml_model__xml_element_model__has_json_property_with_text_model__has_json_property_with_value_model__has_h5_attribute_model__has_h5_keys_model__has_archive_member_model__has_size_model__has_image_center_of_mass_model__has_image_channels_model__has_image_depth_model__has_image_frames_model__has_image_height_model__has_image_mean_intensity_model__has_image_mean_object_size_model__has_image_n_labels_model__has_image_width_model___FieldInfo_annotation_NoneType__required_True__discriminator__that_____has_line_model_nested__has_line_matching_model_nested__has_n_lines_model_nested__has_text_model_nested__has_text_matching_model_nested__not_has_text_model_nested__has_n_columns_model_nested__attribute_is_model_nested__attribute_matches_model_nested__element_text_model_nested__element_text_is_model_nested__element_text_matches_model_nested__has_element_with_path_model_nested__has_n_elements_with_path_model_nested__is_valid_xml_model_nested__xml_element_model_nested__has_json_property_with_text_model_nested__has_json_property_with_value_model_nested__has_h5_attribute_model_nested__has_h5_keys_model_nested__has_archive_member_model_nested__has_size_model_nested__has_image_center_of_mass_model_nested__has_image_channels_model_nested__has_image_depth_model_nested__has_image_frames_model_nested__has_image_height_model_nested__has_image_mean_intensity_model_nested__has_image_mean_object_size_model_nested__has_image_n_labels_model_nested__has_image_width_model_nested___"}, {"type": "null"}], "default": null}, "asserts": {"anyOf": [{"$ref": "#/$defs/RootModel_List_Union_Annotated_Union_has_line_model__has_line_matching_model__has_n_lines_model__has_text_model__has_text_matching_model__not_has_text_model__has_n_columns_model__attribute_is_model__attribute_matches_model__element_text_model__element_text_is_model__element_text_matches_model__has_element_with_path_model__has_n_elements_with_path_model__is_valid_xml_model__xml_element_model__has_json_property_with_text_model__has_json_property_with_value_model__has_h5_attribute_model__has_h5_keys_model__has_archive_member_model__has_size_model__has_image_center_of_mass_model__has_image_channels_model__has_image_depth_model__has_image_frames_model__has_image_height_model__has_image_mean_intensity_model__has_image_mean_object_size_model__has_image_n_labels_model__has_image_width_model___FieldInfo_annotation_NoneType__required_True__discriminator__that_____has_line_model_nested__has_line_matching_model_nested__has_n_lines_model_nested__has_text_model_nested__has_text_matching_model_nested__not_has_text_model_nested__has_n_columns_model_nested__attribute_is_model_nested__attribute_matches_model_nested__element_text_model_nested__element_text_is_model_nested__element_text_matches_model_nested__has_element_with_path_model_nested__has_n_elements_with_path_model_nested__is_valid_xml_model_nested__xml_element_model_nested__has_json_property_with_text_model_nested__has_json_property_with_value_model_nested__has_h5_attribute_model_nested__has_h5_keys_model_nested__has_archive_member_model_nested__has_size_model_nested__has_image_center_of_mass_model_nested__has_image_channels_model_nested__has_image_depth_model_nested__has_image_frames_model_nested__has_image_height_model_nested__has_image_mean_intensity_model_nested__has_image_mean_object_size_model_nested__has_image_n_labels_model_nested__has_image_width_model_nested___"}, {"type": "null"}], "default": null}}, "required": ["path"], "title": "base_has_archive_member_model", "type": "object"}, "base_has_element_with_path_model": {"additionalProperties": false, "description": "base model for has_element_with_path describing attributes.", "properties": {"path": {"description": "The Python xpath-like expression to find the target element.", "title": "Path", "type": "string"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "required": ["path"], "title": "base_has_element_with_path_model", "type": "object"}, "base_has_h5_attribute_model": {"additionalProperties": false, "description": "base model for has_h5_attribute describing attributes.", "properties": {"key": {"description": "HDF5 attribute to check value of.", "title": "Key", "type": "string"}, "value": {"description": "Expected value of HDF5 attribute to check.", "title": "Value", "type": "string"}}, "required": ["key", "value"], "title": "base_has_h5_attribute_model", "type": "object"}, "base_has_h5_keys_model": {"additionalProperties": false, "description": "base model for has_h5_keys describing attributes.", "properties": {"keys": {"description": "HDF5 attributes to check value of as a comma-separated string.", "title": "Keys", "type": "string"}}, "required": ["keys"], "title": "base_has_h5_keys_model", "type": "object"}, "base_has_image_center_of_mass_model": {"additionalProperties": false, "description": "base model for has_image_center_of_mass describing attributes.", "properties": {"center_of_mass": {"description": "The required center of mass of the image intensities (horizontal and vertical coordinate, separated by a comma).", "title": "Center Of Mass", "type": "string"}, "channel": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific channel of the image (where ``0`` corresponds to the first image channel).", "title": "Channel"}, "slice": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific slice of the image (where ``0`` corresponds to the first image slice).", "title": "Slice"}, "frame": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific frame of the image sequence (where ``0`` corresponds to the first image frame).", "title": "Frame"}, "eps": {"anyOf": [{"type": "integer"}, {"type": "number"}], "default": 0.01, "description": "The maximum allowed Euclidean distance to the required center of mass (defaults to ``0.01``).", "title": "Eps"}}, "required": ["center_of_mass"], "title": "base_has_image_center_of_mass_model", "type": "object"}, "base_has_image_channels_model": {"additionalProperties": false, "description": "base model for has_image_channels describing attributes.", "properties": {"channels": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Expected number of channels of the image.", "title": "Channels"}, "delta": {"default": 0, "description": "Maximum allowed difference of the number of channels (default is 0). The observed number of channels has to be in the range ``value +- delta``.", "title": "Delta", "type": "integer"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum allowed number of channels.", "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum allowed number of channels.", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "title": "base_has_image_channels_model", "type": "object"}, "base_has_image_depth_model": {"additionalProperties": false, "description": "base model for has_image_depth describing attributes.", "properties": {"depth": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Expected depth of the image (number of slices).", "title": "Depth"}, "delta": {"default": 0, "description": "Maximum allowed difference of the image depth (number of slices, default is 0). The observed depth has to be in the range ``value +- delta``.", "title": "Delta", "type": "integer"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum allowed depth of the image (number of slices).", "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum allowed depth of the image (number of slices).", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "title": "base_has_image_depth_model", "type": "object"}, "base_has_image_frames_model": {"additionalProperties": false, "description": "base model for has_image_frames describing attributes.", "properties": {"frames": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Expected number of frames in the image sequence (number of time steps).", "title": "Frames"}, "delta": {"default": 0, "description": "Maximum allowed difference of the number of frames in the image sequence (number of time steps, default is 0). The observed number of frames has to be in the range ``value +- delta``.", "title": "Delta", "type": "integer"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum allowed number of frames in the image sequence (number of time steps).", "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum allowed number of frames in the image sequence (number of time steps).", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "title": "base_has_image_frames_model", "type": "object"}, "base_has_image_height_model": {"additionalProperties": false, "description": "base model for has_image_height describing attributes.", "properties": {"height": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Expected height of the image (in pixels).", "title": "Height"}, "delta": {"default": 0, "description": "Maximum allowed difference of the image height (in pixels, default is 0). The observed height has to be in the range ``value +- delta``.", "title": "Delta", "type": "integer"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum allowed height of the image (in pixels).", "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum allowed height of the image (in pixels).", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "title": "base_has_image_height_model", "type": "object"}, "base_has_image_mean_intensity_model": {"additionalProperties": false, "description": "base model for has_image_mean_intensity describing attributes.", "properties": {"channel": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific channel of the image (where ``0`` corresponds to the first image channel).", "title": "Channel"}, "slice": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific slice of the image (where ``0`` corresponds to the first image slice).", "title": "Slice"}, "frame": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific frame of the image sequence (where ``0`` corresponds to the first image frame).", "title": "Frame"}, "mean_intensity": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "The required mean value of the image intensities.", "title": "Mean Intensity"}, "eps": {"anyOf": [{"type": "integer"}, {"type": "number"}], "default": 0.01, "description": "The absolute tolerance to be used for ``value`` (defaults to ``0.01``). The observed mean value of the image intensities has to be in the range ``value +- eps``.", "title": "Eps"}, "min": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "A lower bound of the required mean value of the image intensities.", "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "An upper bound of the required mean value of the image intensities.", "title": "Max"}}, "title": "base_has_image_mean_intensity_model", "type": "object"}, "base_has_image_mean_object_size_model": {"additionalProperties": false, "description": "base model for has_image_mean_object_size describing attributes.", "properties": {"channel": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific channel of the image (where ``0`` corresponds to the first image channel).", "title": "Channel"}, "slice": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific slice of the image (where ``0`` corresponds to the first image slice).", "title": "Slice"}, "frame": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific frame of the image sequence (where ``0`` corresponds to the first image frame).", "title": "Frame"}, "labels": {"anyOf": [{"items": {"type": "integer"}, "type": "array"}, {"type": "null"}], "default": null, "description": "List of labels, separated by a comma. Labels *not* on this list will be excluded from consideration. Cannot be used in combination with ``exclude_labels``.", "title": "Labels"}, "exclude_labels": {"anyOf": [{"items": {"type": "integer"}, "type": "array"}, {"type": "null"}], "default": null, "description": "List of labels to be excluded from consideration, separated by a comma. The primary usage of this attribute is to exclude the background of a label image. Cannot be used in combination with ``labels``.", "title": "Exclude Labels"}, "mean_object_size": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "The required mean size of the uniquely labeled objects.", "title": "Mean Object Size"}, "eps": {"anyOf": [{"type": "integer"}, {"type": "number"}], "default": 0.01, "description": "The absolute tolerance to be used for ``value`` (defaults to ``0.01``). The observed mean size of the uniquely labeled objects has to be in the range ``value +- eps``.", "title": "Eps"}, "min": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "A lower bound of the required mean size of the uniquely labeled objects.", "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "An upper bound of the required mean size of the uniquely labeled objects.", "title": "Max"}}, "title": "base_has_image_mean_object_size_model", "type": "object"}, "base_has_image_n_labels_model": {"additionalProperties": false, "description": "base model for has_image_n_labels describing attributes.", "properties": {"channel": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific channel of the image (where ``0`` corresponds to the first image channel).", "title": "Channel"}, "slice": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific slice of the image (where ``0`` corresponds to the first image slice).", "title": "Slice"}, "frame": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific frame of the image sequence (where ``0`` corresponds to the first image frame).", "title": "Frame"}, "labels": {"anyOf": [{"items": {"type": "integer"}, "type": "array"}, {"type": "null"}], "default": null, "description": "List of labels, separated by a comma. Labels *not* on this list will be excluded from consideration. Cannot be used in combination with ``exclude_labels``.", "title": "Labels"}, "exclude_labels": {"anyOf": [{"items": {"type": "integer"}, "type": "array"}, {"type": "null"}], "default": null, "description": "List of labels to be excluded from consideration, separated by a comma. The primary usage of this attribute is to exclude the background of a label image. Cannot be used in combination with ``labels``.", "title": "Exclude Labels"}, "n": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Expected number of labels.", "title": "N"}, "delta": {"default": 0, "description": "Maximum allowed difference of the number of labels (default is 0). The observed number of labels has to be in the range ``value +- delta``.", "title": "Delta", "type": "integer"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum allowed number of labels.", "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum allowed number of labels.", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "title": "base_has_image_n_labels_model", "type": "object"}, "base_has_image_width_model": {"additionalProperties": false, "description": "base model for has_image_width describing attributes.", "properties": {"width": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Expected width of the image (in pixels).", "title": "Width"}, "delta": {"default": 0, "description": "Maximum allowed difference of the image width (in pixels, default is 0). The observed width has to be in the range ``value +- delta``.", "title": "Delta", "type": "integer"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum allowed width of the image (in pixels).", "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum allowed width of the image (in pixels).", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "title": "base_has_image_width_model", "type": "object"}, "base_has_json_property_with_text_model": {"additionalProperties": false, "description": "base model for has_json_property_with_text describing attributes.", "properties": {"property": {"description": "The property name to search the JSON document for.", "title": "Property", "type": "string"}, "text": {"description": "The expected text value of the target JSON attribute.", "title": "Text", "type": "string"}}, "required": ["property", "text"], "title": "base_has_json_property_with_text_model", "type": "object"}, "base_has_json_property_with_value_model": {"additionalProperties": false, "description": "base model for has_json_property_with_value describing attributes.", "properties": {"property": {"description": "The property name to search the JSON document for.", "title": "Property", "type": "string"}, "value": {"description": "The expected JSON value of the target JSON attribute (as a JSON encoded string).", "title": "Value", "type": "string"}}, "required": ["property", "value"], "title": "base_has_json_property_with_value_model", "type": "object"}, "base_has_line_matching_model": {"additionalProperties": false, "description": "base model for has_line_matching describing attributes.", "properties": {"expression": {"description": "The regular expressions to attempt match in the output.", "title": "Expression", "type": "string"}, "n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "required": ["expression"], "title": "base_has_line_matching_model", "type": "object"}, "base_has_line_model": {"additionalProperties": false, "description": "base model for has_line describing attributes.", "properties": {"line": {"description": "The full line of text to search for in the output.", "title": "Line", "type": "string"}, "n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "required": ["line"], "title": "base_has_line_model", "type": "object"}, "base_has_n_columns_model": {"additionalProperties": false, "description": "base model for has_n_columns describing attributes.", "properties": {"n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "sep": {"default": "\t", "description": "Separator defining columns, default: tab", "title": "Sep", "type": "string"}, "comment": {"default": "", "description": "Comment character(s) used to skip comment lines (which should not be used for counting columns)", "title": "Comment", "type": "string"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "title": "base_has_n_columns_model", "type": "object"}, "base_has_n_elements_with_path_model": {"additionalProperties": false, "description": "base model for has_n_elements_with_path describing attributes.", "properties": {"path": {"description": "The Python xpath-like expression to find the target element.", "title": "Path", "type": "string"}, "n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "required": ["path"], "title": "base_has_n_elements_with_path_model", "type": "object"}, "base_has_n_lines_model": {"additionalProperties": false, "description": "base model for has_n_lines describing attributes.", "properties": {"n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "title": "base_has_n_lines_model", "type": "object"}, "base_has_size_model": {"additionalProperties": false, "description": "base model for has_size describing attributes.", "properties": {"value": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Deprecated alias for `size`", "title": "Value"}, "size": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired size of the output (in bytes), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Size"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "title": "base_has_size_model", "type": "object"}, "base_has_text_matching_model": {"additionalProperties": false, "description": "base model for has_text_matching describing attributes.", "properties": {"expression": {"description": "The regular expressions to attempt match in the output.", "title": "Expression", "type": "string"}, "n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "required": ["expression"], "title": "base_has_text_matching_model", "type": "object"}, "base_has_text_model": {"additionalProperties": false, "description": "base model for has_text describing attributes.", "properties": {"text": {"description": "The text to search for in the output.", "title": "Text", "type": "string"}, "n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}}, "required": ["text"], "title": "base_has_text_model", "type": "object"}, "base_is_valid_xml_model": {"additionalProperties": false, "description": "base model for is_valid_xml describing attributes.", "properties": {}, "title": "base_is_valid_xml_model", "type": "object"}, "base_not_has_text_model": {"additionalProperties": false, "description": "base model for not_has_text describing attributes.", "properties": {"text": {"description": "The text to search for in the output.", "title": "Text", "type": "string"}}, "required": ["text"], "title": "base_not_has_text_model", "type": "object"}, "base_xml_element_model": {"additionalProperties": false, "description": "base model for xml_element describing attributes.", "properties": {"path": {"description": "The Python xpath-like expression to find the target element.", "title": "Path", "type": "string"}, "attribute": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "The XML attribute name to test against from the target XML element.", "title": "Attribute"}, "all": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "Check the sub-assertions for all paths matching the path. Default: false, i.e. only the first ", "title": "All"}, "n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "children": {"anyOf": [{"$ref": "#/$defs/RootModel_List_Union_Annotated_Union_has_line_model__has_line_matching_model__has_n_lines_model__has_text_model__has_text_matching_model__not_has_text_model__has_n_columns_model__attribute_is_model__attribute_matches_model__element_text_model__element_text_is_model__element_text_matches_model__has_element_with_path_model__has_n_elements_with_path_model__is_valid_xml_model__xml_element_model__has_json_property_with_text_model__has_json_property_with_value_model__has_h5_attribute_model__has_h5_keys_model__has_archive_member_model__has_size_model__has_image_center_of_mass_model__has_image_channels_model__has_image_depth_model__has_image_frames_model__has_image_height_model__has_image_mean_intensity_model__has_image_mean_object_size_model__has_image_n_labels_model__has_image_width_model___FieldInfo_annotation_NoneType__required_True__discriminator__that_____has_line_model_nested__has_line_matching_model_nested__has_n_lines_model_nested__has_text_model_nested__has_text_matching_model_nested__not_has_text_model_nested__has_n_columns_model_nested__attribute_is_model_nested__attribute_matches_model_nested__element_text_model_nested__element_text_is_model_nested__element_text_matches_model_nested__has_element_with_path_model_nested__has_n_elements_with_path_model_nested__is_valid_xml_model_nested__xml_element_model_nested__has_json_property_with_text_model_nested__has_json_property_with_value_model_nested__has_h5_attribute_model_nested__has_h5_keys_model_nested__has_archive_member_model_nested__has_size_model_nested__has_image_center_of_mass_model_nested__has_image_channels_model_nested__has_image_depth_model_nested__has_image_frames_model_nested__has_image_height_model_nested__has_image_mean_intensity_model_nested__has_image_mean_object_size_model_nested__has_image_n_labels_model_nested__has_image_width_model_nested___"}, {"type": "null"}], "default": null}, "asserts": {"anyOf": [{"$ref": "#/$defs/RootModel_List_Union_Annotated_Union_has_line_model__has_line_matching_model__has_n_lines_model__has_text_model__has_text_matching_model__not_has_text_model__has_n_columns_model__attribute_is_model__attribute_matches_model__element_text_model__element_text_is_model__element_text_matches_model__has_element_with_path_model__has_n_elements_with_path_model__is_valid_xml_model__xml_element_model__has_json_property_with_text_model__has_json_property_with_value_model__has_h5_attribute_model__has_h5_keys_model__has_archive_member_model__has_size_model__has_image_center_of_mass_model__has_image_channels_model__has_image_depth_model__has_image_frames_model__has_image_height_model__has_image_mean_intensity_model__has_image_mean_object_size_model__has_image_n_labels_model__has_image_width_model___FieldInfo_annotation_NoneType__required_True__discriminator__that_____has_line_model_nested__has_line_matching_model_nested__has_n_lines_model_nested__has_text_model_nested__has_text_matching_model_nested__not_has_text_model_nested__has_n_columns_model_nested__attribute_is_model_nested__attribute_matches_model_nested__element_text_model_nested__element_text_is_model_nested__element_text_matches_model_nested__has_element_with_path_model_nested__has_n_elements_with_path_model_nested__is_valid_xml_model_nested__xml_element_model_nested__has_json_property_with_text_model_nested__has_json_property_with_value_model_nested__has_h5_attribute_model_nested__has_h5_keys_model_nested__has_archive_member_model_nested__has_size_model_nested__has_image_center_of_mass_model_nested__has_image_channels_model_nested__has_image_depth_model_nested__has_image_frames_model_nested__has_image_height_model_nested__has_image_mean_intensity_model_nested__has_image_mean_object_size_model_nested__has_image_n_labels_model_nested__has_image_width_model_nested___"}, {"type": "null"}], "default": null}}, "required": ["path"], "title": "base_xml_element_model", "type": "object"}, "element_text_is_model": {"additionalProperties": false, "description": "Asserts the text of the XML element with the specified XPath-like ``path`` is\nthe specified ``text``.\n\nFor example:\n\n```xml\n\n```\n\nThe assertion implicitly also asserts that an element matching ``path`` exists.\nWith ``negate`` the result of the assertion (on the equality) can be inverted (the\nimplicit assertion on the existence of the path is not affected).", "properties": {"path": {"description": "The Python xpath-like expression to find the target element.", "title": "Path", "type": "string"}, "text": {"description": "The expected element text (body of the XML tag) to test against on the target XML element", "title": "Text", "type": "string"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "element_text_is", "default": "element_text_is", "title": "That", "type": "string"}}, "required": ["path", "text"], "title": "element_text_is_model", "type": "object"}, "element_text_is_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"element_text_is": {"$ref": "#/$defs/base_element_text_is_model"}}, "required": ["element_text_is"], "title": "element_text_is_model_nested", "type": "object"}, "element_text_matches_model": {"additionalProperties": false, "description": "Asserts the text of the XML element with the specified XPath-like ``path``\nmatches the regular expression defined by ``expression``.\n\nFor example:\n\n```xml\n\n```\n\nThe assertion implicitly also asserts that an element matching ``path`` exists.\nWith ``negate`` the result of the assertion (on the matching) can be inverted (the\nimplicit assertion on the existence of the path is not affected).", "properties": {"path": {"description": "The Python xpath-like expression to find the target element.", "title": "Path", "type": "string"}, "expression": {"description": "The regular expressions to apply against the target element.", "title": "Expression", "type": "string"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "element_text_matches", "default": "element_text_matches", "title": "That", "type": "string"}}, "required": ["path", "expression"], "title": "element_text_matches_model", "type": "object"}, "element_text_matches_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"element_text_matches": {"$ref": "#/$defs/base_element_text_matches_model"}}, "required": ["element_text_matches"], "title": "element_text_matches_model_nested", "type": "object"}, "element_text_model": {"additionalProperties": false, "description": "This tag allows the developer to recurisively specify additional assertions as\nchild elements about just the text contained in the element specified by the\nXPath-like ``path``, e.g.\n\n```xml\n\n \n\n```\n\nThe assertion implicitly also asserts that an element matching ``path`` exists.\nWith ``negate`` the result of the implicit assertions can be inverted.\nThe sub-assertions, which have their own ``negate`` attribute, are not affected\nby ``negate``.", "properties": {"path": {"description": "The Python xpath-like expression to find the target element.", "title": "Path", "type": "string"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "children": {"anyOf": [{"$ref": "#/$defs/RootModel_List_Union_Annotated_Union_has_line_model__has_line_matching_model__has_n_lines_model__has_text_model__has_text_matching_model__not_has_text_model__has_n_columns_model__attribute_is_model__attribute_matches_model__element_text_model__element_text_is_model__element_text_matches_model__has_element_with_path_model__has_n_elements_with_path_model__is_valid_xml_model__xml_element_model__has_json_property_with_text_model__has_json_property_with_value_model__has_h5_attribute_model__has_h5_keys_model__has_archive_member_model__has_size_model__has_image_center_of_mass_model__has_image_channels_model__has_image_depth_model__has_image_frames_model__has_image_height_model__has_image_mean_intensity_model__has_image_mean_object_size_model__has_image_n_labels_model__has_image_width_model___FieldInfo_annotation_NoneType__required_True__discriminator__that_____has_line_model_nested__has_line_matching_model_nested__has_n_lines_model_nested__has_text_model_nested__has_text_matching_model_nested__not_has_text_model_nested__has_n_columns_model_nested__attribute_is_model_nested__attribute_matches_model_nested__element_text_model_nested__element_text_is_model_nested__element_text_matches_model_nested__has_element_with_path_model_nested__has_n_elements_with_path_model_nested__is_valid_xml_model_nested__xml_element_model_nested__has_json_property_with_text_model_nested__has_json_property_with_value_model_nested__has_h5_attribute_model_nested__has_h5_keys_model_nested__has_archive_member_model_nested__has_size_model_nested__has_image_center_of_mass_model_nested__has_image_channels_model_nested__has_image_depth_model_nested__has_image_frames_model_nested__has_image_height_model_nested__has_image_mean_intensity_model_nested__has_image_mean_object_size_model_nested__has_image_n_labels_model_nested__has_image_width_model_nested___"}, {"type": "null"}], "default": null}, "asserts": {"anyOf": [{"$ref": "#/$defs/RootModel_List_Union_Annotated_Union_has_line_model__has_line_matching_model__has_n_lines_model__has_text_model__has_text_matching_model__not_has_text_model__has_n_columns_model__attribute_is_model__attribute_matches_model__element_text_model__element_text_is_model__element_text_matches_model__has_element_with_path_model__has_n_elements_with_path_model__is_valid_xml_model__xml_element_model__has_json_property_with_text_model__has_json_property_with_value_model__has_h5_attribute_model__has_h5_keys_model__has_archive_member_model__has_size_model__has_image_center_of_mass_model__has_image_channels_model__has_image_depth_model__has_image_frames_model__has_image_height_model__has_image_mean_intensity_model__has_image_mean_object_size_model__has_image_n_labels_model__has_image_width_model___FieldInfo_annotation_NoneType__required_True__discriminator__that_____has_line_model_nested__has_line_matching_model_nested__has_n_lines_model_nested__has_text_model_nested__has_text_matching_model_nested__not_has_text_model_nested__has_n_columns_model_nested__attribute_is_model_nested__attribute_matches_model_nested__element_text_model_nested__element_text_is_model_nested__element_text_matches_model_nested__has_element_with_path_model_nested__has_n_elements_with_path_model_nested__is_valid_xml_model_nested__xml_element_model_nested__has_json_property_with_text_model_nested__has_json_property_with_value_model_nested__has_h5_attribute_model_nested__has_h5_keys_model_nested__has_archive_member_model_nested__has_size_model_nested__has_image_center_of_mass_model_nested__has_image_channels_model_nested__has_image_depth_model_nested__has_image_frames_model_nested__has_image_height_model_nested__has_image_mean_intensity_model_nested__has_image_mean_object_size_model_nested__has_image_n_labels_model_nested__has_image_width_model_nested___"}, {"type": "null"}], "default": null}, "that": {"const": "element_text", "default": "element_text", "title": "That", "type": "string"}}, "required": ["path"], "title": "element_text_model", "type": "object"}, "element_text_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"element_text": {"$ref": "#/$defs/base_element_text_model"}}, "required": ["element_text"], "title": "element_text_model_nested", "type": "object"}, "has_archive_member_model": {"additionalProperties": false, "description": "This tag allows to check if ``path`` is contained in a compressed file.\n\nThe path is a regular expression that is matched against the full paths of the objects in\nthe compressed file (remember that \"matching\" means it is checked if a prefix of\nthe full path of an archive member is described by the regular expression).\nValid archive formats include ``.zip``, ``.tar``, and ``.tar.gz``. Note that\ndepending on the archive creation method:\n\n- full paths of the members may be prefixed with ``./``\n- directories may be treated as empty files\n\n```xml\n\n```\n\nWith ``n`` and ``delta`` (or ``min`` and ``max``) assertions on the number of\narchive members matching ``path`` can be expressed. The following could be used,\ne.g., to assert an archive containing n±1 elements out of which at least\n4 need to have a ``txt`` extension.\n\n```xml\n\n\n```\n\nIn addition the tag can contain additional assertions as child elements about\nthe first member in the archive matching the regular expression ``path``. For\ninstance\n\n```xml\n\n \n\n```\n\nIf the ``all`` attribute is set to ``true`` then all archive members are subject\nto the assertions. Note that, archive members matching the ``path`` are sorted\nalphabetically.\n\nThe ``negate`` attribute of the ``has_archive_member`` assertion only affects\nthe asserts on the presence and number of matching archive members, but not any\nsub-assertions (which can offer the ``negate`` attribute on their own). The\ncheck if the file is an archive at all, which is also done by the function, is\nnot affected.", "properties": {"path": {"description": "The regular expression specifying the archive member.", "title": "Path", "type": "string"}, "all": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "Check the sub-assertions for all paths matching the path. Default: false, i.e. only the first", "title": "All"}, "n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "children": {"anyOf": [{"$ref": "#/$defs/RootModel_List_Union_Annotated_Union_has_line_model__has_line_matching_model__has_n_lines_model__has_text_model__has_text_matching_model__not_has_text_model__has_n_columns_model__attribute_is_model__attribute_matches_model__element_text_model__element_text_is_model__element_text_matches_model__has_element_with_path_model__has_n_elements_with_path_model__is_valid_xml_model__xml_element_model__has_json_property_with_text_model__has_json_property_with_value_model__has_h5_attribute_model__has_h5_keys_model__has_archive_member_model__has_size_model__has_image_center_of_mass_model__has_image_channels_model__has_image_depth_model__has_image_frames_model__has_image_height_model__has_image_mean_intensity_model__has_image_mean_object_size_model__has_image_n_labels_model__has_image_width_model___FieldInfo_annotation_NoneType__required_True__discriminator__that_____has_line_model_nested__has_line_matching_model_nested__has_n_lines_model_nested__has_text_model_nested__has_text_matching_model_nested__not_has_text_model_nested__has_n_columns_model_nested__attribute_is_model_nested__attribute_matches_model_nested__element_text_model_nested__element_text_is_model_nested__element_text_matches_model_nested__has_element_with_path_model_nested__has_n_elements_with_path_model_nested__is_valid_xml_model_nested__xml_element_model_nested__has_json_property_with_text_model_nested__has_json_property_with_value_model_nested__has_h5_attribute_model_nested__has_h5_keys_model_nested__has_archive_member_model_nested__has_size_model_nested__has_image_center_of_mass_model_nested__has_image_channels_model_nested__has_image_depth_model_nested__has_image_frames_model_nested__has_image_height_model_nested__has_image_mean_intensity_model_nested__has_image_mean_object_size_model_nested__has_image_n_labels_model_nested__has_image_width_model_nested___"}, {"type": "null"}], "default": null}, "asserts": {"anyOf": [{"$ref": "#/$defs/RootModel_List_Union_Annotated_Union_has_line_model__has_line_matching_model__has_n_lines_model__has_text_model__has_text_matching_model__not_has_text_model__has_n_columns_model__attribute_is_model__attribute_matches_model__element_text_model__element_text_is_model__element_text_matches_model__has_element_with_path_model__has_n_elements_with_path_model__is_valid_xml_model__xml_element_model__has_json_property_with_text_model__has_json_property_with_value_model__has_h5_attribute_model__has_h5_keys_model__has_archive_member_model__has_size_model__has_image_center_of_mass_model__has_image_channels_model__has_image_depth_model__has_image_frames_model__has_image_height_model__has_image_mean_intensity_model__has_image_mean_object_size_model__has_image_n_labels_model__has_image_width_model___FieldInfo_annotation_NoneType__required_True__discriminator__that_____has_line_model_nested__has_line_matching_model_nested__has_n_lines_model_nested__has_text_model_nested__has_text_matching_model_nested__not_has_text_model_nested__has_n_columns_model_nested__attribute_is_model_nested__attribute_matches_model_nested__element_text_model_nested__element_text_is_model_nested__element_text_matches_model_nested__has_element_with_path_model_nested__has_n_elements_with_path_model_nested__is_valid_xml_model_nested__xml_element_model_nested__has_json_property_with_text_model_nested__has_json_property_with_value_model_nested__has_h5_attribute_model_nested__has_h5_keys_model_nested__has_archive_member_model_nested__has_size_model_nested__has_image_center_of_mass_model_nested__has_image_channels_model_nested__has_image_depth_model_nested__has_image_frames_model_nested__has_image_height_model_nested__has_image_mean_intensity_model_nested__has_image_mean_object_size_model_nested__has_image_n_labels_model_nested__has_image_width_model_nested___"}, {"type": "null"}], "default": null}, "that": {"const": "has_archive_member", "default": "has_archive_member", "title": "That", "type": "string"}}, "required": ["path"], "title": "has_archive_member_model", "type": "object"}, "has_archive_member_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_archive_member": {"$ref": "#/$defs/base_has_archive_member_model"}}, "required": ["has_archive_member"], "title": "has_archive_member_model_nested", "type": "object"}, "has_element_with_path_model": {"additionalProperties": false, "description": "Asserts the XML output contains at least one element (or tag) with the specified\nXPath-like ``path``, e.g.\n\n```xml\n\n```\n\nWith ``negate`` the result of the assertion can be inverted.", "properties": {"path": {"description": "The Python xpath-like expression to find the target element.", "title": "Path", "type": "string"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "has_element_with_path", "default": "has_element_with_path", "title": "That", "type": "string"}}, "required": ["path"], "title": "has_element_with_path_model", "type": "object"}, "has_element_with_path_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_element_with_path": {"$ref": "#/$defs/base_has_element_with_path_model"}}, "required": ["has_element_with_path"], "title": "has_element_with_path_model_nested", "type": "object"}, "has_h5_attribute_model": {"additionalProperties": false, "description": "Asserts HDF5 output contains the specified ``value`` for an attribute (``key``), e.g.\n\n```xml\n\n```", "properties": {"key": {"description": "HDF5 attribute to check value of.", "title": "Key", "type": "string"}, "value": {"description": "Expected value of HDF5 attribute to check.", "title": "Value", "type": "string"}, "that": {"const": "has_h5_attribute", "default": "has_h5_attribute", "title": "That", "type": "string"}}, "required": ["key", "value"], "title": "has_h5_attribute_model", "type": "object"}, "has_h5_attribute_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_h5_attribute": {"$ref": "#/$defs/base_has_h5_attribute_model"}}, "required": ["has_h5_attribute"], "title": "has_h5_attribute_model_nested", "type": "object"}, "has_h5_keys_model": {"additionalProperties": false, "description": "Asserts the specified HDF5 output has the given keys.", "properties": {"keys": {"description": "HDF5 attributes to check value of as a comma-separated string.", "title": "Keys", "type": "string"}, "that": {"const": "has_h5_keys", "default": "has_h5_keys", "title": "That", "type": "string"}}, "required": ["keys"], "title": "has_h5_keys_model", "type": "object"}, "has_h5_keys_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_h5_keys": {"$ref": "#/$defs/base_has_h5_keys_model"}}, "required": ["has_h5_keys"], "title": "has_h5_keys_model_nested", "type": "object"}, "has_image_center_of_mass_model": {"additionalProperties": false, "description": "Asserts the specified output is an image and has the specified center of mass.\n\nAsserts the output is an image and has a specific center of mass,\nor has an Euclidean distance of ``eps`` or less to that point (e.g.,\n````).", "properties": {"center_of_mass": {"description": "The required center of mass of the image intensities (horizontal and vertical coordinate, separated by a comma).", "title": "Center Of Mass", "type": "string"}, "channel": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific channel of the image (where ``0`` corresponds to the first image channel).", "title": "Channel"}, "slice": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific slice of the image (where ``0`` corresponds to the first image slice).", "title": "Slice"}, "frame": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific frame of the image sequence (where ``0`` corresponds to the first image frame).", "title": "Frame"}, "eps": {"anyOf": [{"type": "integer"}, {"type": "number"}], "default": 0.01, "description": "The maximum allowed Euclidean distance to the required center of mass (defaults to ``0.01``).", "title": "Eps"}, "that": {"const": "has_image_center_of_mass", "default": "has_image_center_of_mass", "title": "That", "type": "string"}}, "required": ["center_of_mass"], "title": "has_image_center_of_mass_model", "type": "object"}, "has_image_center_of_mass_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_image_center_of_mass": {"$ref": "#/$defs/base_has_image_center_of_mass_model"}}, "required": ["has_image_center_of_mass"], "title": "has_image_center_of_mass_model_nested", "type": "object"}, "has_image_channels_model": {"additionalProperties": false, "description": "Asserts the output is an image and has a specific number of channels.\n\nThe number of channels is plus/minus ``delta`` (e.g., ````).\n\nAlternatively the range of the expected number of channels can be specified by ``min`` and/or ``max``.", "properties": {"channels": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Expected number of channels of the image.", "title": "Channels"}, "delta": {"default": 0, "description": "Maximum allowed difference of the number of channels (default is 0). The observed number of channels has to be in the range ``value +- delta``.", "title": "Delta", "type": "integer"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum allowed number of channels.", "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum allowed number of channels.", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "has_image_channels", "default": "has_image_channels", "title": "That", "type": "string"}}, "title": "has_image_channels_model", "type": "object"}, "has_image_channels_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_image_channels": {"$ref": "#/$defs/base_has_image_channels_model"}}, "required": ["has_image_channels"], "title": "has_image_channels_model_nested", "type": "object"}, "has_image_depth_model": {"additionalProperties": false, "description": "Asserts the output is an image and has a specific depth (number of slices).\n\nThe depth is plus/minus ``delta`` (e.g., ````).\nAlternatively the range of the expected depth can be specified by ``min`` and/or ``max``.", "properties": {"depth": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Expected depth of the image (number of slices).", "title": "Depth"}, "delta": {"default": 0, "description": "Maximum allowed difference of the image depth (number of slices, default is 0). The observed depth has to be in the range ``value +- delta``.", "title": "Delta", "type": "integer"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum allowed depth of the image (number of slices).", "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum allowed depth of the image (number of slices).", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "has_image_depth", "default": "has_image_depth", "title": "That", "type": "string"}}, "title": "has_image_depth_model", "type": "object"}, "has_image_depth_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_image_depth": {"$ref": "#/$defs/base_has_image_depth_model"}}, "required": ["has_image_depth"], "title": "has_image_depth_model_nested", "type": "object"}, "has_image_frames_model": {"additionalProperties": false, "description": "Asserts the output is an image and has a specific number of frames (number of time steps).\n\nThe number of frames is plus/minus ``delta`` (e.g., ````).\nAlternatively the range of the expected number of frames can be specified by ``min`` and/or ``max``.", "properties": {"frames": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Expected number of frames in the image sequence (number of time steps).", "title": "Frames"}, "delta": {"default": 0, "description": "Maximum allowed difference of the number of frames in the image sequence (number of time steps, default is 0). The observed number of frames has to be in the range ``value +- delta``.", "title": "Delta", "type": "integer"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum allowed number of frames in the image sequence (number of time steps).", "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum allowed number of frames in the image sequence (number of time steps).", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "has_image_frames", "default": "has_image_frames", "title": "That", "type": "string"}}, "title": "has_image_frames_model", "type": "object"}, "has_image_frames_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_image_frames": {"$ref": "#/$defs/base_has_image_frames_model"}}, "required": ["has_image_frames"], "title": "has_image_frames_model_nested", "type": "object"}, "has_image_height_model": {"additionalProperties": false, "description": "Asserts the output is an image and has a specific height (in pixels).\n\nThe height is plus/minus ``delta`` (e.g., ````).\nAlternatively the range of the expected height can be specified by ``min`` and/or ``max``.", "properties": {"height": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Expected height of the image (in pixels).", "title": "Height"}, "delta": {"default": 0, "description": "Maximum allowed difference of the image height (in pixels, default is 0). The observed height has to be in the range ``value +- delta``.", "title": "Delta", "type": "integer"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum allowed height of the image (in pixels).", "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum allowed height of the image (in pixels).", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "has_image_height", "default": "has_image_height", "title": "That", "type": "string"}}, "title": "has_image_height_model", "type": "object"}, "has_image_height_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_image_height": {"$ref": "#/$defs/base_has_image_height_model"}}, "required": ["has_image_height"], "title": "has_image_height_model_nested", "type": "object"}, "has_image_mean_intensity_model": {"additionalProperties": false, "description": "Asserts the output is an image and has a specific mean intensity value.\n\nThe mean intensity value is plus/minus ``eps`` (e.g., ````).\nAlternatively the range of the expected mean intensity value can be specified by ``min`` and/or ``max``.", "properties": {"channel": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific channel of the image (where ``0`` corresponds to the first image channel).", "title": "Channel"}, "slice": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific slice of the image (where ``0`` corresponds to the first image slice).", "title": "Slice"}, "frame": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific frame of the image sequence (where ``0`` corresponds to the first image frame).", "title": "Frame"}, "mean_intensity": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "The required mean value of the image intensities.", "title": "Mean Intensity"}, "eps": {"anyOf": [{"type": "integer"}, {"type": "number"}], "default": 0.01, "description": "The absolute tolerance to be used for ``value`` (defaults to ``0.01``). The observed mean value of the image intensities has to be in the range ``value +- eps``.", "title": "Eps"}, "min": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "A lower bound of the required mean value of the image intensities.", "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "An upper bound of the required mean value of the image intensities.", "title": "Max"}, "that": {"const": "has_image_mean_intensity", "default": "has_image_mean_intensity", "title": "That", "type": "string"}}, "title": "has_image_mean_intensity_model", "type": "object"}, "has_image_mean_intensity_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_image_mean_intensity": {"$ref": "#/$defs/base_has_image_mean_intensity_model"}}, "required": ["has_image_mean_intensity"], "title": "has_image_mean_intensity_model_nested", "type": "object"}, "has_image_mean_object_size_model": {"additionalProperties": false, "description": "Asserts the output is an image with labeled objects which have the specified mean size (number of pixels),\n\nThe mean size is plus/minus ``eps`` (e.g., ````).\n\nThe labels must be unique.", "properties": {"channel": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific channel of the image (where ``0`` corresponds to the first image channel).", "title": "Channel"}, "slice": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific slice of the image (where ``0`` corresponds to the first image slice).", "title": "Slice"}, "frame": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific frame of the image sequence (where ``0`` corresponds to the first image frame).", "title": "Frame"}, "labels": {"anyOf": [{"items": {"type": "integer"}, "type": "array"}, {"type": "null"}], "default": null, "description": "List of labels, separated by a comma. Labels *not* on this list will be excluded from consideration. Cannot be used in combination with ``exclude_labels``.", "title": "Labels"}, "exclude_labels": {"anyOf": [{"items": {"type": "integer"}, "type": "array"}, {"type": "null"}], "default": null, "description": "List of labels to be excluded from consideration, separated by a comma. The primary usage of this attribute is to exclude the background of a label image. Cannot be used in combination with ``labels``.", "title": "Exclude Labels"}, "mean_object_size": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "The required mean size of the uniquely labeled objects.", "title": "Mean Object Size"}, "eps": {"anyOf": [{"type": "integer"}, {"type": "number"}], "default": 0.01, "description": "The absolute tolerance to be used for ``value`` (defaults to ``0.01``). The observed mean size of the uniquely labeled objects has to be in the range ``value +- eps``.", "title": "Eps"}, "min": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "A lower bound of the required mean size of the uniquely labeled objects.", "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "number"}, {"type": "null"}], "default": null, "description": "An upper bound of the required mean size of the uniquely labeled objects.", "title": "Max"}, "that": {"const": "has_image_mean_object_size", "default": "has_image_mean_object_size", "title": "That", "type": "string"}}, "title": "has_image_mean_object_size_model", "type": "object"}, "has_image_mean_object_size_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_image_mean_object_size": {"$ref": "#/$defs/base_has_image_mean_object_size_model"}}, "required": ["has_image_mean_object_size"], "title": "has_image_mean_object_size_model_nested", "type": "object"}, "has_image_n_labels_model": {"additionalProperties": false, "description": "Asserts the output is an image and has the specified labels.\n\nLabels can be a number of labels or unique values (e.g.,\n````).\n\nThe primary usage of this assertion is to verify the number of objects in images with uniquely labeled objects.", "properties": {"channel": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific channel of the image (where ``0`` corresponds to the first image channel).", "title": "Channel"}, "slice": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific slice of the image (where ``0`` corresponds to the first image slice).", "title": "Slice"}, "frame": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Restricts the assertion to a specific frame of the image sequence (where ``0`` corresponds to the first image frame).", "title": "Frame"}, "labels": {"anyOf": [{"items": {"type": "integer"}, "type": "array"}, {"type": "null"}], "default": null, "description": "List of labels, separated by a comma. Labels *not* on this list will be excluded from consideration. Cannot be used in combination with ``exclude_labels``.", "title": "Labels"}, "exclude_labels": {"anyOf": [{"items": {"type": "integer"}, "type": "array"}, {"type": "null"}], "default": null, "description": "List of labels to be excluded from consideration, separated by a comma. The primary usage of this attribute is to exclude the background of a label image. Cannot be used in combination with ``labels``.", "title": "Exclude Labels"}, "n": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Expected number of labels.", "title": "N"}, "delta": {"default": 0, "description": "Maximum allowed difference of the number of labels (default is 0). The observed number of labels has to be in the range ``value +- delta``.", "title": "Delta", "type": "integer"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum allowed number of labels.", "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum allowed number of labels.", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "has_image_n_labels", "default": "has_image_n_labels", "title": "That", "type": "string"}}, "title": "has_image_n_labels_model", "type": "object"}, "has_image_n_labels_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_image_n_labels": {"$ref": "#/$defs/base_has_image_n_labels_model"}}, "required": ["has_image_n_labels"], "title": "has_image_n_labels_model_nested", "type": "object"}, "has_image_width_model": {"additionalProperties": false, "description": "Asserts the output is an image and has a specific width (in pixels).\n\nThe width is plus/minus ``delta`` (e.g., ````).\nAlternatively the range of the expected width can be specified by ``min`` and/or ``max``.", "properties": {"width": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Expected width of the image (in pixels).", "title": "Width"}, "delta": {"default": 0, "description": "Maximum allowed difference of the image width (in pixels, default is 0). The observed width has to be in the range ``value +- delta``.", "title": "Delta", "type": "integer"}, "min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum allowed width of the image (in pixels).", "title": "Min"}, "max": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum allowed width of the image (in pixels).", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "has_image_width", "default": "has_image_width", "title": "That", "type": "string"}}, "title": "has_image_width_model", "type": "object"}, "has_image_width_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_image_width": {"$ref": "#/$defs/base_has_image_width_model"}}, "required": ["has_image_width"], "title": "has_image_width_model_nested", "type": "object"}, "has_json_property_with_text_model": {"additionalProperties": false, "description": "Asserts the JSON document contains a property or key with the specified text (i.e. string) value.\n\n```xml\n\n```", "properties": {"property": {"description": "The property name to search the JSON document for.", "title": "Property", "type": "string"}, "text": {"description": "The expected text value of the target JSON attribute.", "title": "Text", "type": "string"}, "that": {"const": "has_json_property_with_text", "default": "has_json_property_with_text", "title": "That", "type": "string"}}, "required": ["property", "text"], "title": "has_json_property_with_text_model", "type": "object"}, "has_json_property_with_text_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_json_property_with_text": {"$ref": "#/$defs/base_has_json_property_with_text_model"}}, "required": ["has_json_property_with_text"], "title": "has_json_property_with_text_model_nested", "type": "object"}, "has_json_property_with_value_model": {"additionalProperties": false, "description": "Asserts the JSON document contains a property or key with the specified JSON value.\n\n```xml\n\n```", "properties": {"property": {"description": "The property name to search the JSON document for.", "title": "Property", "type": "string"}, "value": {"description": "The expected JSON value of the target JSON attribute (as a JSON encoded string).", "title": "Value", "type": "string"}, "that": {"const": "has_json_property_with_value", "default": "has_json_property_with_value", "title": "That", "type": "string"}}, "required": ["property", "value"], "title": "has_json_property_with_value_model", "type": "object"}, "has_json_property_with_value_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_json_property_with_value": {"$ref": "#/$defs/base_has_json_property_with_value_model"}}, "required": ["has_json_property_with_value"], "title": "has_json_property_with_value_model_nested", "type": "object"}, "has_line_matching_model": {"additionalProperties": false, "description": "Asserts the specified output contains a line matching the\nregular expression specified by the argument expression. If n is given\nthe assertion checks for exactly n occurences.", "properties": {"expression": {"description": "The regular expressions to attempt match in the output.", "title": "Expression", "type": "string"}, "n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "has_line_matching", "default": "has_line_matching", "title": "That", "type": "string"}}, "required": ["expression"], "title": "has_line_matching_model", "type": "object"}, "has_line_matching_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_line_matching": {"$ref": "#/$defs/base_has_line_matching_model"}}, "required": ["has_line_matching"], "title": "has_line_matching_model_nested", "type": "object"}, "has_line_model": {"additionalProperties": false, "description": "Asserts the specified output contains the line specified by the\nargument line. The exact number of occurrences can be optionally\nspecified by the argument n", "properties": {"line": {"description": "The full line of text to search for in the output.", "title": "Line", "type": "string"}, "n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "has_line", "default": "has_line", "title": "That", "type": "string"}}, "required": ["line"], "title": "has_line_model", "type": "object"}, "has_line_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_line": {"$ref": "#/$defs/base_has_line_model"}}, "required": ["has_line"], "title": "has_line_model_nested", "type": "object"}, "has_n_columns_model": {"additionalProperties": false, "description": "Asserts tabular output contains the specified\nnumber (``n``) of columns.\n\nFor instance, ````. The assertion tests only the first line.\nNumber of columns can optionally also be specified with ``delta``. Alternatively the\nrange of expected occurences can be specified by ``min`` and/or ``max``.\n\nOptionally a column separator (``sep``, default is `` ``) `and comment character(s)\ncan be specified (``comment``, default is empty string). The first non-comment\nline is used for determining the number of columns.", "properties": {"n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "sep": {"default": "\t", "description": "Separator defining columns, default: tab", "title": "Sep", "type": "string"}, "comment": {"default": "", "description": "Comment character(s) used to skip comment lines (which should not be used for counting columns)", "title": "Comment", "type": "string"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "has_n_columns", "default": "has_n_columns", "title": "That", "type": "string"}}, "title": "has_n_columns_model", "type": "object"}, "has_n_columns_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_n_columns": {"$ref": "#/$defs/base_has_n_columns_model"}}, "required": ["has_n_columns"], "title": "has_n_columns_model_nested", "type": "object"}, "has_n_elements_with_path_model": {"additionalProperties": false, "description": "Asserts the XML output contains the specified number (``n``, optionally with ``delta``) of elements (or\ntags) with the specified XPath-like ``path``.\n\nFor example:\n\n```xml\n\n```\n\nAlternatively to ``n`` and ``delta`` also the ``min`` and ``max`` attributes\ncan be used to specify the range of the expected number of occurences.\nWith ``negate`` the result of the assertion can be inverted.", "properties": {"path": {"description": "The Python xpath-like expression to find the target element.", "title": "Path", "type": "string"}, "n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "has_n_elements_with_path", "default": "has_n_elements_with_path", "title": "That", "type": "string"}}, "required": ["path"], "title": "has_n_elements_with_path_model", "type": "object"}, "has_n_elements_with_path_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_n_elements_with_path": {"$ref": "#/$defs/base_has_n_elements_with_path_model"}}, "required": ["has_n_elements_with_path"], "title": "has_n_elements_with_path_model_nested", "type": "object"}, "has_n_lines_model": {"additionalProperties": false, "description": "Asserts the specified output contains ``n`` lines allowing\nfor a difference in the number of lines (delta)\nor relative differebce in the number of lines", "properties": {"n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "has_n_lines", "default": "has_n_lines", "title": "That", "type": "string"}}, "title": "has_n_lines_model", "type": "object"}, "has_n_lines_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_n_lines": {"$ref": "#/$defs/base_has_n_lines_model"}}, "required": ["has_n_lines"], "title": "has_n_lines_model_nested", "type": "object"}, "has_size_model": {"additionalProperties": false, "description": "Asserts the specified output has a size of the specified value\n\nAttributes size and value or synonyms though value is considered deprecated.\nThe size optionally allows for absolute (``delta``) difference.", "properties": {"value": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Deprecated alias for `size`", "title": "Value"}, "size": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired size of the output (in bytes), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Size"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "has_size", "default": "has_size", "title": "That", "type": "string"}}, "title": "has_size_model", "type": "object"}, "has_size_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_size": {"$ref": "#/$defs/base_has_size_model"}}, "required": ["has_size"], "title": "has_size_model_nested", "type": "object"}, "has_text_matching_model": {"additionalProperties": false, "description": "Asserts the specified output contains text matching the\nregular expression specified by the argument expression.\nIf n is given the assertion checks for exacly n (nonoverlapping)\noccurences.", "properties": {"expression": {"description": "The regular expressions to attempt match in the output.", "title": "Expression", "type": "string"}, "n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "has_text_matching", "default": "has_text_matching", "title": "That", "type": "string"}}, "required": ["expression"], "title": "has_text_matching_model", "type": "object"}, "has_text_matching_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_text_matching": {"$ref": "#/$defs/base_has_text_matching_model"}}, "required": ["has_text_matching"], "title": "has_text_matching_model_nested", "type": "object"}, "has_text_model": {"additionalProperties": false, "description": "Asserts specified output contains the substring specified by\nthe argument text. The exact number of occurrences can be\noptionally specified by the argument n", "properties": {"text": {"description": "The text to search for in the output.", "title": "Text", "type": "string"}, "n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "that": {"const": "has_text", "default": "has_text", "title": "That", "type": "string"}}, "required": ["text"], "title": "has_text_model", "type": "object"}, "has_text_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"has_text": {"$ref": "#/$defs/base_has_text_model"}}, "required": ["has_text"], "title": "has_text_model_nested", "type": "object"}, "is_valid_xml_model": {"additionalProperties": false, "description": "Asserts the output is a valid XML file (e.g. ````).", "properties": {"that": {"const": "is_valid_xml", "default": "is_valid_xml", "title": "That", "type": "string"}}, "title": "is_valid_xml_model", "type": "object"}, "is_valid_xml_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"is_valid_xml": {"$ref": "#/$defs/base_is_valid_xml_model"}}, "required": ["is_valid_xml"], "title": "is_valid_xml_model_nested", "type": "object"}, "not_has_text_model": {"additionalProperties": false, "description": "Asserts specified output does not contain the substring\nspecified by the argument text", "properties": {"text": {"description": "The text to search for in the output.", "title": "Text", "type": "string"}, "that": {"const": "not_has_text", "default": "not_has_text", "title": "That", "type": "string"}}, "required": ["text"], "title": "not_has_text_model", "type": "object"}, "not_has_text_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"not_has_text": {"$ref": "#/$defs/base_not_has_text_model"}}, "required": ["not_has_text"], "title": "not_has_text_model_nested", "type": "object"}, "xml_element_model": {"additionalProperties": false, "description": "Assert if the XML file contains element(s) or tag(s) with the specified\n[XPath-like ``path``](https://lxml.de/xpathxslt.html). If ``n`` and ``delta``\nor ``min`` and ``max`` are given also the number of occurences is checked.\n\n```xml\n\n \n \n \n\n```\n\nWith ``negate=\"true\"`` the outcome of the assertions wrt the precence and number\nof ``path`` can be negated. If there are any sub assertions then check them against\n\n- the content of the attribute ``attribute``\n- the element's text if no attribute is given\n\n```xml\n\n \n \n \n\n```\n\nSub-assertions are not subject to the ``negate`` attribute of ``xml_element``.\nIf ``all`` is ``true`` then the sub assertions are checked for all occurences.\n\nNote that all other XML assertions can be expressed by this assertion (Galaxy\nalso implements the other assertions by calling this one).", "properties": {"path": {"description": "The Python xpath-like expression to find the target element.", "title": "Path", "type": "string"}, "attribute": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "The XML attribute name to test against from the target XML element.", "title": "Attribute"}, "all": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "Check the sub-assertions for all paths matching the path. Default: false, i.e. only the first ", "title": "All"}, "n": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Desired number, can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "N"}, "delta": {"anyOf": [{"type": "integer"}, {"type": "string"}], "default": 0, "description": "Allowed difference with respect to n (default: 0), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Delta"}, "min": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Minimum number (default: -infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Min"}, "max": {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}], "default": null, "description": "Maximum number (default: infinity), can be suffixed by ``(k|M|G|T|P|E)i?``", "title": "Max"}, "negate": {"anyOf": [{"type": "boolean"}, {"type": "string"}], "default": false, "description": "A boolean that can be set to true to negate the outcome of the assertion.", "title": "Negate"}, "children": {"anyOf": [{"$ref": "#/$defs/RootModel_List_Union_Annotated_Union_has_line_model__has_line_matching_model__has_n_lines_model__has_text_model__has_text_matching_model__not_has_text_model__has_n_columns_model__attribute_is_model__attribute_matches_model__element_text_model__element_text_is_model__element_text_matches_model__has_element_with_path_model__has_n_elements_with_path_model__is_valid_xml_model__xml_element_model__has_json_property_with_text_model__has_json_property_with_value_model__has_h5_attribute_model__has_h5_keys_model__has_archive_member_model__has_size_model__has_image_center_of_mass_model__has_image_channels_model__has_image_depth_model__has_image_frames_model__has_image_height_model__has_image_mean_intensity_model__has_image_mean_object_size_model__has_image_n_labels_model__has_image_width_model___FieldInfo_annotation_NoneType__required_True__discriminator__that_____has_line_model_nested__has_line_matching_model_nested__has_n_lines_model_nested__has_text_model_nested__has_text_matching_model_nested__not_has_text_model_nested__has_n_columns_model_nested__attribute_is_model_nested__attribute_matches_model_nested__element_text_model_nested__element_text_is_model_nested__element_text_matches_model_nested__has_element_with_path_model_nested__has_n_elements_with_path_model_nested__is_valid_xml_model_nested__xml_element_model_nested__has_json_property_with_text_model_nested__has_json_property_with_value_model_nested__has_h5_attribute_model_nested__has_h5_keys_model_nested__has_archive_member_model_nested__has_size_model_nested__has_image_center_of_mass_model_nested__has_image_channels_model_nested__has_image_depth_model_nested__has_image_frames_model_nested__has_image_height_model_nested__has_image_mean_intensity_model_nested__has_image_mean_object_size_model_nested__has_image_n_labels_model_nested__has_image_width_model_nested___"}, {"type": "null"}], "default": null}, "asserts": {"anyOf": [{"$ref": "#/$defs/RootModel_List_Union_Annotated_Union_has_line_model__has_line_matching_model__has_n_lines_model__has_text_model__has_text_matching_model__not_has_text_model__has_n_columns_model__attribute_is_model__attribute_matches_model__element_text_model__element_text_is_model__element_text_matches_model__has_element_with_path_model__has_n_elements_with_path_model__is_valid_xml_model__xml_element_model__has_json_property_with_text_model__has_json_property_with_value_model__has_h5_attribute_model__has_h5_keys_model__has_archive_member_model__has_size_model__has_image_center_of_mass_model__has_image_channels_model__has_image_depth_model__has_image_frames_model__has_image_height_model__has_image_mean_intensity_model__has_image_mean_object_size_model__has_image_n_labels_model__has_image_width_model___FieldInfo_annotation_NoneType__required_True__discriminator__that_____has_line_model_nested__has_line_matching_model_nested__has_n_lines_model_nested__has_text_model_nested__has_text_matching_model_nested__not_has_text_model_nested__has_n_columns_model_nested__attribute_is_model_nested__attribute_matches_model_nested__element_text_model_nested__element_text_is_model_nested__element_text_matches_model_nested__has_element_with_path_model_nested__has_n_elements_with_path_model_nested__is_valid_xml_model_nested__xml_element_model_nested__has_json_property_with_text_model_nested__has_json_property_with_value_model_nested__has_h5_attribute_model_nested__has_h5_keys_model_nested__has_archive_member_model_nested__has_size_model_nested__has_image_center_of_mass_model_nested__has_image_channels_model_nested__has_image_depth_model_nested__has_image_frames_model_nested__has_image_height_model_nested__has_image_mean_intensity_model_nested__has_image_mean_object_size_model_nested__has_image_n_labels_model_nested__has_image_width_model_nested___"}, {"type": "null"}], "default": null}, "that": {"const": "xml_element", "default": "xml_element", "title": "That", "type": "string"}}, "required": ["path"], "title": "xml_element_model", "type": "object"}, "xml_element_model_nested": {"additionalProperties": false, "description": "Nested version of this assertion model.", "properties": {"xml_element": {"$ref": "#/$defs/base_xml_element_model"}}, "required": ["xml_element"], "title": "xml_element_model_nested", "type": "object"}}, "additionalProperties": false, "properties": {"class": {"const": "GalaxyUserTool", "title": "class_", "type": "string"}, "id": {"description": "Unique identifier for the tool. Should be all lower-case and should not include whitespace.", "examples": ["my-cool-tool"], "maxLength": 255, "minLength": 3, "title": "id", "type": "string"}, "version": {"description": "Version for the tool.", "examples": ["0.1.0"], "title": "version", "type": "string"}, "name": {"description": "The name of the tool, displayed in the tool menu. This is not the same as the tool id, which is a unique identifier for the tool.", "title": "name", "type": "string"}, "description": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "The description is displayed in the tool menu immediately following the hyperlink for the tool.", "title": "description"}, "configfiles": {"anyOf": [{"items": {"$ref": "#/$defs/YamlTemplateConfigFile"}, "type": "array"}, {"type": "null"}], "default": null, "description": "A list of config files for this tool.", "title": "configfiles"}, "container": {"description": "Container image to use for this tool.", "examples": ["quay.io/biocontainers/python:3.13"], "title": "container", "type": "string"}, "requirements": {"anyOf": [{"items": {"anyOf": [{"$ref": "#/$defs/JavascriptRequirement"}, {"$ref": "#/$defs/ResourceRequirement"}, {"$ref": "#/$defs/ContainerRequirement"}]}, "type": "array"}, {"type": "null"}], "default": [], "description": "A list of requirements needed to execute this tool. These can be javascript expressions, resource requirements or container images.", "title": "requirements"}, "shell_command": {"description": "A string that contains the command to be executed. Parameters can be referenced inside $().", "examples": ["head -n '$(inputs.n_lines)' '$(inputs.data_input.path)'"], "title": "shell_command", "type": "string"}, "inputs": {"default": [], "items": {"$ref": "#/$defs/YamlGalaxyToolParameter"}, "title": "inputs", "type": "array"}, "outputs": {"default": [], "items": {"discriminator": {"mapping": {"boolean": "#/$defs/ToolOutputBoolean", "collection": "#/$defs/IncomingToolOutputCollection", "data": "#/$defs/IncomingToolOutputDataset", "float": "#/$defs/ToolOutputFloat", "integer": "#/$defs/ToolOutputInteger", "text": "#/$defs/ToolOutputText"}, "propertyName": "type"}, "oneOf": [{"$ref": "#/$defs/IncomingToolOutputDataset"}, {"$ref": "#/$defs/IncomingToolOutputCollection"}, {"$ref": "#/$defs/ToolOutputText"}, {"$ref": "#/$defs/ToolOutputInteger"}, {"$ref": "#/$defs/ToolOutputFloat"}, {"$ref": "#/$defs/ToolOutputBoolean"}]}, "title": "outputs", "type": "array"}, "citations": {"anyOf": [{"items": {"$ref": "#/$defs/Citation"}, "type": "array"}, {"type": "null"}], "default": null, "title": "citations"}, "license": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "A full URI or a a short [SPDX](https://spdx.org/licenses/) identifier for a license for this tool wrapper. The tool wrapper license can be independent of the underlying tool license. This license covers the tool yaml and associated scripts shipped with the tool.", "examples": ["MIT"], "title": "license"}, "edam_operations": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "default": null, "title": "edam_operations"}, "edam_topics": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "default": null, "title": "edam_topics"}, "xrefs": {"anyOf": [{"items": {"$ref": "#/$defs/XrefDict"}, "type": "array"}, {"type": "null"}], "default": null, "title": "xrefs"}, "profile": {"anyOf": [{"type": "number"}, {"type": "null"}], "default": null, "title": "profile"}, "help": {"anyOf": [{"$ref": "#/$defs/HelpContent"}, {"type": "null"}], "default": null, "description": "Help text shown below the tool interface.", "title": "help"}, "tests": {"anyOf": [{"items": {"$ref": "#/$defs/YamlToolTest"}, "type": "array"}, {"type": "null"}], "default": null, "title": "tests"}}, "required": ["class", "id", "version", "name", "container", "shell_command"], "title": "UserToolSource", "type": "object"} diff --git a/doc/source/admin/user_defined_tools.md b/doc/source/admin/user_defined_tools.md index 3cfe1c080b1..fe0f0e81f8a 100644 --- a/doc/source/admin/user_defined_tools.md +++ b/doc/source/admin/user_defined_tools.md @@ -93,6 +93,66 @@ See https://training.galaxyproject.org/training-material/topics/admin/tutorials/ and see https://github.com/galaxyproject/galaxy/blob/dev/test/integration/embedded_pulsar_job_conf.yml#L29 for a simple example that uses embedded pulsar to isolate mounts and disables network access. While the feature is in beta we recommend that only trusted users are allowed to use this feature. +## Supported input parameter types + +The YAML authoring layer exposes a deliberately narrow subset of Galaxy's +parameter model. The JSON schema published to the editor (`ToolSourceSchema.json`) +is generated from this subset and rejects any unknown fields via +`extra="forbid"`, so unsupported attributes fail fast at parse time. + +Supported leaf parameter types: + +| Type | Supported fields (beyond `name`, `label`, `help`, `optional`) | +| ----------------- | ---------------------------------------------------------------------- | +| `boolean` | `value` | +| `integer` | `value`, `min`, `max`, `validators` (`in_range` only) | +| `float` | `value`, `min`, `max`, `validators` (`in_range` only) | +| `text` | `value`, `area`, `validators` (`length`, `regex`, `empty_field`) | +| `select` | `options` (static, non-empty), `multiple`, `validators` (`no_options`) | +| `color` | `value` | +| `data` | `format`, `multiple`, `min`, `max` | +| `data_collection` | `collection_type`, `format` | + +Supported structural groups: `conditional`, `repeat`, `section`. These recurse +into the supported leaf set. + +Example using several supported types: + +```yaml +class: GalaxyUserTool +id: example_tool +version: "0.1" +name: Example +container: busybox +shell_command: echo "$(inputs.greeting) $(inputs.count)" +inputs: + - name: greeting + type: select + options: + - { label: Hi, value: hi, selected: true } + - { label: Hello, value: hello, selected: false } + - name: count + type: integer + value: 1 + min: 1 + max: 10 + - name: extras + type: repeat + min: 0 + parameters: + - name: input_file + type: data + format: txt +outputs: [] +``` + +Types that exist in the XML tool vocabulary but are **not** supported in YAML +user-defined tools and will be rejected at parse time: `hidden`, `drill_down`, +`data_column`, `genomebuild`, `group_tag`, `baseurl`, `rules`, `directory`. +XML-only fields such as `truevalue`, `falsevalue`, `argument`, `is_dynamic`, +`hidden` (as a field), and `parameter_type` are likewise rejected on any +parameter. + ## Limitations The user-defined tool language is still evolving, and additional safety audits are ongoing. diff --git a/lib/galaxy/tool_util/parameters/convert.py b/lib/galaxy/tool_util/parameters/convert.py index 6467bae75e4..c6bffded3af 100644 --- a/lib/galaxy/tool_util/parameters/convert.py +++ b/lib/galaxy/tool_util/parameters/convert.py @@ -9,6 +9,7 @@ from typing import ( Dict, List, Optional, + Sequence, ) from galaxy.tool_util_models.parameters import ( @@ -537,12 +538,58 @@ DatasetToRuntimeJson = Callable[[DataJobInternalT], DataInternalJson] CollectionToRuntimeJson = Callable[[DataCollectionRequestInternal, Optional[str]], Any] +# Parameter models the narrow YAML authoring layer is allowed to produce. +# Mirrors the v1 supported set in `lib/galaxy/tool_util_models/yaml_parameters.py`. +# Anything outside this set in a YAML-origin tool indicates a bug in the +# authoring → internal mapping and should hard-fail before we try to build +# runtime state. +YAML_V1_SUPPORTED_PARAMETER_MODELS: frozenset = frozenset( + { + BooleanParameterModel, + IntegerParameterModel, + FloatParameterModel, + TextParameterModel, + SelectParameterModel, + DataParameterModel, + DataCollectionParameterModel, + ConditionalParameterModel, + RepeatParameterModel, + SectionParameterModel, + } +) + + +def assert_yaml_v1_parameters(parameters: Sequence[ToolParameterT]) -> None: + """Raise if any parameter (including nested ones) is outside the YAML v1 set. + + Defense-in-depth: the narrow ``YamlGalaxyToolParameter`` cannot produce a + disallowed type, so this guard should never fire for a legitimately + constructed YAML tool. It exists to surface mapping bugs instead of letting + an unsupported type silently pass through ``runtimeify``'s default-case + ``VISITOR_NO_REPLACEMENT``. + """ + for parameter in parameters: + if type(parameter) not in YAML_V1_SUPPORTED_PARAMETER_MODELS: + raise AssertionError( + f"YAML-origin tool produced unsupported parameter type " + f"{type(parameter).__name__} for parameter {getattr(parameter, 'name', '?')!r}" + ) + if isinstance(parameter, ConditionalParameterModel): + for when in parameter.whens: + assert_yaml_v1_parameters(when.parameters) + elif isinstance(parameter, (RepeatParameterModel, SectionParameterModel)): + assert_yaml_v1_parameters(parameter.parameters) + + def runtimeify( internal_state: JobInternalToolState, input_models: ToolParameterBundle, adapt_dataset: DatasetToRuntimeJson, adapt_collection: CollectionToRuntimeJson, + yaml_origin: bool = False, ) -> JobRuntimeToolState: + if yaml_origin: + assert_yaml_v1_parameters(list(input_models.parameters)) def adapt_dict(value: dict): assert isinstance(value, dict), str(value) diff --git a/lib/galaxy/tool_util/parser/interface.py b/lib/galaxy/tool_util/parser/interface.py index 0b81e2c670e..49d82bbcb43 100644 --- a/lib/galaxy/tool_util/parser/interface.py +++ b/lib/galaxy/tool_util/parser/interface.py @@ -26,6 +26,10 @@ from typing_extensions import ( ) from galaxy.tool_util_models.parameter_validators import AnyValidatorModel +from galaxy.tool_util_models.testing_types import ( + AssertionList, + DirectCredential, +) from galaxy.tool_util_models.tool_source import ( BaseJsonTestCollectionDefCollectionElementDict, Citation, @@ -66,13 +70,6 @@ NOT_IMPLEMENTED_MESSAGE = "Galaxy tool format does not yet support this tool fea INPUT_CLASS_T = Literal["galaxy", "cwl"] -class AssertionDict(TypedDict): - tag: str - attributes: Dict[str, Any] - children: "AssertionList" - - -AssertionList = Optional[List[AssertionDict]] XmlInt = Union[str, int] @@ -117,25 +114,6 @@ class ToolSourceTestInput(TypedDict): attributes: ToolSourceTestInputAttributes -class DirectCredentialValue(TypedDict): - """Represents a credential value (variable or secret) provided directly.""" - - name: str - value: str - - -class _DirectCredentialRequired(TypedDict): - name: str # Name of the credentials group - variables: List[DirectCredentialValue] - secrets: List[DirectCredentialValue] - - -class DirectCredential(_DirectCredentialRequired, total=False): - """Represents a credential group with variables and secrets provided directly.""" - - version: str # Version of the credential definition (defaults to "1.0") - - ToolSourceTestInputs = List[ToolSourceTestInput] ToolSourceTestOutputs = List[ToolSourceTestOutput] TestSourceTestOutputColllection = Any diff --git a/lib/galaxy/tool_util/parser/xml.py b/lib/galaxy/tool_util/parser/xml.py index 445d1a80503..5c5c69497b8 100644 --- a/lib/galaxy/tool_util/parser/xml.py +++ b/lib/galaxy/tool_util/parser/xml.py @@ -31,6 +31,10 @@ from galaxy.tool_util.parser.util import ( DEFAULT_SORT, ) from galaxy.tool_util_models.parameter_validators import AnyValidatorModel +from galaxy.tool_util_models.testing_types import ( + AssertionList, + DirectCredential, +) from galaxy.tool_util_models.tool_source import ( Citation, DrillDownOptionsDict, @@ -53,8 +57,6 @@ from galaxy.util import ( xml_to_string, ) from .interface import ( - AssertionList, - DirectCredential, DrillDownDynamicOptions, DynamicOptions, InputSource, diff --git a/lib/galaxy/tool_util/parser/yaml.py b/lib/galaxy/tool_util/parser/yaml.py index 3116f25364c..fed701a34fa 100644 --- a/lib/galaxy/tool_util/parser/yaml.py +++ b/lib/galaxy/tool_util/parser/yaml.py @@ -32,6 +32,11 @@ from galaxy.tool_util_models.parameters import ( ToolParameterBundleModel, ToolParameterT, ) +from galaxy.tool_util_models.testing_types import ( + AssertionDict, + AssertionList, + DirectCredential, +) from galaxy.tool_util_models.tool_source import ( HelpContent, JsonTestCollectionDefDict, @@ -40,9 +45,6 @@ from galaxy.tool_util_models.tool_source import ( ) from galaxy.util import listify from .interface import ( - AssertionDict, - AssertionList, - DirectCredential, InputSource, PageSource, PagesSource, @@ -273,7 +275,7 @@ class YamlToolSource(ToolSource): tests: List[ToolSourceTest] = [] rval: ToolSourceTests = dict(tests=tests) - raw_tests = deepcopy(self.root_dict.get("tests", [])) + raw_tests = deepcopy(self.root_dict.get("tests") or []) for i, test_dict in enumerate(raw_tests): inputs = test_dict.get("inputs", {}) state = TestCaseJsonToolState(inputs) @@ -530,7 +532,11 @@ class YamlInputSource(InputSource): def parse_extensions(self): extensions = self.input_dict.get("extensions") if not extensions: - extensions = self.get("format", "data").split(",") + format_raw = self.get("format", "data") + if isinstance(format_raw, str): + extensions = format_raw.split(",") + else: + extensions = format_raw return [ext.strip().lower() for ext in extensions] def parse_nested_inputs_source(self): diff --git a/lib/galaxy/tool_util/verify/_types.py b/lib/galaxy/tool_util/verify/_types.py index 305d9592675..8ba8ec397d2 100644 --- a/lib/galaxy/tool_util/verify/_types.py +++ b/lib/galaxy/tool_util/verify/_types.py @@ -15,11 +15,13 @@ from typing_extensions import ( ) from galaxy.tool_util.parser.interface import ( - AssertionList, - DirectCredential, TestSourceTestOutputColllection, ToolSourceTestOutputs, ) +from galaxy.tool_util_models.testing_types import ( + AssertionList, + DirectCredential, +) # legacy inputs for working with POST /api/tools # + inputs that have been processed with parse.py and expanded out diff --git a/lib/galaxy/tool_util/verify/interactor.py b/lib/galaxy/tool_util/verify/interactor.py index 5b216169458..0657db7b8cd 100644 --- a/lib/galaxy/tool_util/verify/interactor.py +++ b/lib/galaxy/tool_util/verify/interactor.py @@ -46,8 +46,6 @@ from galaxy.tool_util.parameters import ( ToolParameterBundle, ) from galaxy.tool_util.parser.interface import ( - AssertionList, - DirectCredential, TestCollectionDef, TestCollectionOutputDef, TestSourceTestOutputColllection, @@ -55,6 +53,10 @@ from galaxy.tool_util.parser.interface import ( XmlTestCollectionDefDict, ) from galaxy.tool_util.verify.test_data import TestDataResolver +from galaxy.tool_util_models.testing_types import ( + AssertionList, + DirectCredential, +) from galaxy.tool_util_models.tool_source import ( JsonTestCollectionDefDict, JsonTestDatasetDefDict, diff --git a/lib/galaxy/tool_util_models/__init__.py b/lib/galaxy/tool_util_models/__init__.py index d70c4eb0fa5..34e81b945c5 100644 --- a/lib/galaxy/tool_util_models/__init__.py +++ b/lib/galaxy/tool_util_models/__init__.py @@ -28,7 +28,6 @@ from typing_extensions import ( TypedDict, ) -from galaxy.tool_util_models.parameters import GalaxyToolParameterModel from ._base import ToolSourceBaseModel from .assertions import assertions from .parameters import ToolParameterT @@ -46,6 +45,7 @@ from .tool_source import ( XrefDict, YamlTemplateConfigFile, ) +from .yaml_parameters import YamlGalaxyToolParameter def normalize_dict(values, keys: List[str]): @@ -56,44 +56,24 @@ def normalize_dict(values, keys: List[str]): values[key] = [{"name": k, **v} for k, v in items.items()] -class ToolSourceBase(ToolSourceBaseModel): - id: Optional[str] = None - name: Optional[str] = None - version: Optional[str] = "1.0" - profile: Optional[float] = None - description: Optional[str] = None - container: Optional[str] = None - requirements: Optional[List[Union[JavascriptRequirement, ResourceRequirement, ContainerRequirement]]] = [] - inputs: List[GalaxyToolParameterModel] = [] - outputs: List[IncomingToolOutput] = [] - citations: Optional[List[Citation]] = None - license: Optional[str] = None - edam_operations: Optional[List[str]] = None - edam_topics: Optional[List[str]] = None - xrefs: Optional[List[XrefDict]] = None - help: Optional[HelpContent] = None +class _DynamicToolSourceBase(ToolSourceBaseModel): + # extra="forbid" rejects unknown top-level keys (e.g. a stray `argument:` at + # the tool level), matching the strict-narrow stance on `inputs`. + model_config = ConfigDict( + extra="forbid", + field_title_generator=lambda field_name, field_info: field_name.lower(), + ) - @model_validator(mode="before") - @classmethod - def normalize_items(cls, values): - if isinstance(values, dict): - normalize_dict(values, ["inputs", "outputs"]) - return values - - -# repeated fields to get consistent order, ugh, FIXME obviously -class UserToolSource(ToolSourceBaseModel): - class_: Annotated[Literal["GalaxyUserTool"], Field(alias="class")] id: Annotated[ - str, + Optional[str], Field( description="Unique identifier for the tool. Should be all lower-case and should not include whitespace.", examples=["my-cool-tool"], min_length=3, max_length=255, ), - ] - version: Annotated[str, Field(description="Version for the tool.", examples=["0.1.0"])] + ] = None + version: Annotated[Optional[str], Field(description="Version for the tool.", examples=["0.1.0"])] = None name: Annotated[ str, Field( @@ -109,9 +89,6 @@ class UserToolSource(ToolSourceBaseModel): configfiles: Annotated[ Optional[List[YamlTemplateConfigFile]], Field(description="A list of config files for this tool.") ] = None - container: Annotated[ - str, Field(description="Container image to use for this tool.", examples=["quay.io/biocontainers/python:3.13"]) - ] requirements: Annotated[ Optional[List[Union[JavascriptRequirement, ResourceRequirement, ContainerRequirement]]], Field( @@ -126,7 +103,7 @@ class UserToolSource(ToolSourceBaseModel): examples=["head -n '$(inputs.n_lines)' '$(inputs.data_input.path)'"], ), ] - inputs: List[GalaxyToolParameterModel] = [] + inputs: List[YamlGalaxyToolParameter] = [] outputs: List[IncomingToolOutput] = [] citations: Optional[List[Citation]] = None license: Annotated[ @@ -139,7 +116,9 @@ class UserToolSource(ToolSourceBaseModel): edam_operations: Optional[List[str]] = None edam_topics: Optional[List[str]] = None xrefs: Optional[List[XrefDict]] = None + profile: Optional[float] = None help: Annotated[Optional[HelpContent], Field(description="Help text shown below the tool interface.")] = None + tests: Optional[List["YamlToolTest"]] = None @model_validator(mode="before") @classmethod @@ -149,12 +128,25 @@ class UserToolSource(ToolSourceBaseModel): return values -class AdminToolSource(ToolSourceBase): +class UserToolSource(_DynamicToolSourceBase): + class_: Annotated[Literal["GalaxyUserTool"], Field(alias="class")] + container: Annotated[ + str, Field(description="Container image to use for this tool.", examples=["quay.io/biocontainers/python:3.13"]) + ] + + +class YamlToolSource(_DynamicToolSourceBase): class_: Annotated[Literal["GalaxyTool"], Field(alias="class")] - command: str + container: Annotated[ + Optional[str], + Field( + description="Container image to use for this tool.", + examples=["quay.io/biocontainers/python:3.13"], + ), + ] = None -DynamicToolSources = Annotated[Union[UserToolSource, AdminToolSource], Field(discriminator="class_")] +DynamicToolSources = Annotated[Union[UserToolSource, YamlToolSource], Field(discriminator="class_")] class ParsedTool(ToolSourceBaseModel): @@ -243,6 +235,78 @@ TestOutputLiteral = Union[bool, int, float, str] TestOutputAssertions = Union[TestCollectionOutputAssertions, TestDataOutputAssertions, TestOutputLiteral] + +TestInputValue = Union[bool, int, float, str, List[Any], Dict[str, Any]] + + +class YamlTestCredentialValue(StrictModel): + name: Annotated[str, Field(description="Name of the credential variable or secret.")] + value: Annotated[str, Field(description="Value of the credential variable or secret.")] + + +class YamlTestCredential(StrictModel): + name: Annotated[str, Field(description="Name of the credentials group.")] + variables: Annotated[ + List[YamlTestCredentialValue], + Field(description="Variables exposed to the tool environment."), + ] = [] + secrets: Annotated[ + List[YamlTestCredentialValue], + Field(description="Secrets exposed to the tool environment."), + ] = [] + version: Annotated[ + Optional[str], + Field(description="Version of the credential definition."), + ] = None + + +class YamlToolTest(BaseModel): + """In-tool test case as authored in YAML tool fixtures.""" + + model_config = ConfigDict(extra="forbid") + + doc: Annotated[Optional[str], Field(description="Human-readable description of this test case.")] = None + inputs: Annotated[ + Optional[Dict[str, TestInputValue]], + Field(description="Mapping of input parameter names to test values."), + ] = None + outputs: Annotated[ + Dict[str, TestOutputAssertions], + Field(description="Mapping of output names to expected values or assertions."), + ] = {} + assert_stdout: Annotated[ + Optional[assertions], + Field(description="Assertions to apply against the tool's standard output."), + ] = None + assert_stderr: Annotated[ + Optional[assertions], + Field(description="Assertions to apply against the tool's standard error."), + ] = None + command: Annotated[ + Optional[assertions], + Field(description="Assertions to apply against the executed command line."), + ] = None + expect_exit_code: Annotated[ + Optional[int], + Field(description="Expected process exit code."), + ] = None + expect_failure: Annotated[ + Optional[bool], + Field(description="If true, the tool is expected to produce an error."), + ] = None + expect_test_failure: Annotated[ + Optional[bool], + Field(description="If true, the test itself is expected to fail."), + ] = None + credentials: Annotated[ + Optional[List[YamlTestCredential]], + Field(description="Credentials to inject for this test case."), + ] = None + + +UserToolSource.model_rebuild() +YamlToolSource.model_rebuild() + JobDict = Dict[str, Any] diff --git a/lib/galaxy/tool_util_models/assertions.py b/lib/galaxy/tool_util_models/assertions.py index ee198312c8b..be14dc39a1b 100644 --- a/lib/galaxy/tool_util_models/assertions.py +++ b/lib/galaxy/tool_util_models/assertions.py @@ -313,7 +313,7 @@ class base_has_line_matching_model_relaxed(AssertionModel): class has_line_matching_model(base_has_line_matching_model): r"""Asserts the specified output contains a line matching the regular expression specified by the argument expression. If n is given - the assertion checks for exactly n occurences.""" + the assertion checks for exactly n occurrences.""" that: Literal["has_line_matching"] = "has_line_matching" @@ -327,7 +327,7 @@ class has_line_matching_model_nested(AssertionModel): class has_line_matching_model_relaxed(base_has_line_matching_model_relaxed): r"""Asserts the specified output contains a line matching the regular expression specified by the argument expression. If n is given - the assertion checks for exactly n occurences.""" + the assertion checks for exactly n occurrences.""" that: Literal["has_line_matching"] = "has_line_matching" @@ -700,8 +700,8 @@ class base_has_text_matching_model_relaxed(AssertionModel): class has_text_matching_model(base_has_text_matching_model): r"""Asserts the specified output contains text matching the regular expression specified by the argument expression. - If n is given the assertion checks for exacly n (nonoverlapping) - occurences.""" + If n is given the assertion checks for exactly n (nonoverlapping) + occurrences.""" that: Literal["has_text_matching"] = "has_text_matching" @@ -715,8 +715,8 @@ class has_text_matching_model_nested(AssertionModel): class has_text_matching_model_relaxed(base_has_text_matching_model_relaxed): r"""Asserts the specified output contains text matching the regular expression specified by the argument expression. - If n is given the assertion checks for exacly n (nonoverlapping) - occurences.""" + If n is given the assertion checks for exactly n (nonoverlapping) + occurrences.""" that: Literal["has_text_matching"] = "has_text_matching" @@ -893,7 +893,7 @@ class has_n_columns_model(base_has_n_columns_model): For instance, ````. The assertion tests only the first line. Number of columns can optionally also be specified with ``delta``. Alternatively the - range of expected occurences can be specified by ``min`` and/or ``max``. + range of expected occurrences can be specified by ``min`` and/or ``max``. Optionally a column separator (``sep``, default is `` ``) `and comment character(s) can be specified (``comment``, default is empty string). The first non-comment @@ -914,7 +914,7 @@ class has_n_columns_model_relaxed(base_has_n_columns_model_relaxed): For instance, ````. The assertion tests only the first line. Number of columns can optionally also be specified with ``delta``. Alternatively the - range of expected occurences can be specified by ``min`` and/or ``max``. + range of expected occurrences can be specified by ``min`` and/or ``max``. Optionally a column separator (``sep``, default is `` ``) `and comment character(s) can be specified (``comment``, default is empty string). The first non-comment @@ -1585,7 +1585,7 @@ class has_n_elements_with_path_model(base_has_n_elements_with_path_model): ``` Alternatively to ``n`` and ``delta`` also the ``min`` and ``max`` attributes - can be used to specify the range of the expected number of occurences. + can be used to specify the range of the expected number of occurrences. With ``negate`` the result of the assertion can be inverted.""" that: Literal["has_n_elements_with_path"] = "has_n_elements_with_path" @@ -1608,7 +1608,7 @@ class has_n_elements_with_path_model_relaxed(base_has_n_elements_with_path_model ``` Alternatively to ``n`` and ``delta`` also the ``min`` and ``max`` attributes - can be used to specify the range of the expected number of occurences. + can be used to specify the range of the expected number of occurrences. With ``negate`` the result of the assertion can be inverted.""" that: Literal["has_n_elements_with_path"] = "has_n_elements_with_path" @@ -1786,7 +1786,7 @@ class base_xml_element_model_relaxed(AssertionModel): class xml_element_model(base_xml_element_model): r"""Assert if the XML file contains element(s) or tag(s) with the specified [XPath-like ``path``](https://lxml.de/xpathxslt.html). If ``n`` and ``delta`` - or ``min`` and ``max`` are given also the number of occurences is checked. + or ``min`` and ``max`` are given also the number of occurrences is checked. ```xml @@ -1796,7 +1796,7 @@ class xml_element_model(base_xml_element_model): ``` - With ``negate="true"`` the outcome of the assertions wrt the precence and number + With ``negate="true"`` the outcome of the assertions wrt the presence and number of ``path`` can be negated. If there are any sub assertions then check them against - the content of the attribute ``attribute`` @@ -1811,7 +1811,7 @@ class xml_element_model(base_xml_element_model): ``` Sub-assertions are not subject to the ``negate`` attribute of ``xml_element``. - If ``all`` is ``true`` then the sub assertions are checked for all occurences. + If ``all`` is ``true`` then the sub assertions are checked for all occurrences. Note that all other XML assertions can be expressed by this assertion (Galaxy also implements the other assertions by calling this one).""" @@ -1828,7 +1828,7 @@ class xml_element_model_nested(AssertionModel): class xml_element_model_relaxed(base_xml_element_model_relaxed): r"""Assert if the XML file contains element(s) or tag(s) with the specified [XPath-like ``path``](https://lxml.de/xpathxslt.html). If ``n`` and ``delta`` - or ``min`` and ``max`` are given also the number of occurences is checked. + or ``min`` and ``max`` are given also the number of occurrences is checked. ```xml @@ -1838,7 +1838,7 @@ class xml_element_model_relaxed(base_xml_element_model_relaxed): ``` - With ``negate="true"`` the outcome of the assertions wrt the precence and number + With ``negate="true"`` the outcome of the assertions wrt the presence and number of ``path`` can be negated. If there are any sub assertions then check them against - the content of the attribute ``attribute`` @@ -1853,7 +1853,7 @@ class xml_element_model_relaxed(base_xml_element_model_relaxed): ``` Sub-assertions are not subject to the ``negate`` attribute of ``xml_element``. - If ``all`` is ``true`` then the sub assertions are checked for all occurences. + If ``all`` is ``true`` then the sub assertions are checked for all occurrences. Note that all other XML assertions can be expressed by this assertion (Galaxy also implements the other assertions by calling this one).""" diff --git a/lib/galaxy/tool_util_models/testing_types.py b/lib/galaxy/tool_util_models/testing_types.py new file mode 100644 index 00000000000..cb27a87762d --- /dev/null +++ b/lib/galaxy/tool_util_models/testing_types.py @@ -0,0 +1,42 @@ +"""Shared TypedDicts for tool test definitions and assertion structures. + +These live in ``tool_util_models`` so both ``tool_util_models`` and +``tool_util.parser`` can depend on them without creating a circular import. +""" + +from typing import ( + Any, + Dict, + List, + Optional, +) + +from typing_extensions import TypedDict + + +class AssertionDict(TypedDict): + tag: str + attributes: Dict[str, Any] + children: "AssertionList" + + +AssertionList = Optional[List[AssertionDict]] + + +class DirectCredentialValue(TypedDict): + """Represents a credential value (variable or secret) provided directly.""" + + name: str + value: str + + +class _DirectCredentialRequired(TypedDict): + name: str + variables: List[DirectCredentialValue] + secrets: List[DirectCredentialValue] + + +class DirectCredential(_DirectCredentialRequired, total=False): + """Represents a credential group with variables and secrets provided directly.""" + + version: str diff --git a/lib/galaxy/tool_util_models/yaml_parameters.py b/lib/galaxy/tool_util_models/yaml_parameters.py new file mode 100644 index 00000000000..6b94ee5f0ea --- /dev/null +++ b/lib/galaxy/tool_util_models/yaml_parameters.py @@ -0,0 +1,324 @@ +"""Narrow YAML-facing tool parameter models. + +`UserToolSource` and `YamlToolSource` use these for their `inputs` field instead +of the full internal Galaxy XML metamodel union. The YAML layer is purely an +authoring/publication surface: it validates what users may write in YAML tools and +rejects XML-only fields and unsupported parameter types via ``extra="forbid"``. + +Every model exposes ``to_internal()`` returning the matching internal +``GalaxyParameterT`` instance so callers that need the internal metamodel (e.g. +round-trip tests) can construct it directly without re-parsing through +``YamlToolSource``. The primary production path still builds internal models via +``input_models_for_tool_source`` from the raw validated dict, so ``to_internal()`` +is not load-bearing for execution today. +""" + +from typing import ( + List, + Optional, + Union, +) + +from pydantic import ( + BaseModel, + ConfigDict, + Field, + field_validator, + RootModel, +) +from typing_extensions import ( + Annotated, + Literal, +) + +from .parameter_validators import ( + EmptyFieldParameterValidatorModel, + InRangeParameterValidatorModel, + LengthParameterValidatorModel, + NoOptionsParameterValidatorModel, + RegexParameterValidatorModel, +) +from .parameters import ( + BooleanParameterModel, + ColorParameterModel, + cond_test_parameter_default_value, + ConditionalParameterModel, + ConditionalWhen, + DataCollectionParameterModel, + DataParameterModel, + FloatParameterModel, + GalaxyParameterT, + IntegerParameterModel, + LabelValue, + RepeatParameterModel, + SectionParameterModel, + SelectParameterModel, + TextParameterModel, +) + + +class YamlLabelValue(BaseModel): + """YAML-friendly option model — ``selected`` defaults to ``False``.""" + + label: str + value: str + selected: bool = False + + def to_internal(self) -> LabelValue: + return LabelValue(label=self.label, value=self.value, selected=self.selected) + + +# Narrow validator unions — drops XML-only validators like Expression. +YamlTextValidators = Union[ + LengthParameterValidatorModel, + RegexParameterValidatorModel, + EmptyFieldParameterValidatorModel, +] +YamlNumberValidators = Union[InRangeParameterValidatorModel,] +YamlSelectValidators = Union[NoOptionsParameterValidatorModel,] + + +class _YamlParamBase(BaseModel): + model_config = ConfigDict(extra="forbid", populate_by_name=True) + + name: str + label: Optional[str] = None + help: Optional[str] = None + optional: bool = False + + +def _common_internal_kwargs(yaml_param: "_YamlParamBase") -> dict: + kwargs: dict = {"name": yaml_param.name, "optional": yaml_param.optional} + if yaml_param.label is not None: + kwargs["label"] = yaml_param.label + if yaml_param.help is not None: + kwargs["help"] = yaml_param.help + return kwargs + + +class YamlBooleanParameter(_YamlParamBase): + type: Literal["boolean"] + value: Optional[bool] = False + + def to_internal(self) -> BooleanParameterModel: + return BooleanParameterModel(type="boolean", value=self.value, **_common_internal_kwargs(self)) + + +class YamlIntegerParameter(_YamlParamBase): + type: Literal["integer"] + value: Optional[int] = None + min: Optional[int] = None + max: Optional[int] = None + validators: List[YamlNumberValidators] = [] + + def to_internal(self) -> IntegerParameterModel: + return IntegerParameterModel( + type="integer", + value=self.value, + min=self.min, + max=self.max, + validators=list(self.validators), + **_common_internal_kwargs(self), + ) + + +class YamlFloatParameter(_YamlParamBase): + type: Literal["float"] + value: Optional[float] = None + min: Optional[float] = None + max: Optional[float] = None + validators: List[YamlNumberValidators] = [] + + def to_internal(self) -> FloatParameterModel: + return FloatParameterModel( + type="float", + value=self.value, + min=self.min, + max=self.max, + validators=list(self.validators), + **_common_internal_kwargs(self), + ) + + +class YamlTextParameter(_YamlParamBase): + type: Literal["text"] + value: Optional[str] = Field(default=None, alias="value") + area: bool = False + validators: List[YamlTextValidators] = [] + + def to_internal(self) -> TextParameterModel: + return TextParameterModel( + type="text", + default_value=self.value, + area=self.area, + validators=list(self.validators), + **_common_internal_kwargs(self), + ) + + +class YamlSelectParameter(_YamlParamBase): + type: Literal["select"] + options: Annotated[List[YamlLabelValue], Field(min_length=1)] + multiple: bool = False + validators: List[YamlSelectValidators] = [] + + def to_internal(self) -> SelectParameterModel: + return SelectParameterModel( + type="select", + options=[o.to_internal() for o in self.options], + multiple=self.multiple, + validators=list(self.validators), + **_common_internal_kwargs(self), + ) + + +class YamlColorParameter(_YamlParamBase): + type: Literal["color"] + value: Optional[str] = None + + def to_internal(self) -> ColorParameterModel: + return ColorParameterModel(type="color", value=self.value, **_common_internal_kwargs(self)) + + +def _split_format(v): + # Accept the XML-style comma-separated string form (`format: "txt,tabular"`) + # as well as a list. Internal `DataParameterModel.extensions` is always a list. + if isinstance(v, str): + return [ext.strip().lower() for ext in v.split(",") if ext.strip()] + return v + + +class YamlDataParameter(_YamlParamBase): + type: Literal["data"] + format: List[str] = ["data"] + multiple: bool = False + min: Optional[int] = None + max: Optional[int] = None + + @field_validator("format", mode="before") + @classmethod + def _coerce_format(cls, v): + return _split_format(v) + + def to_internal(self) -> DataParameterModel: + return DataParameterModel( + type="data", + extensions=list(self.format), + multiple=self.multiple, + min=self.min, + max=self.max, + **_common_internal_kwargs(self), + ) + + +class YamlDataCollectionParameter(_YamlParamBase): + type: Literal["data_collection"] + collection_type: Optional[str] = None + format: List[str] = ["data"] + + @field_validator("format", mode="before") + @classmethod + def _coerce_format(cls, v): + return _split_format(v) + + def to_internal(self) -> DataCollectionParameterModel: + return DataCollectionParameterModel( + type="data_collection", + collection_type=self.collection_type, + extensions=list(self.format), + value=None, + **_common_internal_kwargs(self), + ) + + +YamlConditionalTestParameter = Annotated[Union[YamlBooleanParameter, YamlSelectParameter], Field(discriminator="type")] + + +class YamlConditionalWhen(BaseModel): + model_config = ConfigDict(extra="forbid", populate_by_name=True) + + discriminator: Union[bool, str] + parameters: List["YamlGalaxyToolParameter"] = [] + + +class YamlConditionalParameter(_YamlParamBase): + type: Literal["conditional"] + test_parameter: YamlConditionalTestParameter + whens: Annotated[List[YamlConditionalWhen], Field(min_length=1)] + + def to_internal(self) -> ConditionalParameterModel: + internal_test = self.test_parameter.to_internal() + default_value = cond_test_parameter_default_value(internal_test) + internal_whens: List[ConditionalWhen] = [] + for when in self.whens: + internal_params = [p.root.to_internal() for p in when.parameters] + internal_whens.append( + ConditionalWhen( + discriminator=when.discriminator, + parameters=internal_params, + is_default_when=when.discriminator == default_value, + ) + ) + return ConditionalParameterModel( + type="conditional", + test_parameter=internal_test, + whens=internal_whens, + **_common_internal_kwargs(self), + ) + + +class YamlRepeatParameter(_YamlParamBase): + type: Literal["repeat"] + parameters: List["YamlGalaxyToolParameter"] = [] + min: Optional[int] = None + max: Optional[int] = None + + def to_internal(self) -> RepeatParameterModel: + return RepeatParameterModel( + type="repeat", + parameters=[p.root.to_internal() for p in self.parameters], + min=self.min, + max=self.max, + **_common_internal_kwargs(self), + ) + + +class YamlSectionParameter(_YamlParamBase): + type: Literal["section"] + parameters: List["YamlGalaxyToolParameter"] = [] + + def to_internal(self) -> SectionParameterModel: + return SectionParameterModel( + type="section", + parameters=[p.root.to_internal() for p in self.parameters], + **_common_internal_kwargs(self), + ) + + +YamlGalaxyParameterT = Union[ + YamlBooleanParameter, + YamlIntegerParameter, + YamlFloatParameter, + YamlTextParameter, + YamlSelectParameter, + YamlColorParameter, + YamlDataParameter, + YamlDataCollectionParameter, + YamlConditionalParameter, + YamlRepeatParameter, + YamlSectionParameter, +] + + +class YamlGalaxyToolParameter(RootModel): + root: Annotated[YamlGalaxyParameterT, Field(discriminator="type")] + + def to_internal(self) -> GalaxyParameterT: + return self.root.to_internal() + + +YamlConditionalWhen.model_rebuild() +YamlConditionalParameter.model_rebuild() +YamlRepeatParameter.model_rebuild() +YamlSectionParameter.model_rebuild() +YamlGalaxyToolParameter.model_rebuild() diff --git a/lib/galaxy/tools/evaluation.py b/lib/galaxy/tools/evaluation.py index eeed6cd6628..5a6e52d0328 100644 --- a/lib/galaxy/tools/evaluation.py +++ b/lib/galaxy/tools/evaluation.py @@ -1099,7 +1099,14 @@ class UserToolEvaluator(ToolEvaluator): if self.tool.parameters is None: raise RequestParameterInvalidException(f"Tool {self.tool.id} has no parameters defined") parameter_bundle = ToolParameterBundleModel(parameters=self.tool.parameters) - job_runtime_state = runtimeify(validated_tool_state, parameter_bundle, adapt_datasets, adapt_collections) + yaml_origin = self.tool.tool_source.parse_class() in ("GalaxyUserTool", "GalaxyTool") + job_runtime_state = runtimeify( + validated_tool_state, + parameter_bundle, + adapt_datasets, + adapt_collections, + yaml_origin=yaml_origin, + ) cwl_style_inputs = job_runtime_state.input_state else: from galaxy.workflow.modules import to_cwl diff --git a/lib/galaxy_test/api/test_tools.py b/lib/galaxy_test/api/test_tools.py index 77d2e78698e..1f2f2e92366 100644 --- a/lib/galaxy_test/api/test_tools.py +++ b/lib/galaxy_test/api/test_tools.py @@ -43,17 +43,17 @@ MINIMAL_TOOL = { "name": "Minimal Tool", "class": "GalaxyTool", "version": "1.0.0", - "command": "echo 'Hello World' > $output1", + "shell_command": "echo 'Hello World' > 'output.txt'", "inputs": [], - "outputs": {"output1": {"format": "txt", "type": "data"}}, + "outputs": {"output1": {"format": "txt", "type": "data", "from_work_dir": "output.txt"}}, } MINIMAL_TOOL_NO_ID = { "name": "Minimal Tool", "class": "GalaxyTool", "version": "1.0.0", - "command": "echo 'Hello World 2' > $output1", + "shell_command": "echo 'Hello World 2' > 'output.txt'", "inputs": [], - "outputs": {"output1": {"format": "txt", "type": "data"}}, + "outputs": {"output1": {"format": "txt", "type": "data", "from_work_dir": "output.txt"}}, } diff --git a/test/functional/tools/parameters/gx_boolean_user.yml b/test/functional/tools/parameters/gx_boolean_user.yml index e5baea972af..7f06e9b76c8 100644 --- a/test/functional/tools/parameters/gx_boolean_user.yml +++ b/test/functional/tools/parameters/gx_boolean_user.yml @@ -2,12 +2,11 @@ class: GalaxyUserTool id: gx_boolean_user version: "1.0.0" name: gx_boolean_user +container: busybox shell_command: echo '$(inputs.parameter)' >> output.txt inputs: - name: parameter type: boolean - truevalue: mytrue - falsevalue: myfalse outputs: - name: output type: data diff --git a/test/functional/tools/parameters/gx_data_collection_sample_sheet.yml b/test/functional/tools/parameters/gx_data_collection_sample_sheet.yml index a645aedd164..4f1a7cc556b 100644 --- a/test/functional/tools/parameters/gx_data_collection_sample_sheet.yml +++ b/test/functional/tools/parameters/gx_data_collection_sample_sheet.yml @@ -1,4 +1,4 @@ -class: GalaxyTool +class: GalaxyUserTool id: gx_data_collection_sample_sheet_y name: gx_data_collection_sample_sheet_y version: "1.0.0" diff --git a/test/unit/app/managers/test_DynamicToolManager.py b/test/unit/app/managers/test_DynamicToolManager.py index a286d5a0554..88135ae15ad 100644 --- a/test/unit/app/managers/test_DynamicToolManager.py +++ b/test/unit/app/managers/test_DynamicToolManager.py @@ -14,7 +14,12 @@ class TestDynamicToolManager(BaseToolBoxTestCase): def test_create_tool(self): tool_version = "0.1" payload = DynamicToolCreatePayload( - representation={"class": "GalaxyTool", "version": tool_version, "command": "echo 42"} + representation={ + "class": "GalaxyTool", + "name": "Test Tool", + "version": tool_version, + "shell_command": "echo 42", + } ) dynamic_tool = self.dynamic_tool_manager.create_tool(payload) assert dynamic_tool.active @@ -23,6 +28,8 @@ class TestDynamicToolManager(BaseToolBoxTestCase): assert dynamic_tool.tool_version == tool_version def test_create_tool_no_version(self): - payload = DynamicToolCreatePayload(representation={"class": "GalaxyTool", "command": "echo 42"}) + payload = DynamicToolCreatePayload( + representation={"class": "GalaxyTool", "name": "Test Tool", "shell_command": "echo 42"} + ) with self.assertRaises(ValueError): self.dynamic_tool_manager.create_tool(payload) diff --git a/test/unit/tool_util/test_user_tool_source_fixtures.py b/test/unit/tool_util/test_user_tool_source_fixtures.py new file mode 100644 index 00000000000..bb4628861be --- /dev/null +++ b/test/unit/tool_util/test_user_tool_source_fixtures.py @@ -0,0 +1,71 @@ +"""Validate every YAML tool fixture in ``test/functional/tools`` against the +narrow authoring models (``UserToolSource`` / ``YamlToolSource``). + +The existing ``test_validate_framework_test_tools`` in +``test_parameter_test_cases.py`` only exercises the XML-era +``YamlToolSource`` dict parser path; it does not touch the narrow pydantic +authoring schema in ``lib/galaxy/tool_util_models/yaml_parameters.py``. +This file closes that gap so a stray XML-only field (e.g. ``truevalue``) or +a deferred parameter type added to any fixture fails a cheap unit test +instead of only an API integration. +""" + +import os +from typing import List + +import pytest +import yaml +from pydantic import TypeAdapter + +from galaxy.tool_util.unittest_utils import functional_test_tool_directory +from galaxy.tool_util_models import DynamicToolSources + +# Fixtures that predate the narrow authoring schema and use conventions +# (``checked``, ``display``, ``blocks``, ``when``, unquoted version floats, +# dict-style collection outputs) that cannot be represented via +# ``UserToolSource`` / ``YamlToolSource``. +_LEGACY_FIXTURES = { + "simple_constructs.yml", + "collection_creates_pair_y.yml", +} + +_dynamic_tool_source_adapter: TypeAdapter = TypeAdapter(DynamicToolSources) + + +def _collect_yaml_tool_fixtures() -> List[str]: + root = functional_test_tool_directory() + directories = [root, os.path.join(root, "parameters")] + paths: List[str] = [] + for directory in directories: + if not os.path.isdir(directory): + continue + for name in sorted(os.listdir(directory)): + if name in _LEGACY_FIXTURES: + continue + if not name.endswith(".yml"): + continue + full = os.path.join(directory, name) + if os.path.isdir(full): + continue + paths.append(full) + return paths + + +_YAML_FIXTURES = _collect_yaml_tool_fixtures() + + +@pytest.mark.parametrize( + "tool_path", _YAML_FIXTURES, ids=lambda p: os.path.relpath(p, functional_test_tool_directory()) +) +def test_yaml_fixture_validates_against_authoring_schema(tool_path: str): + with open(tool_path) as fh: + raw = yaml.safe_load(fh) + assert isinstance(raw, dict), f"{tool_path}: expected top-level mapping" + assert "class" in raw, f"{tool_path}: missing `class:` key" + # Validates against the UserToolSource / YamlToolSource union, + # discriminated on ``class``. + _dynamic_tool_source_adapter.validate_python(raw) + + +def test_fixture_collection_is_non_empty(): + assert _YAML_FIXTURES, "no YAML tool fixtures discovered under test/functional/tools" diff --git a/test/unit/tool_util/test_yaml_parameters.py b/test/unit/tool_util/test_yaml_parameters.py new file mode 100644 index 00000000000..2111be7855f --- /dev/null +++ b/test/unit/tool_util/test_yaml_parameters.py @@ -0,0 +1,355 @@ +"""Tests for the narrow YAML tool parameter models. + +Covers: +- reject cases for XML-only fields and unsupported parameter types, +- green round-trip from YAML authoring models through ``to_internal()`` into the + existing internal metamodel, including the ``create_job_runtime_model`` path + that backs ``/api/unprivileged_tools/runtime_model``. +""" + +import pytest +from pydantic import ValidationError + +from galaxy.tool_util.parameters.convert import assert_yaml_v1_parameters +from galaxy.tool_util_models import UserToolSource +from galaxy.tool_util_models.parameters import ( + BooleanParameterModel, + ConditionalParameterModel, + create_job_runtime_model, + DataParameterModel, + HiddenParameterModel, + RepeatParameterModel, + SectionParameterModel, + SelectParameterModel, + ToolParameterBundleModel, +) +from galaxy.tool_util_models.yaml_parameters import YamlGalaxyToolParameter + + +def _validate(input_dict): + return YamlGalaxyToolParameter.model_validate(input_dict) + + +# --------------------------------------------------------------------------- +# Red cases: XML-only fields rejected on otherwise-supported types +# --------------------------------------------------------------------------- + + +@pytest.mark.parametrize( + "extra_field", + [ + {"truevalue": "yes"}, + {"falsevalue": "no"}, + {"argument": "--foo"}, + {"is_dynamic": True}, + {"hidden": True}, + {"parameter_type": "gx_boolean"}, + ], +) +def test_boolean_rejects_xml_only_fields(extra_field): + with pytest.raises(ValidationError): + _validate({"name": "b", "type": "boolean", **extra_field}) + + +def test_text_rejects_expression_validator(): + with pytest.raises(ValidationError): + _validate( + { + "name": "t", + "type": "text", + "validators": [{"type": "expression", "expression": "value=='ok'"}], + } + ) + + +def test_select_rejects_empty_options(): + with pytest.raises(ValidationError): + _validate({"name": "s", "type": "select", "options": []}) + + +def test_select_rejects_dynamic_options(): + # No `dynamic_options` field on YamlSelectParameter → extra forbid. + with pytest.raises(ValidationError): + _validate( + { + "name": "s", + "type": "select", + "options": [{"label": "A", "value": "a", "selected": True}], + "dynamic_options": "some_fn()", + } + ) + + +# --------------------------------------------------------------------------- +# Red cases: whole parameter types rejected +# --------------------------------------------------------------------------- + + +@pytest.mark.parametrize( + "bad_type", + [ + "hidden", + "drill_down", + "data_column", + "genomebuild", + "group_tag", + "baseurl", + "rules", + "directory", + ], +) +def test_unsupported_parameter_types_rejected(bad_type): + with pytest.raises(ValidationError): + _validate({"name": "x", "type": bad_type}) + + +# --------------------------------------------------------------------------- +# Green cases: leaf types round-trip through to_internal() +# --------------------------------------------------------------------------- + + +def test_boolean_roundtrip(): + p = _validate({"name": "b", "type": "boolean", "value": True}) + internal = p.to_internal() + assert isinstance(internal, BooleanParameterModel) + assert internal.value is True + # YAML layer did not populate Cheetah-only fields on the internal model. + assert internal.truevalue is None + assert internal.falsevalue is None + + +def test_integer_with_inrange_validator(): + p = _validate( + { + "name": "n", + "type": "integer", + "value": 5, + "min": 0, + "max": 10, + "validators": [{"type": "in_range", "min": 0, "max": 10}], + } + ) + internal = p.to_internal() + assert internal.min == 0 + assert internal.max == 10 + assert len(internal.validators) == 1 + + +def test_select_static_options(): + p = _validate( + { + "name": "s", + "type": "select", + "multiple": False, + "options": [ + {"label": "A", "value": "a", "selected": True}, + {"label": "B", "value": "b", "selected": False}, + ], + } + ) + internal = p.to_internal() + assert isinstance(internal, SelectParameterModel) + assert internal.default_value == "a" + + +def test_data_accepts_format_string(): + # Matches the XML `format="txt"` vocabulary and the PR 19434 example. + p = _validate({"name": "input1", "type": "data", "format": "txt"}) + internal = p.to_internal() + assert isinstance(internal, DataParameterModel) + assert internal.extensions == ["txt"] + + +def test_data_accepts_format_list(): + p = _validate({"name": "input1", "type": "data", "format": ["txt", "tabular"]}) + assert p.to_internal().extensions == ["txt", "tabular"] + + +def test_data_accepts_format_comma_string(): + p = _validate({"name": "input1", "type": "data", "format": "txt,tabular"}) + assert p.to_internal().extensions == ["txt", "tabular"] + + +def test_data_rejects_extensions_key(): + # `extensions` is the internal metamodel name; the YAML authoring surface + # exposes `format` only. + with pytest.raises(ValidationError): + _validate({"name": "input1", "type": "data", "extensions": ["txt"]}) + + +# --------------------------------------------------------------------------- +# Green cases: structural groups +# --------------------------------------------------------------------------- + + +def test_conditional_rejects_empty_whens(): + with pytest.raises(ValidationError): + _validate( + { + "name": "cond", + "type": "conditional", + "test_parameter": { + "name": "mode", + "type": "select", + "options": [{"label": "A", "value": "a", "selected": True}], + }, + "whens": [], + } + ) + + +def test_conditional_with_select_test_parameter(): + p = _validate( + { + "name": "cond", + "type": "conditional", + "test_parameter": { + "name": "mode", + "type": "select", + "options": [ + {"label": "A", "value": "a", "selected": True}, + {"label": "B", "value": "b", "selected": False}, + ], + }, + "whens": [ + { + "discriminator": "a", + "parameters": [{"name": "x", "type": "text", "value": "hi"}], + }, + {"discriminator": "b", "parameters": []}, + ], + } + ) + internal = p.to_internal() + assert isinstance(internal, ConditionalParameterModel) + default_flags = {w.discriminator: w.is_default_when for w in internal.whens} + assert default_flags == {"a": True, "b": False} + + +def test_repeat_of_data(): + p = _validate( + { + "name": "rep", + "type": "repeat", + "min": 1, + "max": 3, + "parameters": [{"name": "input1", "type": "data", "format": "txt"}], + } + ) + internal = p.to_internal() + assert isinstance(internal, RepeatParameterModel) + assert internal.min == 1 + assert internal.max == 3 + assert isinstance(internal.parameters[0], DataParameterModel) + + +def test_section_recurses(): + p = _validate( + { + "name": "sec", + "type": "section", + "parameters": [ + {"name": "a", "type": "integer", "value": 1}, + {"name": "b", "type": "boolean", "value": False}, + ], + } + ) + internal = p.to_internal() + assert isinstance(internal, SectionParameterModel) + assert [p.name for p in internal.parameters] == ["a", "b"] + + +# --------------------------------------------------------------------------- +# Green: UserToolSource end-to-end for the PR 19434 example shape +# --------------------------------------------------------------------------- + + +CAT_USER_DEFINED = { + "class": "GalaxyUserTool", + "id": "cat_user_defined", + "version": "0.1", + "name": "cat_user_defined", + "description": "concatenates a file", + "container": "busybox", + "shell_command": "cat '$(inputs.input1.path)' > output.txt", + "inputs": [{"name": "input1", "type": "data", "format": "txt"}], + "outputs": [], +} + + +def test_user_tool_source_rejects_unknown_top_level_key(): + bad = {**CAT_USER_DEFINED, "argument": "--nope"} + with pytest.raises(ValidationError): + UserToolSource.model_validate(bad) + + +def test_user_tool_source_validates_pr19434_example(): + tool = UserToolSource.model_validate(CAT_USER_DEFINED) + assert tool.inputs[0].root.type == "data" + assert tool.inputs[0].root.format == ["txt"] + + +def test_runtime_model_pipeline_from_yaml_internal(): + tool = UserToolSource.model_validate(CAT_USER_DEFINED) + bundle = ToolParameterBundleModel(parameters=[i.to_internal() for i in tool.inputs]) + model = create_job_runtime_model(bundle) + schema = model.model_json_schema() + assert "input1" in schema["properties"] + + +# --------------------------------------------------------------------------- +# Snapshot: published ToolSourceSchema.json is free of XML-only leaks +# --------------------------------------------------------------------------- + + +_BLACKLIST_SUBSTRINGS = ( + "truevalue", + "falsevalue", + "argument", + "is_dynamic", + "parameter_type", + "hierarchy", + "data_ref", + "gx_hidden", + "gx_drill_down", + "gx_genomebuild", + "gx_group_tag", + "gx_baseurl", + "gx_rules", +) + + +# --------------------------------------------------------------------------- +# Step 6: runtimeify enforces the v1 parameter allowlist for YAML-origin tools +# --------------------------------------------------------------------------- + + +def test_assert_yaml_v1_parameters_accepts_supported_set(): + tool = UserToolSource.model_validate(CAT_USER_DEFINED) + parameters = [i.to_internal() for i in tool.inputs] + # should not raise + assert_yaml_v1_parameters(parameters) + + +def test_assert_yaml_v1_parameters_rejects_deferred_type(): + hidden = HiddenParameterModel(type="hidden", name="h", value=None) + with pytest.raises(AssertionError): + assert_yaml_v1_parameters([hidden]) + + +def test_assert_yaml_v1_parameters_walks_nested_groups(): + hidden = HiddenParameterModel(type="hidden", name="h", value=None) + repeat = RepeatParameterModel(type="repeat", name="r", parameters=[hidden], min=None, max=None) + with pytest.raises(AssertionError): + assert_yaml_v1_parameters([repeat]) + + +def test_published_tool_source_schema_has_no_xml_only_leaks(): + raw = UserToolSource.model_json_schema() + # Collect all property names across every $defs entry and the top level. + all_property_names: set = set() + for defn in raw.get("$defs", {}).values(): + all_property_names.update(defn.get("properties", {}).keys()) + all_property_names.update(raw.get("properties", {}).keys()) + leaks = [bad for bad in _BLACKLIST_SUBSTRINGS if bad in all_property_names] + assert not leaks, f"XML-only fields leaked into published schema: {leaks}"